-/*
- * Copyright 2001-2010 Internet2
+/**
+ * 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.
*
- * 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
+ * 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
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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.
+ * 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.
*/
/**
#include "ServiceProvider.h"
#include "metadata/MetadataProviderCriteria.h"
+#include <boost/algorithm/string.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
+#include <xercesc/util/regx/RegularExpression.hpp>
#include <xsec/framework/XSECDefs.hpp>
+
#include <saml/version.h>
#include <saml/binding/SAMLArtifact.h>
#include <saml/saml2/metadata/Metadata.h>
#include <saml/saml2/metadata/DynamicMetadataProvider.h>
+
#include <xmltooling/logging.h>
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/security/Credential.h>
using namespace std;
namespace shibsp {
- class SAML_DLLLOCAL DummyCredentialResolver : public CredentialResolver
- {
- public:
- DummyCredentialResolver() {}
- ~DummyCredentialResolver() {}
-
- Lockable* lock() {return this;}
- void unlock() {}
-
- const Credential* resolve(const CredentialCriteria* criteria=nullptr) const {return nullptr;}
- vector<const Credential*>::size_type resolve(
- vector<const Credential*>& results, const CredentialCriteria* criteria=nullptr
- ) const {return 0;}
- };
-
class SHIBSP_DLLLOCAL DynamicMetadataProvider : public saml2md::DynamicMetadataProvider
{
public:
DynamicMetadataProvider(const xercesc::DOMElement* e=nullptr);
- virtual ~DynamicMetadataProvider() {
- delete m_trust;
- }
+ virtual ~DynamicMetadataProvider() {}
protected:
saml2md::EntityDescriptor* resolve(const saml2md::MetadataProvider::Criteria& criteria) const;
private:
bool m_verifyHost,m_ignoreTransport,m_encoded;
string m_subst, m_match, m_regex;
- X509TrustEngine* m_trust;
+ boost::scoped_ptr<X509TrustEngine> m_trust;
+ boost::scoped_ptr<CredentialResolver> m_dummyCR;
};
-
saml2md::MetadataProvider* SHIBSP_DLLLOCAL DynamicMetadataProviderFactory(const DOMElement* const & e)
{
return new DynamicMetadataProvider(e);
static const XMLCh Regex[] = UNICODE_LITERAL_5(R,e,g,e,x);
static const XMLCh Subst[] = UNICODE_LITERAL_5(S,u,b,s,t);
static const XMLCh _TrustEngine[] = UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);
- static const XMLCh type[] = UNICODE_LITERAL_4(t,y,p,e);
+ static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
static const XMLCh verifyHost[] = UNICODE_LITERAL_10(v,e,r,i,f,y,H,o,s,t);
};
DynamicMetadataProvider::DynamicMetadataProvider(const DOMElement* e)
- : saml2md::DynamicMetadataProvider(e), m_verifyHost(true), m_ignoreTransport(false), m_encoded(true), m_trust(nullptr)
+ : saml2md::DynamicMetadataProvider(e),
+ m_verifyHost(XMLHelper::getAttrBool(e, true, verifyHost)),
+ m_ignoreTransport(XMLHelper::getAttrBool(e, false, ignoreTransport)),
+ m_encoded(true), m_trust(nullptr)
{
- const XMLCh* flag = e ? e->getAttributeNS(nullptr, verifyHost) : nullptr;
- if (flag && (*flag == chLatin_f || *flag == chDigit_0))
- m_verifyHost = false;
- flag = e ? e->getAttributeNS(nullptr, ignoreTransport) : nullptr;
- if (flag && (*flag == chLatin_t || *flag == chDigit_1)) {
- m_ignoreTransport = true;
- return;
- }
-
- const DOMElement* child = e ? XMLHelper::getFirstChildElement(e, Subst) : nullptr;
+ const DOMElement* child = XMLHelper::getFirstChildElement(e, Subst);
if (child && child->hasChildNodes()) {
auto_ptr_char s(child->getFirstChild()->getNodeValue());
if (s.get() && *s.get()) {
m_subst = s.get();
- flag = child->getAttributeNS(nullptr, encoded);
- if (flag && (*flag == chLatin_f || *flag == chDigit_0))
- m_encoded = false;
+ m_encoded = XMLHelper::getAttrBool(child, true, encoded);
}
}
if (m_subst.empty()) {
- child = e ? XMLHelper::getFirstChildElement(e, Regex) : nullptr;
+ child = XMLHelper::getFirstChildElement(e, Regex);
if (child && child->hasChildNodes() && child->hasAttributeNS(nullptr, match)) {
- auto_ptr_char m(child->getAttributeNS(nullptr, match));
+ m_match = XMLHelper::getAttrString(child, nullptr, match);
auto_ptr_char repl(child->getFirstChild()->getNodeValue());
- if (m.get() && *m.get() && repl.get() && *repl.get()) {
- m_match = m.get();
+ if (repl.get() && *repl.get())
m_regex = repl.get();
- }
}
}
- child = e ? XMLHelper::getFirstChildElement(e, _TrustEngine) : nullptr;
- auto_ptr_char t2(child ? child->getAttributeNS(nullptr,type) : nullptr);
- if (t2.get()) {
- TrustEngine* trust = XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t2.get(), child);
- if (!(m_trust = dynamic_cast<X509TrustEngine*>(trust))) {
- delete trust;
- throw ConfigurationException("DynamicMetadataProvider requires an X509TrustEngine plugin.");
+ if (!m_ignoreTransport) {
+ child = XMLHelper::getFirstChildElement(e, _TrustEngine);
+ string t = XMLHelper::getAttrString(child, nullptr, _type);
+ if (!t.empty()) {
+ TrustEngine* trust = XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), child);
+ if (!dynamic_cast<X509TrustEngine*>(trust)) {
+ delete trust;
+ throw ConfigurationException("DynamicMetadataProvider requires an X509TrustEngine plugin.");
+ }
+ m_trust.reset(dynamic_cast<X509TrustEngine*>(trust));
+ m_dummyCR.reset(XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(DUMMY_CREDENTIAL_RESOLVER, nullptr));
}
- return;
- }
- throw ConfigurationException("DynamicMetadataProvider requires an X509TrustEngine plugin unless ignoreTransport is true.");
+ if (!m_trust.get() || !m_dummyCR.get())
+ throw ConfigurationException("DynamicMetadataProvider requires an X509TrustEngine plugin unless ignoreTransport is true.");
+ }
}
saml2md::EntityDescriptor* DynamicMetadataProvider::resolve(const saml2md::MetadataProvider::Criteria& criteria) const
#ifdef _DEBUG
xmltooling::NDC("resolve");
#endif
- Category& log=Category::getInstance(SHIBSP_LOGCAT".MetadataProvider.Dynamic");
+ Category& log=Category::getInstance(SHIBSP_LOGCAT ".MetadataProvider.Dynamic");
string name;
if (criteria.entityID_ascii) {
name = temp.get();
}
else if (criteria.artifact) {
- throw saml2md::MetadataException("Unable to resolve metadata dynamically from an artifact.");
+ if (m_subst.empty() && (m_regex.empty() || m_match.empty()))
+ throw saml2md::MetadataException("Unable to resolve metadata dynamically from an artifact.");
+ name = "{sha1}" + criteria.artifact->getSource();
}
// Possibly transform the input into a different URL to use.
if (!m_subst.empty()) {
- string::size_type pos = m_subst.find("$entityID");
- if (pos != string::npos) {
- string name2 = m_subst;
- name2.replace(pos, 9, m_encoded ? XMLToolingConfig::getConfig().getURLEncoder()->encode(name.c_str()) : name);
- log.info("transformed location from (%s) to (%s)", name.c_str(), name2.c_str());
- name = name2;
- }
+ string name2 = boost::replace_first_copy(m_subst, "$entityID",
+ m_encoded ? XMLToolingConfig::getConfig().getURLEncoder()->encode(name.c_str()) : name);
+ log.info("transformed location from (%s) to (%s)", name.c_str(), name2.c_str());
+ name = name2;
}
else if (!m_match.empty() && !m_regex.empty()) {
try {
if (!mpc)
throw saml2md::MetadataException("Dynamic MetadataProvider requires Shibboleth-aware lookup criteria, check calling code.");
const PropertySet* relyingParty;
- if (criteria.entityID_unicode)
+ if (criteria.artifact)
+ relyingParty = mpc->application.getRelyingParty((XMLCh*)nullptr);
+ else if (criteria.entityID_unicode)
relyingParty = mpc->application.getRelyingParty(criteria.entityID_unicode);
else {
auto_ptr_XMLCh temp2(name.c_str());
if (!pch)
throw IOException("location was not a URL.");
string scheme(addr.m_endpoint, pch-addr.m_endpoint);
- SOAPTransport* transport=nullptr;
+ boost::scoped_ptr<SOAPTransport> transport;
try {
- transport = XMLToolingConfig::getConfig().SOAPTransportManager.newPlugin(scheme.c_str(), addr);
+ transport.reset(XMLToolingConfig::getConfig().SOAPTransportManager.newPlugin(scheme.c_str(), addr));
}
catch (exception& ex) {
log.error("exception while building transport object to resolve URL: %s", ex.what());
throw IOException("Unable to resolve entityID with a known transport protocol.");
}
- auto_ptr<SOAPTransport> transportwrapper(transport);
// Apply properties as directed.
transport->setVerifyHost(m_verifyHost);
- DummyCredentialResolver dcr;
- if (m_trust && !transport->setTrustEngine(m_trust, &dcr))
- throw IOException("Unable to install X509TrustEngine into metadata resolver.");
+ if (m_trust.get() && m_dummyCR.get() && !transport->setTrustEngine(m_trust.get(), m_dummyCR.get()))
+ throw IOException("Unable to install X509TrustEngine into transport object.");
Locker credlocker(nullptr, false);
CredentialResolver* credResolver = nullptr;
transport->setTimeout(timeout.first ? timeout.second : 20);
mpc->application.getServiceProvider().setTransportOptions(*transport);
- HTTPSOAPTransport* http = dynamic_cast<HTTPSOAPTransport*>(transport);
+ HTTPSOAPTransport* http = dynamic_cast<HTTPSOAPTransport*>(transport.get());
if (http) {
pair<bool,bool> flag = relyingParty->getBool("chunkedEncoding");
http->useChunkedEncoding(flag.first && flag.second);
http->setRequestHeader("Xerces-C", XERCES_FULLVERSIONDOT);
http->setRequestHeader("XML-Security-C", XSEC_FULLVERSIONDOT);
- http->setRequestHeader("OpenSAML-C", OPENSAML_FULLVERSIONDOT);
- http->setRequestHeader("User-Agent", PACKAGE_NAME);
+ http->setRequestHeader("OpenSAML-C", gOpenSAMLDotVersionStr);
http->setRequestHeader(PACKAGE_NAME, PACKAGE_VERSION);
}
// Wrap the document for now.
XercesJanitor<DOMDocument> docjanitor(doc);
+ // Check root element.
+ if (!doc->getDocumentElement() || !XMLHelper::isNodeNamed(doc->getDocumentElement(),
+ samlconstants::SAML20MD_NS, saml2md::EntityDescriptor::LOCAL_NAME)) {
+ throw saml2md::MetadataException("Root of metadata instance was not an EntityDescriptor");
+ }
+
// Unmarshall objects, binding the document.
auto_ptr<XMLObject> xmlObject(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
docjanitor.release();