2 * Copyright 2009-2010 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.
18 * BearerConfirmationRule.cpp
20 * SAML 2.0 Bearer SubjectConfirmation SecurityPolicyRule.
24 #include "exceptions.h"
25 #include "binding/SecurityPolicyRule.h"
26 #include "saml2/core/Assertions.h"
27 #include "saml2/profile/SAML2AssertionPolicy.h"
29 #include <xercesc/util/XMLUniDefs.hpp>
30 #include <xmltooling/logging.h>
31 #include <xmltooling/XMLToolingConfig.h>
32 #include <xmltooling/io/HTTPRequest.h>
34 using namespace opensaml::saml2;
35 using namespace xmltooling;
41 class SAML_DLLLOCAL BearerConfirmationRule : public opensaml::SecurityPolicyRule
44 BearerConfirmationRule(const DOMElement* e);
46 virtual ~BearerConfirmationRule() {
48 const char* getType() const {
49 return BEARER_POLICY_RULE;
51 bool evaluate(const XMLObject& message, const GenericRequest* request, opensaml::SecurityPolicy& policy) const;
54 bool m_validity, m_recipient, m_correlation, m_fatal;
57 opensaml::SecurityPolicyRule* SAML_DLLLOCAL BearerConfirmationRuleFactory(const DOMElement* const & e)
59 return new BearerConfirmationRule(e);
62 static const XMLCh checkValidity[] = UNICODE_LITERAL_13(c,h,e,c,k,V,a,l,i,d,i,t,y);
63 static const XMLCh checkRecipient[] = UNICODE_LITERAL_14(c,h,e,c,k,R,e,c,i,p,i,e,n,t);
64 static const XMLCh checkCorrelation[] = UNICODE_LITERAL_16(c,h,e,c,k,C,o,r,r,e,l,a,t,i,o,n);
65 static const XMLCh missingFatal[] = UNICODE_LITERAL_12(m,i,s,s,i,n,g,F,a,t,a,l);
69 BearerConfirmationRule::BearerConfirmationRule(const DOMElement* e) : m_validity(true), m_recipient(true), m_correlation(true), m_fatal(true)
71 const XMLCh* flag = e ? e->getAttributeNS(nullptr, checkValidity) : nullptr;
72 m_validity = (!flag || (*flag != chLatin_f && *flag != chDigit_0));
73 flag = e ? e->getAttributeNS(nullptr, checkRecipient) : nullptr;
74 m_recipient = (!flag || (*flag != chLatin_f && *flag != chDigit_0));
75 flag = e ? e->getAttributeNS(nullptr, checkCorrelation) : nullptr;
76 m_correlation = (!flag || (*flag != chLatin_f && *flag != chDigit_0));
77 flag = e ? e->getAttributeNS(nullptr, missingFatal) : nullptr;
78 m_fatal = (!flag || (*flag != chLatin_f && *flag != chDigit_0));
81 bool BearerConfirmationRule::evaluate(const XMLObject& message, const GenericRequest* request, opensaml::SecurityPolicy& policy) const
83 const Assertion* a=dynamic_cast<const Assertion*>(&message);
87 logging::Category& log = logging::Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.BearerConfirmation");
89 const char* msg="assertion is missing bearer SubjectConfirmation";
90 const Subject* subject = a->getSubject();
92 const vector<SubjectConfirmation*>& confs = subject->getSubjectConfirmations();
93 for (vector<SubjectConfirmation*>::const_iterator sc = confs.begin(); sc!=confs.end(); ++sc) {
94 if (XMLString::equals((*sc)->getMethod(), SubjectConfirmation::BEARER)) {
96 const SubjectConfirmationDataType* data = dynamic_cast<const SubjectConfirmationDataType*>((*sc)->getSubjectConfirmationData());
99 const HTTPRequest* httpRequest = dynamic_cast<const HTTPRequest*>(request);
100 if (httpRequest && httpRequest->getRequestURL()) {
101 string dest = httpRequest->getRequestURL();
102 auto_ptr_XMLCh destination(dest.substr(0,dest.find('?')).c_str());
103 if (!XMLString::equals(destination.get(), data ? data->getRecipient() : nullptr)) {
104 msg = "bearer confirmation failed with recipient mismatch";
110 if (m_correlation && policy.getCorrelationID() && *(policy.getCorrelationID())) {
111 if (!XMLString::equals(policy.getCorrelationID(), data ? data->getInResponseTo() : nullptr)) {
112 msg = "bearer confirmation failed with request correlation mismatch";
118 if (!data || !data->getNotOnOrAfter()) {
119 msg = "bearer SubjectConfirmationData missing NotOnOrAfter attribute";
122 else if (data->getNotOnOrAfterEpoch() <= policy.getTime() - XMLToolingConfig::getConfig().clock_skew_secs) {
123 msg = "bearer confirmation has expired";
127 if (data && data->getNotBefore() && policy.getTime() + XMLToolingConfig::getConfig().clock_skew_secs < data->getNotBeforeEpoch()) {
128 msg = "bearer confirmation not yet valid";
133 SAML2AssertionPolicy* saml2policy = dynamic_cast<SAML2AssertionPolicy*>(&policy);
135 saml2policy->setSubjectConfirmation(*sc);
136 log.debug("assertion satisfied bearer confirmation requirements");
142 log.error(msg ? msg : "no error message");
144 throw SecurityPolicyException("Unable to locate satisfiable bearer SubjectConfirmation in assertion.");