Add policy rules for SAML 1 SSO and SAML 2 Bearer confirmation, with unit tests.
[shibboleth/cpp-opensaml.git] / saml / saml1 / profile / impl / SAML1BrowserSSORule.cpp
1 /*
2  *  Copyright 2009 Internet2
3  *
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /**
18  * SAML1BrowserSSORule.cpp
19  *
20  * SAML 1.x Browser SSO Profile SecurityPolicyRule
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "binding/SecurityPolicyRule.h"
26 #include "saml1/core/Assertions.h"
27
28 #include <xmltooling/logging.h>
29
30 using namespace opensaml::saml1;
31 using namespace xmltooling::logging;
32 using namespace xmltooling;
33 using namespace std;
34
35 namespace opensaml {
36     namespace saml1 {
37
38         class SAML_DLLLOCAL BrowserSSORule : public opensaml::SecurityPolicyRule
39         {
40         public:
41             BrowserSSORule(const DOMElement* e) {}
42
43             virtual ~BrowserSSORule() {
44             }
45             const char* getType() const {
46                 return SAML1BROWSERSSO_POLICY_RULE;
47             }
48             bool evaluate(const XMLObject& message, const GenericRequest* request, opensaml::SecurityPolicy& policy) const;
49         };
50
51         opensaml::SecurityPolicyRule* SAML_DLLLOCAL BrowserSSORuleFactory(const DOMElement* const & e)
52         {
53             return new BrowserSSORule(e);
54         }
55
56         class SAML_DLLLOCAL _checkMethod : public unary_function<const SubjectStatement*,void>,
57             public unary_function<const ConfirmationMethod*,bool>
58         {
59         public:
60             void operator()(const SubjectStatement* s) const {
61                 const Subject* sub = s->getSubject();
62                 if (s) {
63                     const SubjectConfirmation* sc = sub->getSubjectConfirmation();
64                     if (sc) {
65                         const vector<ConfirmationMethod*>& methods = sc->getConfirmationMethods();
66                         if (find_if(methods.begin(), methods.end(), _checkMethod())!=methods.end())
67                             return;     // methods checked out
68                     }
69                 }
70                 throw SecurityPolicyException("Assertion contained a statement without a supported ConfirmationMethod.");
71             }
72
73             bool operator()(const ConfirmationMethod* cm) const {
74                 const XMLCh* m = cm->getMethod();
75                 return (XMLString::equals(m,SubjectConfirmation::BEARER) ||
76                     XMLString::equals(m,SubjectConfirmation::ARTIFACT) ||
77                     XMLString::equals(m,SubjectConfirmation::ARTIFACT01));
78             }
79         };
80     };
81 };
82
83 bool BrowserSSORule::evaluate(const XMLObject& message, const GenericRequest* request, opensaml::SecurityPolicy& policy) const
84 {
85     const Assertion* a=dynamic_cast<const Assertion*>(&message);
86     if (!a)
87         return false;
88
89     // Make sure the assertion is bounded.
90     const Conditions* conds = a->getConditions();
91     if (!conds || !conds->getNotBefore() || !conds->getNotOnOrAfter())
92         throw SecurityPolicyException("Browser SSO assertions MUST contain NotBefore/NotOnOrAfter attributes.");
93
94     // Each statement MUST have proper confirmation requirements.
95     const vector<AuthenticationStatement*>& authn = a->getAuthenticationStatements();
96     for_each(authn.begin(), authn.end(), _checkMethod());
97     const vector<AttributeStatement*>& attr = a->getAttributeStatements();
98     for_each(attr.begin(), attr.end(), _checkMethod());
99
100     return true;
101 }