2.0 SOAP Encoder
authorScott Cantor <cantor.2@osu.edu>
Sun, 12 Nov 2006 22:40:36 +0000 (22:40 +0000)
committerScott Cantor <cantor.2@osu.edu>
Sun, 12 Nov 2006 22:40:36 +0000 (22:40 +0000)
saml/Makefile.am
saml/binding/impl/MessageDecoder.cpp
saml/binding/impl/MessageEncoder.cpp
saml/saml.vcproj
saml/saml1/binding/SAML1SOAPEncoder.h
saml/saml1/binding/impl/SAML1SOAPEncoder.cpp
saml/saml2/binding/SAML2SOAPEncoder.h [new file with mode: 0644]
saml/saml2/binding/impl/SAML2SOAPEncoder.cpp [new file with mode: 0644]

index 78ae9b2..c5f69ec 100644 (file)
@@ -94,7 +94,8 @@ saml2bindinclude_HEADERS = \
        saml2/binding/SAML2Redirect.h \
        saml2/binding/SAML2RedirectDecoder.h \
        saml2/binding/SAML2RedirectEncoder.h \
-       saml2/binding/SAML2SOAPDecoder.h
+       saml2/binding/SAML2SOAPDecoder.h \
+       saml2/binding/SAML2SOAPEncoder.h
 
 saml2mdinclude_HEADERS = \
        saml2/metadata/AbstractMetadataProvider.h \
@@ -155,6 +156,7 @@ libsaml_la_SOURCES = \
        saml2/binding/impl/SAML2RedirectDecoder.cpp \
        saml2/binding/impl/SAML2RedirectEncoder.cpp \
        saml2/binding/impl/SAML2SOAPDecoder.cpp \
+       saml2/binding/impl/SAML2SOAPEncoder.cpp \
        encryption/EncryptedKeyResolver.cpp \
        security/impl/TrustEngine.cpp \
        security/impl/AbstractPKIXTrustEngine.cpp \
index 83bd7b1..cf785f6 100644 (file)
@@ -38,6 +38,7 @@ namespace opensaml {
         SAML_DLLLOCAL PluginManager<MessageDecoder,const DOMElement*>::Factory SAML2ArtifactDecoderFactory;
         SAML_DLLLOCAL PluginManager<MessageDecoder,const DOMElement*>::Factory SAML2POSTDecoderFactory;
         SAML_DLLLOCAL PluginManager<MessageDecoder,const DOMElement*>::Factory SAML2RedirectDecoderFactory;
+        SAML_DLLLOCAL PluginManager<MessageDecoder,const DOMElement*>::Factory SAML2SOAPDecoderFactory;
     };
 };
 
@@ -51,4 +52,5 @@ void SAML_API opensaml::registerMessageDecoders()
     conf.MessageDecoderManager.registerFactory(samlconstants::SAML20_BINDING_HTTP_POST, saml2p::SAML2POSTDecoderFactory);
     conf.MessageDecoderManager.registerFactory(samlconstants::SAML20_BINDING_HTTP_POST_SIMPLESIGN, saml2p::SAML2POSTDecoderFactory);
     conf.MessageDecoderManager.registerFactory(samlconstants::SAML20_BINDING_HTTP_REDIRECT, saml2p::SAML2RedirectDecoderFactory);
+    conf.MessageDecoderManager.registerFactory(samlconstants::SAML20_BINDING_SOAP, saml2p::SAML2SOAPDecoderFactory);
 }
