X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-opensaml.git;a=blobdiff_plain;f=saml%2Fsaml2%2Fbinding%2Fimpl%2FSAML2SOAPClient.cpp;h=a78b8b209ca9b621f62a472f5b1c7886f8ca2f5f;hp=7ed6c1b76754485d5e63ff880869cfc0c4e3cddb;hb=1462057b3b9ae7e165d34d988e30b14c213672ca;hpb=dab12be1b1ebadf1dce9806529474694ac885c11 diff --git a/saml/saml2/binding/impl/SAML2SOAPClient.cpp b/saml/saml2/binding/impl/SAML2SOAPClient.cpp index 7ed6c1b..a78b8b2 100644 --- a/saml/saml2/binding/impl/SAML2SOAPClient.cpp +++ b/saml/saml2/binding/impl/SAML2SOAPClient.cpp @@ -1,17 +1,21 @@ -/* - * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * 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. */ /** @@ -22,28 +26,42 @@ #include "internal.h" #include "exceptions.h" +#include "binding/SecurityPolicy.h" +#include "binding/SOAPClient.h" #include "saml2/binding/SAML2SOAPClient.h" #include "saml2/core/Protocols.h" #include "saml2/metadata/Metadata.h" +#include "saml2/metadata/MetadataProvider.h" -#include +#include #include +using namespace opensaml::saml2; using namespace opensaml::saml2p; using namespace opensaml::saml2md; using namespace opensaml; using namespace soap11; +using namespace xmltooling::logging; using namespace xmltooling; -using namespace log4cpp; using namespace std; -void SAML2SOAPClient::sendSAML(RequestAbstractType* request, const RoleDescriptor& peer, const char* endpoint) +SAML2SOAPClient::SAML2SOAPClient(opensaml::SOAPClient& soaper, bool fatalSAMLErrors) + : m_soaper(soaper), m_fatal(fatalSAMLErrors), m_correlate(nullptr) +{ +} + +SAML2SOAPClient::~SAML2SOAPClient() +{ + XMLString::release(&m_correlate); +} + +void SAML2SOAPClient::sendSAML(RequestAbstractType* request, const char* from, MetadataCredentialCriteria& to, const char* endpoint) { auto_ptr env(EnvelopeBuilder::buildEnvelope()); Body* body = BodyBuilder::buildBody(); env->setBody(body); body->getUnknownXMLObjects().push_back(request); - m_soaper.send(*env.get(), peer, endpoint); + m_soaper.send(*env.get(), from, to, endpoint); m_correlate = XMLString::replicate(request->getID()); } @@ -56,20 +74,35 @@ StatusResponseType* SAML2SOAPClient::receiveSAML() // Check for SAML Response. StatusResponseType* response = dynamic_cast(body->getUnknownXMLObjects().front()); if (response) { - // Check InResponseTo. if (m_correlate && response->getInResponseTo() && !XMLString::equals(m_correlate, response->getInResponseTo())) - throw BindingException("InResponseTo attribute did not correlate with the Request ID."); - + throw SecurityPolicyException("InResponseTo attribute did not correlate with the Request ID."); + + SecurityPolicy& policy = m_soaper.getPolicy(); + policy.reset(true); + + // Extract Response details. + policy.setMessageID(response->getID()); + policy.setIssueInstant(response->getIssueInstantEpoch()); + + // Extract and re-verify Issuer if present. + const Issuer* issuer = response->getIssuer(); + if (issuer) + policy.setIssuer(issuer); // This will throw if it conflicts with the known peer identity. + + // Now run the policy. + policy.evaluate(*response); + // Check Status. Status* status = response->getStatus(); if (status) { - const XMLCh* code = status->getStatusCode() ? status->getStatusCode()->getValue() : NULL; - if (code && !XMLString::equals(code,StatusCode::SUCCESS) && handleError(*status)) - throw BindingException("SAML Response contained an error."); + const XMLCh* code = status->getStatusCode() ? status->getStatusCode()->getValue() : nullptr; + if (code && !XMLString::equals(code,StatusCode::SUCCESS) && handleError(*status)) { + BindingException ex("SAML response contained an error."); + annotateException(&ex, policy.getIssuerMetadata(), status); // throws it + } } - m_soaper.getPolicy().evaluate(*response); env.release(); body->detach(); // frees Envelope response->detach(); // frees Body @@ -77,19 +110,23 @@ StatusResponseType* SAML2SOAPClient::receiveSAML() } } - throw BindingException("SOAP Envelope did not contain a SAML Response or a Fault."); + BindingException ex("SOAP Envelope did not contain a SAML Response or a Fault."); + if (m_soaper.getPolicy().getIssuerMetadata()) + annotateException(&ex, m_soaper.getPolicy().getIssuerMetadata()); // throws it + else + ex.raise(); } - return NULL; + return nullptr; } -bool SAML2SOAPClient::handleError(const Status& status) +bool SAML2SOAPClient::handleError(const saml2p::Status& status) { - auto_ptr_char code((status.getStatusCode() ? status.getStatusCode()->getValue() : NULL)); - auto_ptr_char str((status.getStatusMessage() ? status.getStatusMessage()->getMessage() : NULL)); - Category::getInstance(SAML_LOGCAT".SOAPClient").error( + auto_ptr_char code((status.getStatusCode() ? status.getStatusCode()->getValue() : nullptr)); + auto_ptr_char str((status.getStatusMessage() ? status.getStatusMessage()->getMessage() : nullptr)); + Category::getInstance(SAML_LOGCAT ".SOAPClient").error( "SOAP client detected a SAML error: (%s) (%s)", (code.get() ? code.get() : "no code"), (str.get() ? str.get() : "no message") ); - return true; + return m_fatal; }