Merge branch '1.x' of ssh://authdev.it.ohio-state.edu/~scantor/git/cpp-xmltooling...
[shibboleth/cpp-xmltooling.git] / xmltooling / signature / impl / XMLSecSignatureImpl.cpp
index f3072c6..1d69463 100644 (file)
@@ -1,23 +1,27 @@
-/*
-*  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
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * UCAID licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the
+ * License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ * 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.
+ * 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
+ * Signature class for XMLSec-based signature-handling.
  */
 
 #include "internal.h"
@@ -25,6 +29,7 @@
 #include "logging.h"
 #include "impl/UnknownElement.h"
 #include "security/Credential.h"
+#include "signature/ContentReference.h"
 #include "signature/KeyInfo.h"
 #include "signature/Signature.h"
 #include "util/NDC.h"
@@ -52,19 +57,19 @@ using namespace std;
 using xmlconstants::XMLSIG_NS;
 using xmlconstants::XMLSIG_PREFIX;
 
+namespace xmlsignature {
+
 #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) {}
+            m_signature(nullptr), m_c14n(nullptr), m_sm(nullptr), m_key(nullptr), m_keyInfo(nullptr), m_reference(nullptr) {}
         virtual ~XMLSecSignatureImpl();
         
         void releaseDOM() const;
@@ -78,8 +83,8 @@ namespace xmlsignature {
         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;
+        DOMElement* marshall(DOMDocument* document=nullptr, const vector<Signature*>* sigs=nullptr, const Credential* credential=nullptr) const;
+        DOMElement* marshall(DOMElement* parentElement, const vector<Signature*>* sigs=nullptr, const Credential* credential=nullptr) const;
         XMLObject* unmarshall(DOMElement* element, bool bindDocument=false);
         
         // Getters
@@ -90,12 +95,15 @@ namespace xmlsignature {
         }
         const XMLCh* getSignatureAlgorithm() const {
             if (!m_sm && m_signature) {
+#ifdef XMLTOOLING_XMLSEC_SIGALGORITHM
+                m_sm = XMLString::replicate(m_signature->getAlgorithmURI());
+#else
                 safeBuffer sURI;
-                if (signatureHashMethod2URI(sURI, m_signature->getSignatureMethod(), m_signature->getHashMethod()) == false)
-                    return NULL;
-                m_sm = XMLString::replicate(sURI.sbStrToXMLCh());
+                if (signatureHashMethod2URI(sURI, m_signature->getSignatureMethod(), m_signature->getHashMethod()))
+                    m_sm = XMLString::replicate(sURI.sbStrToXMLCh());
+#endif
             }
-            return m_sm ? m_sm : DSIGConstants::s_unicodeStrURIRSA_SHA1;
+            return m_sm;
         }
 
         KeyInfo* getKeyInfo() const { return m_keyInfo; }
@@ -118,7 +126,7 @@ namespace xmlsignature {
             m_reference=reference;
         }
         
-        void sign(const Credential* credential=NULL);
+        void sign(const Credential* credential=nullptr);
 
     private:
         mutable DSIGSignature* m_signature;
@@ -128,12 +136,27 @@ namespace xmlsignature {
         mutable KeyInfo* m_keyInfo;
         ContentReference* m_reference;
     };
-    
-};
 
 #if defined (_MSC_VER)
     #pragma warning( pop )
 #endif
+};
+
+ContentReference::ContentReference()
+{
+}
+
+ContentReference::~ContentReference()
+{
+}
+
+Signature::Signature()
+{
+}
+
+Signature::~Signature()
+{
+}
 
 XMLSecSignatureImpl::~XMLSecSignatureImpl()
 {
@@ -157,7 +180,7 @@ void XMLSecSignatureImpl::releaseDOM() const
         // Release the associated signature.
         if (m_signature) {
             XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);
-            m_signature=NULL;
+            m_signature=nullptr;
         }
     }
 }
@@ -255,12 +278,15 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector<Si
         // Fresh signature, so we just create an empty one.
         log.debug("creating empty Signature element");
         if (!document) {
-            document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument();
+            document=DOMImplementationRegistry::getDOMImplementation(nullptr)->createDocument();
             bindDocument=true;
         }
         DSIGSignature* temp=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
         temp->setDSIGNSPrefix(XMLSIG_PREFIX);