index 74e9a8a..5b6f761 100644 (file)
@@ -36,6 +36,7 @@ namespace opensaml {
     namespace saml1p {
         SAML_DLLLOCAL PluginManager<MessageEncoder,const DOMElement*>::Factory SAML1ArtifactEncoderFactory;
         SAML_DLLLOCAL PluginManager<MessageEncoder,const DOMElement*>::Factory SAML1POSTEncoderFactory;
+        SAML_DLLLOCAL PluginManager<MessageEncoder,const DOMElement*>::Factory SAML1SOAPEncoderFactory;
     }; 
 
     namespace saml2p {
@@ -43,6 +44,7 @@ namespace opensaml {
         SAML_DLLLOCAL PluginManager<MessageEncoder,const DOMElement*>::Factory SAML2POSTEncoderFactory;
         SAML_DLLLOCAL PluginManager<MessageEncoder,const DOMElement*>::Factory SAML2POSTSimpleSignEncoderFactory;
         SAML_DLLLOCAL PluginManager<MessageEncoder,const DOMElement*>::Factory SAML2RedirectEncoderFactory;
+        SAML_DLLLOCAL PluginManager<MessageEncoder,const DOMElement*>::Factory SAML2SOAPEncoderFactory;
     };
 };
 
@@ -51,10 +53,12 @@ void SAML_API opensaml::registerMessageEncoders()
     SAMLConfig& conf=SAMLConfig::getConfig();
     conf.MessageEncoderManager.registerFactory(samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT, saml1p::SAML1ArtifactEncoderFactory);
     conf.MessageEncoderManager.registerFactory(samlconstants::SAML1_PROFILE_BROWSER_POST, saml1p::SAML1POSTEncoderFactory);
+    conf.MessageEncoderManager.registerFactory(samlconstants::SAML1_BINDING_SOAP, saml1p::SAML1SOAPEncoderFactory);
     conf.MessageEncoderManager.registerFactory(samlconstants::SAML20_BINDING_HTTP_ARTIFACT, saml2p::SAML2ArtifactEncoderFactory);
     conf.MessageEncoderManager.registerFactory(samlconstants::SAML20_BINDING_HTTP_POST, saml2p::SAML2POSTEncoderFactory);
     conf.MessageEncoderManager.registerFactory(samlconstants::SAML20_BINDING_HTTP_POST_SIMPLESIGN, saml2p::SAML2POSTSimpleSignEncoderFactory);
     conf.MessageEncoderManager.registerFactory(samlconstants::SAML20_BINDING_HTTP_REDIRECT, saml2p::SAML2RedirectEncoderFactory);
+    conf.MessageEncoderManager.registerFactory(samlconstants::SAML20_BINDING_SOAP, saml2p::SAML2SOAPEncoderFactory);
 }
 
 namespace {
index 80d71c6..3183249 100644 (file)
                                                        RelativePath=".\saml2\binding\impl\SAML2SOAPDecoder.cpp"\r
                                                        >\r
                                                </File>\r
+                                               <File\r
+                                                       RelativePath=".\saml2\binding\impl\SAML2SOAPEncoder.cpp"\r
+                                                       >\r
+                                               </File>\r
                                        </Filter>\r
                                </Filter>\r
                        </Filter>\r
                                                RelativePath=".\saml2\binding\SAML2SOAPDecoder.h"\r
                                                >\r
                                        </File>\r
+                                       <File\r
+                                               RelativePath=".\saml2\binding\SAML2SOAPEncoder.h"\r
+                                               >\r
+                                       </File>\r
                                </Filter>\r
                        </Filter>\r
                        <Filter\r
index ca52837..52e20bc 100644 (file)
@@ -27,7 +27,7 @@ namespace opensaml {
     namespace saml1p {
 
         /**
-         * SAML 1.x POST binding/profile message encoder
+         * SAML 1.x POST binding message encoder
          */
         class SAML_API SAML1SOAPEncoder : public MessageEncoder
         {
index 121acbe..b112dae 100644 (file)
@@ -70,6 +70,11 @@ long SAML1SOAPEncoder::encode(
         throw BindingException("Cannot encode XML content with parent.");
 
     genericResponse.setContentType("text/xml");
+    HTTPResponse* httpResponse = dynamic_cast<HTTPResponse*>(&genericResponse);
+    if (httpResponse) {
+        httpResponse->setHeader("Cache-Control", "no-cache, no-store, must-revalidate, private");
+        httpResponse->setHeader("Pragma", "no-cache");
+    }
 
     DOMElement* rootElement = NULL;
     Response* response = dynamic_cast<Response*>(xmlObject);
diff --git a/saml/saml2/binding/SAML2SOAPEncoder.h b/saml/saml2/binding/SAML2SOAPEncoder.h
new file mode 100644 (file)
index 0000000..6df8d7e
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  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 saml/saml2/binding/SAML2SOAPEncoder.h
+ * 
+ * SAML 2.0 SOAP binding message encoder
+ */
+
+#include <saml/binding/MessageEncoder.h>
+
+
+namespace opensaml {
+    namespace saml2p {
+
+        /**
+         * SAML 2.0 POST binding message encoder
+         */
+        class SAML_API SAML2SOAPEncoder : public MessageEncoder
+        {
+        public:
+            SAML2SOAPEncoder(const DOMElement* e);
+            virtual ~SAML2SOAPEncoder() {}
+            
+            long encode(
+                GenericResponse& genericResponse,
+                xmltooling::XMLObject* xmlObject,
+                const char* destination,
+                const char* recipientID=NULL,
+                const char* relayState=NULL,
+                const xmlsignature::CredentialResolver* credResolver=NULL,
+                const XMLCh* sigAlgorithm=NULL
+                ) const;
+        };
+
+    };
+};
diff --git a/saml/saml2/binding/impl/SAML2SOAPEncoder.cpp b/saml/saml2/binding/impl/SAML2SOAPEncoder.cpp
new file mode 100644 (file)
index 0000000..7b56dee
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ *  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.
+ */
+
+/**
+ * SAML2SOAPEncoder.cpp
+ * 
+ * SAML 2.0 SOAP binding message encoder
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "binding/HTTPResponse.h"
+#include "saml2/binding/SAML2SOAPEncoder.h"
+#include "saml2/core/Protocols.h"
+
+#include <sstream>
+#include <log4cpp/Category.hh>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/soap/SOAP.h>
+
+using namespace opensaml::saml2p;
+using namespace opensaml;
+using namespace xmlsignature;
+using namespace soap11;
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+
+namespace opensaml {
+    namespace saml2p {              
+        MessageEncoder* SAML_DLLLOCAL SAML2SOAPEncoderFactory(const DOMElement* const & e)
+        {
+            return new SAML2SOAPEncoder(e);
+        }
+    };
+};
+
+SAML2SOAPEncoder::SAML2SOAPEncoder(const DOMElement* e) {}
+
+long SAML2SOAPEncoder::encode(
+    GenericResponse& genericResponse,
+    XMLObject* xmlObject,
+    const char* destination,
+    const char* recipientID,
+    const char* relayState,
+    const CredentialResolver* credResolver,
+    const XMLCh* sigAlgorithm
+    ) const
+{
+#ifdef _DEBUG
+    xmltooling::NDC ndc("encode");
+#endif
+    Category& log = Category::getInstance(SAML_LOGCAT".MessageEncoder.SAML1SOAP");
+
+    log.debug("validating input");
+    if (xmlObject->getParent())
+        throw BindingException("Cannot encode XML content with parent.");
+
+    genericResponse.setContentType("text/xml");
+    HTTPResponse* httpResponse = dynamic_cast<HTTPResponse*>(&genericResponse);
+    if (httpResponse) {
+        httpResponse->setHeader("Cache-Control", "no-cache, no-store, must-revalidate, private");
+        httpResponse->setHeader("Pragma", "no-cache");
+    }
+
+    DOMElement* rootElement = NULL;
+    StatusResponseType* response = dynamic_cast<StatusResponseType*>(xmlObject);
+    if (response) {
+        try {
+            Envelope* env = EnvelopeBuilder::buildEnvelope();
+            Body* body = BodyBuilder::buildBody();
+            env->setBody(body);
+            body->getXMLObjects().push_back(response);
+            if (credResolver ) {
+                if (response->getSignature()) {
+                    log.debug("response already signed, skipping signature operation");
+                    rootElement = env->marshall();
+                }
+                else {
+                    log.debug("signing and marshalling the response");
+        
+                    // Build a Signature.
+                    Signature* sig = buildSignature(credResolver, sigAlgorithm);
+                    response->setSignature(sig);
+            
+                    // Sign response while marshalling.
+                    vector<Signature*> sigs(1,sig);
+                    rootElement = env->marshall((DOMDocument*)NULL,&sigs);
+                }
+            }
+            else {
+                log.debug("marshalling the response");
+                rootElement = env->marshall();
+            }
+            
+            string xmlbuf;
+            XMLHelper::serialize(rootElement, xmlbuf);
+            istringstream s(xmlbuf);
+            log.debug("sending serialized response");
+            long ret = genericResponse.sendResponse(s);
+        
+            // Cleanup by destroying XML.
+            delete env;
+            return ret;
+        }
+        catch (XMLToolingException&) {
+            // A bit weird...we have to "revert" things so that the response is isolated
+            // so the caller can free it.
+            if (response->getParent()) {
+                response->getParent()->detach();
+                response->detach();
+            }
+            throw;
+        }
+    }
+
+    Fault* fault = dynamic_cast<Fault*>(xmlObject);
+    if (fault) {
+        try {
+            log.debug("building Envelope and marshalling Fault");
+            Envelope* env = EnvelopeBuilder::buildEnvelope();
+            Body* body = BodyBuilder::buildBody();
+            env->setBody(body);
+            body->getXMLObjects().push_back(fault);
+            rootElement = env->marshall();
+    
+            string xmlbuf;
+            XMLHelper::serialize(rootElement, xmlbuf);
+            istringstream s(xmlbuf);
+            log.debug("sending serialized fault");
+            long ret = genericResponse.sendError(s);
+        
+            // Cleanup by destroying XML.
+            delete env;
+            return ret;
+        }
+        catch (XMLToolingException&) {
+            // A bit weird...we have to "revert" things so that the fault is isolated
+            // so the caller can free it.
+            if (fault->getParent()) {
+                fault->getParent()->detach();
+                fault->detach();
+            }
+            throw;
+        }
+    }
+
+    Envelope* env = dynamic_cast<Envelope*>(xmlObject);
+    if (env) {
+        log.debug("marshalling envelope");
+        rootElement = env->marshall();
+
+        bool error =
+            (env->getBody() &&
+                env->getBody()->hasChildren() &&
+                    dynamic_cast<Fault*>(env->getBody()->getXMLObjects().front()));
+
+        string xmlbuf;
+        XMLHelper::serialize(rootElement, xmlbuf);
+        istringstream s(xmlbuf);
+        log.debug("sending serialized envelope");
+        long ret = error ? genericResponse.sendError(s) : genericResponse.sendResponse(s);
+    
+        // Cleanup by destroying XML.
+        delete env;
+        return ret;
+    }
+
+    throw BindingException("XML content for SAML 2.0 SOAP Encoder must be a SAML 2.0 response or SOAP Fault/Envelope.");
+}