X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2Fsignature%2Fimpl%2FXMLSecSignatureImpl.cpp;h=2082939f72d3b23d4488e7d8d386843fe739b0c8;hb=f4ff096a4048e157b8b377ddf253f2e76b7fee53;hp=b56181475ab032948c766aaee2c2a19b3f2aced1;hpb=7c2636878325d3c99889f626a93dc876b5a77d65;p=shibboleth%2Fcpp-xmltooling.git diff --git a/xmltooling/signature/impl/XMLSecSignatureImpl.cpp b/xmltooling/signature/impl/XMLSecSignatureImpl.cpp index b561814..2082939 100644 --- a/xmltooling/signature/impl/XMLSecSignatureImpl.cpp +++ b/xmltooling/signature/impl/XMLSecSignatureImpl.cpp @@ -36,6 +36,7 @@ #include #include +using namespace xmlsignature; using namespace xmltooling; using namespace log4cpp; using namespace std; @@ -45,37 +46,65 @@ using namespace std; #pragma warning( disable : 4250 4251 ) #endif -namespace xmltooling { +namespace xmlsignature { class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature { public: XMLSecSignatureImpl() : UnknownElementImpl(XMLConstants::XMLSIG_NS, Signature::LOCAL_NAME, XMLConstants::XMLSIG_PREFIX), - m_signature(NULL), m_c14n(NULL), m_sm(NULL) {} + m_signature(NULL), m_c14n(NULL), m_sm(NULL), m_key(NULL), m_keyInfo(NULL), m_reference(NULL) {} virtual ~XMLSecSignatureImpl(); - void releaseDOM(); + 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, MarshallingContext* ctx=NULL) const; - DOMElement* marshall(DOMElement* parentElement, MarshallingContext* ctx=NULL) const; + DOMElement* marshall(DOMDocument* document=NULL, const vector* sigs=NULL) const; + DOMElement* marshall(DOMElement* parentElement, const vector* sigs=NULL) const; XMLObject* unmarshall(DOMElement* element, bool bindDocument=false); // Getters const XMLCh* getCanonicalizationMethod() const { return m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC; } const XMLCh* getSignatureAlgorithm() const { 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 sign(const SigningContext& ctx); - void verify(const VerifyingContext& ctx) const; + void setSigningKey(XSECCryptoKey* signingKey) { + delete m_key; + m_key=signingKey; + if (m_key) + releaseThisandParentDOM(); + } + void setKeyInfo(KeyInfo* keyInfo) { + prepareForAssignment(m_keyInfo, keyInfo); + m_keyInfo=keyInfo; + } + void setContentReference(ContentReference* reference) { + delete m_reference; + m_reference=reference; + releaseThisandParentDOM(); + } + + void sign(); private: mutable DSIGSignature* m_signature; XMLCh* m_c14n; XMLCh* m_sm; + XSECCryptoKey* m_key; + KeyInfo* m_keyInfo; + ContentReference* m_reference; }; }; @@ -92,26 +121,40 @@ XMLSecSignatureImpl::~XMLSecSignatureImpl() XMLString::release(&m_c14n); XMLString::release(&m_sm); + delete m_key; + delete m_keyInfo; + delete m_reference; } -void XMLSecSignatureImpl::releaseDOM() +void XMLSecSignatureImpl::releaseDOM() const { - // 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; + 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()) @@ -122,33 +165,24 @@ XMLObject* XMLSecSignatureImpl::clone() const return ret; } -class _addcert : public std::binary_function { -public: - void operator()(DSIGKeyInfoX509* bag, XSECCryptoX509* cert) const { - safeBuffer& buf=cert->getDEREncodingSB(); - bag->appendX509Certificate(buf.sbStrToXMLCh()); - } -}; - -void XMLSecSignatureImpl::sign(const SigningContext& ctx) +void XMLSecSignatureImpl::sign() { 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_key) + throw SignatureException("No signing key available for signature creation."); + else if (!m_reference) + throw SignatureException("No ContentReference object set for signature creation."); try { - log.debug("creating signature content"); - ctx.createSignature(m_signature); - const std::vector& certs=ctx.getX509Certificates(); - if (!certs.empty()) { - DSIGKeyInfoX509* x509Data=m_signature->appendX509Data(); - for_each(certs.begin(),certs.end(),bind1st(_addcert(),x509Data)); - } + log.debug("creating signature reference(s)"); + m_reference->createReferences(m_signature); log.debug("computing signature"); - m_signature->setSigningKey(ctx.getSigningKey()); + m_signature->setSigningKey(m_key->clone()); m_signature->sign(); } catch(XSECException& e) { @@ -160,27 +194,7 @@ void XMLSecSignatureImpl::sign(const SigningContext& ctx) } } -void XMLSecSignatureImpl::verify(const VerifyingContext& ctx) const -{ - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature"); - log.debug("verifying signature"); - - if (!m_signature) - throw SignatureException("Only a marshalled Signature object can be verified."); - - try { - ctx.verifySignature(m_signature); - } - catch(XSECException& e) { - auto_ptr_char temp(e.getMsg()); - throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + temp.get()); - } - catch(XSECCryptoException& e) { - throw SignatureException(string("Caught an XMLSecurity exception verifying signature: ") + e.getMsg()); - } -} - -DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, MarshallingContext* ctx) const +DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector* sigs) const { #ifdef _DEBUG xmltooling::NDC ndc("marshall"); @@ -199,32 +213,13 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, MarshallingCont return cachedDOM; } - // We have a DOM but it doesn't match the document we were given, so we import - // it into the new document. - cachedDOM=static_cast(document->importNode(cachedDOM, true)); - - try { - XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature); - m_signature=NULL; - m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM( - document, 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()); - } - - // Recache the DOM. - setDocumentElement(document, cachedDOM); - log.debug("caching imported DOM for Signature"); - setDOM(cachedDOM, false); - 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. @@ -245,7 +240,7 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, MarshallingCont MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl"); Wrapper4InputSource dsrc(&src,false); log.debug("parsing Signature XML back into DOM tree"); - DOMDocument* internalDoc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(dsrc); + 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. @@ -280,6 +275,11 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, MarshallingCont } } + // Marshall KeyInfo data. + 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 "); @@ -289,7 +289,7 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, MarshallingCont return cachedDOM; } -DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, MarshallingContext* ctx) const +DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vector* sigs) const { #ifdef _DEBUG xmltooling::NDC ndc("marshall"); @@ -302,37 +302,20 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, Marshalling if (cachedDOM) { if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) { log.debug("Signature has a usable cached DOM, reusing it"); - parentElement->appendChild(cachedDOM); - releaseParentDOM(true); + 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, so we import - // it into the new document. - cachedDOM=static_cast(parentElement->getOwnerDocument()->importNode(cachedDOM, true)); - - try { - XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature); - m_signature=NULL; - 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()); - } - - // Recache the DOM. - parentElement->appendChild(cachedDOM); - log.debug("caching imported DOM for Signature"); - setDOM(cachedDOM, false); - 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. @@ -349,7 +332,7 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, Marshalling MemBufInputSource src(reinterpret_cast(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl"); Wrapper4InputSource dsrc(&src,false); log.debug("parsing XML back into DOM tree"); - DOMDocument* internalDoc=XMLToolingInternalConfig::getInternalConfig().m_parserPool->parse(dsrc); + DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc); log.debug("reimporting new DOM into caller-supplied document"); cachedDOM=static_cast(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(),true)); @@ -371,6 +354,11 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, Marshalling } } + // Marshall KeyInfo data. + 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");