-        cachedDOM=temp->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm());
+        const XMLCh* alg = getSignatureAlgorithm();
+        if (!alg)
+            alg = DSIGConstants::s_unicodeStrURIRSA_SHA1;
+        cachedDOM=temp->createBlankSignature(document, getCanonicalizationMethod(), alg);
         m_signature = temp;
     }
     else {
@@ -273,7 +299,16 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector<Si
             // 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));
+            try {
+                cachedDOM=static_cast<DOMElement*>(document->importNode(internalDoc->getDocumentElement(), true));
+            }
+            catch (XMLException& ex) {
+                internalDoc->release();
+                auto_ptr_char temp(ex.getMessage());
+                throw XMLParserException(
+                    string("Error importing DOM into caller-supplied document: ") + (temp.get() ? temp.get() : "no message")
+                    );
+            }
             internalDoc->release();
         }
         else {
@@ -306,7 +341,7 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector<Si
     // Marshall KeyInfo data.
     if (credential) {
         delete m_keyInfo;
-        m_keyInfo = NULL;
+        m_keyInfo = nullptr;
         m_keyInfo = credential->getKeyInfo();
     }
     if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {
@@ -357,7 +392,10 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vecto
         log.debug("creating empty Signature element");
         DSIGSignature* temp=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
         temp->setDSIGNSPrefix(XMLSIG_PREFIX);
-        cachedDOM=temp->createBlankSignature(parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm());
+        const XMLCh* alg = getSignatureAlgorithm();
+        if (!alg)
+            alg = DSIGConstants::s_unicodeStrURIRSA_SHA1;
+        cachedDOM=temp->createBlankSignature(parentElement->getOwnerDocument(), getCanonicalizationMethod(), alg);
         m_signature = temp;
     }
     else {
@@ -367,7 +405,16 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vecto
         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));
+        try {
+            cachedDOM=static_cast<DOMElement*>(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(),true));
+        }
+        catch (XMLException& ex) {
+            internalDoc->release();
+            auto_ptr_char temp(ex.getMessage());
+            throw XMLParserException(
+                string("Error importing DOM into caller-supplied document: ") + (temp.get() ? temp.get() : "no message")
+                );
+        }
         internalDoc->release();
 
         // Now reload the signature from the DOM.
@@ -389,7 +436,7 @@ DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vecto
     // Marshall KeyInfo data.
     if (credential) {
         delete m_keyInfo;
-        m_keyInfo = NULL;
+        m_keyInfo = nullptr;
         m_keyInfo = credential->getKeyInfo();
     }
     if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {
@@ -451,6 +498,20 @@ SignatureBuilder::buildObject() const
     return new XMLSecSignatureImpl();
 }
 
+Signature* SignatureBuilder::buildSignature() {
+    const SignatureBuilder* b = dynamic_cast<const SignatureBuilder*>(
+        XMLObjectBuilder::getBuilder(xmltooling::QName(xmlconstants::XMLSIG_NS,Signature::LOCAL_NAME))
+        );
+    if (b) {
+#ifdef HAVE_COVARIANT_RETURNS
+        return b->buildObject();
+#else
+        return dynamic_cast<Signature*>(b->buildObject());
+#endif
+    }
+    throw XMLObjectException("Unable to obtain typed builder for Signature.");
+}
+
 const XMLCh Signature::LOCAL_NAME[] = UNICODE_LITERAL_9(S,i,g,n,a,t,u,r,e);
 
 // Raw signature methods.
@@ -469,7 +530,7 @@ unsigned int Signature::createRawSignature(
         // Move input into a safeBuffer to source the transform chain.
         safeBuffer sb,sbout;
         sb.sbStrncpyIn(in,in_len);
-        TXFMSB* sbt = new TXFMSB(NULL);
+        TXFMSB* sbt = new TXFMSB(nullptr);
         sbt->setInput(sb, in_len);
         TXFMChain tx(sbt);
         
@@ -515,7 +576,7 @@ bool Signature::verifyRawSignature(
         // Move input into a safeBuffer to source the transform chain.
         safeBuffer sb;
         sb.sbStrncpyIn(in,in_len);
-        TXFMSB* sbt = new TXFMSB(NULL);
+        TXFMSB* sbt = new TXFMSB(nullptr);
         sbt->setInput(sb, in_len);
         TXFMChain tx(sbt);