Set fourth file version digit to signify rebuild.
[shibboleth/cpp-opensaml.git] / saml / saml2 / profile / impl / BrowserSSOProfile20Validator.cpp
1 /**
2  * Licensed to the University Corporation for Advanced Internet
3  * Development, Inc. (UCAID) under one or more contributor license
4  * agreements. See the NOTICE file distributed with this work for
5  * additional information regarding copyright ownership.
6  *
7  * UCAID licenses this file to you under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except
9  * in compliance with the License. You may obtain a copy of the
10  * License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17  * either express or implied. See the License for the specific
18  * language governing permissions and limitations under the License.
19  */
20
21 /**
22  * BrowserSSOProfile20Validator.cpp
23  *
24  * SAML 2.0 Browser SSO Profile Assertion Validator.
25  */
26
27 #include "internal.h"
28 #include "saml2/core/Assertions.h"
29 #include "saml2/profile/BrowserSSOProfileValidator.h"
30
31 #include <xmltooling/logging.h>
32 #include <xmltooling/XMLToolingConfig.h>
33 #include <xmltooling/util/NDC.h>
34
35 using namespace opensaml::saml2;
36 using namespace xmltooling::logging;
37 using namespace xmltooling;
38 using namespace std;
39
40 BrowserSSOProfileValidator::BrowserSSOProfileValidator(
41     const XMLCh* recipient,
42     const vector<const XMLCh*>* audiences,
43     time_t ts,
44     const char* destination,
45     const char* requestID
46     ) : AssertionValidator(recipient, audiences, ts), m_destination(destination), m_requestID(requestID)
47 {
48 }
49
50 BrowserSSOProfileValidator::~BrowserSSOProfileValidator()
51 {
52 }
53
54 void BrowserSSOProfileValidator::validateAssertion(const Assertion& assertion) const
55 {
56 #ifdef _DEBUG
57     xmltooling::NDC ndc("validate");
58 #endif
59     Category& log = Category::getInstance(SAML_LOGCAT ".AssertionValidator");
60
61     // The assertion MUST have proper confirmation requirements.
62     const char* msg="assertion is missing bearer SubjectConfirmation";
63     const Subject* subject = assertion.getSubject();
64     if (subject) {
65         const vector<SubjectConfirmation*>& confs = subject->getSubjectConfirmations();
66         for (vector<SubjectConfirmation*>::const_iterator sc = confs.begin(); sc!=confs.end(); ++sc) {
67             if (XMLString::equals((*sc)->getMethod(), SubjectConfirmation::BEARER)) {
68                 const SubjectConfirmationDataType* data = dynamic_cast<const SubjectConfirmationDataType*>((*sc)->getSubjectConfirmationData());
69
70                 if (m_destination.get()) {
71                     if (!XMLString::equals(m_destination.get(), data ? data->getRecipient() : nullptr)) {
72                         msg = "bearer confirmation failed with recipient mismatch";
73                         continue;
74                     }
75                 }
76
77                 if (m_requestID.get()) {
78                     if (!XMLString::equals(m_requestID.get(), data ? data->getInResponseTo() : nullptr)) {
79                         msg = "bearer confirmation failed with request correlation mismatch";
80                         continue;
81                     }
82                 }
83
84                 if (m_ts) {
85                     if (!data || !data->getNotOnOrAfter()) {
86                         msg = "bearer confirmation missing NotOnOrAfter attribute";
87                         continue;
88                     }
89                     else if (data->getNotOnOrAfterEpoch() <= m_ts - XMLToolingConfig::getConfig().clock_skew_secs) {
90                         msg = "bearer confirmation has expired";
91                         continue;
92                     }
93                 }
94
95                 // Save off client address.
96                 if (data) {
97                     auto_ptr_char ip(data->getAddress());
98                     if (ip.get())
99                         m_address = ip.get();
100                 }
101
102                 // Pass up for additional checking.
103                 return AssertionValidator::validateAssertion(assertion);
104             }
105         }
106     }
107
108     log.error(msg ? msg : "no error message");
109     throw ValidationException("Unable to locate satisfiable bearer SubjectConfirmation in assertion.");
110 }
111
112 const char* BrowserSSOProfileValidator::getAddress() const
113 {
114     return m_address.c_str();
115 }