/*
- * Copyright 2001-2009 Internet2
+ * Copyright 2001-2010 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include "internal.h"
+#include "exceptions.h"
#include "Application.h"
#include "ServiceProvider.h"
+#include "attribute/Attribute.h"
#include "attribute/AttributeDecoder.h"
#include "attribute/filtering/AttributeFilter.h"
#include "attribute/filtering/BasicFilteringContext.h"
#include "attribute/resolver/AttributeExtractor.h"
+#include "remoting/ddf.h"
#include "security/SecurityPolicy.h"
#include "util/SPConstants.h"
#include <saml/SAMLConfig.h>
#include <saml/saml1/core/Assertions.h>
#include <saml/saml2/core/Assertions.h>
+#include <saml/saml2/metadata/Metadata.h>
#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
#include <saml/saml2/metadata/ObservableMetadataProvider.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/security/TrustEngine.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/ReloadableXMLFile.h>
+#include <xmltooling/util/Threads.h>
#include <xmltooling/util/XMLHelper.h>
#include <xercesc/util/XMLUniDefs.hpp>
) const;
void extractAttributes(
const Application& application,
+ const char* assertingParty,
+ const char* relyingParty,
+ const saml1::AttributeStatement& statement,
+ vector<Attribute*>& attributes
+ ) const;
+ void extractAttributes(
+ const Application& application,
+ const char* assertingParty,
+ const char* relyingParty,
+ const saml2::AttributeStatement& statement,
+ vector<Attribute*>& attributes
+ ) const;
+ void extractAttributes(
+ const Application& application,
const ObservableMetadataProvider* observable,
const XMLCh* entityID,
const char* relyingParty,
{
public:
XMLExtractor(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.XML")), m_impl(NULL) {
- load();
+ background_load();
}
~XMLExtractor() {
delete m_impl;
}
protected:
- pair<bool,DOMElement*> load();
+ pair<bool,DOMElement*> background_load();
private:
XMLExtractorImpl* m_impl;
m_metadata(NULL),
m_trust(NULL),
m_filter(NULL),
- m_entityAssertions(false),
+ m_entityAssertions(true),
m_attrLock(NULL)
{
#ifdef _DEBUG
auto_ptr<MetadataProvider> mp(SAMLConfig::getConfig().MetadataProviderManager.newPlugin(type.get(), child));
mp->init();
m_metadata = mp.release();
- m_entityAssertions = true;
}
catch (exception& ex) {
- m_log.crit(
- "disabling support for Assertions in EntityAttributes extension, error building/initializing MetadataProvider: %s",
- ex.what()
- );
+ m_entityAssertions = false;
+ m_log.crit("error building/initializing dedicated MetadataProvider: %s", ex.what());
+ m_log.crit("disabling support for Assertions in EntityAttributes extension");
}
}
- else {
- m_log.info("no dedicated MetadataProvider supplied, disabling support for Assertions in EntityAttributes extension");
- }
if (m_entityAssertions) {
child = XMLHelper::getFirstChildElement(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _TrustEngine);
m_trust = XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(type.get(), child);
}
catch (exception& ex) {
- m_log.crit(
- "disabling support for Assertions in EntityAttributes extension, error building TrustEngine: %s", ex.what()
- );
m_entityAssertions = false;
+ m_log.crit("error building/initializing dedicated TrustEngine: %s", ex.what());
+ m_log.crit("disabling support for Assertions in EntityAttributes extension");
}
}
}
m_filter = SPConfig::getConfig().AttributeFilterManager.newPlugin(type.get(), child);
}
catch (exception& ex) {
- m_log.crit(
- "disabling support for Assertions in EntityAttributes extension, error building AttributeFilter: %s", ex.what()
- );
m_entityAssertions = false;
+ m_log.crit("error building/initializing dedicated AttributeFilter: %s", ex.what());
+ m_log.crit("disabling support for Assertions in EntityAttributes extension");
}
}
}
void XMLExtractorImpl::extractAttributes(
const Application& application,
+ const char* assertingParty,
+ const char* relyingParty,
+ const saml1::AttributeStatement& statement,
+ vector<Attribute*>& attributes
+ ) const
+{
+ const vector<saml1::Attribute*>& attrs = statement.getAttributes();
+ for (vector<saml1::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)
+ extractAttributes(application, assertingParty, relyingParty, *(*a), attributes);
+}
+
+void XMLExtractorImpl::extractAttributes(
+ const Application& application,
+ const char* assertingParty,
+ const char* relyingParty,
+ const saml2::AttributeStatement& statement,
+ vector<Attribute*>& attributes
+ ) const
+{
+ const vector<saml2::Attribute*>& attrs = statement.getAttributes();
+ for (vector<saml2::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)
+ extractAttributes(application, assertingParty, relyingParty, *(*a), attributes);
+}
+
+void XMLExtractorImpl::extractAttributes(
+ const Application& application,
const ObservableMetadataProvider* observable,
const XMLCh* entityID,
const char* relyingParty,
// Set up and evaluate a policy for an AA asserting attributes to us.
shibsp::SecurityPolicy policy(application, &AttributeAuthorityDescriptor::ELEMENT_QNAME, false, m_policyId.get());
Locker locker(m_metadata);
- policy.setMetadataProvider(m_metadata);
+ if (m_metadata)
+ policy.setMetadataProvider(m_metadata);
if (m_trust)
policy.setTrustEngine(m_trust);
// Populate recipient as audience.
}
}
- // Authenticate the assertion. We have to marshall them to establish the signature for verification.
- (*assert)->marshall();
- policy.evaluate(*(*assert));
+ // Authenticate the assertion. We have to clone and marshall it to establish the signature for verification.
+ auto_ptr<saml2::Assertion> tokencopy((*assert)->cloneAssertion());
+ tokencopy->marshall();
+ policy.evaluate(*tokencopy);
if (!policy.isAuthenticated()) {
if (m_log.isDebugEnabled()) {
- auto_ptr_char tempid((*assert)->getID());
+ auto_ptr_char tempid(tokencopy->getID());
auto_ptr_char eid(entityID);
m_log.debug(
"failed to authenticate assertion (%s) in metadata extension for entity (%s)", tempid.get(), eid.get()
);
}
- (*assert)->releaseThisAndChildrenDOM();
- (*assert)->setDocument(NULL);
continue;
}
auto_ptr_char inlineAssertingParty(inlineEntity ? inlineEntity->getEntityID() : NULL);
relyingParty = application.getRelyingParty(inlineEntity)->getString("entityID").second;
const vector<saml2::Attribute*>& attrs2 =
- const_cast<const saml2::AttributeStatement*>((*assert)->getAttributeStatements().front())->getAttributes();
+ const_cast<const saml2::AttributeStatement*>(tokencopy->getAttributeStatements().front())->getAttributes();
for (vector<saml2::Attribute*>::const_iterator a = attrs2.begin(); a!=attrs2.end(); ++a)
extractAttributes(application, inlineAssertingParty.get(), relyingParty, *(*a), holding2);
- (*assert)->releaseThisAndChildrenDOM();
- (*assert)->setDocument(NULL);
// Now we locally filter the attributes so that the actual issuer can be properly set.
// If we relied on outside filtering, the attributes couldn't be distinguished from the
ex.what()
);
}
- (*assert)->releaseThisAndChildrenDOM();
- (*assert)->setDocument(NULL);
for_each(holding2.begin(), holding2.end(), xmltooling::cleanup<Attribute>());
continue;
}
// Unknown exceptions are fatal.
if (useCache)
m_attrLock->unlock();
- (*assert)->releaseThisAndChildrenDOM();
- (*assert)->setDocument(NULL);
for_each(holding.begin(), holding.end(), xmltooling::cleanup<Attribute>());
for_each(holding2.begin(), holding2.end(), xmltooling::cleanup<Attribute>());
throw;
const EntityDescriptor* entity = issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent()) : NULL;
const char* relyingParty = application.getRelyingParty(entity)->getString("entityID").second;
+ // Check for statements.
+ if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), saml1::AttributeStatement::LOCAL_NAME)) {
+ const saml2::AttributeStatement* statement2 = dynamic_cast<const saml2::AttributeStatement*>(&xmlObject);
+ if (statement2) {
+ auto_ptr_char assertingParty(entity ? entity->getEntityID() : NULL);
+ m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *statement2, attributes);
+ // Handle EncryptedAttributes inline so we have access to the role descriptor.
+ const vector<saml2::EncryptedAttribute*>& encattrs = statement2->getEncryptedAttributes();
+ for (vector<saml2::EncryptedAttribute*>::const_iterator ea = encattrs.begin(); ea!=encattrs.end(); ++ea)
+ extractAttributes(application, issuer, *(*ea), attributes);
+ return;
+ }
+
+ const saml1::AttributeStatement* statement1 = dynamic_cast<const saml1::AttributeStatement*>(&xmlObject);
+ if (statement1) {
+ auto_ptr_char assertingParty(entity ? entity->getEntityID() : NULL);
+ m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *statement1, attributes);
+ return;
+ }
+
+ throw AttributeExtractionException("Unable to extract attributes, unknown object type.");
+ }
+
// Check for assertions.
if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), saml1::Assertion::LOCAL_NAME)) {
const saml2::Assertion* token2 = dynamic_cast<const saml2::Assertion*>(&xmlObject);
auto_ptr_char assertingParty(entity ? entity->getEntityID() : NULL);
const vector<saml2::AttributeStatement*>& statements = token2->getAttributeStatements();
for (vector<saml2::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {
- const vector<saml2::Attribute*>& attrs = const_cast<const saml2::AttributeStatement*>(*s)->getAttributes();
- for (vector<saml2::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)
- m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *(*a), attributes);
-
+ m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *(*s), attributes);
+ // Handle EncryptedAttributes inline so we have access to the role descriptor.
const vector<saml2::EncryptedAttribute*>& encattrs = const_cast<const saml2::AttributeStatement*>(*s)->getEncryptedAttributes();
for (vector<saml2::EncryptedAttribute*>::const_iterator ea = encattrs.begin(); ea!=encattrs.end(); ++ea)
extractAttributes(application, issuer, *(*ea), attributes);
if (token1) {
auto_ptr_char assertingParty(entity ? entity->getEntityID() : NULL);
const vector<saml1::AttributeStatement*>& statements = token1->getAttributeStatements();
- for (vector<saml1::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {
- const vector<saml1::Attribute*>& attrs = const_cast<const saml1::AttributeStatement*>(*s)->getAttributes();
- for (vector<saml1::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)
- m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *(*a), attributes);
- }
+ for (vector<saml1::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s)
+ m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *(*s), attributes);
return;
}
throw AttributeExtractionException("Unable to extract attributes, unknown object type.");
}
-pair<bool,DOMElement*> XMLExtractor::load()
+pair<bool,DOMElement*> XMLExtractor::background_load()
{
// Load from source using base class.
pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
// If we held the document, transfer it to the impl. If we didn't, it's a no-op.
impl->setDocument(docjanitor.release());
+ // Perform the swap inside a lock.
+ if (m_lock)
+ m_lock->wrlock();
+ SharedLock locker(m_lock, false);
delete m_impl;
m_impl = impl;