83e8f388dd725692c4e63f8e176e74f07e466943
[shibboleth/sp.git] / shibsp / attribute / resolver / impl / AssertionAttributeExtractor.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  * AssertionAttributeExtractor.cpp
23  *
24  * AttributeExtractor for SAML assertion content.
25  */
26
27 #include "internal.h"
28 #include "Application.h"
29 #include "ServiceProvider.h"
30 #include "attribute/SimpleAttribute.h"
31 #include "attribute/resolver/AttributeExtractor.h"
32
33 #include <saml/saml1/core/Assertions.h>
34 #include <saml/saml2/core/Assertions.h>
35 #include <saml/saml2/metadata/Metadata.h>
36 #include <xmltooling/util/DateTime.h>
37 #include <xmltooling/util/XMLHelper.h>
38 #include <xercesc/util/XMLUniDefs.hpp>
39
40 using namespace shibsp;
41 using namespace opensaml::saml2;
42 using namespace opensaml::saml2md;
43 using namespace opensaml::saml1;
44 using namespace opensaml;
45 using namespace xmltooling;
46 using namespace std;
47
48 namespace shibsp {
49
50 #if defined (_MSC_VER)
51     #pragma warning( push )
52     #pragma warning( disable : 4250 )
53 #endif
54
55     class AssertionExtractor : public AttributeExtractor
56     {
57     public:
58         AssertionExtractor(const DOMElement* e);
59         ~AssertionExtractor() {}
60
61         Lockable* lock() {
62             return this;
63         }
64
65         void unlock() {
66         }
67
68         void extractAttributes(
69             const Application& application,
70             const RoleDescriptor* issuer,
71             const XMLObject& xmlObject,
72             vector<shibsp::Attribute*>& attributes
73             ) const;
74         void getAttributeIds(vector<string>& attributes) const;
75
76     private:
77         string m_authnAuthority,
78             m_authnClass,
79             m_authnDecl,
80             m_authnInstant,
81             m_issuer,
82             m_notOnOrAfter,
83             m_sessionIndex,
84             m_sessionNotOnOrAfter,
85             m_subjectAddress,
86             m_subjectDNS;
87     };
88
89 #if defined (_MSC_VER)
90     #pragma warning( pop )
91 #endif
92
93     AttributeExtractor* SHIBSP_DLLLOCAL AssertionAttributeExtractorFactory(const DOMElement* const & e)
94     {
95         return new AssertionExtractor(e);
96     }
97
98 };
99
100 AssertionExtractor::AssertionExtractor(const DOMElement* e)
101     : m_authnAuthority(XMLHelper::getAttrString(e, nullptr, AuthenticatingAuthority::LOCAL_NAME)),
102         m_authnClass(XMLHelper::getAttrString(e, nullptr, AuthnContextClassRef::LOCAL_NAME)),
103         m_authnDecl(XMLHelper::getAttrString(e, nullptr, AuthnContextDeclRef::LOCAL_NAME)),
104         m_authnInstant(XMLHelper::getAttrString(e, nullptr, AuthnStatement::AUTHNINSTANT_ATTRIB_NAME)),
105         m_issuer(XMLHelper::getAttrString(e, nullptr, Issuer::LOCAL_NAME)),
106         m_notOnOrAfter(XMLHelper::getAttrString(e, nullptr, saml2::Conditions::NOTONORAFTER_ATTRIB_NAME)),
107         m_sessionIndex(XMLHelper::getAttrString(e, nullptr, AuthnStatement::SESSIONINDEX_ATTRIB_NAME)),
108         m_sessionNotOnOrAfter(XMLHelper::getAttrString(e, nullptr, AuthnStatement::SESSIONNOTONORAFTER_ATTRIB_NAME)),
109         m_subjectAddress(XMLHelper::getAttrString(e, nullptr, saml2::SubjectLocality::ADDRESS_ATTRIB_NAME)),
110         m_subjectDNS(XMLHelper::getAttrString(e, nullptr, saml2::SubjectLocality::DNSNAME_ATTRIB_NAME))
111 {
112 }
113
114 void AssertionExtractor::extractAttributes(
115     const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<shibsp::Attribute*>& attributes
116     ) const
117 {
118     const saml2::Assertion* saml2assertion = dynamic_cast<const saml2::Assertion*>(&xmlObject);
119     if (saml2assertion) {
120         // Issuer
121         if (!m_issuer.empty()) {
122             const Issuer* i = saml2assertion->getIssuer();
123             if (i && (!i->getFormat() || !*(i->getFormat()) || XMLString::equals(i->getFormat(), NameIDType::ENTITY))) {
124                 auto_ptr_char temp(i->getName());
125                 if (temp.get()) {
126                     auto_ptr<SimpleAttribute> issuer(new SimpleAttribute(vector<string>(1, m_issuer)));
127                     issuer->getValues().push_back(temp.get());
128                     attributes.push_back(issuer.get());
129                     issuer.release();
130                 }
131             }
132         }
133
134         // NotOnOrAfter
135         if (!m_notOnOrAfter.empty() && saml2assertion->getConditions() && saml2assertion->getConditions()->getNotOnOrAfter()) {
136             auto_ptr_char temp(saml2assertion->getConditions()->getNotOnOrAfter()->getRawData());
137             if (temp.get()) {
138                 auto_ptr<SimpleAttribute> notonorafter(new SimpleAttribute(vector<string>(1, m_notOnOrAfter)));
139                 notonorafter->getValues().push_back(temp.get());
140                 attributes.push_back(notonorafter.get());
141                 notonorafter.release();
142             }
143         }
144     }
145     else {
146         const AuthnStatement* saml2statement = dynamic_cast<const AuthnStatement*>(&xmlObject);
147         if (saml2statement) {
148             // AuthnInstant
149             if (!m_authnInstant.empty() && saml2statement->getAuthnInstant()) {
150                 auto_ptr_char temp(saml2statement->getAuthnInstant()->getRawData());
151                 if (temp.get()) {
152                     auto_ptr<SimpleAttribute> authninstant(new SimpleAttribute(vector<string>(1, m_authnInstant)));
153                     authninstant->getValues().push_back(temp.get());
154                     attributes.push_back(authninstant.get());
155                     authninstant.release();
156                 }
157             }
158
159             // SessionIndex
160             if (!m_sessionIndex.empty() && saml2statement->getSessionIndex() && *(saml2statement->getSessionIndex())) {
161                 auto_ptr_char temp(saml2statement->getSessionIndex());
162                 if (temp.get()) {
163                     auto_ptr<SimpleAttribute> sessionindex(new SimpleAttribute(vector<string>(1, m_sessionIndex)));
164                     sessionindex->getValues().push_back(temp.get());
165                     attributes.push_back(sessionindex.get());
166                     sessionindex.release();
167                 }
168             }
169
170             // SessionNotOnOrAfter
171             if (!m_sessionNotOnOrAfter.empty() && saml2statement->getSessionNotOnOrAfter()) {
172                 auto_ptr_char temp(saml2statement->getSessionNotOnOrAfter()->getRawData());
173                 if (temp.get()) {
174                     auto_ptr<SimpleAttribute> sessionnotonorafter(new SimpleAttribute(vector<string>(1, m_sessionNotOnOrAfter)));
175                     sessionnotonorafter->getValues().push_back(temp.get());
176                     attributes.push_back(sessionnotonorafter.get());
177                     sessionnotonorafter.release();
178                 }
179             }
180
181             if (saml2statement->getSubjectLocality()) {
182                 const saml2::SubjectLocality* locality = saml2statement->getSubjectLocality();
183                 // Address
184                 if (!m_subjectAddress.empty() && locality->getAddress() && *(locality->getAddress())) {
185                     auto_ptr_char temp(locality->getAddress());
186                     if (temp.get()) {
187                         auto_ptr<SimpleAttribute> address(new SimpleAttribute(vector<string>(1, m_subjectAddress)));
188                         address->getValues().push_back(temp.get());
189                         attributes.push_back(address.get());
190                         address.release();
191                     }
192                 }
193
194                 // DNSName
195                 if (!m_subjectDNS.empty() && locality->getDNSName() && *(locality->getDNSName())) {
196                     auto_ptr_char temp(locality->getDNSName());
197                     if (temp.get()) {
198                         auto_ptr<SimpleAttribute> dns(new SimpleAttribute(vector<string>(1, m_subjectDNS)));
199                         dns->getValues().push_back(temp.get());
200                         attributes.push_back(dns.get());
201                         dns.release();
202                     }
203                 }
204             }
205
206             if (saml2statement->getAuthnContext()) {
207                 const AuthnContext* ac = saml2statement->getAuthnContext();
208                 // AuthnContextClassRef
209                 if (!m_authnClass.empty() && ac->getAuthnContextClassRef() && ac->getAuthnContextClassRef()->getReference()) {
210                     auto_ptr_char temp(ac->getAuthnContextClassRef()->getReference());
211                     if (temp.get()) {
212                         auto_ptr<SimpleAttribute> classref(new SimpleAttribute(vector<string>(1, m_authnClass)));
213                         classref->getValues().push_back(temp.get());
214                         attributes.push_back(classref.get());
215                         classref.release();
216                     }
217                 }
218
219                 // AuthnContextDeclRef
220                 if (!m_authnDecl.empty() && ac->getAuthnContextDeclRef() && ac->getAuthnContextDeclRef()->getReference()) {
221                     auto_ptr_char temp(ac->getAuthnContextDeclRef()->getReference());
222                     if (temp.get()) {
223                         auto_ptr<SimpleAttribute> declref(new SimpleAttribute(vector<string>(1, m_authnDecl)));
224                         declref->getValues().push_back(temp.get());
225                         attributes.push_back(declref.get());
226                         declref.release();
227                     }
228                 }
229
230                 // AuthenticatingAuthority
231                 if (!m_authnAuthority.empty() && !ac->getAuthenticatingAuthoritys().empty()) {
232                     auto_ptr<SimpleAttribute> attr(new SimpleAttribute(vector<string>(1, m_authnAuthority)));
233                     const vector<AuthenticatingAuthority*>& authorities = ac->getAuthenticatingAuthoritys();
234                     for (vector<AuthenticatingAuthority*>::const_iterator a = authorities.begin(); a != authorities.end(); ++a) {
235                         auto_ptr_char temp((*a)->getID());
236                         if (temp.get())
237                             attr->getValues().push_back(temp.get());
238                     }
239                     if (attr->valueCount() > 0) {
240                         attributes.push_back(attr.get());
241                         attr.release();
242                     }
243                 }
244             }
245         }
246         else {
247             const saml1::Assertion* saml1assertion = dynamic_cast<const saml1::Assertion*>(&xmlObject);
248             if (saml1assertion) {
249                 // Issuer
250                 if (!m_issuer.empty()) {
251                     if (saml1assertion->getIssuer() && *(saml1assertion->getIssuer())) {
252                         auto_ptr_char temp(saml1assertion->getIssuer());
253                         if (temp.get()) {
254                             auto_ptr<SimpleAttribute> issuer(new SimpleAttribute(vector<string>(1, m_issuer)));
255                             issuer->getValues().push_back(temp.get());
256                             attributes.push_back(issuer.get());
257                             issuer.release();
258                         }
259                     }
260                 }
261
262                 // NotOnOrAfter
263                 if (!m_notOnOrAfter.empty() && saml1assertion->getConditions() && saml1assertion->getConditions()->getNotOnOrAfter()) {
264                     auto_ptr_char temp(saml1assertion->getConditions()->getNotOnOrAfter()->getRawData());
265                     if (temp.get()) {
266                         auto_ptr<SimpleAttribute> notonorafter(new SimpleAttribute(vector<string>(1, m_notOnOrAfter)));
267                         notonorafter->getValues().push_back(temp.get());
268                         attributes.push_back(notonorafter.get());
269                         notonorafter.release();
270                     }
271                 }
272             }
273             else {
274                 const AuthenticationStatement* saml1statement = dynamic_cast<const AuthenticationStatement*>(&xmlObject);
275                 if (saml1statement) {
276                     // AuthnInstant
277                     if (!m_authnInstant.empty() && saml1statement->getAuthenticationInstant()) {
278                         auto_ptr_char temp(saml1statement->getAuthenticationInstant()->getRawData());
279                         if (temp.get()) {
280                             auto_ptr<SimpleAttribute> authninstant(new SimpleAttribute(vector<string>(1, m_authnInstant)));
281                             authninstant->getValues().push_back(temp.get());
282                             attributes.push_back(authninstant.get());
283                             authninstant.release();
284                         }
285                     }
286
287                     // AuthenticationMethod
288                     if (!m_authnClass.empty() && saml1statement->getAuthenticationMethod() && *(saml1statement->getAuthenticationMethod())) {
289                         auto_ptr_char temp(saml1statement->getAuthenticationMethod());
290                         if (temp.get()) {
291                             auto_ptr<SimpleAttribute> authnmethod(new SimpleAttribute(vector<string>(1, m_authnClass)));
292                             authnmethod->getValues().push_back(temp.get());
293                             attributes.push_back(authnmethod.get());
294                             authnmethod.release();
295                         }
296                     }
297
298                     if (saml1statement->getSubjectLocality()) {
299                         const saml1::SubjectLocality* locality = saml1statement->getSubjectLocality();
300                         // IPAddress
301                         if (!m_subjectAddress.empty() && locality->getIPAddress() && *(locality->getIPAddress())) {
302                             auto_ptr_char temp(locality->getIPAddress());
303                             if (temp.get()) {
304                                 auto_ptr<SimpleAttribute> address(new SimpleAttribute(vector<string>(1, m_subjectAddress)));
305                                 address->getValues().push_back(temp.get());
306                                 attributes.push_back(address.get());
307                                 address.release();
308                             }
309                         }
310
311                         // DNSAddress
312                         if (!m_subjectDNS.empty() && locality->getDNSAddress() && *(locality->getDNSAddress())) {
313                             auto_ptr_char temp(locality->getDNSAddress());
314                             if (temp.get()) {
315                                 auto_ptr<SimpleAttribute> dns(new SimpleAttribute(vector<string>(1, m_subjectDNS)));
316                                 dns->getValues().push_back(temp.get());
317                                 attributes.push_back(dns.get());
318                                 dns.release();
319                             }
320                         }
321                     }
322                 }
323             }
324         }
325     }
326 }
327
328 void AssertionExtractor::getAttributeIds(vector<string>& attributes) const
329 {
330     if (!m_authnAuthority.empty())
331         attributes.push_back(m_authnAuthority);
332     if (!m_authnClass.empty())
333         attributes.push_back(m_authnClass);
334     if (!m_authnDecl.empty())
335         attributes.push_back(m_authnDecl);
336     if (!m_authnInstant.empty())
337         attributes.push_back(m_authnInstant);
338     if (!m_issuer.empty())
339         attributes.push_back(m_issuer);
340     if (!m_notOnOrAfter.empty())
341         attributes.push_back(m_notOnOrAfter);
342     if (!m_sessionIndex.empty())
343         attributes.push_back(m_sessionIndex);
344     if (!m_sessionNotOnOrAfter.empty())
345         attributes.push_back(m_sessionNotOnOrAfter);
346     if (!m_subjectAddress.empty())
347         attributes.push_back(m_subjectAddress);
348     if (!m_subjectDNS.empty())
349         attributes.push_back(m_subjectDNS);
350 }