First SOAP encoder.
authorScott Cantor <cantor.2@osu.edu>
Sun, 12 Nov 2006 05:11:23 +0000 (05:11 +0000)
committerScott Cantor <cantor.2@osu.edu>
Sun, 12 Nov 2006 05:11:23 +0000 (05:11 +0000)
25 files changed:
saml/Makefile.am
saml/binding/GenericResponse.h
saml/binding/HTTPResponse.h
saml/saml.vcproj
saml/saml1/binding/SAML1ArtifactDecoder.h
saml/saml1/binding/SAML1ArtifactEncoder.h
saml/saml1/binding/SAML1POSTDecoder.h
saml/saml1/binding/SAML1POSTEncoder.h
saml/saml1/binding/SAML1SOAPEncoder.h [new file with mode: 0644]
saml/saml1/binding/impl/SAML1ArtifactDecoder.cpp
saml/saml1/binding/impl/SAML1ArtifactEncoder.cpp
saml/saml1/binding/impl/SAML1POSTDecoder.cpp
saml/saml1/binding/impl/SAML1POSTEncoder.cpp
saml/saml1/binding/impl/SAML1SOAPEncoder.cpp [new file with mode: 0644]
saml/saml2/binding/SAML2ArtifactDecoder.h
saml/saml2/binding/SAML2ArtifactEncoder.h
saml/saml2/binding/SAML2POSTDecoder.h
saml/saml2/binding/SAML2POSTEncoder.h
saml/saml2/binding/SAML2RedirectDecoder.h
saml/saml2/binding/impl/SAML2ArtifactDecoder.cpp
saml/saml2/binding/impl/SAML2ArtifactEncoder.cpp
saml/saml2/binding/impl/SAML2POSTDecoder.cpp
saml/saml2/binding/impl/SAML2POSTEncoder.cpp
saml/saml2/binding/impl/SAML2RedirectDecoder.cpp
samltest/binding.h

index 70fe4a7..78ae9b2 100644 (file)
@@ -77,7 +77,8 @@ saml1bindinclude_HEADERS = \
        saml1/binding/SAML1ArtifactEncoder.h \
        saml1/binding/SAML1POSTDecoder.h \
        saml1/binding/SAML1POSTEncoder.h \
-       saml1/binding/SAML1SOAPDecoder.h
+       saml1/binding/SAML1SOAPDecoder.h \
+       saml1/binding/SAML1SOAPEncoder.h
 
 saml2coreinclude_HEADERS = \
        saml2/core/Assertions.h \
@@ -129,6 +130,7 @@ libsaml_la_SOURCES = \
        saml1/binding/impl/SAML1POSTDecoder.cpp \
        saml1/binding/impl/SAML1POSTEncoder.cpp \
        saml1/binding/impl/SAML1SOAPDecoder.cpp \
+       saml1/binding/impl/SAML1SOAPEncoder.cpp \
        saml2/core/impl/Assertions20Impl.cpp \
        saml2/core/impl/Assertions20SchemaValidators.cpp \
        saml2/core/impl/Protocols20Impl.cpp \
index f955e5c..6947a37 100644 (file)
@@ -49,6 +49,24 @@ namespace opensaml {
         virtual void setContentType(const char* type=NULL)=0;
 
         /**
+         * Sends a completed response to the client along with a
+         * transport-specific "OK" indication. Used for "normal" responses.
+         * 
+         * @param inputStream   reference to source of response data
+         * @return a result code to return from the calling MessageEncoder
+         */
+        virtual long sendResponse(std::istream& inputStream)=0;
+
+        /**
+         * Sends an "error" response to the client along with a
+         * transport-specific error indication.
+         * 
+         * @param inputStream   reference to source of response data
+         * @return a result code to return from the calling MessageEncoder
+         */
+        virtual long sendError(std::istream& inputStream)=0;
+
+        /**
          * Sends a completed response to the client.
          * 
          * @param inputStream   reference to source of response data
index e77e17d..4a94e1d 100644 (file)
@@ -71,7 +71,8 @@ namespace opensaml {
         /** Some common HTTP status codes. */
         enum status_t {
             SAML_HTTP_STATUS_OK = 200,
-            SAML_HTTP_STATUS_MOVED = 302
+            SAML_HTTP_STATUS_MOVED = 302,
+            SAML_HTTP_STATUS_ERROR = 500
         };
     };
 };
index f8190eb..80d71c6 100644 (file)
                                                        >\r
                                                </File>\r
                                                <File\r
