xsec/dsig/DSIGTransformC14n.cpp (193 lines of code) (raw):

/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * XSEC * * DSIGTransformC14n := Class that performs C14n canonicalisation * * $Id$ * */ #include <xsec/dsig/DSIGSignature.hpp> #include <xsec/dsig/DSIGTransformC14n.hpp> #include <xsec/framework/XSECEnv.hpp> #include <xsec/framework/XSECError.hpp> #include <xsec/framework/XSECException.hpp> #include <xsec/transformers/TXFMC14n.hpp> #include <xsec/transformers/TXFMChain.hpp> #include "../utils/XSECAlgorithmSupport.hpp" #include "../utils/XSECDOMUtils.hpp" XERCES_CPP_NAMESPACE_USE // -------------------------------------------------------------------------------- // Constructors and Destructors // -------------------------------------------------------------------------------- DSIGTransformC14n::DSIGTransformC14n(const XSECEnv* env, DOMNode* node) : DSIGTransform(env, node) { m_cMethod = NULL; mp_inclNSNode = NULL; mp_inclNSStr = NULL; m_exclusive = false; m_comments = false; m_onedotone = false; } DSIGTransformC14n::DSIGTransformC14n(const XSECEnv* env) : DSIGTransform(env) { m_cMethod = NULL; mp_inclNSNode = NULL; mp_inclNSStr = NULL; m_exclusive = false; m_comments = false; m_onedotone = false; } DSIGTransformC14n::~DSIGTransformC14n() {}; // -------------------------------------------------------------------------------- // Interface Methods // -------------------------------------------------------------------------------- void DSIGTransformC14n::appendTransformer(TXFMChain* input) { TXFMC14n* c; XSECnew(c, TXFMC14n(mp_txfmNode->getOwnerDocument())); input->appendTxfm(c); if (m_comments) c->activateComments(); else c->stripComments(); // Check for exclusive and 1.1 if (m_exclusive) { if (mp_inclNSStr == NULL) { c->setExclusive(); } else { safeBuffer incl; incl << (*(mp_env->getSBFormatter()) << mp_inclNSStr); c->setExclusive(incl); } } else if (m_onedotone) { c->setInclusive11(); } } DOMElement* DSIGTransformC14n::createBlankTransform(DOMDocument* parentDoc) { safeBuffer str; const XMLCh * prefix; DOMElement *ret; DOMDocument *doc = mp_env->getParentDocument(); prefix = mp_env->getDSIGNSPrefix(); // Create the transform node makeQName(str, prefix, "Transform"); ret = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer()); ret->setAttributeNS(NULL,DSIGConstants::s_unicodeStrAlgorithm, DSIGConstants::s_unicodeStrURIC14N_NOC); m_cMethod = ret->getAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm); m_comments = false; m_exclusive = false; m_onedotone = false; mp_txfmNode = ret; mp_inclNSStr = NULL; mp_inclNSNode = NULL; return ret; } void DSIGTransformC14n::load() { DOMNamedNodeMap* atts; DOMNode* att; // Read the URI for the type if (mp_txfmNode == NULL) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected <Transform> Node in DSIGTrasnformC14n::load"); } atts = mp_txfmNode->getAttributes(); if (atts == NULL || ((att = atts->getNamedItem(DSIGConstants::s_unicodeStrAlgorithm)) == NULL)) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected to find Algorithm attribute in <Transform> node"); } m_cMethod = att->getNodeValue(); if (!XSECAlgorithmSupport::evalCanonicalizationMethod(m_cMethod, m_exclusive, m_comments, m_onedotone)) { throw XSECException(XSECException::TransformError, "Unexpected URI found in canonicalization <Transform>"); } // Determine whether there is an InclusiveNamespaces list if (m_exclusive) { // Exclusive, so there may be an InclusiveNamespaces node DOMNode* inclNSNode = mp_txfmNode->getFirstChild(); while (inclNSNode != NULL && (inclNSNode->getNodeType() != DOMNode::ELEMENT_NODE || !strEquals(getECLocalName(inclNSNode), "InclusiveNamespaces"))) inclNSNode = inclNSNode->getNextSibling(); if (inclNSNode != 0) { mp_inclNSNode = static_cast<DOMElement *>(inclNSNode); // Have a prefix list atts = mp_inclNSNode->getAttributes(); safeBuffer inSB; if (atts == 0 || ((att = atts->getNamedItem(MAKE_UNICODE_STRING("PrefixList"))) == NULL)) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected PrefixList in InclusiveNamespaces"); } mp_inclNSStr = att->getNodeValue(); } } } // -------------------------------------------------------------------------------- // Canonicalization Specific Methods // -------------------------------------------------------------------------------- void DSIGTransformC14n::setCanonicalizationMethod(const XMLCh* uri) { bool exclusive; bool comments; bool onedotone; if (mp_txfmNode == NULL || !XSECAlgorithmSupport::evalCanonicalizationMethod(uri, exclusive, comments, onedotone)) { throw XSECException(XSECException::TransformError, "Either method unknown or Node not set in setCanonicalizationMethod"); } // Switching from exclusive to inclusive? if (!exclusive && m_exclusive) { if (mp_inclNSNode != 0) { mp_txfmNode->removeChild(mp_inclNSNode); mp_inclNSNode->release(); // No longer required mp_inclNSNode = NULL; mp_inclNSStr = NULL; } } // Now do the set. ((DOMElement *) mp_txfmNode)->setAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm, uri); m_cMethod = ((DOMElement *) mp_txfmNode)->getAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm); m_exclusive = exclusive; m_comments = comments; m_onedotone = onedotone; } const XMLCh* DSIGTransformC14n::getCanonicalizationMethod() const { return m_cMethod; } void DSIGTransformC14n::createInclusiveNamespaceNode() { // Creates an empty inclusiveNamespace node. Does _not_ set the prefixlist attribute if (mp_inclNSNode != NULL) return; // Already exists safeBuffer str; const XMLCh * prefix; DOMDocument *doc = mp_env->getParentDocument(); // Use the Exclusive Canonicalisation prefix prefix = mp_env->getECNSPrefix(); // Create the transform node makeQName(str, prefix, "InclusiveNamespaces"); mp_inclNSNode = doc->createElementNS(DSIGConstants::s_unicodeStrURIEC, str.rawXMLChBuffer()); // Add the node to the owner element mp_env->doPrettyPrint(mp_txfmNode); mp_txfmNode->appendChild(mp_inclNSNode); mp_env->doPrettyPrint(mp_txfmNode); // Set the namespace attribute if (prefix[0] == '\0') { str.sbTranscodeIn("xmlns"); } else { str.sbTranscodeIn("xmlns:"); str.sbXMLChCat(prefix); } mp_inclNSNode->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS, str.rawXMLChBuffer(), DSIGConstants::s_unicodeStrURIEC); } void DSIGTransformC14n::setInclusiveNamespaces(const XMLCh* ns) { // Set all the namespaces at once if (!m_exclusive) { throw XSECException(XSECException::TransformError, "Cannot set inclusive namespaces on non Exclusive Canonicalization"); } if (mp_inclNSNode == NULL) { // Create the transform node createInclusiveNamespaceNode(); } // Now create the prefix list mp_inclNSNode->setAttributeNS(NULL,MAKE_UNICODE_STRING("PrefixList"), ns); mp_inclNSStr = mp_inclNSNode->getAttributes()->getNamedItem(MAKE_UNICODE_STRING("PrefixList"))->getNodeValue(); } void DSIGTransformC14n::addInclusiveNamespace(const char* ns) { if (!m_exclusive) { throw XSECException(XSECException::TransformError, "Cannot set inclusive namespaces on non Exclusive Canonicalization"); } if (mp_inclNSNode == NULL) { // Create the transform node createInclusiveNamespaceNode(); // Now create the prefix list mp_inclNSNode->setAttributeNS(NULL,MAKE_UNICODE_STRING("PrefixList"), MAKE_UNICODE_STRING(ns)); mp_inclNSStr = mp_inclNSNode->getAttributes()->getNamedItem(MAKE_UNICODE_STRING("PrefixList"))->getNodeValue(); } else { // More tricky safeBuffer str; str << (*(mp_env->getSBFormatter()) << mp_inclNSStr); str.sbStrcatIn(" "); str.sbStrcatIn((char *) ns); mp_inclNSNode->setAttributeNS(NULL,MAKE_UNICODE_STRING("PrefixList"), str.sbStrToXMLCh()); mp_inclNSStr = mp_inclNSNode->getAttributes()->getNamedItem(MAKE_UNICODE_STRING("PrefixList"))->getNodeValue(); } } const XMLCh* DSIGTransformC14n::getPrefixList() const { return mp_inclNSStr; } void DSIGTransformC14n::clearInclusiveNamespaces() { if (mp_inclNSNode != 0) { mp_txfmNode->removeChild(mp_inclNSNode); mp_inclNSNode->release(); // No longer required mp_inclNSNode = NULL; mp_inclNSStr = NULL; } }