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<XMLObject*>& roles=entity->getOrderedChildren();
- for (list<XMLObject*>::const_iterator child=roles.begin(); child!=roles.end(); ++child) {
- const RoleDescriptor* role=dynamic_cast<RoleDescriptor*>(*child);
- if (role && role->isValid()) {
- const vector<ContactPerson*>& contacts=role->getContactPersons();
- for (vector<ContactPerson*>::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<EmailAddress*>& emails=const_cast<const ContactPerson*>(*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<XMLObject*>::const_iterator child=roles.begin(); !role && child!=roles.end(); ++child) {
+ role=dynamic_cast<RoleDescriptor*>(*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<EntityDescriptor*>(role->getParent())->getEntityID());
}
}
+ 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();
}
namespace opensaml {
+ namespace saml2p {
+ class SAML_API Status;
+ };
namespace saml2md {
class SAML_API EntityDescriptor;
class SAML_API RoleDescriptor;
* rethrows the object. The following named properties are attached, when possible:
*
* <dl>
- * <dt>providerId</dt> <dd>The unique ID of the entity</dd>
+ * <dt>entityID</dt> <dd>The unique ID of the entity</dd>
* <dt>errorURL</dt> <dd>The error support URL of a random role</dd>
* <dt>contactName</dt> <dd>A formatted support or technical contact name</dd>
* <dt>contactEmail</dt> <dd>A contact email address</dd>
+ * <dt>statusCode</dt> <dd>Top-level status code from Status object</dd>
+ * <dt>statusCode2</dt> <dd>Second-level status code from Status object</dd>
+ * <dt>statusMessage</dt> <dd>StatusMessage from Status object</dd>
* </dl>
*
* @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
);
/**
* rethrows the object. The following named properties are attached, when possible:
*
* <dl>
- * <dt>providerId</dt> <dd>The unique ID of the entity</dd>
+ * <dt>entityID</dt> <dd>The unique ID of the entity</dd>
* <dt>errorURL</dt> <dd>The error support URL of the role</dd>
* <dt>contactName</dt> <dd>A formatted support or technical contact name</dd>
* <dt>contactEmail</dt> <dd>A contact email address</dd>
+ * <dt>statusCode</dt> <dd>Top-level status code from Status object</dd>
+ * <dt>statusCode2</dt> <dd>Second-level status code from Status object</dd>
* </dl>
*
* @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
);
};
// 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
}
}
- 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;
}
// 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
}
}
- 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;
}