saml1/binding/SAML1POSTDecoder.h \
saml1/binding/SAML1POSTEncoder.h \
saml1/binding/SAML1SOAPDecoder.h \
- saml1/binding/SAML1SOAPEncoder.h
+ saml1/binding/SAML1SOAPEncoder.h \
+ saml1/binding/SAML1SOAPClient.h
saml2coreinclude_HEADERS = \
saml2/core/Assertions.h \
saml1/binding/impl/SAML1POSTEncoder.cpp \
saml1/binding/impl/SAML1SOAPDecoder.cpp \
saml1/binding/impl/SAML1SOAPEncoder.cpp \
+ saml1/binding/impl/SAML1SOAPClient.cpp \
saml2/core/impl/Assertions20Impl.cpp \
saml2/core/impl/Assertions20SchemaValidators.cpp \
saml2/core/impl/Protocols20Impl.cpp \
>\r
</File>\r
<File\r
+ RelativePath=".\saml1\binding\impl\SAML1SOAPClient.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\saml1\binding\impl\SAML1SOAPDecoder.cpp"\r
>\r
</File>\r
>\r
</File>\r
<File\r
+ RelativePath=".\saml1\binding\SAML1SOAPClient.h"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\saml1\binding\SAML1SOAPDecoder.h"\r
>\r
</File>\r
--- /dev/null
+/*
+ * 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/SAML1SOAPClient.h
+ *
+ * Specialized SOAPClient for SAML 1.x SOAP binding.
+ */
+
+#ifndef __saml1_soap11client_h__
+#define __saml1_soap11client_h__
+
+#include <saml/binding/SOAPClient.h>
+
+namespace opensaml {
+ namespace saml1p {
+
+ class SAML_API Request;
+ class SAML_API Response;
+ class SAML_API Status;
+
+ /**
+ * Specialized SOAPClient for SAML 1.x SOAP binding.
+ */
+ class SAML_API SAML1SOAPClient : opensaml::SOAPClient
+ {
+ public:
+ /**
+ * Creates a SOAP client instance with a particular SecurityPolicy.
+ *
+ * @param policy reference to SecurityPolicy to apply
+ */
+ SAML1SOAPClient(SecurityPolicy& policy) : opensaml::SOAPClient(policy), m_correlate(NULL) {}
+
+ virtual ~SAML1SOAPClient() {
+ XMLString::release(&m_correlate);
+ }
+
+ /**
+ * Specialized method for sending SAML 1.x requests. The SOAP layer will be
+ * constructed automatically.
+ *
+ * <p>The request will be freed by the client object if the method succeeds.
+ *
+ * @param request SAML request to send
+ * @param peer peer to send message to, expressed in metadata terms
+ * @param endpoint URL of endpoint to recieve message
+ */
+ virtual void sendSAML(Request* request, const saml2md::RoleDescriptor& peer, const char* endpoint);
+
+ /**
+ * Specialized method for receiving SAML 1.x responses. The SOAP layer will be
+ * evaluated automatically, and the attached policy will be applied to the Response.
+ *
+ * <p>The caller is responsible for freeing the Response.
+ *
+ * @return SAML 1.x Response, after SecurityPolicy has been applied
+ */
+ virtual Response* receiveSAML();
+
+ protected:
+ /**
+ * Handling of SAML errors.
+ *
+ * @param status SAML Status received by client
+ * @return true iff the error should be treated as a fatal error
+ */
+ virtual bool handleError(const Status& status);
+
+ private:
+ XMLCh* m_correlate;
+ };
+
+ };
+};
+
+#endif /* __saml1_soap11client_h__ */
--- /dev/null
+/*
+ * 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.
+ */
+
+/**
+ * SAML1SOAPClient.cpp
+ *
+ * Specialized SOAPClient for SAML 1.x SOAP binding.
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "saml1/binding/SAML1SOAPClient.h"
+#include "saml1/core/Protocols.h"
+#include "saml2/metadata/Metadata.h"
+
+#include <log4cpp/Category.hh>
+#include <xmltooling/soap/SOAP.h>
+
+using namespace opensaml::saml1p;
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace soap11;
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+
+void SAML1SOAPClient::sendSAML(Request* request, const RoleDescriptor& peer, const char* endpoint)
+{
+ Envelope* env = EnvelopeBuilder::buildEnvelope();
+ Body* body = BodyBuilder::buildBody();
+ env->setBody(body);
+ body->getXMLObjects().push_back(request);
+ try {
+ send(env, peer, endpoint);
+ m_correlate = XMLString::replicate(request->getRequestID());
+ delete env;
+ }
+ catch (XMLToolingException&) {
+ // A bit weird...we have to "revert" things so that the request is isolated
+ // so the caller can free it.
+ request->getParent()->detach();
+ request->detach();
+ throw;
+ }
+}
+
+Response* SAML1SOAPClient::receiveSAML()
+{
+ auto_ptr<Envelope> env(receive());
+ if (env.get()) {
+ Body* body = env->getBody();
+ if (body && body->hasChildren()) {
+ // Check for SAML Response.
+ Response* response = dynamic_cast<Response*>(body->getXMLObjects().front());
+ if (response) {
+
+ // Check InResponseTo.
+ if (m_correlate && !XMLString::equals(m_correlate, response->getInResponseTo()))
+ throw BindingException("InResponseTo attribute did not correlate with the Request ID.");
+
+ // Check Status.
+ Status* status = response->getStatus();
+ if (status) {
+ const QName* code = status->getStatusCode() ? status->getStatusCode()->getValue() : NULL;
+ if (code && *code != StatusCode::SUCCESS && handleError(*status))
+ throw BindingException("SAML Response contained an error.");
+ }
+
+ m_policy.evaluate(*response);
+ env.release();
+ body->detach(); // frees Envelope
+ response->detach(); // frees Body
+ return response;
+ }
+ }
+
+ throw BindingException("SOAP Envelope did not contain a SAML Response or a Fault.");
+ }
+ return NULL;
+}
+
+bool SAML1SOAPClient::handleError(const Status& status)
+{
+ const QName* code = status.getStatusCode() ? status.getStatusCode()->getValue() : NULL;
+ auto_ptr_char str((status.getStatusMessage() ? status.getStatusMessage()->getMessage() : NULL));
+ Category::getInstance(SAML_LOGCAT".SOAPClient").error(
+ "SOAP client detected a SAML error: (%s) (%s)",
+ (code ? code->toString().c_str() : "no code"),
+ (str.get() ? str.get() : "no message")
+ );
+ return true;
+}