From 79a4c41067afcfa75eb82aa3c49ba3573640b0bd Mon Sep 17 00:00:00 2001 From: cantor Date: Tue, 10 Jul 2007 22:22:16 +0000 Subject: [PATCH] Annotate exceptions with status information. git-svn-id: https://svn.middleware.georgetown.edu/cpp-opensaml2/trunk@283 fb386ef7-a10c-0410-8ebf-fd3f8e989ab0 --- saml/SAMLConfig.cpp | 69 +++++++++++------------------ saml/exceptions.h | 24 ++++++++-- saml/saml1/binding/impl/SAML1SOAPClient.cpp | 32 +++++++++---- saml/saml2/binding/impl/SAML2SOAPClient.cpp | 26 +++++++---- 4 files changed, 85 insertions(+), 66 deletions(-) diff --git a/saml/SAMLConfig.cpp b/saml/SAMLConfig.cpp index 49869c2..88aa180 100644 --- a/saml/SAMLConfig.cpp +++ b/saml/SAMLConfig.cpp @@ -217,59 +217,24 @@ string SAMLInternalConfig::hashSHA1(const char* s, bool toHex) throw XMLSecurityException("Unable to generate SHA-1 hash."); } +using namespace saml2p; using namespace saml2md; -void opensaml::annotateException(XMLToolingException* e, const EntityDescriptor* entity, bool rethrow) +void opensaml::annotateException(XMLToolingException* e, const EntityDescriptor* entity, const Status* status, bool rethrow) { + const RoleDescriptor* role = NULL; if (entity) { - auto_ptr_char id(entity->getEntityID()); - e->addProperty("entityID",id.get()); const list& roles=entity->getOrderedChildren(); - for (list::const_iterator child=roles.begin(); child!=roles.end(); ++child) { - const RoleDescriptor* role=dynamic_cast(*child); - if (role && role->isValid()) { - const vector& contacts=role->getContactPersons(); - for (vector::const_iterator c=contacts.begin(); c!=contacts.end(); ++c) { - const XMLCh* ctype=(*c)->getContactType(); - if (ctype && (XMLString::equals(ctype,ContactPerson::CONTACT_SUPPORT) - || XMLString::equals(ctype,ContactPerson::CONTACT_TECHNICAL))) { - GivenName* fname=(*c)->getGivenName(); - SurName* lname=(*c)->getSurName(); - auto_ptr_char first(fname ? fname->getName() : NULL); - auto_ptr_char last(lname ? lname->getName() : NULL); - if (first.get() && last.get()) { - string contact=string(first.get()) + ' ' + last.get(); - e->addProperty("contactName",contact.c_str()); - } - else if (first.get()) - e->addProperty("contactName",first.get()); - else if (last.get()) - e->addProperty("contactName",last.get()); - const vector& emails=const_cast(*c)->getEmailAddresss(); - if (!emails.empty()) { - auto_ptr_char email(emails.front()->getAddress()); - if (email.get()) - e->addProperty("contactEmail",email.get()); - } - break; - } - } - if (e->getProperty("contactName") || e->getProperty("contactEmail")) { - auto_ptr_char eurl(role->getErrorURL()); - if (eurl.get()) { - e->addProperty("errorURL",eurl.get()); - } - } - break; - } + for (list::const_iterator child=roles.begin(); !role && child!=roles.end(); ++child) { + role=dynamic_cast(*child); + if (role && !role->isValid()) + role = NULL; } } - - if (rethrow) - e->raise(); + annotateException(e, role, status, rethrow); } -void opensaml::annotateException(XMLToolingException* e, const RoleDescriptor* role, bool rethrow) +void opensaml::annotateException(XMLToolingException* e, const RoleDescriptor* role, const Status* status, bool rethrow) { if (role) { auto_ptr_char id(dynamic_cast(role->getParent())->getEntityID()); @@ -308,6 +273,22 @@ void opensaml::annotateException(XMLToolingException* e, const RoleDescriptor* r } } + if (status) { + auto_ptr_char sc(status->getStatusCode() ? status->getStatusCode()->getValue() : NULL); + if (sc.get() && *sc.get()) + e->addProperty("statusCode", sc.get()); + if (status->getStatusCode()->getStatusCode()) { + auto_ptr_char sc2(status->getStatusCode()->getStatusCode()->getValue()); + if (sc2.get() && *sc.get()) + e->addProperty("statusCode2", sc2.get()); + } + if (status->getStatusMessage()) { + auto_ptr_char msg(status->getStatusMessage()->getMessage()); + if (msg.get() && *msg.get()) + e->addProperty("statusMessage", msg.get()); + } + } + if (rethrow) e->raise(); } diff --git a/saml/exceptions.h b/saml/exceptions.h index d66caf5..a691001 100644 --- a/saml/exceptions.h +++ b/saml/exceptions.h @@ -28,6 +28,9 @@ namespace opensaml { + namespace saml2p { + class SAML_API Status; + }; namespace saml2md { class SAML_API EntityDescriptor; class SAML_API RoleDescriptor; @@ -44,18 +47,25 @@ namespace opensaml { * rethrows the object. The following named properties are attached, when possible: * *
- *
providerId
The unique ID of the entity
+ *
entityID
The unique ID of the entity
*
errorURL
The error support URL of a random role
*
contactName
A formatted support or technical contact name
*
contactEmail
A contact email address
+ *
statusCode
Top-level status code from Status object
+ *
statusCode2
Second-level status code from Status object
+ *
statusMessage
StatusMessage from Status object
*
* * @param e pointer to exception object * @param entity pointer to entity + * @param status pointer to Status from message * @param rethrow true iff the exception should be rethrown */ void SAML_API annotateException( - xmltooling::XMLToolingException* e, const saml2md::EntityDescriptor* entity, bool rethrow=true + xmltooling::XMLToolingException* e, + const saml2md::EntityDescriptor* entity, + const saml2p::Status* status=NULL, + bool rethrow=true ); /** @@ -63,18 +73,24 @@ namespace opensaml { * rethrows the object. The following named properties are attached, when possible: * *
- *
providerId
The unique ID of the entity
+ *
entityID
The unique ID of the entity
*
errorURL
The error support URL of the role
*
contactName
A formatted support or technical contact name
*
contactEmail
A contact email address
+ *
statusCode
Top-level status code from Status object
+ *
statusCode2
Second-level status code from Status object
*
* * @param e pointer to exception object * @param entity pointer to role + * @param status pointer to Status from message * @param rethrow true iff the exception should be rethrown */ void SAML_API annotateException( - xmltooling::XMLToolingException* e, const saml2md::RoleDescriptor* role, bool rethrow=true + xmltooling::XMLToolingException* e, + const saml2md::RoleDescriptor* role, + const saml2p::Status* status=NULL, + bool rethrow=true ); }; diff --git a/saml/saml1/binding/impl/SAML1SOAPClient.cpp b/saml/saml1/binding/impl/SAML1SOAPClient.cpp index 30f0bf7..bcd76c1 100644 --- a/saml/saml1/binding/impl/SAML1SOAPClient.cpp +++ b/saml/saml1/binding/impl/SAML1SOAPClient.cpp @@ -59,21 +59,31 @@ Response* SAML1SOAPClient::receiveSAML() // 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."); + + m_soaper.getPolicy().evaluate(*response); + + if (!m_soaper.getPolicy().isSecure()) { + SecurityPolicyException ex("Security policy could not authenticate the message."); + if (m_soaper.getPolicy().getIssuerMetadata()) + annotateException(&ex, m_soaper.getPolicy().getIssuerMetadata()); // throws it + else + ex.raise(); + } // 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."); + if (code && *code != StatusCode::SUCCESS && handleError(*status)) { + BindingException ex("SAML Response contained an error."); + if (m_soaper.getPolicy().getIssuerMetadata()) + annotateException(&ex, m_soaper.getPolicy().getIssuerMetadata()); // throws it + else + ex.raise(); + } } - m_soaper.getPolicy().evaluate(*response); - - if (!m_soaper.getPolicy().isSecure()) - throw BindingException("Security policy could not authenticate the message."); - env.release(); body->detach(); // frees Envelope response->detach(); // frees Body @@ -81,7 +91,11 @@ Response* SAML1SOAPClient::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; } diff --git a/saml/saml2/binding/impl/SAML2SOAPClient.cpp b/saml/saml2/binding/impl/SAML2SOAPClient.cpp index f2a4d42..92f835a 100644 --- a/saml/saml2/binding/impl/SAML2SOAPClient.cpp +++ b/saml/saml2/binding/impl/SAML2SOAPClient.cpp @@ -59,20 +59,24 @@ StatusResponseType* SAML2SOAPClient::receiveSAML() // 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."); + + m_soaper.getPolicy().evaluate(*response); + if (!m_soaper.getPolicy().isSecure()) { + SecurityPolicyException ex("Security policy could not authenticate the message."); + annotateException(&ex, m_soaper.getPolicy().getIssuerMetadata(), response->getStatus()); // throws it + } + // 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."); + if (code && !XMLString::equals(code,StatusCode::SUCCESS) && handleError(*status)) { + BindingException ex("SAML response contained an error."); + annotateException(&ex, m_soaper.getPolicy().getIssuerMetadata(), status); // throws it + } } - m_soaper.getPolicy().evaluate(*response); - if (!m_soaper.getPolicy().isSecure()) - throw BindingException("Security policy could not authenticate the message."); - env.release(); body->detach(); // frees Envelope response->detach(); // frees Body @@ -80,7 +84,11 @@ 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; } -- 2.1.4