314e744ff1a5dd272bab4956048ffa3e8f2c449f
[shibboleth/cpp-sp.git] / shib / Metadata.cpp
1 /*
2  *  Copyright 2001-2005 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
27 using namespace shibboleth;
28 using namespace saml;
29 using namespace std;
30
31 const IEntityDescriptor* Metadata::lookup(const XMLCh* id, bool strict)
32 {
33     if (m_mapper) {
34         m_mapper->unlock();
35         m_mapper=NULL;
36     }
37     const IEntityDescriptor* ret=NULL;
38     m_metadatas.reset();
39     while (m_metadatas.hasNext()) {
40         m_mapper=m_metadatas.next();
41         m_mapper->lock();
42         if (ret=m_mapper->lookup(id,strict)) {
43             return ret;
44         }
45         m_mapper->unlock();
46         m_mapper=NULL;
47     }
48     return NULL;
49 }
50
51 const IEntityDescriptor* Metadata::lookup(const char* id, bool strict)
52 {
53     if (m_mapper) {
54         m_mapper->unlock();
55         m_mapper=NULL;
56     }
57     const IEntityDescriptor* ret=NULL;
58     m_metadatas.reset();
59     while (m_metadatas.hasNext()) {
60         m_mapper=m_metadatas.next();
61         m_mapper->lock();
62         if (ret=m_mapper->lookup(id,strict)) {
63             return ret;
64         }
65         m_mapper->unlock();
66         m_mapper=NULL;
67     }
68     return NULL;
69 }
70
71 const IEntityDescriptor* Metadata::lookup(const SAMLArtifact* artifact)
72 {
73     if (m_mapper) {
74         m_mapper->unlock();
75         m_mapper=NULL;
76     }
77     const IEntityDescriptor* ret=NULL;
78     m_metadatas.reset();
79     while (m_metadatas.hasNext()) {
80         m_mapper=m_metadatas.next();
81         m_mapper->lock();
82         if (ret=m_mapper->lookup(artifact)) {
83             return ret;
84         }
85         m_mapper->unlock();
86         m_mapper=NULL;
87     }
88     return NULL;
89 }
90
91 Metadata::~Metadata()
92 {
93     if (m_mapper) {
94         m_mapper->unlock();
95         m_mapper=NULL;
96     }
97 }
98
99 bool Trust::validate(const SAMLSignedObject& token, const IRoleDescriptor* role) const
100 {
101     m_trusts.reset();
102     while (m_trusts.hasNext()) {
103         if (m_trusts.next()->validate(token,role))
104             return true;
105     }
106     return false;
107 }
108
109 bool Trust::validate(void* certEE, const Iterator<void*>& certChain, const IRoleDescriptor* role, bool checkName) const
110 {
111     m_trusts.reset();
112     while (m_trusts.hasNext()) {
113         if (m_trusts.next()->validate(certEE,certChain,role,checkName))
114             return true;
115     }
116     return false;
117 }
118
119 const ICredResolver* Credentials::lookup(const char* id)
120 {
121     if (m_mapper) {
122         m_mapper->unlock();
123         m_mapper=NULL;
124     }
125     const ICredResolver* ret=NULL;
126     m_creds.reset();
127     while (m_creds.hasNext()) {
128         m_mapper=m_creds.next();
129         m_mapper->lock();
130         if (ret=m_mapper->lookup(id)) {
131             return ret;
132         }
133         m_mapper->unlock();
134         m_mapper=NULL;
135     }
136     return NULL;
137 }
138
139 Credentials::~Credentials()
140 {
141     if (m_mapper) {
142         m_mapper->unlock();
143         m_mapper=NULL;
144     }
145 }
146
147 AAP::AAP(const saml::Iterator<IAAP*>& aaps, const XMLCh* attrName, const XMLCh* attrNamespace) : m_mapper(NULL), m_rule(NULL)
148 {
149     aaps.reset();
150     while (aaps.hasNext()) {
151         m_mapper=aaps.next();
152         m_mapper->lock();
153         if (m_rule=m_mapper->lookup(attrName,attrNamespace)) {
154             break;
155         }
156         m_mapper->unlock();
157         m_mapper=NULL;
158     }
159 }
160
161 AAP::AAP(const saml::Iterator<IAAP*>& aaps, const char* alias) : m_mapper(NULL), m_rule(NULL)
162 {
163     aaps.reset();
164     while (aaps.hasNext()) {
165         m_mapper=aaps.next();
166         m_mapper->lock();
167         if (m_rule=m_mapper->lookup(alias)) {
168             break;
169         }
170         m_mapper->unlock();
171         m_mapper=NULL;
172     }
173 }
174
175 AAP::~AAP()
176 {
177     if (m_mapper) {
178         m_mapper->unlock();
179         m_mapper=NULL;
180     }
181 }
182
183 void AAP::apply(const saml::Iterator<IAAP*>& aaps, saml::SAMLAssertion& assertion, const IEntityDescriptor* source)
184 {
185 #ifdef _DEBUG
186     saml::NDC("apply");
187 #endif
188     log4cpp::Category& log=log4cpp::Category::getInstance(SHIB_LOGCAT".AAP");
189     
190     // First check for no providers or AnyAttribute.
191     if (aaps.size()==0) {
192         log.info("no filters specified, accepting entire assertion");
193         return;
194     }
195     aaps.reset();
196     while (aaps.hasNext()) {
197         IAAP* p=aaps.next();
198         Locker locker(p);
199         if (p->anyAttribute()) {
200             log.info("any attribute enabled, accepting entire assertion");
201             return;
202         }
203     }
204     
205     // Check each statement.
206     const IAttributeRule* rule=NULL;
207     Iterator<SAMLStatement*> statements=assertion.getStatements();
208     for (unsigned int scount=0; scount < statements.size();) {
209         SAMLAttributeStatement* s=dynamic_cast<SAMLAttributeStatement*>(statements[scount]);
210         if (!s) {
211             scount++;
212             continue;
213         }
214         
215         // Check each attribute, applying any matching rules.
216         Iterator<SAMLAttribute*> attrs=s->getAttributes();
217         for (unsigned long acount=0; acount < attrs.size();) {
218             SAMLAttribute* a=attrs[acount];
219             bool ruleFound=false;
220             aaps.reset();
221             while (aaps.hasNext()) {
222                 IAAP* i=aaps.next();
223                 Locker locker(i);
224                 if (rule=i->lookup(a->getName(),a->getNamespace())) {
225                     ruleFound=true;
226                     try {
227                         rule->apply(*a,source);
228                     }
229                     catch (SAMLException&) {
230                         // The attribute is now defunct.
231                         log.info("no values remain, removing attribute");
232                         s->removeAttribute(acount--);
233                         break;
234                     }
235                 }
236             }
237             if (!ruleFound) {
238                 if (log.isWarnEnabled()) {
239                     auto_ptr_char temp(a->getName());
240                     log.warn("no rule found for attribute (%s), filtering it out",temp.get());
241                 }
242                 s->removeAttribute(acount--);
243             }
244             acount++;
245         }
246
247         try {
248             s->checkValidity();
249             scount++;
250         }
251         catch (SAMLException&) {
252             // The statement is now defunct.
253             log.info("no attributes remain, removing statement");
254             assertion.removeStatement(scount);
255         }
256     }
257     
258     // Now see if we trashed it irrevocably.
259     assertion.checkValidity();
260 }