-/*\r
-* Copyright 2001-2006 Internet2\r
- * \r
-* Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * XMLSecSignatureImpl.cpp\r
- * \r
- * Signature class for XMLSec-based signature-handling\r
- */\r
-\r
-#include "internal.h"\r
-#include "exceptions.h"\r
-#include "impl/UnknownElement.h"\r
-#include "signature/Signature.h"\r
-#include "util/NDC.h"\r
-#include "util/XMLConstants.h"\r
-#include "util/XMLHelper.h"\r
-\r
-#include <log4cpp/Category.hh>\r
-#include <xercesc/framework/MemBufInputSource.hpp>\r
-#include <xercesc/framework/Wrapper4InputSource.hpp>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-#include <xsec/dsig/DSIGKeyInfoX509.hpp>\r
-#include <xsec/enc/XSECCryptoException.hpp>\r
-#include <xsec/framework/XSECException.hpp>\r
-\r
-using namespace xmlsignature;\r
-using namespace xmltooling;\r
-using namespace log4cpp;\r
-using namespace std;\r
-\r
-#if defined (_MSC_VER)\r
- #pragma warning( push )\r
- #pragma warning( disable : 4250 4251 )\r
-#endif\r
-\r
-namespace xmlsignature {\r
- \r
- class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature\r
- {\r
- public:\r
- XMLSecSignatureImpl() : UnknownElementImpl(XMLConstants::XMLSIG_NS, Signature::LOCAL_NAME, XMLConstants::XMLSIG_PREFIX),\r
- m_signature(NULL), m_c14n(NULL), m_sm(NULL) {}\r
- virtual ~XMLSecSignatureImpl();\r
- \r
- void releaseDOM();\r
- XMLObject* clone() const;\r
-\r
- DOMElement* marshall(DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const;\r
- DOMElement* marshall(DOMElement* parentElement, MarshallingContext* ctx=NULL) const;\r
- XMLObject* unmarshall(DOMElement* element, bool bindDocument=false);\r
- \r
- // Getters\r
- const XMLCh* getCanonicalizationMethod() const { return m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC; }\r
- const XMLCh* getSignatureAlgorithm() const { return m_sm ? m_sm : DSIGConstants::s_unicodeStrURIRSA_SHA1; }\r
-\r
- // Setters\r
- void setCanonicalizationMethod(const XMLCh* c14n) { m_c14n = prepareForAssignment(m_c14n,c14n); }\r
- void setSignatureAlgorithm(const XMLCh* sm) { m_sm = prepareForAssignment(m_sm,sm); }\r
-\r
- void sign(const SigningContext& ctx);\r
- void verify(const VerifyingContext& ctx) const;\r
-\r
- private:\r
- mutable DSIGSignature* m_signature;\r
- XMLCh* m_c14n;\r
- XMLCh* m_sm;\r
- };\r
- \r
-};\r
-\r
-#if defined (_MSC_VER)\r
- #pragma warning( pop )\r
-#endif\r
-\r
-XMLSecSignatureImpl::~XMLSecSignatureImpl()\r
-{\r
- // Release the associated signature.\r
- if (m_signature)\r
- XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);\r
-\r
- XMLString::release(&m_c14n);\r
- XMLString::release(&m_sm);\r
-}\r
-\r
-void XMLSecSignatureImpl::releaseDOM()\r
-{\r
- // This should save off the DOM\r
- UnknownElementImpl::releaseDOM();\r
- \r
- // Release the associated signature.\r
- if (m_signature) {\r
- XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);\r
- m_signature=NULL;\r
- }\r
-}\r
-\r
-XMLObject* XMLSecSignatureImpl::clone() const\r
-{\r
- XMLSecSignatureImpl* ret=new XMLSecSignatureImpl();\r
-\r
- ret->m_c14n=XMLString::replicate(m_c14n);\r
- ret->m_sm=XMLString::replicate(m_sm);\r
-\r
- // If there's no XML locally, serialize this object into the new one, otherwise just copy it over.\r
- if (m_xml.empty())\r
- serialize(ret->m_xml);\r
- else\r
- ret->m_xml=m_xml;\r
-\r
- return ret;\r
-}\r
-\r
-class _addcert : public std::binary_function<DSIGKeyInfoX509*,XSECCryptoX509*,void> {\r
-public:\r
- void operator()(DSIGKeyInfoX509* bag, XSECCryptoX509* cert) const {\r
- safeBuffer& buf=cert->getDEREncodingSB();\r
- bag->appendX509Certificate(buf.sbStrToXMLCh());\r
- }\r
-};\r
-\r
-void XMLSecSignatureImpl::sign(const SigningContext& ctx)\r
-{\r
- Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");\r
- log.debug("applying signature");\r
-\r
- if (!m_signature)\r
- throw SignatureException("Only a marshalled Signature object can be signed.");\r
-\r
- try {\r
- log.debug("creating signature content");\r
- ctx.createSignature(m_signature);\r
- const std::vector<XSECCryptoX509*>& certs=ctx.getX509Certificates();\r
- if (!certs.empty()) {\r
- DSIGKeyInfoX509* x509Data=m_signature->appendX509Data();\r
- for_each(certs.begin(),certs.end(),bind1st(_addcert(),x509Data));\r
- }\r
- \r
- log.debug("computing signature");\r
- m_signature->setSigningKey(ctx.getSigningKey());\r
- m_signature->sign();\r
- }\r
- catch(XSECException& e) {\r
- auto_ptr_char temp(e.getMsg());\r
- throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + temp.get());\r
- }\r
- catch(XSECCryptoException& e) {\r
- throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + e.getMsg());\r
- }\r
-}\r
-\r
-void XMLSecSignatureImpl::verify(const VerifyingContext& ctx) const\r
-{\r
- Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");\r
- log.debug("verifying signature");\r
-\r
- if (!m_signature)\r
- throw SignatureException("Only a marshalled Signature object can be verified.");\r
-\r
- try {\r
- ctx.verifySignature(m_signature);\r
- }\r
- catch(XSECException& e) {\r
- auto_ptr_char temp(e.getMsg());\r
- throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + temp.get());\r
- }\r
- catch(XSECCryptoException& e) {\r
- throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + e.getMsg());\r
- }\r
-}\r
-\r
-DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, MarshallingContext* ctx) const\r
-{\r
-#ifdef _DEBUG\r
- xmltooling::NDC ndc("marshall");\r
-#endif\r
- \r
- Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");\r
- log.debug("marshalling ds:Signature");\r
-\r
- DOMElement* cachedDOM=getDOM();\r
- if (cachedDOM) {\r
- if (!document || document==cachedDOM->getOwnerDocument()) {\r
- log.debug("Signature has a usable cached DOM, reusing it");\r
- if (document)\r
- setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM);\r
- releaseParentDOM(true);\r
- return cachedDOM;\r
- }\r
- \r
- // We have a DOM but it doesn't match the document we were given, so we import\r
- // it into the new document.\r
- cachedDOM=static_cast<DOMElement*>(document->importNode(cachedDOM, true));\r
-\r
- try {\r
- XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);\r
- m_signature=NULL;\r
- m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(\r
- document, cachedDOM\r
- );\r
- m_signature->load();\r
- }\r
- catch(XSECException& e) {\r
- auto_ptr_char temp(e.getMsg());\r
- throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());\r
- }\r
- catch(XSECCryptoException& e) {\r
- throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());\r
- }\r
-\r
- // Recache the DOM.\r
- setDocumentElement(document, cachedDOM);\r
- log.debug("caching imported DOM for Signature");\r
- setDOM(cachedDOM, false);\r
- releaseParentDOM(true);\r
- return cachedDOM;\r
- }\r
- \r
- // If we get here, we didn't have a usable DOM.\r
- bool bindDocument=false;\r
- if (m_xml.empty()) {\r
- // Fresh signature, so we just create an empty one.\r
- log.debug("creating empty Signature element");\r
- if (!document) {\r
- document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument();\r
- bindDocument=true;\r
- }\r
- m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();\r
- m_signature->setDSIGNSPrefix(XMLConstants::XMLSIG_PREFIX);\r
- cachedDOM=m_signature->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm());\r
- }\r
- else {\r
- // We need to reparse the XML we saved off into a new DOM.\r
- MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl");\r
- Wrapper4InputSource dsrc(&src,false);\r
- log.debug("parsing Signature XML back into DOM tree");\r
- DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc);\r
- if (document) {\r
- // The caller insists on using his own document, so we now have to import the thing\r
- // into it. Then we're just dumping the one we built.\r
- log.debug("reimporting new DOM into caller-supplied document");\r
- cachedDOM=static_cast<DOMElement*>(document->importNode(internalDoc->getDocumentElement(), true));\r
- internalDoc->release();\r
- }\r
- else {\r
- // We just bind the document we built to the object as the result.\r
- cachedDOM=static_cast<DOMElement*>(internalDoc->getDocumentElement());\r
- document=internalDoc;\r
- bindDocument=true;\r
- }\r
-\r
- // Now reload the signature from the DOM.\r
- try {\r
- m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(\r
- document, cachedDOM\r
- );\r
- m_signature->load();\r
- }\r
- catch(XSECException& e) {\r
- if (bindDocument)\r
- document->release();\r
- auto_ptr_char temp(e.getMsg());\r
- throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());\r
- }\r
- catch(XSECCryptoException& e) {\r
- if (bindDocument)\r
- document->release();\r
- throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());\r
- }\r
- }\r
- \r
- // Recache the DOM and clear the serialized copy.\r
- setDocumentElement(document, cachedDOM);\r
- log.debug("caching DOM for Signature (document is %sbound)", bindDocument ? "" : "not ");\r
- setDOM(cachedDOM, bindDocument);\r
- releaseParentDOM(true);\r
- m_xml.erase();\r
- return cachedDOM;\r
-}\r
-\r
-DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, MarshallingContext* ctx) const\r
-{\r
-#ifdef _DEBUG\r
- xmltooling::NDC ndc("marshall");\r
-#endif\r
- \r
- Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");\r
- log.debug("marshalling ds:Signature");\r
-\r
- DOMElement* cachedDOM=getDOM();\r
- if (cachedDOM) {\r
- if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) {\r
- log.debug("Signature has a usable cached DOM, reusing it");\r
- parentElement->appendChild(cachedDOM);\r
- releaseParentDOM(true);\r
- return cachedDOM;\r
- }\r
- \r
- // We have a DOM but it doesn't match the document we were given, so we import\r
- // it into the new document.\r
- cachedDOM=static_cast<DOMElement*>(parentElement->getOwnerDocument()->importNode(cachedDOM, true));\r
-\r
- try {\r
- XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);\r
- m_signature=NULL;\r
- m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(\r
- parentElement->getOwnerDocument(), cachedDOM\r
- );\r
- m_signature->load();\r
- }\r
- catch(XSECException& e) {\r
- auto_ptr_char temp(e.getMsg());\r
- throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());\r
- }\r
- catch(XSECCryptoException& e) {\r
- throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());\r
- }\r
-\r
- // Recache the DOM.\r
- parentElement->appendChild(cachedDOM);\r
- log.debug("caching imported DOM for Signature");\r
- setDOM(cachedDOM, false);\r
- releaseParentDOM(true);\r
- return cachedDOM;\r
- }\r
- \r
- // If we get here, we didn't have a usable DOM.\r
- if (m_xml.empty()) {\r
- // Fresh signature, so we just create an empty one.\r
- log.debug("creating empty Signature element");\r
- m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();\r
- m_signature->setDSIGNSPrefix(XMLConstants::XMLSIG_PREFIX);\r
- cachedDOM=m_signature->createBlankSignature(\r
- parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm()\r
- );\r
- }\r
- else {\r
- MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl");\r
- Wrapper4InputSource dsrc(&src,false);\r
- log.debug("parsing XML back into DOM tree");\r
- DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc);\r
- \r
- log.debug("reimporting new DOM into caller-supplied document");\r
- cachedDOM=static_cast<DOMElement*>(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(),true));\r
- internalDoc->release();\r
-\r
- // Now reload the signature from the DOM.\r
- try {\r
- m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(\r
- parentElement->getOwnerDocument(), cachedDOM\r
- );\r
- m_signature->load();\r
- }\r
- catch(XSECException& e) {\r
- auto_ptr_char temp(e.getMsg());\r
- throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());\r
- }\r
- catch(XSECCryptoException& e) {\r
- throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());\r
- }\r
- }\r
-\r
- // Recache the DOM and clear the serialized copy.\r
- parentElement->appendChild(cachedDOM);\r
- log.debug("caching DOM for Signature");\r
- setDOM(cachedDOM, false);\r
- releaseParentDOM(true);\r
- m_xml.erase();\r
- return cachedDOM;\r
-}\r
-\r
-XMLObject* XMLSecSignatureImpl::unmarshall(DOMElement* element, bool bindDocument)\r
-{\r
- Category::getInstance(XMLTOOLING_LOGCAT".Signature").debug("unmarshalling ds:Signature");\r
-\r
- try {\r
- m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(\r
- element->getOwnerDocument(), element\r
- );\r
- m_signature->load();\r
- }\r
- catch(XSECException& e) {\r
- auto_ptr_char temp(e.getMsg());\r
- throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());\r
- }\r
- catch(XSECCryptoException& e) {\r
- throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());\r
- }\r
-\r
- setDOM(element, bindDocument);\r
- return this;\r
-}\r
-\r
-Signature* SignatureBuilder::buildObject(\r
- const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType\r
- ) const\r
-{\r
- if (!XMLString::equals(nsURI,XMLConstants::XMLSIG_NS) || !XMLString::equals(localName,Signature::LOCAL_NAME))\r
- throw XMLObjectException("XMLSecSignatureBuilder requires standard Signature element name.");\r
- return buildObject();\r
-}\r
-\r
-Signature* SignatureBuilder::buildObject() const\r
-{\r
- return new XMLSecSignatureImpl();\r
-}\r
-\r
-const XMLCh Signature::LOCAL_NAME[] = UNICODE_LITERAL_9(S,i,g,n,a,t,u,r,e);\r
+/*
+* Copyright 2001-2007 Internet2
+ *
+* Licensed 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.
+ */
+
+/**
+ * XMLSecSignatureImpl.cpp
+ *
+ * Signature class for XMLSec-based signature-handling
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "impl/UnknownElement.h"
+#include "security/Credential.h"
+#include "signature/KeyInfo.h"
+#include "signature/Signature.h"
+#include "util/NDC.h"
+#include "util/XMLConstants.h"
+#include "util/XMLHelper.h"
+
+#include <log4cpp/Category.hh>
+#include <xercesc/framework/MemBufInputSource.hpp>
+#include <xercesc/framework/Wrapper4InputSource.hpp>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xsec/dsig/DSIGKeyInfoX509.hpp>
+#include <xsec/dsig/DSIGReference.hpp>
+#include <xsec/enc/XSECCryptoException.hpp>
+#include <xsec/framework/XSECAlgorithmHandler.hpp>
+#include <xsec/framework/XSECAlgorithmMapper.hpp>
+#include <xsec/framework/XSECException.hpp>
+#include <xsec/transformers/TXFMSB.hpp>
+#include <xsec/transformers/TXFMChain.hpp>
+#include <xsec/transformers/TXFMOutputFile.hpp>
+
+using namespace xmlsignature;
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+using xmlconstants::XMLSIG_NS;
+using xmlconstants::XMLSIG_PREFIX;
+
+#if defined (_MSC_VER)
+ #pragma warning( push )
+ #pragma warning( disable : 4250 4251 )
+#endif
+
+namespace xmlsignature {
+
+ class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature
+ {
+ public:
+ XMLSecSignatureImpl() : AbstractXMLObject(XMLSIG_NS, Signature::LOCAL_NAME, XMLSIG_PREFIX),
+ UnknownElementImpl(XMLSIG_NS, Signature::LOCAL_NAME, XMLSIG_PREFIX),
+ m_signature(NULL), m_c14n(NULL), m_sm(NULL), m_key(NULL), m_keyInfo(NULL), m_reference(NULL) {}
+ virtual ~XMLSecSignatureImpl();
+
+ void releaseDOM() const;
+ void releaseChildrenDOM(bool propagateRelease=true) const {
+ if (m_keyInfo) {
+ m_keyInfo->releaseDOM();
+ if (propagateRelease)
+ m_keyInfo->releaseChildrenDOM();
+ }
+ }
+ XMLObject* clone() const;
+ Signature* cloneSignature() const;
+
+ DOMElement* marshall(DOMDocument* document=NULL, const vector<Signature*>* sigs=NULL, const Credential* credential=NULL) const;
+ DOMElement* marshall(DOMElement* parentElement, const vector<Signature*>* sigs=NULL, const Credential* credential=NULL) const;
+ XMLObject* unmarshall(DOMElement* element, bool bindDocument=false);
+
+ // Getters
+ const XMLCh* getCanonicalizationMethod() const {
+ if (m_signature)
+ return canonicalizationMethod2UNICODEURI(m_signature->getCanonicalizationMethod());
+ return m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC;
+ }
+ const XMLCh* getSignatureAlgorithm() const {
+ if (!m_sm && m_signature) {
+ safeBuffer sURI;
+ if (signatureHashMethod2URI(sURI, m_signature->getSignatureMethod(), m_signature->getHashMethod()) == false)
+ return NULL;
+ m_sm = XMLString::replicate(sURI.sbStrToXMLCh());
+ }
+ return m_sm ? m_sm : DSIGConstants::s_unicodeStrURIRSA_SHA1;
+ }
+
+ KeyInfo* getKeyInfo() const { return m_keyInfo; }
+ ContentReference* getContentReference() const { return m_reference; }
+ DSIGSignature* getXMLSignature() const { return m_signature; }
+
+ // Setters
+ void setCanonicalizationMethod(const XMLCh* c14n) { m_c14n = prepareForAssignment(m_c14n,c14n); }
+ void setSignatureAlgorithm(const XMLCh* sm) { m_sm = prepareForAssignment(m_sm,sm); }
+ void setSigningKey(XSECCryptoKey* signingKey) {
+ delete m_key;
+ m_key=signingKey;
+ }
+ void setKeyInfo(KeyInfo* keyInfo) {
+ prepareForAssignment(m_keyInfo, keyInfo);
+ m_keyInfo=keyInfo;
+ }
+ void setContentReference(ContentReference* reference) {
+ delete m_reference;
+ m_reference=reference;
+ }
+
+ void sign(const Credential* credential=NULL);
+
+ private:
+ mutable DSIGSignature* m_signature;
+ XMLCh* m_c14n;
+ mutable XMLCh* m_sm;
+ XSECCryptoKey* m_key;
+ mutable KeyInfo* m_keyInfo;
+ ContentReference* m_reference;
+ };
+
+};
+
+#if defined (_MSC_VER)
+ #pragma warning( pop )
+#endif
+
+XMLSecSignatureImpl::~XMLSecSignatureImpl()
+{
+ // Release the associated signature.
+ if (m_signature)
+ XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);
+
+ XMLString::release(&m_c14n);
+ XMLString::release(&m_sm);
+ delete m_key;
+ delete m_keyInfo;
+ delete m_reference;
+}
+
+void XMLSecSignatureImpl::releaseDOM() const
+{
+ if (getDOM()) {
+ // This should save off the DOM
+ UnknownElementImpl::releaseDOM();
+
+ // Release the associated signature.
+ if (m_signature) {
+ XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);
+ m_signature=NULL;
+ }
+ }
+}
+
+XMLObject* XMLSecSignatureImpl::clone() const
+{
+ return cloneSignature();
+}
+
+Signature* XMLSecSignatureImpl::cloneSignature() const
+{
+ XMLSecSignatureImpl* ret=new XMLSecSignatureImpl();
+
+ ret->m_c14n=XMLString::replicate(m_c14n);
+ ret->m_sm=XMLString::replicate(m_sm);
+ if (m_key)
+ ret->m_key=m_key->clone();
+ if (m_keyInfo)
+ ret->m_keyInfo=m_keyInfo->cloneKeyInfo();
+
+ // If there's no XML locally, serialize this object into the new one, otherwise just copy it over.
+ if (m_xml.empty())
+ serialize(ret->m_xml);
+ else
+ ret->m_xml=m_xml;
+
+ return ret;
+}
+
+void XMLSecSignatureImpl::sign(const Credential* credential)
+{
+ Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");
+ log.debug("applying signature");
+
+ if (!m_signature)
+ throw SignatureException("Only a marshalled Signature object can be signed.");
+ else if (!m_reference)
+ throw SignatureException("No ContentReference object set for signature creation.");
+
+ XSECCryptoKey* key = credential ? credential->getPrivateKey() : m_key;
+ if (!key)
+ throw SignatureException("No signing key available for signature creation.");
+
+ try {
+ log.debug("creating signature reference(s)");
+ DSIGReferenceList* refs = m_signature->getReferenceList();
+ while (refs && refs->getSize())
+ delete refs->removeReference(0);
+ m_reference->createReferences(m_signature);
+
+ log.debug("computing signature");
+ m_signature->setSigningKey(key->clone());
+ m_signature->sign();
+ }
+ catch(XSECException& e) {
+ auto_ptr_char temp(e.getMsg());
+ throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + temp.get());
+ }
+ catch(XSECCryptoException& e) {
+ throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + e.getMsg());
+ }
+}
+
+DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector<Signature*>* sigs, const Credential* credential) const
+{
+#ifdef _DEBUG
+ xmltooling::NDC ndc("marshall");
+#endif
+
+ Category& log=Category::getInstance(XMLTOOLING_LOGCAT".XMLObject.Signature");
+ log.debug("marshalling ds:Signature");
+
+ DOMElement* cachedDOM=getDOM();
+ if (cachedDOM) {
+ if (!document || document==cachedDOM->getOwnerDocument()) {
+ log.debug("Signature has a usable cached DOM, reusing it");
+ if (document)
+ setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM);
+ releaseParentDOM(true);
+ return cachedDOM;
+ }
+
+ // We have a DOM but it doesn't match the document we were given. This both sucks and blows.
+ // Without an adoptNode option to maintain the child pointers, we have to either import the
+ // DOM while somehow reassigning all the nested references (which amounts to a complete
+ // *unmarshall* operation), or we just release the existing DOM and hope that we can get
+ // it back. This depends on all objects being able to preserve their DOM at all costs.
+ releaseChildrenDOM(true);
+ releaseDOM();
+ }
+
+ // If we get here, we didn't have a usable DOM.
+ bool bindDocument=false;
+ if (m_xml.empty()) {
+ // Fresh signature, so we just create an empty one.
+ log.debug("creating empty Signature element");
+ if (!document) {
+ document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument();
+ bindDocument=true;
+ }
+ DSIGSignature* temp=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
+ temp->setDSIGNSPrefix(XMLSIG_PREFIX);
+ cachedDOM=temp->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm());
+ m_signature = temp;
+ }
+ else {
+ // We need to reparse the XML we saved off into a new DOM.
+ MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl");
+ Wrapper4InputSource dsrc(&src,false);
+ log.debug("parsing Signature XML back into DOM tree");
+ DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc);
+ if (document) {
+ // The caller insists on using his own document, so we now have to import the thing
+ // into it. Then we're just dumping the one we built.
+ log.debug("reimporting new DOM into caller-supplied document");
+ cachedDOM=static_cast<DOMElement*>(document->importNode(internalDoc->getDocumentElement(), true));
+ internalDoc->release();
+ }
+ else {
+ // We just bind the document we built to the object as the result.
+ cachedDOM=static_cast<DOMElement*>(internalDoc->getDocumentElement());
+ document=internalDoc;
+ bindDocument=true;
+ }
+
+ // Now reload the signature from the DOM.
+ try {
+ m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(
+ document, cachedDOM
+ );
+ m_signature->load();
+ }
+ catch(XSECException& e) {
+ if (bindDocument)
+ document->release();
+ auto_ptr_char temp(e.getMsg());
+ throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());
+ }
+ catch(XSECCryptoException& e) {
+ if (bindDocument)
+ document->release();
+ throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());
+ }
+ }
+
+ // Marshall KeyInfo data.
+ if (credential) {
+ delete m_keyInfo;
+ m_keyInfo = NULL;
+ m_keyInfo = credential->getKeyInfo();
+ }
+ if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {
+ m_keyInfo->marshall(cachedDOM);
+ }
+
+ // Recache the DOM and clear the serialized copy.
+ setDocumentElement(document, cachedDOM);
+ log.debug("caching DOM for Signature (document is %sbound)", bindDocument ? "" : "not ");
+ setDOM(cachedDOM, bindDocument);
+ releaseParentDOM(true);
+ m_xml.erase();
+ return cachedDOM;
+}
+
+DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vector<Signature*>* sigs, const Credential* credential) const
+{
+#ifdef _DEBUG
+ xmltooling::NDC ndc("marshall");
+#endif
+
+ Category& log=Category::getInstance(XMLTOOLING_LOGCAT".XMLObject.Signature");
+ log.debug("marshalling ds:Signature");
+
+ DOMElement* cachedDOM=getDOM();
+ if (cachedDOM) {
+ if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) {
+ log.debug("Signature has a usable cached DOM, reusing it");
+ if (parentElement!=cachedDOM->getParentNode()) {
+ parentElement->appendChild(cachedDOM);
+ releaseParentDOM(true);
+ }
+ return cachedDOM;
+ }
+
+ // We have a DOM but it doesn't match the document we were given. This both sucks and blows.
+ // Without an adoptNode option to maintain the child pointers, we have to either import the
+ // DOM while somehow reassigning all the nested references (which amounts to a complete
+ // *unmarshall* operation), or we just release the existing DOM and hope that we can get
+ // it back. This depends on all objects being able to preserve their DOM at all costs.
+ releaseChildrenDOM(true);
+ releaseDOM();
+ }
+
+ // If we get here, we didn't have a usable DOM.
+ if (m_xml.empty()) {
+ // Fresh signature, so we just create an empty one.
+ log.debug("creating empty Signature element");
+ DSIGSignature* temp=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
+ temp->setDSIGNSPrefix(XMLSIG_PREFIX);
+ cachedDOM=temp->createBlankSignature(parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm());
+ m_signature = temp;
+ }
+ else {
+ MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl");
+ Wrapper4InputSource dsrc(&src,false);
+ log.debug("parsing XML back into DOM tree");
+ DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc);
+
+ log.debug("reimporting new DOM into caller-supplied document");
+ cachedDOM=static_cast<DOMElement*>(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(),true));
+ internalDoc->release();
+
+ // Now reload the signature from the DOM.
+ try {
+ m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(
+ parentElement->getOwnerDocument(), cachedDOM
+ );
+ m_signature->load();
+ }
+ catch(XSECException& e) {
+ auto_ptr_char temp(e.getMsg());
+ throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());
+ }
+ catch(XSECCryptoException& e) {
+ throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());
+ }
+ }
+
+ // Marshall KeyInfo data.
+ if (credential) {
+ delete m_keyInfo;
+ m_keyInfo = NULL;
+ m_keyInfo = credential->getKeyInfo();
+ }
+ if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {
+ m_keyInfo->marshall(cachedDOM);
+ }
+
+ // Recache the DOM and clear the serialized copy.
+ parentElement->appendChild(cachedDOM);
+ log.debug("caching DOM for Signature");
+ setDOM(cachedDOM, false);
+ releaseParentDOM(true);
+ m_xml.erase();
+ return cachedDOM;
+}
+
+XMLObject* XMLSecSignatureImpl::unmarshall(DOMElement* element, bool bindDocument)
+{
+ Category::getInstance(XMLTOOLING_LOGCAT".XMLObject.Signature").debug("unmarshalling ds:Signature");
+
+ try {
+ m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(
+ element->getOwnerDocument(), element
+ );
+ m_signature->load();
+ }
+ catch(XSECException& e) {
+ auto_ptr_char temp(e.getMsg());
+ throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());
+ }
+ catch(XSECCryptoException& e) {
+ throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());
+ }
+
+ setDOM(element, bindDocument);
+ return this;
+}
+
+#ifdef HAVE_COVARIANT_RETURNS
+Signature*
+#else
+XMLObject*
+#endif
+SignatureBuilder::buildObject(
+ const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType
+ ) const
+{
+ if (!XMLString::equals(nsURI,XMLSIG_NS) || !XMLString::equals(localName,Signature::LOCAL_NAME))
+ throw XMLObjectException("XMLSecSignatureBuilder requires standard Signature element name.");
+ return buildObject();
+}
+
+#ifdef HAVE_COVARIANT_RETURNS
+Signature*
+#else
+XMLObject*
+#endif
+SignatureBuilder::buildObject() const
+{
+ return new XMLSecSignatureImpl();
+}
+
+const XMLCh Signature::LOCAL_NAME[] = UNICODE_LITERAL_9(S,i,g,n,a,t,u,r,e);
+
+// Raw signature methods.
+
+unsigned int Signature::createRawSignature(
+ XSECCryptoKey* key, const XMLCh* sigAlgorithm, const char* in, unsigned int in_len, char* out, unsigned int out_len
+ )
+{
+ try {
+ XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(sigAlgorithm);
+ if (!handler) {
+ auto_ptr_char alg(sigAlgorithm);
+ throw SignatureException("Unsupported signature algorithm ($1).", params(1,alg.get()));
+ }
+
+ // Move input into a safeBuffer to source the transform chain.
+ safeBuffer sb,sbout;
+ sb.sbStrncpyIn(in,in_len);
+ TXFMSB* sbt = new TXFMSB(NULL);
+ sbt->setInput(sb, in_len);
+ TXFMChain tx(sbt);
+
+ // Sign the chain.
+ unsigned int siglen = handler->signToSafeBuffer(&tx, sigAlgorithm, key, out_len-1, sbout);
+ if (siglen >= out_len)
+ throw SignatureException("Signature size exceeded output buffer size.");
+
+ // Push all non-whitespace into buffer.
+ unsigned int ret_len = 0;
+ const char* source = sbout.rawCharBuffer();
+ while (siglen--) {
+ if (isspace(*source))
+ ++source;
+ else {
+ *out++ = *source++;
+ ++ret_len;
+ }
+ }
+ *out = 0;
+ return ret_len;
+ }
+ catch(XSECException& e) {
+ auto_ptr_char temp(e.getMsg());
+ throw SignatureException(string("Caught an XMLSecurity exception while creating raw signature: ") + temp.get());
+ }
+ catch(XSECCryptoException& e) {
+ throw SignatureException(string("Caught an XMLSecurity exception while creating raw signature: ") + e.getMsg());
+ }
+}
+
+bool Signature::verifyRawSignature(
+ XSECCryptoKey* key, const XMLCh* sigAlgorithm, const char* signature, const char* in, unsigned int in_len
+ )
+{
+ try {
+ XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(sigAlgorithm);
+ if (!handler) {
+ auto_ptr_char alg(sigAlgorithm);
+ throw SignatureException("Unsupported signature algorithm ($1).", params(1,alg.get()));
+ }
+
+ // Move input into a safeBuffer to source the transform chain.
+ safeBuffer sb;
+ sb.sbStrncpyIn(in,in_len);
+ TXFMSB* sbt = new TXFMSB(NULL);
+ sbt->setInput(sb, in_len);
+ TXFMChain tx(sbt);
+
+ // Verify the chain.
+ return handler->verifyBase64Signature(&tx, sigAlgorithm, signature, 0, key);
+ }
+ catch(XSECException& e) {
+ auto_ptr_char temp(e.getMsg());
+ throw SignatureException(string("Caught an XMLSecurity exception while verifying raw signature: ") + temp.get());
+ }
+ catch(XSECCryptoException& e) {
+ throw SignatureException(string("Caught an XMLSecurity exception while verifying raw signature: ") + e.getMsg());
+ }
+}
+
+void Signature::extractNames(DSIGKeyInfoList* keyInfo, set<string>& names)
+{
+ char* kn;
+ const XMLCh* n;
+
+ for (size_t s=0; s<keyInfo->getSize(); s++) {
+ n=keyInfo->item(s)->getKeyName();
+ if (n && *n) {
+ kn=toUTF8(n);
+ names.insert(kn);
+ delete[] kn;
+ }
+ }
+}