/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* Returns a reference to a MetadataProvider::Criteria instance suitable for use with the
* installed MetadataProvider.
*
+ * <p>The object will be cleared/reset when returned, so do not mutate it and then
+ * call the method again before using it.
+ *
* @return reference to a MetadataProvider::Criteria instance
*/
virtual saml2md::MetadataProvider::Criteria& getMetadataProviderCriteria() const;
}
/**
+ * Sets a MetadataProvider::Criteria instance suitable for use with the
+ * installed MetadataProvider.
+ *
+ * <p>The policy will take ownership of the criteria object when this
+ * method completes.
+ *
+ * @param criteria a MetadataProvider::Criteria instance, or NULL
+ */
+ void setMetadataProviderCriteria(saml2md::MetadataProvider::Criteria* criteria);
+
+ /**
* Sets a peer role element/type for to the policy.
*
* @param role the peer role element/type or NULL
*
* @param messageOnly true iff security and issuer state should be left in place
*/
- void reset(bool messageOnly=false);
+ virtual void reset(bool messageOnly=false);
+
+ /**
+ * Resets the policy object and/or clears any per-message state for only this specific class.
+ *
+ * <p>Resets can be complete (the default) or merely clear the previous message ID and timestamp
+ * when evaluating multiple layers of a message.
+ *
+ * @param messageOnly true iff security and issuer state should be left in place
+ */
+ void _reset(bool messageOnly=false);
/**
* Returns the message identifier as determined by the registered policies.
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* <p>An exception will be raised if the message is invalid according to
* a policy rule.
+ *
+ * <p>The return value is used to indicate whether a message was ignored or
+ * successfully processed. A false value signals that the rule wasn't successful
+ * but was also not unsuccessful, because the rule was inapplicable to the message.
*
* @param message the incoming message
* @param request the protocol request
* @param policy SecurityPolicy to provide various components and track message data
+ * @return indicator as to whether a message was understood and processed
*/
- virtual void evaluate(
+ virtual bool evaluate(
const xmltooling::XMLObject& message,
const xmltooling::GenericRequest* request,
SecurityPolicy& policy
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
const char* getType() const {
return CLIENTCERTAUTH_POLICY_RULE;
}
- void evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const;
+ bool evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const;
private:
bool m_errorFatal;
}
}
-void ClientCertAuthRule::evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const
+bool ClientCertAuthRule::evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const
{
Category& log=Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.ClientCertAuth");
if (!request)
- return;
+ return false;
if (!policy.getIssuerMetadata()) {
log.debug("ignoring message, no issuer metadata supplied");
- return;
+ return false;
}
const X509TrustEngine* x509trust;
if (!(x509trust=dynamic_cast<const X509TrustEngine*>(policy.getTrustEngine()))) {
log.debug("ignoring message, no X509TrustEngine supplied");
- return;
+ return false;
}
const std::vector<XSECCryptoX509*>& chain = request->getClientCertificates();
if (chain.empty())
- return;
+ return false;
// Set up criteria object, including peer name to enforce cert name checking.
MetadataCredentialCriteria cc(*(policy.getIssuerMetadata()));
if (m_errorFatal)
throw SecurityPolicyException("Client certificate supplied, but could not be verified.");
log.error("unable to verify certificate chain with supplied trust engine");
- return;
+ return false;
}
log.debug("client certificate verified against message issuer");
policy.setAuthenticated(true);
+ return true;
}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
const char* getType() const {
return MESSAGEFLOW_POLICY_RULE;
}
- void evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const;
+ bool evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const;
private:
bool m_checkReplay;
}
}
-void MessageFlowRule::evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const
+bool MessageFlowRule::evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const
{
Category& log=Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.MessageFlow");
log.debug("evaluating message flow policy (replay checking %s, expiration %lu)", m_checkReplay ? "on" : "off", m_expires);
if (m_checkReplay) {
const XMLCh* id = policy.getMessageID();
if (!id || !*id)
- return;
+ return false;
ReplayCache* replayCache = XMLToolingConfig::getConfig().getReplayCache();
if (!replayCache) {
log.warn("no ReplayCache available, skipping requested replay check");
- return;
+ return false;
}
auto_ptr_char temp(id);
log.error("replay detected of message ID (%s)", temp.get());
throw SecurityPolicyException("Rejecting replayed message ID ($1).", params(1,temp.get()));
}
+ return true;
}
+ return false;
}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
const char* getType() const {
return NULLSECURITY_POLICY_RULE;
}
- void evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const {
+ bool evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const {
m_log.warn("security enforced using NULL policy rule, be sure you know what you're doing");
policy.setAuthenticated(true);
+ return true;
}
private:
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
SecurityPolicy::~SecurityPolicy()
{
- reset(false);
+ XMLString::release(&m_messageID);
+ delete m_metadataCriteria;
+ delete m_issuer;
}
void SecurityPolicy::reset(bool messageOnly)
{
+ _reset();
+}
+
+void SecurityPolicy::_reset(bool messageOnly)
+{
XMLString::release(&m_messageID);
m_messageID=NULL;
m_issueInstant=0;
- delete m_metadataCriteria;
- m_metadataCriteria=NULL;
if (!messageOnly) {
delete m_issuer;
m_issuer=NULL;
{
if (!m_metadataCriteria)
m_metadataCriteria=new MetadataProvider::Criteria();
+ else
+ m_metadataCriteria->reset();
return *m_metadataCriteria;
}
+void SecurityPolicy::setMetadataProviderCriteria(saml2md::MetadataProvider::Criteria* criteria)
+{
+ if (m_metadataCriteria)
+ delete m_metadataCriteria;
+ m_metadataCriteria=criteria;
+}
+
void SecurityPolicy::evaluate(const XMLObject& message, const GenericRequest* request)
{
for (vector<const SecurityPolicyRule*>::const_iterator i=m_rules.begin(); i!=m_rules.end(); ++i)
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
const char* getType() const {
return SIMPLESIGNING_POLICY_RULE;
}
- void evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const;
+ bool evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const;
private:
// Appends a raw parameter=value pair to the string.
}
}
-void SimpleSigningRule::evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const
+bool SimpleSigningRule::evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const
{
Category& log=Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.SimpleSigning");
if (!policy.getIssuerMetadata()) {
log.debug("ignoring message, no issuer metadata supplied");
- return;
+ return false;
}
const SignatureTrustEngine* sigtrust;
if (!(sigtrust=dynamic_cast<const SignatureTrustEngine*>(policy.getTrustEngine()))) {
log.debug("ignoring message, no SignatureTrustEngine supplied");
- return;
+ return false;
}
const HTTPRequest* httpRequest = dynamic_cast<const HTTPRequest*>(request);
if (!request || !httpRequest)
- return;
+ return false;
const char* signature = request->getParameter("Signature");
if (!signature)
- return;
+ return false;
const char* sigAlgorithm = request->getParameter("SigAlg");
if (!sigAlgorithm) {
log.error("SigAlg parameter not found, no way to verify the signature");
- return;
+ return false;
}
string input;
XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(pch),&x);
if (!decoded) {
log.warn("unable to decode base64 in POST binding message");
- return;
+ return false;
}
input = string("SAMLRequest=") + reinterpret_cast<const char*>(decoded);
#ifdef OPENSAML_XERCESC_HAS_XMLBYTE_RELEASE
XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(pch),&x);
if (!decoded) {
log.warn("unable to decode base64 in POST binding message");
- return;
+ return false;
}
input = string("SAMLResponse=") + reinterpret_cast<const char*>(decoded);
#ifdef OPENSAML_XERCESC_HAS_XMLBYTE_RELEASE
log.error("unable to verify message signature with supplied trust engine");
if (m_errorFatal)
throw SecurityPolicyException("Message was signed, but signature could not be verified.");
- return;
+ return false;
}
log.debug("signature verified against message issuer");
policy.setAuthenticated(true);
+ return true;
}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
const char* getType() const {
return XMLSIGNING_POLICY_RULE;
}
- void evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const;
+ bool evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const;
private:
bool m_errorFatal;
}
}
-void XMLSigningRule::evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const
+bool XMLSigningRule::evaluate(const XMLObject& message, const GenericRequest* request, SecurityPolicy& policy) const
{
Category& log=Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.XMLSigning");
if (!policy.getIssuerMetadata()) {
log.debug("ignoring message, no issuer metadata supplied");
- return;
+ return false;
}
const SignatureTrustEngine* sigtrust;
if (!(sigtrust=dynamic_cast<const SignatureTrustEngine*>(policy.getTrustEngine()))) {
log.debug("ignoring message, no SignatureTrustEngine supplied");
- return;
+ return false;
}
const SignableObject* signable = dynamic_cast<const SignableObject*>(&message);
if (!signable || !signable->getSignature())
- return;
+ return false;
log.debug("validating signature profile");
try {
log.error("signature profile failed to validate: %s", ve.what());
if (m_errorFatal)
throw;
- return;
+ return false;
}
// Set up criteria object.
log.error("unable to verify message signature with supplied trust engine");
if (m_errorFatal)
throw SecurityPolicyException("Message was signed, but signature could not be verified.");
- return;
+ return false;
}
log.debug("signature verified against message issuer");
policy.setAuthenticated(true);
+ return true;
}
/*
* 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
/**
* @file saml/saml2/metadata/MetadataProvider.h
- *
+ *
* Supplies an individual source of metadata.
*/
#include <xmltooling/security/CredentialResolver.h>
namespace opensaml {
-
+
class SAML_API SAMLArtifact;
namespace saml2md {
/**
* Supplies an individual source of metadata.
- *
+ *
* The source can be a local file, remote service, or the result of a
* dynamic lookup, can include local caching, etc. Providers
* <strong>MUST</strong> be locked before any lookup operations.
protected:
/**
* Constructor.
- *
+ *
* If a DOM is supplied, a set of default logic will be used to identify
* and build MetadataFilter plugins and install them into the provider.
- *
+ *
* The following XML content is supported:
- *
+ *
* <ul>
* <li><MetadataFilter> elements with a type attribute and type-specific content
* <li><Exclude> elements representing a BlacklistMetadataFilter
- * <li><BlacklistMetadataFilter> element containing <Exclude> elements
+ * <li><BlacklistMetadataFilter> element containing <Exclude> elements
* <li><Include> elements representing a WhitelistMetadataFilter
- * <li><SignatureMetadataFilter> element containing a <KeyResolver> element
- * <li><WhitelistMetadataFilter> element containing <Include> elements
+ * <li><SignatureMetadataFilter> element containing a <KeyResolver> element
+ * <li><WhitelistMetadataFilter> element containing <Include> elements
* </ul>
- *
+ *
* XML namespaces are ignored in the processing of these elements.
- *
+ *
* @param e DOM to supply configuration for provider
*/
MetadataProvider(const xercesc::DOMElement* e=NULL);
-
+
public:
/**
* Destructor will delete any installed filters.
*/
virtual ~MetadataProvider();
-
+
/**
* Adds a metadata filter to apply to any resolved metadata. Will not be applied
* to metadata that is already loaded.
- *
+ *
* @param newFilter metadata filter to add
*/
virtual void addMetadataFilter(MetadataFilter* newFilter) {
/**
* Removes a metadata filter. The caller must delete the filter if necessary.
- *
+ *
* @param oldFilter metadata filter to remove
* @return the old filter
*/
}
return NULL;
}
-
+
/**
* Should be called after instantiating provider and adding filters, but before
* performing any lookup operations. Allows the provider to defer initialization
* this method so as to report/log any errors that would affect later processing.
*/
virtual void init()=0;
-
+
/**
* Gets the entire metadata tree, after the registered filter has been applied.
* The caller MUST unlock the provider when finished with the data.
- *
+ *
* @return the entire metadata tree
*/
virtual const xmltooling::XMLObject* getMetadata() const=0;
-
+
/**
* Gets the metadata for a given group of entities. If a valid group is returned,
* the resolver will be left in a locked state. The caller MUST unlock the
* resolver when finished with the group.
- *
+ *
* @param name the name of the group
* @param requireValidMetadata indicates whether the metadata for the group must be valid/current
- *
+ *
* @return the group's metadata or NULL if there is no metadata or no valid metadata
*/
virtual const EntitiesDescriptor* getEntitiesDescriptor(const XMLCh* name, bool requireValidMetadata=true) const;
* Gets the metadata for a given group of entities. If a valid group is returned,
* the resolver will be left in a locked state. The caller MUST unlock the
* resolver when finished with the group.
- *
+ *
* @param name the name of the group
* @param requireValidMetadata indicates whether the metadata for the group must be valid/current
- *
+ *
* @return the group's metadata or NULL if there is no metadata or no valid metadata
*/
virtual const EntitiesDescriptor* getEntitiesDescriptor(const char* name, bool requireValidMetadata=true) const=0;
*/
Criteria() : entityID_unicode(NULL), entityID_ascii(NULL), artifact(NULL), role(NULL), protocol(NULL), protocol2(NULL), validOnly(true) {
}
-
+
/**
* Constructor.
- *
+ *
* @param id entityID to lookup
* @param q element/type of role, if any
* @param prot protocol support constant, if any
Criteria(const XMLCh* id, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true)
: entityID_unicode(id), entityID_ascii(NULL), artifact(NULL), role(q), protocol(prot), protocol2(NULL), validOnly(valid) {
}
-
+
/**
* Constructor.
- *
+ *
* @param id entityID to lookup
* @param q element/type of role, if any
* @param prot protocol support constant, if any
/**
* Constructor.
- *
+ *
* @param a artifact to lookup
* @param q element/type of role, if any
* @param prot protocol support constant, if any
Criteria(const SAMLArtifact* a, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true)
: entityID_unicode(NULL), entityID_ascii(NULL), artifact(a), role(q), protocol(prot), protocol2(NULL), validOnly(valid) {
}
-
+
virtual ~Criteria() {}
-
+
+ /**
+ * Restores the object to its default state.
+ */
+ virtual void reset() {
+ entityID_unicode=NULL;
+ entityID_ascii=NULL;
+ artifact=NULL;
+ role=NULL;
+ protocol=NULL;
+ protocol2=NULL;
+ validOnly=true;
+ }
+
/** Unique ID of entity. */
const XMLCh* entityID_unicode;
/** Unique ID of entity. */
/** Controls whether stale metadata is ignored. */
bool validOnly;
};
-
+
/**
* Gets entity metadata based on supplied criteria. If a valid entity is returned,
* the provider will be left in a locked state. The caller MUST unlock the
* provider when finished with the entity.
- *
+ *
* @param criteria lookup criteria
- *
+ *
* @return the entity's metadata (and optionally a role) or NULL if there is no qualifying metadata
*/
virtual std::pair<const EntityDescriptor*,const RoleDescriptor*> getEntityDescriptor(const Criteria& criteria) const=0;
protected:
/**
* Applies any installed filters to a metadata instance.
- *
+ *
* @param xmlObject the metadata to be filtered
*/
void doFilters(xmltooling::XMLObject& xmlObject) const;
* Registers MetadataProvider classes into the runtime.
*/
void SAML_API registerMetadataProviders();
-
+
/** MetadataProvider based on local or remote XML file */
#define XML_METADATA_PROVIDER "XML"