2 * Copyright 2001-2005 Internet2
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 /* ShibBrowserProfile.cpp - Shibboleth-specific wrapper around SAML browser profile
29 #include <openssl/x509v3.h>
31 using namespace shibboleth::logging;
32 using namespace shibboleth;
36 ShibBrowserProfile::ShibBrowserProfile(const Iterator<IMetadata*>& metadatas, const Iterator<ITrust*>& trusts)
37 : m_metadatas(metadatas), m_trusts(trusts)
39 m_profile=SAMLBrowserProfile::getInstance();
42 ShibBrowserProfile::~ShibBrowserProfile()
47 SAMLBrowserProfile::BrowserProfileResponse ShibBrowserProfile::receive(
49 const XMLCh* recipient,
50 int supportedProfiles,
51 IReplayCache* replayCache,
52 SAMLBrowserProfile::ArtifactMapper* callback,
59 Category& log=Category::getInstance(SHIB_LOGCAT".ShibBrowserProfile");
61 // The built-in SAML functionality will do most of the basic non-crypto checks.
62 // Note that if the response only contains a status error, it gets tossed out
64 SAMLBrowserProfile::BrowserProfileResponse bpr;
66 bpr=m_profile->receive(packet, recipient, supportedProfiles, replayCache, callback, minorVersion);
68 catch (SAMLException& e) {
69 // Try our best to attach additional information.
70 if (e.getProperty("issuer")) {
71 Metadata m(m_metadatas);
72 const IEntityDescriptor* provider=m.lookup(e.getProperty("issuer"),false);
74 const IIDPSSODescriptor* role=provider->getIDPSSODescriptor(
75 minorVersion==1 ? saml::XML::SAML11_PROTOCOL_ENUM : saml::XML::SAML10_PROTOCOL_ENUM
77 if (role) annotateException(&e,role); // throws it
78 annotateException(&e,provider); // throws it
84 // Try and locate metadata for the IdP. We try Issuer first.
85 log.debug("searching metadata for assertion issuer...");
86 Metadata m(m_metadatas);
87 const IEntityDescriptor* provider=m.lookup(bpr.assertion->getIssuer());
89 log.debug("matched assertion issuer against metadata");
90 else if (bpr.authnStatement->getSubject()->getNameIdentifier() &&
91 bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier()) {
92 // Might be a down-level origin.
93 provider=m.lookup(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier());
95 log.debug("matched subject name qualifier against metadata");
98 // No metadata at all.
100 auto_ptr_char issuer(bpr.assertion->getIssuer());
101 auto_ptr_char nq(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier());
102 log.error("assertion issuer not found in metadata (Issuer='%s', NameQualifier='%s')",
103 issuer.get(), (nq.get() ? nq.get() : "none"));
105 // Try a non-strict lookup for more contact info.
106 const IEntityDescriptor* provider=m.lookup(bpr.assertion->getIssuer(),false);
108 log.debug("found invalid metadata for assertion issuer, using for contact info");
110 MetadataException ex("metadata lookup failed, unable to process assertion");
111 annotateException(&ex,provider); // throws it
114 throw MetadataException("metadata lookup failed, unable to process assertion",namedparams(1,"issuer",issuer.get()));
117 // Is this provider an IdP?
118 const IIDPSSODescriptor* role=provider->getIDPSSODescriptor(
119 minorVersion==1 ? saml::XML::SAML11_PROTOCOL_ENUM : saml::XML::SAML10_PROTOCOL_ENUM
122 // Use this role to evaluate the signature(s). If the response is unsigned, we know
123 // it was an artifact profile run.
125 if (bpr.response->isSigned()) {
126 log.debug("passing signed response to trust layer");
127 if (!t.validate(*bpr.response,role)) {
129 log.error("unable to verify signed profile response");
130 TrustException ex("unable to verify signed profile response");
131 annotateException(&ex,role); // throws it
134 // SSO assertion signed?
135 if (bpr.assertion->isSigned()) {
136 log.debug("passing signed authentication assertion to trust layer");
137 if (!t.validate(*bpr.assertion,role)) {
139 log.error("unable to verify signed authentication assertion");
140 TrustException ex("unable to verify signed authentication assertion");
141 annotateException(&ex,role); // throws it
145 // Finally, discard any assertions not issued by the same entity that issued the authn.
146 Iterator<SAMLAssertion*> assertions=bpr.response->getAssertions();
147 for (unsigned long a=0; a<assertions.size();) {
148 if (XMLString::compareString(bpr.assertion->getIssuer(),assertions[a]->getIssuer())) {
149 auto_ptr_char bad(assertions[a]->getIssuer());
150 log.warn("discarding assertion not issued by authenticating IdP, instead by (%s)",bad.get());
151 bpr.response->removeAssertion(a);
160 auto_ptr_char issuer(bpr.assertion->getIssuer());
161 auto_ptr_char nq(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier());
162 log.error("metadata for assertion issuer indicates no SAML 1.%d identity provider role (Issuer='%s', NameQualifier='%s'",
163 minorVersion, issuer.get(), (nq.get() ? nq.get() : "none"));
165 MetadataException ex("metadata lookup failed, issuer not registered as SAML 1.x identity provider");
166 annotateException(&ex,provider,false);