#include "internal.h"\r
#include "exceptions.h"\r
#include "impl/UnknownElement.h"\r
-#include "signature/impl/XMLSecSignatureImpl.h"\r
+#include "signature/Signature.h"\r
#include "util/NDC.h"\r
#include "util/XMLConstants.h"\r
#include "util/XMLHelper.h"\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/dsig/DSIGReference.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
#pragma warning( disable : 4250 4251 )\r
#endif\r
\r
-namespace xmltooling {\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
+ m_signature(NULL), m_c14n(NULL), m_sm(NULL), m_key(NULL), m_keyInfo(NULL), m_reference(NULL) {}\r
virtual ~XMLSecSignatureImpl();\r
\r
- void releaseDOM();\r
+ void releaseDOM() const;\r
+ void releaseChildrenDOM(bool propagateRelease=true) const {\r
+ if (m_keyInfo) {\r
+ m_keyInfo->releaseDOM();\r
+ if (propagateRelease)\r
+ m_keyInfo->releaseChildrenDOM();\r
+ }\r
+ }\r
XMLObject* clone() const;\r
+ Signature* cloneSignature() const;\r
\r
- DOMElement* marshall(DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const;\r
- DOMElement* marshall(DOMElement* parentElement, MarshallingContext* ctx=NULL) const;\r
+ DOMElement* marshall(DOMDocument* document=NULL, const vector<Signature*>* sigs=NULL) const;\r
+ DOMElement* marshall(DOMElement* parentElement, const vector<Signature*>* sigs=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
+ KeyInfo* getKeyInfo() const { return m_keyInfo; }\r
+ ContentReference* getContentReference() const { return m_reference; }\r
+ DSIGSignature* getXMLSignature() const { return m_signature; }\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
+ void setSigningKey(XSECCryptoKey* signingKey) {\r
+ delete m_key;\r
+ m_key=signingKey;\r
+ }\r
+ void setKeyInfo(KeyInfo* keyInfo) {\r
+ prepareForAssignment(m_keyInfo, keyInfo);\r
+ m_keyInfo=keyInfo;\r
+ }\r
+ void setContentReference(ContentReference* reference) {\r
+ delete m_reference;\r
+ m_reference=reference;\r
+ }\r
+ \r
+ void sign();\r
\r
private:\r
mutable DSIGSignature* m_signature;\r
XMLCh* m_c14n;\r
XMLCh* m_sm;\r
+ XSECCryptoKey* m_key;\r
+ KeyInfo* m_keyInfo;\r
+ ContentReference* m_reference;\r
};\r
\r
};\r
\r
XMLString::release(&m_c14n);\r
XMLString::release(&m_sm);\r
+ delete m_key;\r
+ delete m_keyInfo;\r
+ delete m_reference;\r
}\r
\r
-void XMLSecSignatureImpl::releaseDOM()\r
+void XMLSecSignatureImpl::releaseDOM() const\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
+ if (getDOM()) {\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
\r
XMLObject* XMLSecSignatureImpl::clone() const\r
{\r
+ return cloneSignature();\r
+}\r
+\r
+Signature* XMLSecSignatureImpl::cloneSignature() 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
+ if (m_key)\r
+ ret->m_key=m_key->clone();\r
+ if (m_keyInfo)\r
+ ret->m_keyInfo=m_keyInfo->cloneKeyInfo();\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
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
+void XMLSecSignatureImpl::sign()\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
+ else if (!m_key)\r
+ throw SignatureException("No signing key available for signature creation.");\r
+ else if (!m_reference)\r
+ throw SignatureException("No ContentReference object set for signature creation.");\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
+ log.debug("creating signature reference(s)");\r
+ // TODO: Need XML-Sec fixed to clear references.\r
+ //DSIGReferenceList* refs = m_signature->getReferenceList();\r
+ //while (refs && refs->getSize())\r
+ // delete refs->removeReference(0);\r
+ m_reference->createReferences(m_signature);\r
\r
log.debug("computing signature");\r
- m_signature->setSigningKey(ctx.getSigningKey());\r
+ m_signature->setSigningKey(m_key->clone());\r
m_signature->sign();\r
}\r
catch(XSECException& e) {\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
+DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector<Signature*>* sigs) const\r
{\r
#ifdef _DEBUG\r
xmltooling::NDC ndc("marshall");\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
+ // We have a DOM but it doesn't match the document we were given. This both sucks and blows.\r
+ // Without an adoptNode option to maintain the child pointers, we have to either import the\r
+ // DOM while somehow reassigning all the nested references (which amounts to a complete\r
+ // *unmarshall* operation), or we just release the existing DOM and hope that we can get\r
+ // it back. This depends on all objects being able to preserve their DOM at all costs.\r
+ releaseChildrenDOM(true);\r
+ releaseDOM();\r
}\r
\r
// If we get here, we didn't have a usable DOM.\r
bindDocument=true;\r
}\r
m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();\r
- m_signature->setDSIGNSPrefix(Signature::PREFIX);\r
+ m_signature->setDSIGNSPrefix(XMLConstants::XMLSIG_PREFIX);\r
cachedDOM=m_signature->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm());\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 Signature XML back into DOM tree");\r
- DOMDocument* internalDoc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(dsrc);\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
}\r
}\r
\r
+ // Marshall KeyInfo data.\r
+ if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {\r
+ m_keyInfo->marshall(cachedDOM);\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
return cachedDOM;\r
}\r
\r
-DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, MarshallingContext* ctx) const\r
+DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vector<Signature*>* sigs) const\r
{\r
#ifdef _DEBUG\r
xmltooling::NDC ndc("marshall");\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
+ if (parentElement!=cachedDOM->getParentNode()) {\r
+ parentElement->appendChild(cachedDOM);\r
+ releaseParentDOM(true);\r
+ }\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
+ // We have a DOM but it doesn't match the document we were given. This both sucks and blows.\r
+ // Without an adoptNode option to maintain the child pointers, we have to either import the\r
+ // DOM while somehow reassigning all the nested references (which amounts to a complete\r
+ // *unmarshall* operation), or we just release the existing DOM and hope that we can get\r
+ // it back. This depends on all objects being able to preserve their DOM at all costs.\r
+ releaseChildrenDOM(true);\r
+ releaseDOM();\r
}\r
\r
// If we get here, we didn't have a usable DOM.\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(Signature::PREFIX);\r
+ m_signature->setDSIGNSPrefix(XMLConstants::XMLSIG_PREFIX);\r
cachedDOM=m_signature->createBlankSignature(\r
parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm()\r
);\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=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(dsrc);\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
}\r
}\r
\r
+ // Marshall KeyInfo data.\r
+ if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {\r
+ m_keyInfo->marshall(cachedDOM);\r
+ }\r
+\r
// Recache the DOM and clear the serialized copy.\r
parentElement->appendChild(cachedDOM);\r
log.debug("caching DOM for Signature");\r
return this;\r
}\r
\r
-Signature* XMLSecSignatureBuilder::buildObject(const XMLCh* ns, const XMLCh* name, const XMLCh* prefix) const\r
+Signature* SignatureBuilder::buildObject(\r
+ const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType\r
+ ) const\r
{\r
- if (!XMLString::equals(ns,XMLConstants::XMLSIG_NS) || !XMLString::equals(name,Signature::LOCAL_NAME))\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* XMLSecSignatureBuilder::buildObject() const\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