+                                                       RelativePath=".\saml1\binding\impl\SAML1SOAPEncoder.cpp"\r
+                                                       >\r
+                                               </File>\r
+                                               <File\r
                                                        RelativePath=".\saml1\binding\impl\SAMLArtifactType0001.cpp"\r
                                                        >\r
                                                </File>\r
                                                >\r
                                        </File>\r
                                        <File\r
+                                               RelativePath=".\saml1\binding\SAML1SOAPEncoder.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
                                                RelativePath=".\saml1\binding\SAMLArtifactType0001.h"\r
                                                >\r
                                        </File>\r
index c1e384b..d1e3e89 100644 (file)
@@ -34,7 +34,7 @@ namespace opensaml {
         {
         public:
             SAML1ArtifactDecoder(const DOMElement* e);
-            virtual ~SAML1ArtifactDecoder();
+            virtual ~SAML1ArtifactDecoder() {}
             
             Response* decode(
                 std::string& relayState,
index a4d4718..40ce726 100644 (file)
@@ -33,7 +33,7 @@ namespace opensaml {
         {
         public:
             SAML1ArtifactEncoder(const DOMElement* e);
-            virtual ~SAML1ArtifactEncoder();
+            virtual ~SAML1ArtifactEncoder() {}
             
             long encode(
                 GenericResponse& genericResponse,
index 9ed3334..ead184b 100644 (file)
@@ -34,7 +34,7 @@ namespace opensaml {
         {
         public:
             SAML1POSTDecoder(const DOMElement* e);
-            virtual ~SAML1POSTDecoder();
+            virtual ~SAML1POSTDecoder() {}
             
             Response* decode(
                 std::string& relayState,
index 1496aff..a5abad7 100644 (file)
@@ -33,7 +33,7 @@ namespace opensaml {
         {
         public:
             SAML1POSTEncoder(const DOMElement* e);
-            virtual ~SAML1POSTEncoder();
+            virtual ~SAML1POSTEncoder() {}
             
             long encode(
                 GenericResponse& genericResponse,
diff --git a/saml/saml1/binding/SAML1SOAPEncoder.h b/saml/saml1/binding/SAML1SOAPEncoder.h
new file mode 100644 (file)
index 0000000..ca52837
--- /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/saml1/binding/SAML1SOAPEncoder.h
+ * 
+ * SAML 1.x SOAP binding message encoder
+ */
+
+#include <saml/binding/MessageEncoder.h>
+
+
+namespace opensaml {
+    namespace saml1p {
+
+        /**
+         * SAML 1.x POST binding/profile message encoder
+         */
+        class SAML_API SAML1SOAPEncoder : public MessageEncoder
+        {
+        public:
+            SAML1SOAPEncoder(const DOMElement* e);
+            virtual ~SAML1SOAPEncoder() {}
+            
+            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;
+        };
+
+    };
+};
index 83cd7ba..70cee0f 100644 (file)
@@ -50,8 +50,6 @@ namespace opensaml {
 
 SAML1ArtifactDecoder::SAML1ArtifactDecoder(const DOMElement* e) {}
 
-SAML1ArtifactDecoder::~SAML1ArtifactDecoder() {}
-
 Response* SAML1ArtifactDecoder::decode(
     string& relayState,
     const GenericRequest& genericRequest,
index 7252831..d40f64c 100644 (file)
@@ -51,8 +51,6 @@ namespace opensaml {
 
 SAML1ArtifactEncoder::SAML1ArtifactEncoder(const DOMElement* e) {}
 
-SAML1ArtifactEncoder::~SAML1ArtifactEncoder() {}
-
 long SAML1ArtifactEncoder::encode(
     GenericResponse& genericResponse,
     XMLObject* xmlObject,
index 33ac05f..bccc690 100644 (file)
@@ -52,8 +52,6 @@ namespace opensaml {
 
 SAML1POSTDecoder::SAML1POSTDecoder(const DOMElement* e) {}
 
-SAML1POSTDecoder::~SAML1POSTDecoder() {}
-
 Response* SAML1POSTDecoder::decode(
     string& relayState,
     const GenericRequest& genericRequest,
index ce99ce1..5c15044 100644 (file)
@@ -22,7 +22,6 @@
 
 #include "internal.h"
 #include "exceptions.h"
-#include "binding/HTTPResponse.h"
 #include "saml1/binding/SAML1POSTEncoder.h"
 #include "saml1/core/Protocols.h"
 
@@ -62,8 +61,6 @@ SAML1POSTEncoder::SAML1POSTEncoder(const DOMElement* e)
         throw XMLToolingException("SAML1POSTEncoder requires template attribute.");
 }
 
-SAML1POSTEncoder::~SAML1POSTEncoder() {}
-
 long SAML1POSTEncoder::encode(
     GenericResponse& genericResponse,
     XMLObject* xmlObject,
@@ -80,9 +77,6 @@ long SAML1POSTEncoder::encode(
     Category& log = Category::getInstance(SAML_LOGCAT".MessageEncoder.SAML1POST");
 
     log.debug("validating input");
-    HTTPResponse* httpResponse=dynamic_cast<HTTPResponse*>(&genericResponse);
-    if (!httpResponse)
-        throw BindingException("Unable to cast response interface to HTTPResponse type.");
     if (xmlObject->getParent())
         throw BindingException("Cannot encode XML content with parent.");
     Response* response = dynamic_cast<Response*>(xmlObject);
@@ -141,8 +135,8 @@ long SAML1POSTEncoder::encode(
     params["TARGET"] = relayState;
     stringstream s;
     engine->run(infile, s, params);
-    httpResponse->setContentType("text/html");
-    long ret = httpResponse->sendResponse(s, HTTPResponse::SAML_HTTP_STATUS_OK);
+    genericResponse.setContentType("text/html");
+    long ret = genericResponse.sendResponse(s);
 
     // Cleanup by destroying XML.
     delete xmlObject;
diff --git a/saml/saml1/binding/impl/SAML1SOAPEncoder.cpp b/saml/saml1/binding/impl/SAML1SOAPEncoder.cpp
new file mode 100644 (file)
index 0000000..121acbe
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ *  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.
+ */
+
+/**
+ * SAML1SOAPEncoder.cpp
+ * 
+ * SAML 1.x SOAP binding message encoder
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "binding/HTTPResponse.h"
+#include "saml1/binding/SAML1SOAPEncoder.h"
+#include "saml1/core/Protocols.h"
+
+#include <sstream>
+#include <log4cpp/Category.hh>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/soap/SOAP.h>
+
+using namespace opensaml::saml1p;
+using namespace opensaml;
+using namespace xmlsignature;
+using namespace soap11;
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+
+namespace opensaml {
+    namespace saml1p {              
+        MessageEncoder* SAML_DLLLOCAL SAML1SOAPEncoderFactory(const DOMElement* const & e)
+        {
+            return new SAML1SOAPEncoder(e);
+        }
+    };
+};
+
+SAML1SOAPEncoder::SAML1SOAPEncoder(const DOMElement* e) {}
+
+long SAML1SOAPEncoder::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");
+
+    DOMElement* rootElement = NULL;
+    Response* response = dynamic_cast<Response*>(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 1.x SOAP Encoder must be a SAML 1.x <Response> or SOAP Fault/Envelope.");
+}
index bf297c0..ad35e45 100644 (file)
@@ -37,7 +37,7 @@ namespace opensaml {
         {
         public:
             SAML2ArtifactDecoder(const DOMElement* e);
-            virtual ~SAML2ArtifactDecoder();
+            virtual ~SAML2ArtifactDecoder() {}
             
             xmltooling::XMLObject* decode(
                 std::string& relayState,
index d3f5f3d..0977df3 100644 (file)
@@ -33,7 +33,7 @@ namespace opensaml {
         {
         public:
             SAML2ArtifactEncoder(const DOMElement* e);
-            virtual ~SAML2ArtifactEncoder();
+            virtual ~SAML2ArtifactEncoder() {}
             
             long encode(
                 GenericResponse& genericResponse,
index 00edb7a..e311366 100644 (file)
@@ -34,7 +34,7 @@ namespace opensaml {
         {
         public:
             SAML2POSTDecoder(const DOMElement* e);
-            virtual ~SAML2POSTDecoder();
+            virtual ~SAML2POSTDecoder() {}
             
             saml2::RootObject* decode(
                 std::string& relayState,
index 2c0c25d..521a4ae 100644 (file)
@@ -33,7 +33,7 @@ namespace opensaml {
         {
         public:
             SAML2POSTEncoder(const DOMElement* e, bool simple=false);
-            virtual ~SAML2POSTEncoder();
+            virtual ~SAML2POSTEncoder() {}
             
             long encode(
                 GenericResponse& genericResponse,
index f0ced2b..64743d1 100644 (file)
@@ -32,7 +32,7 @@ namespace opensaml {
         {
         public:
             SAML2RedirectDecoder(const DOMElement* e);
-            virtual ~SAML2RedirectDecoder();
+            virtual ~SAML2RedirectDecoder() {}
             
             xmltooling::XMLObject* decode(
                 std::string& relayState,
index 1cd434e..48fcceb 100644 (file)
@@ -53,8 +53,6 @@ namespace opensaml {
 
 SAML2ArtifactDecoder::SAML2ArtifactDecoder(const DOMElement* e) {}
 
-SAML2ArtifactDecoder::~SAML2ArtifactDecoder() {}
-
 XMLObject* SAML2ArtifactDecoder::decode(
     string& relayState,
     const GenericRequest& genericRequest,
index 2ce48a3..a6445bd 100644 (file)
@@ -62,8 +62,6 @@ SAML2ArtifactEncoder::SAML2ArtifactEncoder(const DOMElement* e)
     }
 }
 
-SAML2ArtifactEncoder::~SAML2ArtifactEncoder() {}
-
 long SAML2ArtifactEncoder::encode(
     GenericResponse& genericResponse,
     xmltooling::XMLObject* xmlObject,
@@ -158,6 +156,6 @@ long SAML2ArtifactEncoder::encode(
         stringstream s;
         engine->run(infile, s, params);
         httpResponse->setContentType("text/html");
-        return httpResponse->sendResponse(s, HTTPResponse::SAML_HTTP_STATUS_OK);
+        return httpResponse->sendResponse(s);
     }
 }
index f216a8d..32aedea 100644 (file)
@@ -52,8 +52,6 @@ namespace opensaml {
 
 SAML2POSTDecoder::SAML2POSTDecoder(const DOMElement* e) {}
 
-SAML2POSTDecoder::~SAML2POSTDecoder() {}
-
 saml2::RootObject* SAML2POSTDecoder::decode(
     std::string& relayState,
     const GenericRequest& genericRequest,
index 3a5fe25..3c73d86 100644 (file)
@@ -22,7 +22,6 @@
 
 #include "internal.h"
 #include "exceptions.h"
-#include "binding/HTTPResponse.h"
 #include "saml2/binding/SAML2POSTEncoder.h"
 #include "saml2/core/Protocols.h"
 
@@ -67,8 +66,6 @@ SAML2POSTEncoder::SAML2POSTEncoder(const DOMElement* e, bool simple) : m_simple(
         throw XMLToolingException("SAML2POSTEncoder requires template attribute.");
 }
 
-SAML2POSTEncoder::~SAML2POSTEncoder() {}
-
 long SAML2POSTEncoder::encode(
     GenericResponse& genericResponse,
     XMLObject* xmlObject,
@@ -85,9 +82,6 @@ long SAML2POSTEncoder::encode(
     Category& log = Category::getInstance(SAML_LOGCAT".MessageEncoder.SAML2POST");
 
     log.debug("validating input");
-    HTTPResponse* httpResponse=dynamic_cast<HTTPResponse*>(&genericResponse);
-    if (!httpResponse)
-        throw BindingException("Unable to cast response interface to HTTPResponse type.");
     if (xmlObject->getParent())
         throw BindingException("Cannot encode XML content with parent.");
     
@@ -170,8 +164,8 @@ long SAML2POSTEncoder::encode(
     pmap["action"] = destination;
     stringstream s;
     engine->run(infile, s, pmap);
-    httpResponse->setContentType("text/html");
-    long ret = httpResponse->sendResponse(s, HTTPResponse::SAML_HTTP_STATUS_OK);
+    genericResponse.setContentType("text/html");
+    long ret = genericResponse.sendResponse(s);
 
     // Cleanup by destroying XML.
     delete xmlObject;
index 4ea64ff..5c1dc39 100644 (file)
@@ -54,8 +54,6 @@ namespace opensaml {
 
 SAML2RedirectDecoder::SAML2RedirectDecoder(const DOMElement* e) {}
 
-SAML2RedirectDecoder::~SAML2RedirectDecoder() {}
-
 XMLObject* SAML2RedirectDecoder::decode(
     string& relayState,
     const GenericRequest& genericRequest,
index aa0bff9..13638f1 100644 (file)
@@ -237,6 +237,14 @@ public:
         return decoded;\r
     }\r
     \r
+    long sendResponse(std::istream& inputStream) {\r
+        return sendResponse(inputStream, HTTPResponse::SAML_HTTP_STATUS_OK);\r
+    }\r
+\r
+    long sendError(std::istream& inputStream) {\r
+        return sendResponse(inputStream, HTTPResponse::SAML_HTTP_STATUS_ERROR);\r
+    }\r
+\r
     long sendResponse(std::istream& inputStream, long status) {\r
         m_method="POST";\r
         string page,line;\r