Attribute lookup, port ACL code and mainline SP code to Session/Attribute API.
[shibboleth/cpp-sp.git] / shib / Metadata.cpp
1 /*
2  *  Copyright 2001-2007 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 /* Metadata.h - glue classes that interface to metadata providers
18
19    Scott Cantor
20    9/27/02
21
22    $History:$
23 */
24
25 #include "internal.h"
26 #include <xmltooling/util/NDC.h>
27
28 using namespace shibboleth;
29 using namespace opensaml::saml2md;
30 using namespace saml;
31 using namespace std;
32
33 AAP::AAP(const saml::Iterator<IAAP*>& aaps, const XMLCh* attrName, const XMLCh* attrNamespace) : m_mapper(NULL), m_rule(NULL)
34 {
35     aaps.reset();
36     while (aaps.hasNext()) {
37         m_mapper=aaps.next();
38         m_mapper->lock();
39         if (m_rule=m_mapper->lookup(attrName,attrNamespace)) {
40             break;
41         }
42         m_mapper->unlock();
43         m_mapper=NULL;
44     }
45 }
46
47 AAP::AAP(const saml::Iterator<IAAP*>& aaps, const char* alias) : m_mapper(NULL), m_rule(NULL)
48 {
49     aaps.reset();
50     while (aaps.hasNext()) {
51         m_mapper=aaps.next();
52         m_mapper->lock();
53         if (m_rule=m_mapper->lookup(alias)) {
54             break;
55         }
56         m_mapper->unlock();
57         m_mapper=NULL;
58     }
59 }
60
61 AAP::~AAP()
62 {
63     if (m_mapper) {
64         m_mapper->unlock();
65         m_mapper=NULL;
66     }
67 }
68
69 void AAP::apply(const saml::Iterator<IAAP*>& aaps, saml::SAMLAssertion& assertion, const RoleDescriptor* role)
70 {
71 #ifdef _DEBUG
72     xmltooling::NDC("apply");
73 #endif
74     log4cpp::Category& log=log4cpp::Category::getInstance(SHIB_LOGCAT".AAP");
75     
76     // First check for no providers or AnyAttribute.
77     if (aaps.size()==0) {
78         log.info("no filters specified, accepting entire assertion");
79         return;
80     }
81     aaps.reset();
82     while (aaps.hasNext()) {
83         IAAP* p=aaps.next();
84         xmltooling::Locker locker(p);
85         if (p->anyAttribute()) {
86             log.info("any attribute enabled, accepting entire assertion");
87             return;
88         }
89     }
90     
91     // Check each statement.
92     const IAttributeRule* rule=NULL;
93     Iterator<SAMLStatement*> statements=assertion.getStatements();
94     for (unsigned int scount=0; scount < statements.size();) {
95         SAMLAttributeStatement* s=dynamic_cast<SAMLAttributeStatement*>(statements[scount]);
96         if (!s) {
97             scount++;
98             continue;
99         }
100         
101         // Check each attribute, applying any matching rules.
102         Iterator<SAMLAttribute*> attrs=s->getAttributes();
103         for (unsigned long acount=0; acount < attrs.size();) {
104             SAMLAttribute* a=attrs[acount];
105             bool ruleFound=false;
106             aaps.reset();
107             while (aaps.hasNext()) {
108                 IAAP* i=aaps.next();
109                 xmltooling::Locker locker(i);
110                 if (rule=i->lookup(a->getName(),a->getNamespace())) {
111                     ruleFound=true;
112                     try {
113                         rule->apply(*a,role);
114                     }
115                     catch (SAMLException&) {
116                         // The attribute is now defunct.
117                         log.info("no values remain, removing attribute");
118                         s->removeAttribute(acount--);
119                         break;
120                     }
121                 }
122             }
123             if (!ruleFound) {
124                 if (log.isWarnEnabled()) {
125                     auto_ptr_char temp(a->getName());
126                     log.warn("no rule found for attribute (%s), filtering it out",temp.get());
127                 }
128                 s->removeAttribute(acount--);
129             }
130             acount++;
131         }
132
133         try {
134             s->checkValidity();
135             scount++;
136         }
137         catch (SAMLException&) {
138             // The statement is now defunct.
139             log.info("no attributes remain, removing statement");
140             assertion.removeStatement(scount);
141         }
142     }
143     
144     // Now see if we trashed it irrevocably.
145     assertion.checkValidity();
146 }