From: Scott Cantor Date: Thu, 18 May 2006 04:21:33 +0000 (+0000) Subject: Refactored Signature signing/validation, various Validator bugs fixed. X-Git-Tag: 1.0-alpha1~241 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-xmltooling.git;a=commitdiff_plain;h=c8af116ba2481115019276801ecd041067479c40 Refactored Signature signing/validation, various Validator bugs fixed. --- diff --git a/xmltooling/AbstractXMLObject.cpp b/xmltooling/AbstractXMLObject.cpp index 3111c8d..3a47620 100644 --- a/xmltooling/AbstractXMLObject.cpp +++ b/xmltooling/AbstractXMLObject.cpp @@ -1,139 +1,139 @@ -/* -* Copyright 2001-2006 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. - */ - -/** - * AbstractXMLObject.cpp - * - * An abstract implementation of XMLObject. - */ - -#include "internal.h" -#include "AbstractXMLObject.h" -#include "exceptions.h" - -#include -#include - -using namespace xmltooling; - -AbstractXMLObject::AbstractXMLObject(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType) - : m_log(&log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")), - m_parent(NULL), m_elementQname(nsURI, localName, prefix), m_typeQname(NULL) -{ - addNamespace(Namespace(nsURI, prefix)); - if (schemaType) { - m_typeQname = new QName(*schemaType); - addNamespace(Namespace(m_typeQname->getNamespaceURI(), m_typeQname->getPrefix())); - } -} - -AbstractXMLObject::AbstractXMLObject(const AbstractXMLObject& src) - : m_namespaces(src.m_namespaces), m_log(src.m_log), m_parent(NULL), m_elementQname(src.m_elementQname), m_typeQname(NULL) -{ - if (src.m_typeQname) - m_typeQname=new QName(*src.m_typeQname); -} - -XMLCh* AbstractXMLObject::prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue) -{ - XMLCh* newString = XMLString::replicate(newValue); - XMLString::trim(newString); - if (!XMLString::equals(oldValue,newValue)) { - releaseThisandParentDOM(); - XMLString::release(&oldValue); - return newString; - } - XMLString::release(&newString); - return oldValue; -} - -QName* AbstractXMLObject::prepareForAssignment(QName* oldValue, const QName* newValue) -{ - if (!oldValue) { - if (newValue) { - releaseThisandParentDOM(); +/* +* Copyright 2001-2006 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. + */ + +/** + * AbstractXMLObject.cpp + * + * An abstract implementation of XMLObject. + */ + +#include "internal.h" +#include "AbstractXMLObject.h" +#include "exceptions.h" + +#include +#include + +using namespace xmltooling; + +AbstractXMLObject::AbstractXMLObject(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType) + : m_log(&log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")), + m_parent(NULL), m_elementQname(nsURI, localName, prefix), m_typeQname(NULL) +{ + addNamespace(Namespace(nsURI, prefix)); + if (schemaType) { + m_typeQname = new QName(*schemaType); + addNamespace(Namespace(m_typeQname->getNamespaceURI(), m_typeQname->getPrefix())); + } +} + +AbstractXMLObject::AbstractXMLObject(const AbstractXMLObject& src) + : m_namespaces(src.m_namespaces), m_log(src.m_log), m_parent(NULL), m_elementQname(src.m_elementQname), m_typeQname(NULL) +{ + if (src.m_typeQname) + m_typeQname=new QName(*src.m_typeQname); +} + +XMLCh* AbstractXMLObject::prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue) +{ + XMLCh* newString = XMLString::replicate(newValue); + XMLString::trim(newString); + if (!XMLString::equals(oldValue,newValue)) { + releaseThisandParentDOM(); + XMLString::release(&oldValue); + return newString; + } + XMLString::release(&newString); + return oldValue; +} + +QName* AbstractXMLObject::prepareForAssignment(QName* oldValue, const QName* newValue) +{ + if (!oldValue) { + if (newValue) { + releaseThisandParentDOM(); Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix()); addNamespace(newNamespace); - return new QName(*newValue); - } - return NULL; - } - - delete oldValue; - releaseThisandParentDOM(); - if (newValue) { + return new QName(*newValue); + } + return NULL; + } + + delete oldValue; + releaseThisandParentDOM(); + if (newValue) { Namespace newNamespace(newValue->getNamespaceURI(), newValue->getPrefix()); addNamespace(newNamespace); return new QName(*newValue); - } - return NULL; -} - -DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const DateTime* newValue) -{ - if (!oldValue) { - if (newValue) { - releaseThisandParentDOM(); - return new DateTime(*newValue); - } - return NULL; - } - - delete oldValue; - releaseThisandParentDOM(); - return newValue ? new DateTime(*newValue) : NULL; -} - -DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, time_t newValue) -{ - delete oldValue; - releaseThisandParentDOM(); - DateTime* ret = new DateTime(newValue); - ret->parseDateTime(); - return ret; -} - -DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const XMLCh* newValue) -{ - delete oldValue; - releaseThisandParentDOM(); - DateTime* ret = new DateTime(newValue); - ret->parseDateTime(); - return ret; -} - -XMLObject* AbstractXMLObject::prepareForAssignment(XMLObject* oldValue, XMLObject* newValue) -{ - if (newValue && newValue->hasParent()) - throw XMLObjectException("child XMLObject cannot be added - it is already the child of another XMLObject"); - - if (!oldValue) { - if (newValue) { - releaseThisandParentDOM(); - newValue->setParent(this); - } - return newValue; - } - - if (oldValue != newValue) { - delete oldValue; - releaseThisandParentDOM(); - if (newValue) - newValue->setParent(this); - } - - return newValue; -} + } + return NULL; +} + +DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const DateTime* newValue) +{ + if (!oldValue) { + if (newValue) { + releaseThisandParentDOM(); + return new DateTime(*newValue); + } + return NULL; + } + + delete oldValue; + releaseThisandParentDOM(); + return newValue ? new DateTime(*newValue) : NULL; +} + +DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, time_t newValue) +{ + delete oldValue; + releaseThisandParentDOM(); + DateTime* ret = new DateTime(newValue); + ret->parseDateTime(); + return ret; +} + +DateTime* AbstractXMLObject::prepareForAssignment(DateTime* oldValue, const XMLCh* newValue) +{ + delete oldValue; + releaseThisandParentDOM(); + DateTime* ret = new DateTime(newValue); + ret->parseDateTime(); + return ret; +} + +XMLObject* AbstractXMLObject::prepareForAssignment(XMLObject* oldValue, XMLObject* newValue) +{ + if (newValue && newValue->hasParent()) + throw XMLObjectException("child XMLObject cannot be added - it is already the child of another XMLObject"); + + if (!oldValue) { + if (newValue) { + releaseThisandParentDOM(); + newValue->setParent(this); + } + return newValue; + } + + if (oldValue != newValue) { + delete oldValue; + releaseThisandParentDOM(); + if (newValue) + newValue->setParent(this); + } + + return newValue; +} diff --git a/xmltooling/Makefile.am b/xmltooling/Makefile.am index c5126d9..963fa87 100644 --- a/xmltooling/Makefile.am +++ b/xmltooling/Makefile.am @@ -49,8 +49,7 @@ ioinclude_HEADERS = \ siginclude_HEADERS = \ signature/KeyInfo.h \ signature/Signature.h \ - signature/SigningContext.h \ - signature/VerifyingContext.h + signature/ContentReference.h utilinclude_HEADERS = \ util/CredentialResolver.h \ diff --git a/xmltooling/XMLObject.h b/xmltooling/XMLObject.h index d32d155..ed750ce 100644 --- a/xmltooling/XMLObject.h +++ b/xmltooling/XMLObject.h @@ -35,7 +35,6 @@ using namespace xercesc; #ifndef XMLTOOLING_NO_XMLSEC namespace xmlsignature { class XMLTOOL_API Signature; - class XMLTOOL_API SigningContext; }; #endif @@ -47,36 +46,6 @@ namespace xmlsignature { namespace xmltooling { /** - * Supplies additional information to the marshalling process. - * Currently this only consists of signature related information. - */ - class XMLTOOL_API MarshallingContext - { - MAKE_NONCOPYABLE(MarshallingContext); - public: - /** - * Default constructor. - */ - MarshallingContext() {} - ~MarshallingContext() {} - -#ifndef XMLTOOLING_NO_XMLSEC - /** - * Builds a marshalling context with an initial signature/context pair. - * - * @param sig a signature object - * @param ctx the signing context to associate with the signature - */ - MarshallingContext(xmlsignature::Signature* sig, xmlsignature::SigningContext* ctx) { - m_signingContexts.push_back(std::make_pair(sig,ctx)); - } - - /** Array of signing contexts, keyed off of the associated Signature */ - std::vector< std::pair > m_signingContexts; -#endif - }; - - /** * Object that represents an XML Element that has been unmarshalled into this C++ object. */ class XMLTOOL_API XMLObject @@ -244,13 +213,18 @@ namespace xmltooling { * marshalled, unless an existing DOM can be reused without creating a new document. * * @param document the DOM document the marshalled element will be placed in, or NULL - * @param ctx optional marshalling context + * @param sigs ordered array of signatures to create after marshalling is complete * @return the DOM element representing this XMLObject * * @throws MarshallingException thrown if there is a problem marshalling the given object * @throws SignatureException thrown if a problem occurs during signature creation */ - virtual DOMElement* marshall(DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const=0; + virtual DOMElement* marshall( + DOMDocument* document=NULL +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs=NULL +#endif + ) const=0; /** * Marshalls the XMLObject and appends it as a child of the given parent element. @@ -259,13 +233,18 @@ namespace xmltooling { * the Document owning the given Element. * * @param parentElement the parent element to append the resulting DOM tree - * @param ctx optional marshalling context + * @param sigs ordered array of signatures to create after marshalling is complete * @return the marshalled element tree * @throws MarshallingException thrown if the given XMLObject can not be marshalled. * @throws SignatureException thrown if a problem occurs during signature creation */ - virtual DOMElement* marshall(DOMElement* parentElement, MarshallingContext* ctx=NULL) const=0; + virtual DOMElement* marshall( + DOMElement* parentElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs=NULL +#endif + ) const=0; /** * Unmarshalls the given W3C DOM element into the XMLObject. diff --git a/xmltooling/impl/UnknownElement.cpp b/xmltooling/impl/UnknownElement.cpp index 09dbbdd..27fcfd9 100644 --- a/xmltooling/impl/UnknownElement.cpp +++ b/xmltooling/impl/UnknownElement.cpp @@ -70,7 +70,12 @@ void UnknownElementImpl::serialize(string& s) const XMLHelper::serialize(getDOM(),s); } -DOMElement* UnknownElementImpl::marshall(DOMDocument* document, MarshallingContext* ctx) const +DOMElement* UnknownElementImpl::marshall( + DOMDocument* document +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs +#endif + ) const { #ifdef _DEBUG xmltooling::NDC ndc("marshall"); @@ -131,7 +136,13 @@ DOMElement* UnknownElementImpl::marshall(DOMDocument* document, MarshallingConte return cachedDOM; } -DOMElement* UnknownElementImpl::marshall(DOMElement* parentElement, MarshallingContext* ctx) const + +DOMElement* UnknownElementImpl::marshall( + DOMElement* parentElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs +#endif + ) const { #ifdef _DEBUG xmltooling::NDC ndc("marshall"); diff --git a/xmltooling/impl/UnknownElement.h b/xmltooling/impl/UnknownElement.h index ea2aafd..18e9cab 100644 --- a/xmltooling/impl/UnknownElement.h +++ b/xmltooling/impl/UnknownElement.h @@ -49,15 +49,26 @@ namespace xmltooling { XMLObject* clone() const; - DOMElement* marshall(DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const; - DOMElement* marshall(DOMElement* parentElement, MarshallingContext* ctx=NULL) const; + DOMElement* marshall( + DOMDocument* document=NULL +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs=NULL +#endif + ) const; + + DOMElement* marshall( + DOMElement* parentElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs=NULL +#endif + ) const; XMLObject* unmarshall(DOMElement* element, bool bindDocument=false); protected: void setDocumentElement(DOMDocument* document, DOMElement* element) const { DOMElement* documentRoot = document->getDocumentElement(); if (documentRoot) - document->replaceChild(documentRoot, element); + document->replaceChild(element, documentRoot); else document->appendChild(element); } diff --git a/xmltooling/io/AbstractXMLObjectMarshaller.cpp b/xmltooling/io/AbstractXMLObjectMarshaller.cpp index 8567d59..5d22362 100644 --- a/xmltooling/io/AbstractXMLObjectMarshaller.cpp +++ b/xmltooling/io/AbstractXMLObjectMarshaller.cpp @@ -44,7 +44,12 @@ using namespace std; #define XT_log (*static_cast(m_log)) -DOMElement* AbstractXMLObjectMarshaller::marshall(DOMDocument* document, MarshallingContext* ctx) const +DOMElement* AbstractXMLObjectMarshaller::marshall( + DOMDocument* document +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs +#endif + ) const { #ifdef _DEBUG xmltooling::NDC ndc("marshall"); @@ -87,8 +92,11 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(DOMDocument* document, Marshal getElementQName().getNamespaceURI(), getElementQName().getLocalPart() ); setDocumentElement(document, domElement); - marshallInto(domElement, ctx); - +#ifndef XMLTOOLING_NO_XMLSEC + marshallInto(domElement, sigs); +#else + marshallInto(domElement); +#endif //Recache the DOM. XT_log.debug("caching DOM for XMLObject (document is %sbound)", bindDocument ? "" : "not "); setDOM(domElement, bindDocument); @@ -105,7 +113,12 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(DOMDocument* document, Marshal } } -DOMElement* AbstractXMLObjectMarshaller::marshall(DOMElement* parentElement, MarshallingContext* ctx) const +DOMElement* AbstractXMLObjectMarshaller::marshall( + DOMElement* parentElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs +#endif + ) const { #ifdef _DEBUG xmltooling::NDC ndc("marshall"); @@ -141,7 +154,11 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(DOMElement* parentElement, Mar getElementQName().getNamespaceURI(), getElementQName().getLocalPart() ); parentElement->appendChild(domElement); - marshallInto(domElement, ctx); +#ifndef XMLTOOLING_NO_XMLSEC + marshallInto(domElement, sigs); +#else + marshallInto(domElement); +#endif //Recache the DOM. XT_log.debug("caching DOM for XMLObject"); @@ -151,16 +168,12 @@ DOMElement* AbstractXMLObjectMarshaller::marshall(DOMElement* parentElement, Mar return domElement; } +void AbstractXMLObjectMarshaller::marshallInto( + DOMElement* targetElement #ifndef XMLTOOLING_NO_XMLSEC - class _signit : public unary_function&, void> { - public: - void operator()(const pair& p) const { - p.first->sign(*(p.second)); - } - }; + ,const std::vector* sigs #endif - -void AbstractXMLObjectMarshaller::marshallInto(DOMElement* targetElement, MarshallingContext* ctx) const + ) const { if (getElementQName().hasPrefix()) targetElement->setPrefix(getElementQName().getPrefix()); @@ -171,8 +184,8 @@ void AbstractXMLObjectMarshaller::marshallInto(DOMElement* targetElement, Marsha marshallElementContent(targetElement); #ifndef XMLTOOLING_NO_XMLSEC - if (ctx) { - for_each(ctx->m_signingContexts.begin(),ctx->m_signingContexts.end(),_signit()); + if (sigs) { + for_each(sigs->begin(),sigs->end(),mem_fun(&Signature::sign)); } #endif } diff --git a/xmltooling/io/AbstractXMLObjectMarshaller.h b/xmltooling/io/AbstractXMLObjectMarshaller.h index f52ae1c..18d9056 100644 --- a/xmltooling/io/AbstractXMLObjectMarshaller.h +++ b/xmltooling/io/AbstractXMLObjectMarshaller.h @@ -40,9 +40,19 @@ namespace xmltooling { public: virtual ~AbstractXMLObjectMarshaller() {} - DOMElement* marshall(DOMDocument* document=NULL, MarshallingContext* ctx=NULL) const; + DOMElement* marshall( + DOMDocument* document=NULL +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs=NULL +#endif + ) const; - DOMElement* marshall(DOMElement* parentElement, MarshallingContext* ctx=NULL) const; + DOMElement* marshall( + DOMElement* parentElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs=NULL +#endif + ) const; protected: AbstractXMLObjectMarshaller() {} @@ -57,7 +67,7 @@ namespace xmltooling { void setDocumentElement(DOMDocument* document, DOMElement* element) const { DOMElement* documentRoot = document->getDocumentElement(); if (documentRoot) - document->replaceChild(documentRoot, element); + document->replaceChild(element, documentRoot); else document->appendChild(element); } @@ -72,7 +82,12 @@ namespace xmltooling { * @throws MarshallingException thrown if there is a problem marshalling the object * @throws SignatureException thrown if a problem occurs during signature creation */ - void marshallInto(DOMElement* targetElement, MarshallingContext* ctx) const; + void marshallInto( + DOMElement* targetElement +#ifndef XMLTOOLING_NO_XMLSEC + ,const std::vector* sigs +#endif + ) const; /** * Creates an xsi:type attribute, corresponding to the given type of the XMLObject, on the DOM element. diff --git a/xmltooling/signature/ContentReference.h b/xmltooling/signature/ContentReference.h new file mode 100644 index 0000000..7760de6 --- /dev/null +++ b/xmltooling/signature/ContentReference.h @@ -0,0 +1,69 @@ +/* + * Copyright 2001-2006 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. + */ + +/** + * @file ContentReference.h + * + * Interface for creating signature references + */ + +#if !defined(__xmltooling_sigref_h__) && !defined(XMLTOOLING_NO_XMLSEC) +#define __xmltooling_sigref_h__ + +#include +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmlsignature { + + /** + * Interface for creating signature references based on application requirements. + */ + class XMLTOOL_API ContentReference + { + MAKE_NONCOPYABLE(ContentReference); + public: + virtual ~ContentReference() {} + + /** + * Given a native signature, asks the object to create the reference(s). + * + * @param sig native signature interface + */ + virtual void createReferences(DSIGSignature* sig)=0; + + /** + * Creates an independent copy of this object. + * + * @return the cloned object + */ + virtual ContentReference* clone() const=0; + + protected: + ContentReference() {} + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_sigref_h__ */ diff --git a/xmltooling/signature/Signature.h b/xmltooling/signature/Signature.h index 3dba1b4..14549ec 100644 --- a/xmltooling/signature/Signature.h +++ b/xmltooling/signature/Signature.h @@ -25,10 +25,13 @@ #include #include -#include -#include +#include +#include +#include #include +#include + /** * @namespace xmlsignature * Public namespace of XML Signature classes @@ -40,7 +43,7 @@ namespace xmlsignature { * The default signature settings include Exclusive c14n w/o comments, SHA-1 digests, * and RSA-SHA1 signing. */ - class XMLTOOL_API Signature : public virtual xmltooling::XMLObject + class XMLTOOL_API Signature : public virtual xmltooling::ValidatingXMLObject { public: virtual ~Signature() {} @@ -61,24 +64,68 @@ namespace xmlsignature { * @param sm the signature algorithm */ virtual void setSignatureAlgorithm(const XMLCh* sm)=0; - + /** - * Applies an XML signature based on the supplied context. + * Sets the signing key used to create the signature. * - * @param ctx the signing context that determines the signature's content - * @throws SignatureException thrown if the signing operation fails + * @param signingKey the secret/private key used to create the signature */ - virtual void sign(SigningContext& ctx)=0; - + virtual void setSigningKey(XSECCryptoKey* signingKey)=0; + + /** + * Sets a KeyInfo object to embed in the Signature. + * + * @param keyInfo pointer to a KeyInfo object, or NULL + */ + virtual void setKeyInfo(KeyInfo* keyInfo)=0; + + /** + * Gets the KeyInfo object associated with the Signature. + * This is NOT provided for access to the + * data associated with an unmarshalled signature. It is + * used only in the creation of signatures. Access to data + * for validation purposes is provided through the native + * DSIGSignature object. + * + * @return pointer to a KeyInfo object, or NULL + */ + virtual KeyInfo* getKeyInfo() const=0; + /** - * Verifies an XML signature based on the supplied context. + * Sets the ContentReference object to the Signature to be applied + * when the signature is created. * - * @param ctx the verifying context that validates the signature's content - * @throws SignatureException thrown if the verifying operation fails + * @param reference the reference to attach, or NULL */ - virtual void verify(const VerifyingContext& ctx) const=0; + virtual void setContentReference(ContentReference* reference)=0; + + /** + * Gets the ContentReference object associated with the Signature. + * This is NOT provided for access to the + * data associated with an unmarshalled signature. It is + * used only in the creation of signatures. Access to data + * for validation purposes is provided through the native + * DSIGSignature object. + * + * @return pointer to a ContentReference object, or NULL + */ + virtual ContentReference* getContentReference() const=0; + /** + * Gets the native Apache signature object, if present. + * + * @return the native Apache signature interface + */ + virtual DSIGSignature* getXMLSignature() const=0; + + /** + * Compute and append the signature based on the assigned + * ContentReference, KeyInfo, and signing key. + */ + virtual void sign()=0; + + /** * Type-safe clone operation. * * @return copy of object @@ -106,7 +153,7 @@ namespace xmlsignature { */ virtual Signature* buildObject() const; - static Signature* newSignature() { + static Signature* buildSignature() { const SignatureBuilder* b = dynamic_cast( xmltooling::XMLObjectBuilder::getBuilder( xmltooling::QName(xmltooling::XMLConstants::XMLSIG_NS,Signature::LOCAL_NAME) diff --git a/xmltooling/signature/SigningContext.h b/xmltooling/signature/SigningContext.h deleted file mode 100644 index f04b724..0000000 --- a/xmltooling/signature/SigningContext.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2001-2006 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. - */ - -/** - * @file SigningContext.h - * - * Interface to signing process supplied by a signing application - */ - -#if !defined(__xmltooling_signctx_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_signctx_h__ - -#include -#include - -#include -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmlsignature { - - /** - * Interface to signing process supplied by a signing application - */ - class XMLTOOL_API SigningContext - { - MAKE_NONCOPYABLE(SigningContext); - public: - virtual ~SigningContext() {} - - /** - * Given a "blank" native signature, asks the context to define the - * appropriate signature transforms, references, etc. The context - * should return true iff the necessary ds:KeyInfo information was - * also attached. - * - * @param sig native signature interface - * @return indicator whether ds:KeyInfo was created by context - */ - virtual bool createSignature(DSIGSignature* sig)=0; - - /** - * Gets a reference to a credential resolver. - * The resolver's certificates will be included in the signature only - * if the context returns false when creating the signature and returns - * NULL from the getKeyInfo() method. - * - * - * @return a resolver to the credentials to sign with - */ - virtual xmltooling::CredentialResolver& getCredentialResolver()=0; - - /** - * Gets a KeyInfo structure to embed. - * Ownership of the object MUST be transferred to the caller. - * - * @return pointer to a KeyInfo structure, will be freed by caller - */ - virtual KeyInfo* getKeyInfo()=0; - - protected: - SigningContext() {} - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_signctx_h__ */ diff --git a/xmltooling/signature/VerifyingContext.h b/xmltooling/signature/VerifyingContext.h deleted file mode 100644 index 7e0e436..0000000 --- a/xmltooling/signature/VerifyingContext.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2001-2006 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. - */ - -/** - * @file VerifyingContext.h - * - * Interface to signature verification process supplied by a relying party - */ - -#if !defined(__xmltooling_verctx_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_verctx_h__ - -#include - -namespace xmlsignature { - - /** - * Interface to signature verification process supplied by a relying party - */ - class XMLTOOL_API VerifyingContext - { - MAKE_NONCOPYABLE(VerifyingContext); - public: - virtual ~VerifyingContext() {} - - /** - * Given a native signature, asks the context to verify the signature - * in accordance with the relying party's requirements. - * - * @param sig native signature object - * - * @throws SignatureException raised if signature is invalid - */ - virtual void verifySignature(DSIGSignature* sig) const=0; - - protected: - VerifyingContext() {} - }; - -}; - -#endif /* __xmltooling_verctx_h__ */ diff --git a/xmltooling/signature/impl/XMLSecSignatureImpl.cpp b/xmltooling/signature/impl/XMLSecSignatureImpl.cpp index cf3afd2..5218d57 100644 --- a/xmltooling/signature/impl/XMLSecSignatureImpl.cpp +++ b/xmltooling/signature/impl/XMLSecSignatureImpl.cpp @@ -27,6 +27,7 @@ #include "util/NDC.h" #include "util/XMLConstants.h" #include "util/XMLHelper.h" +#include "validation/ValidatingXMLObject.h" #include #include @@ -48,36 +49,70 @@ using namespace std; namespace xmlsignature { - class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature + class XMLTOOL_DLLLOCAL XMLSecSignatureImpl + : public UnknownElementImpl, public virtual Signature, public virtual ValidatingXMLObject { 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 releaseChildrenDOM(bool propagateRelease=true) { + 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 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(); - void sign(SigningContext& ctx); - void verify(const VerifyingContext& ctx) const; + void registerValidator(Validator* validator); + void deregisterValidator(Validator* validator); + void deregisterAll(); + void validate(bool validateDescendants) const; private: mutable DSIGSignature* m_signature; XMLCh* m_c14n; XMLCh* m_sm; + XSECCryptoKey* m_key; + KeyInfo* m_keyInfo; + ContentReference* m_reference; + vector m_validators; }; }; @@ -94,6 +129,10 @@ XMLSecSignatureImpl::~XMLSecSignatureImpl() XMLString::release(&m_c14n); XMLString::release(&m_sm); + delete m_key; + delete m_keyInfo; + delete m_reference; + for_each(m_validators.begin(),m_validators.end(),cleanup()); } void XMLSecSignatureImpl::releaseDOM() @@ -119,6 +158,14 @@ Signature* XMLSecSignatureImpl::cloneSignature() const 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 (m_reference) + ret->m_reference=m_reference->clone(); + + xmltooling::clone(m_validators,ret->m_validators); // If there's no XML locally, serialize this object into the new one, otherwise just copy it over. if (m_xml.empty()) @@ -129,47 +176,27 @@ Signature* XMLSecSignatureImpl::cloneSignature() 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(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"); - CredentialResolver& cr=ctx.getCredentialResolver(); - if (!ctx.createSignature(m_signature)) { - auto_ptr keyInfo(ctx.getKeyInfo()); - if (keyInfo.get()) { - DOMElement* domElement=keyInfo->marshall(m_signature->getParentDocument()); - getDOM()->appendChild(domElement); - } - else { - Locker locker1(cr); - const std::vector* certs=cr.getX509Certificates(); - if (certs && !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); + if (m_keyInfo) { + m_keyInfo->marshall(getDOM()); } log.debug("computing signature"); - Locker locker2(cr); - XSECCryptoKey* key=cr.getPrivateKey(); - if (!key) - throw SignatureException(string("Unable to obtain signing key from CredentialResolver (") + cr.getId() + ")"); - m_signature->setSigningKey(key->clone()); + m_signature->setSigningKey(m_key->clone()); m_signature->sign(); } catch(XSECException& e) { @@ -181,27 +208,7 @@ void XMLSecSignatureImpl::sign(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"); @@ -310,7 +317,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"); @@ -423,6 +430,49 @@ XMLObject* XMLSecSignatureImpl::unmarshall(DOMElement* element, bool bindDocumen return this; } +void XMLSecSignatureImpl::registerValidator(Validator* validator) +{ + m_validators.push_back(validator); +} + +void XMLSecSignatureImpl::deregisterValidator(Validator* validator) +{ + for (vector::iterator i=m_validators.begin(); i!=m_validators.end(); i++) { + if ((*i)==validator) { + m_validators.erase(i); + return; + } + } +} + +void XMLSecSignatureImpl::deregisterAll() +{ + for_each(m_validators.begin(),m_validators.end(),cleanup()); + m_validators.clear(); +} + +class _validate : public binary_function { +public: + void operator()(const XMLObject* obj, bool propagate) const { + const ValidatingXMLObject* val = dynamic_cast(obj); + if (val) { + val->validate(propagate); + } + } +}; + +void XMLSecSignatureImpl::validate(bool validateDescendants) const +{ + for_each( + m_validators.begin(),m_validators.end(), + bind2nd(mem_fun(&Validator::validate),this) + ); + + if (validateDescendants && m_keyInfo) { + m_keyInfo->validate(validateDescendants); + } +} + Signature* SignatureBuilder::buildObject( const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType ) const diff --git a/xmltooling/util/CredentialResolver.h b/xmltooling/util/CredentialResolver.h deleted file mode 100644 index f325b4c..0000000 --- a/xmltooling/util/CredentialResolver.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2001-2006 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. - */ - -/** - * @file CredentialResolver.h - * - * Provides access to keys and certificates. - */ - -#if !defined(__xmltooling_credres_h__) && !defined(XMLTOOLING_NO_XMLSEC) -#define __xmltooling_credres_h__ - -#include - -#include -#include -#include - -namespace xmltooling { - - /** - * An abstract interface to credential formats like files, keystores, hardware tokens, etc. - * All non-const methods require that the interface be locked. - */ - class XMLTOOL_API CredentialResolver : public virtual Lockable - { - MAKE_NONCOPYABLE(CredentialResolver); - public: - virtual ~CredentialResolver() {} - - /** - * Returns an identifier for the credential. - * - * @return the identifier - */ - virtual const char* getId() const=0; - - /** - * Gets the public key associated with the credential. - * The caller MUST NOT modify the object. - * - * @return the public key, or NULL - */ - virtual XSECCryptoKey* getPublicKey()=0; - - /** - * Gets the private key associated with the credential. - * The caller MUST NOT modify the object. - * - * @return the private key, or NULL - */ - virtual XSECCryptoKey* getPrivateKey()=0; - - /** - * Gets the certificate chain associated with the credential. - * The caller MUST NOT modify the objects. - * The EE certificate MUST be first. - * - * @return a chain of certificates, or NULL - */ - virtual const std::vector* getX509Certificates()=0; - - protected: - CredentialResolver() {} - }; - -}; - -#endif /* __xmltooling_credres_h__ */ diff --git a/xmltooling/validation/AbstractValidatingXMLObject.cpp b/xmltooling/validation/AbstractValidatingXMLObject.cpp index 6df3ab4..5e50d3e 100644 --- a/xmltooling/validation/AbstractValidatingXMLObject.cpp +++ b/xmltooling/validation/AbstractValidatingXMLObject.cpp @@ -49,24 +49,31 @@ AbstractValidatingXMLObject::~AbstractValidatingXMLObject() delete m_validators; } -void AbstractValidatingXMLObject::registerValidator(Validator* validator) const +void AbstractValidatingXMLObject::registerValidator(Validator* validator) { if (!m_validators) m_validators=new ValidatorWrapper(); m_validators->v.push_back(validator); } -void AbstractValidatingXMLObject::deregisterValidator(Validator* validator) const +void AbstractValidatingXMLObject::deregisterValidator(Validator* validator) { if (m_validators) { for (std::vector::iterator i=m_validators->v.begin(); i!=m_validators->v.end(); i++) { - if ((*i)==validator) + if ((*i)==validator) { m_validators->v.erase(i); return; + } } } } +void AbstractValidatingXMLObject::deregisterAll() +{ + delete m_validators; + m_validators=NULL; +} + class _validate : public binary_function { public: void operator()(const XMLObject* obj, bool propagate) const { diff --git a/xmltooling/validation/AbstractValidatingXMLObject.h b/xmltooling/validation/AbstractValidatingXMLObject.h index 0eda2c6..5252e50 100644 --- a/xmltooling/validation/AbstractValidatingXMLObject.h +++ b/xmltooling/validation/AbstractValidatingXMLObject.h @@ -44,12 +44,17 @@ namespace xmltooling { /** * @see ValidatingXMLObject::registerValidator() */ - void registerValidator(Validator* validator) const; + void registerValidator(Validator* validator); /** * @see ValidatingXMLObject::deregisterValidator() */ - void deregisterValidator(Validator* validator) const; + void deregisterValidator(Validator* validator); + + /** + * @see ValidatingXMLObject::deregisterAll() + */ + void deregisterAll(); /** * @see ValidatingXMLObject::validate() diff --git a/xmltooling/validation/ValidatingXMLObject.h b/xmltooling/validation/ValidatingXMLObject.h index 07d4a0e..0943be5 100644 --- a/xmltooling/validation/ValidatingXMLObject.h +++ b/xmltooling/validation/ValidatingXMLObject.h @@ -51,14 +51,19 @@ namespace xmltooling { * * @param validator the validator */ - virtual void registerValidator(Validator* validator) const=0; + virtual void registerValidator(Validator* validator)=0; /** * Deregisters a validator for this XMLObject. * * @param validator the validator */ - virtual void deregisterValidator(Validator* validator) const=0; + virtual void deregisterValidator(Validator* validator)=0; + + /** + * Deregisters all validators for this XMLObject. + */ + virtual void deregisterAll()=0; /** * Validates this XMLObject against all registered validators. diff --git a/xmltooling/xmltooling.vcproj b/xmltooling/xmltooling.vcproj index 525480e..146d950 100644 --- a/xmltooling/xmltooling.vcproj +++ b/xmltooling/xmltooling.vcproj @@ -475,15 +475,15 @@ Name="signature" > diff --git a/xmltoolingtest/SignatureTest.h b/xmltoolingtest/SignatureTest.h index 62bd6a3..2312f8e 100644 --- a/xmltoolingtest/SignatureTest.h +++ b/xmltoolingtest/SignatureTest.h @@ -23,80 +23,115 @@ #include #include #include +#include +#include -class TestContext : public SigningContext, public VerifyingContext, CredentialResolver +class TestContext : public ContentReference { - XSECCryptoKey* m_key; - vector m_certs; XMLCh* m_uri; public: TestContext(const XMLCh* uri) { - string keypath=data_path + "key.pem"; - BIO* in=BIO_new(BIO_s_file_internal()); - if (in && BIO_read_filename(in,keypath.c_str())>0) { - EVP_PKEY* pkey=PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); - if (pkey) { - m_key=new OpenSSLCryptoKeyRSA(pkey); - EVP_PKEY_free(pkey); - } - } - if (in) BIO_free(in); - TS_ASSERT(m_key!=NULL); - - string certpath=data_path + "cert.pem"; - in=BIO_new(BIO_s_file_internal()); - if (in && BIO_read_filename(in,certpath.c_str())>0) { - X509* x=NULL; - while (x=PEM_read_bio_X509(in,NULL,NULL,NULL)) { - m_certs.push_back(new OpenSSLCryptoX509(x)); - X509_free(x); - } - } - if (in) BIO_free(in); - TS_ASSERT(m_certs.size()>0); - m_uri=XMLString::replicate(uri); } virtual ~TestContext() { - delete m_key; - for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup()); XMLString::release(&m_uri); } - bool createSignature(DSIGSignature* sig) { + ContentReference* clone() const { + return new TestContext(m_uri); + } + + void createReferences(DSIGSignature* sig) { DSIGReference* ref=sig->createReference(m_uri); ref->appendEnvelopedSignatureTransform(); ref->appendCanonicalizationTransform(CANON_C14NE_NOC); - return false; + } +}; + +class TestValidator : public Validator +{ + XMLCh* m_uri; + +public: + TestValidator(const XMLCh* uri) { + m_uri=XMLString::replicate(uri); + } + + virtual ~TestValidator() { + XMLString::release(&m_uri); + } + + Validator* clone() const { + return new TestValidator(m_uri); } - void verifySignature(DSIGSignature* sig) const { + void validate(const XMLObject* xmlObject) const { + DSIGSignature* sig=dynamic_cast(xmlObject)->getXMLSignature(); + if (!sig) + throw SignatureException("Only a marshalled Signature object can be verified."); const XMLCh* uri=sig->getReferenceList()->item(0)->getURI(); TSM_ASSERT_SAME_DATA("Reference URI does not match.",uri,m_uri,XMLString::stringLen(uri)); XSECKeyInfoResolverDefault resolver; sig->setKeyInfoResolver(&resolver); // It will clone the resolver for us. - sig->verify(); + try { + if (!sig->verify()) + throw SignatureException("Signature did not verify."); + } + 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()); + } + } +}; + +class _addcert : public std::binary_function { +public: + void operator()(X509Data* bag, XSECCryptoX509* cert) const { + safeBuffer& buf=cert->getDEREncodingSB(); + X509Certificate* x=X509CertificateBuilder::buildX509Certificate(); + x->setValue(buf.sbStrToXMLCh()); + bag->getX509Certificates().push_back(x); } - - KeyInfo* getKeyInfo() { return NULL; } - CredentialResolver& getCredentialResolver() { return *this; } - const char* getId() const { return "test"; } - const std::vector* getX509Certificates() { return &m_certs; } - XSECCryptoKey* getPublicKey() { return m_key; } - XSECCryptoKey* getPrivateKey() { return m_key; } - Lockable& lock() { return *this; } - void unlock() {} }; class SignatureTest : public CxxTest::TestSuite { + XSECCryptoKey* m_key; + vector m_certs; public: void setUp() { QName qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME); QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); XMLObjectBuilder::registerBuilder(qname, new SimpleXMLObjectBuilder()); XMLObjectBuilder::registerBuilder(qtype, new SimpleXMLObjectBuilder()); + string keypath=data_path + "key.pem"; + BIO* in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,keypath.c_str())>0) { + EVP_PKEY* pkey=PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); + if (pkey) { + m_key=new OpenSSLCryptoKeyRSA(pkey); + EVP_PKEY_free(pkey); + } + } + if (in) BIO_free(in); + TS_ASSERT(m_key!=NULL); + + string certpath=data_path + "cert.pem"; + in=BIO_new(BIO_s_file_internal()); + if (in && BIO_read_filename(in,certpath.c_str())>0) { + X509* x=NULL; + while (x=PEM_read_bio_X509(in,NULL,NULL,NULL)) { + m_certs.push_back(new OpenSSLCryptoX509(x)); + X509_free(x); + } + } + if (in) BIO_free(in); + TS_ASSERT(m_certs.size()>0); + } void tearDown() { @@ -104,6 +139,8 @@ public: QName qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME); XMLObjectBuilder::deregisterBuilder(qname); XMLObjectBuilder::deregisterBuilder(qtype); + delete m_key; + for_each(m_certs.begin(),m_certs.end(),xmltooling::cleanup()); } void testSignature() { @@ -126,13 +163,28 @@ public: kids[1]->setValue(bar.get()); // Append a Signature. - Signature* sig=SignatureBuilder::newSignature(); + Signature* sig=SignatureBuilder::buildSignature(); sxObject->setSignature(sig); + sig->setContentReference(new TestContext(&chNull)); + sig->setSigningKey(m_key->clone()); + + // Build KeyInfo. + KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo(); + X509Data* x509Data=X509DataBuilder::buildX509Data(); + keyInfo->getX509Datas().push_back(x509Data); + for_each(m_certs.begin(),m_certs.end(),bind1st(_addcert(),x509Data)); + sig->setKeyInfo(keyInfo); // Signing context for the whole document. - TestContext tc(&chNull); - MarshallingContext mctx(sig,&tc); - DOMElement* rootElement = sxObject->marshall((DOMDocument*)NULL,&mctx); + vector sigs(1,sig); + DOMElement* rootElement = NULL; + try { + rootElement=sxObject->marshall((DOMDocument*)NULL,&sigs); + } + catch (XMLToolingException& e) { + TS_TRACE(e.what()); + throw; + } string buf; XMLHelper::serialize(rootElement, buf); @@ -143,11 +195,12 @@ public: auto_ptr sxObject2(dynamic_cast(b->buildFromDocument(doc))); TS_ASSERT(sxObject2.get()!=NULL); TS_ASSERT(sxObject2->getSignature()!=NULL); + sxObject2->getSignature()->registerValidator(new TestValidator(&chNull)); try { - sxObject2->getSignature()->verify(tc); + sxObject2->getSignature()->validate(false); } - catch (SignatureException& e) { + catch (XMLToolingException& e) { TS_TRACE(e.what()); throw; }