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/Protocols.h>
35 #include <saml/saml2/metadata/Metadata.h>
36 #include <xmltooling/util/XMLHelper.h>
37 #include <xercesc/util/XMLUniDefs.hpp>
38
39 using namespace shibsp;
40 using namespace opensaml::saml2;
41 using namespace opensaml::saml2md;
42 using namespace opensaml::saml1;
43 using namespace opensaml;
44 using namespace xmltooling;
45 using namespace std;
46
47 namespace shibsp {
48
49 #if defined (_MSC_VER)
50 #pragma warning( push )
51 #pragma warning( disable : 4250 )
52 #endif
53
54 class AssertionExtractor : public AttributeExtractor
55 {
56 public:
57 AssertionExtractor(const DOMElement* e);
~AssertionExtractor()58 ~AssertionExtractor() {}
59
lock()60 Lockable* lock() {
61 return this;
62 }
63
unlock()64 void unlock() {
65 }
66
67 void extractAttributes(
68 const Application& application,
69 const GenericRequest* request,
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_issuerFormat,
83 m_notBefore,
84 m_notOnOrAfter,
85 m_sessionIndex,
86 m_sessionNotOnOrAfter,
87 m_subjectAddress,
88 m_subjectDNS,
89 m_consent;
90 };
91
92 #if defined (_MSC_VER)
93 #pragma warning( pop )
94 #endif
95
AssertionAttributeExtractorFactory(const DOMElement * const & e,bool)96 AttributeExtractor* SHIBSP_DLLLOCAL AssertionAttributeExtractorFactory(const DOMElement* const & e, bool)
97 {
98 return new AssertionExtractor(e);
99 }
100
101 static const XMLCh IssuerFormat[] = UNICODE_LITERAL_12(I,s,s,u,e,r,F,o,r,m,a,t);
102 };
103
AssertionExtractor(const DOMElement * e)104 AssertionExtractor::AssertionExtractor(const DOMElement* e)
105 : m_authnAuthority(XMLHelper::getAttrString(e, nullptr, AuthenticatingAuthority::LOCAL_NAME)),
106 m_authnClass(XMLHelper::getAttrString(e, nullptr, AuthnContextClassRef::LOCAL_NAME)),
107 m_authnDecl(XMLHelper::getAttrString(e, nullptr, AuthnContextDeclRef::LOCAL_NAME)),
108 m_authnInstant(XMLHelper::getAttrString(e, nullptr, AuthnStatement::AUTHNINSTANT_ATTRIB_NAME)),
109 m_issuer(XMLHelper::getAttrString(e, nullptr, Issuer::LOCAL_NAME)),
110 m_issuerFormat(XMLHelper::getAttrString(e, nullptr, IssuerFormat)),
111 m_notBefore(XMLHelper::getAttrString(e, nullptr, saml2::Conditions::NOTBEFORE_ATTRIB_NAME)),
112 m_notOnOrAfter(XMLHelper::getAttrString(e, nullptr, saml2::Conditions::NOTONORAFTER_ATTRIB_NAME)),
113 m_sessionIndex(XMLHelper::getAttrString(e, nullptr, AuthnStatement::SESSIONINDEX_ATTRIB_NAME)),
114 m_sessionNotOnOrAfter(XMLHelper::getAttrString(e, nullptr, AuthnStatement::SESSIONNOTONORAFTER_ATTRIB_NAME)),
115 m_subjectAddress(XMLHelper::getAttrString(e, nullptr, saml2::SubjectLocality::ADDRESS_ATTRIB_NAME)),
116 m_subjectDNS(XMLHelper::getAttrString(e, nullptr, saml2::SubjectLocality::DNSNAME_ATTRIB_NAME)),
117 m_consent(XMLHelper::getAttrString(e, nullptr, saml2p::StatusResponseType::CONSENT_ATTRIB_NAME))
118 {
119 }
120
extractAttributes(const Application & application,const GenericRequest * request,const RoleDescriptor * issuer,const XMLObject & xmlObject,vector<shibsp::Attribute * > & attributes) const121 void AssertionExtractor::extractAttributes(
122 const Application& application, const GenericRequest* request, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<shibsp::Attribute*>& attributes
123 ) const
124 {
125 const saml2p::StatusResponseType* srt = dynamic_cast<const saml2p::StatusResponseType*>(&xmlObject);
126 if (srt) {
127 // Consent
128 if (!m_consent.empty() && srt->getConsent()) {
129 auto_ptr_char temp(srt->getConsent());
130 if (temp.get() && *temp.get()) {
131 auto_ptr<SimpleAttribute> consent(new SimpleAttribute(vector<string>(1, m_consent)));
132 consent->getValues().push_back(temp.get());
133 attributes.push_back(consent.get());
134 consent.release();
135 }
136 }
137 return;
138 }
139
140 const saml2::Assertion* saml2assertion = dynamic_cast<const saml2::Assertion*>(&xmlObject);
141 if (saml2assertion) {
142
143 if (saml2assertion->getIssuer()) {
144 // Issuer
145 if (!m_issuer.empty()) {
146 auto_ptr_char temp(saml2assertion->getIssuer()->getName());
147 if (temp.get() && *temp.get()) {
148 auto_ptr<SimpleAttribute> issuer(new SimpleAttribute(vector<string>(1, m_issuer)));
149 issuer->getValues().push_back(temp.get());
150 attributes.push_back(issuer.get());
151 issuer.release();
152 }
153 }
154
155 // Format
156 if (!m_issuerFormat.empty()) {
157 auto_ptr_char temp(saml2assertion->getIssuer()->getFormat());
158 if (temp.get()) {
159 auto_ptr<SimpleAttribute> format(new SimpleAttribute(vector<string>(1, m_issuerFormat)));
160 format->getValues().push_back(temp.get());
161 attributes.push_back(format.get());
162 format.release();
163 }
164 }
165 }
166
167 // NotBefore / NotOnOrAfter
168 if (saml2assertion->getConditions()) {
169 if (!m_notBefore.empty() && saml2assertion->getConditions()->getNotBefore()) {
170 auto_ptr_char temp(saml2assertion->getConditions()->getNotBefore()->getRawData());
171 if (temp.get()) {
172 auto_ptr<SimpleAttribute> notbefore(new SimpleAttribute(vector<string>(1, m_notBefore)));
173 notbefore->getValues().push_back(temp.get());
174 attributes.push_back(notbefore.get());
175 notbefore.release();
176 }
177 }
178 if (!m_notOnOrAfter.empty() && saml2assertion->getConditions()->getNotOnOrAfter()) {
179 auto_ptr_char temp(saml2assertion->getConditions()->getNotOnOrAfter()->getRawData());
180 if (temp.get()) {
181 auto_ptr<SimpleAttribute> notonorafter(new SimpleAttribute(vector<string>(1, m_notOnOrAfter)));
182 notonorafter->getValues().push_back(temp.get());
183 attributes.push_back(notonorafter.get());
184 notonorafter.release();
185 }
186 }
187 }
188
189 return;
190 }
191
192 const AuthnStatement* saml2statement = dynamic_cast<const AuthnStatement*>(&xmlObject);
193 if (saml2statement) {
194 // AuthnInstant
195 if (!m_authnInstant.empty() && saml2statement->getAuthnInstant()) {
196 auto_ptr_char temp(saml2statement->getAuthnInstant()->getRawData());
197 if (temp.get()) {
198 auto_ptr<SimpleAttribute> authninstant(new SimpleAttribute(vector<string>(1, m_authnInstant)));
199 authninstant->getValues().push_back(temp.get());
200 attributes.push_back(authninstant.get());
201 authninstant.release();
202 }
203 }
204
205 // SessionIndex
206 if (!m_sessionIndex.empty() && saml2statement->getSessionIndex() && *(saml2statement->getSessionIndex())) {
207 auto_ptr_char temp(saml2statement->getSessionIndex());
208 if (temp.get()) {
209 auto_ptr<SimpleAttribute> sessionindex(new SimpleAttribute(vector<string>(1, m_sessionIndex)));
210 sessionindex->getValues().push_back(temp.get());
211 attributes.push_back(sessionindex.get());
212 sessionindex.release();
213 }
214 }
215
216 // SessionNotOnOrAfter
217 if (!m_sessionNotOnOrAfter.empty() && saml2statement->getSessionNotOnOrAfter()) {
218 auto_ptr_char temp(saml2statement->getSessionNotOnOrAfter()->getRawData());
219 if (temp.get()) {
220 auto_ptr<SimpleAttribute> sessionnotonorafter(new SimpleAttribute(vector<string>(1, m_sessionNotOnOrAfter)));
221 sessionnotonorafter->getValues().push_back(temp.get());
222 attributes.push_back(sessionnotonorafter.get());
223 sessionnotonorafter.release();
224 }
225 }
226
227 if (saml2statement->getSubjectLocality()) {
228 const saml2::SubjectLocality* locality = saml2statement->getSubjectLocality();
229 // Address
230 if (!m_subjectAddress.empty() && locality->getAddress() && *(locality->getAddress())) {
231 auto_ptr_char temp(locality->getAddress());
232 if (temp.get()) {
233 auto_ptr<SimpleAttribute> address(new SimpleAttribute(vector<string>(1, m_subjectAddress)));
234 address->getValues().push_back(temp.get());
235 attributes.push_back(address.get());
236 address.release();
237 }
238 }
239
240 // DNSName
241 if (!m_subjectDNS.empty() && locality->getDNSName() && *(locality->getDNSName())) {
242 auto_ptr_char temp(locality->getDNSName());
243 if (temp.get()) {
244 auto_ptr<SimpleAttribute> dns(new SimpleAttribute(vector<string>(1, m_subjectDNS)));
245 dns->getValues().push_back(temp.get());
246 attributes.push_back(dns.get());
247 dns.release();
248 }
249 }
250 }
251
252 if (saml2statement->getAuthnContext()) {
253 const AuthnContext* ac = saml2statement->getAuthnContext();
254 // AuthnContextClassRef
255 if (!m_authnClass.empty() && ac->getAuthnContextClassRef() && ac->getAuthnContextClassRef()->getReference()) {
256 auto_ptr_char temp(ac->getAuthnContextClassRef()->getReference());
257 if (temp.get()) {
258 auto_ptr<SimpleAttribute> classref(new SimpleAttribute(vector<string>(1, m_authnClass)));
259 classref->getValues().push_back(temp.get());
260 attributes.push_back(classref.get());
261 classref.release();
262 }
263 }
264
265 // AuthnContextDeclRef
266 if (!m_authnDecl.empty() && ac->getAuthnContextDeclRef() && ac->getAuthnContextDeclRef()->getReference()) {
267 auto_ptr_char temp(ac->getAuthnContextDeclRef()->getReference());
268 if (temp.get()) {
269 auto_ptr<SimpleAttribute> declref(new SimpleAttribute(vector<string>(1, m_authnDecl)));
270 declref->getValues().push_back(temp.get());
271 attributes.push_back(declref.get());
272 declref.release();
273 }
274 }
275
276 // AuthenticatingAuthority
277 if (!m_authnAuthority.empty() && !ac->getAuthenticatingAuthoritys().empty()) {
278 auto_ptr<SimpleAttribute> attr(new SimpleAttribute(vector<string>(1, m_authnAuthority)));
279 const vector<AuthenticatingAuthority*>& authorities = ac->getAuthenticatingAuthoritys();
280 for (vector<AuthenticatingAuthority*>::const_iterator a = authorities.begin(); a != authorities.end(); ++a) {
281 auto_ptr_char temp((*a)->getID());
282 if (temp.get())
283 attr->getValues().push_back(temp.get());
284 }
285 if (attr->valueCount() > 0) {
286 attributes.push_back(attr.get());
287 attr.release();
288 }
289 }
290 }
291
292 return;
293 }
294
295 const saml1::Assertion* saml1assertion = dynamic_cast<const saml1::Assertion*>(&xmlObject);
296 if (saml1assertion) {
297 // Issuer
298 if (!m_issuer.empty()) {
299 if (saml1assertion->getIssuer() && *(saml1assertion->getIssuer())) {
300 auto_ptr_char temp(saml1assertion->getIssuer());
301 if (temp.get()) {
302 auto_ptr<SimpleAttribute> issuer(new SimpleAttribute(vector<string>(1, m_issuer)));
303 issuer->getValues().push_back(temp.get());
304 attributes.push_back(issuer.get());
305 issuer.release();
306 }
307 }
308 }
309
310 // NotOnOrAfter
311 if (!m_notOnOrAfter.empty() && saml1assertion->getConditions() && saml1assertion->getConditions()->getNotOnOrAfter()) {
312 auto_ptr_char temp(saml1assertion->getConditions()->getNotOnOrAfter()->getRawData());
313 if (temp.get()) {
314 auto_ptr<SimpleAttribute> notonorafter(new SimpleAttribute(vector<string>(1, m_notOnOrAfter)));
315 notonorafter->getValues().push_back(temp.get());
316 attributes.push_back(notonorafter.get());
317 notonorafter.release();
318 }
319 }
320
321 return;
322 }
323
324 const AuthenticationStatement* saml1statement = dynamic_cast<const AuthenticationStatement*>(&xmlObject);
325 if (saml1statement) {
326 // AuthnInstant
327 if (!m_authnInstant.empty() && saml1statement->getAuthenticationInstant()) {
328 auto_ptr_char temp(saml1statement->getAuthenticationInstant()->getRawData());
329 if (temp.get()) {
330 auto_ptr<SimpleAttribute> authninstant(new SimpleAttribute(vector<string>(1, m_authnInstant)));
331 authninstant->getValues().push_back(temp.get());
332 attributes.push_back(authninstant.get());
333 authninstant.release();
334 }
335 }
336
337 // AuthenticationMethod
338 if (!m_authnClass.empty() && saml1statement->getAuthenticationMethod() && *(saml1statement->getAuthenticationMethod())) {
339 auto_ptr_char temp(saml1statement->getAuthenticationMethod());
340 if (temp.get()) {
341 auto_ptr<SimpleAttribute> authnmethod(new SimpleAttribute(vector<string>(1, m_authnClass)));
342 authnmethod->getValues().push_back(temp.get());
343 attributes.push_back(authnmethod.get());
344 authnmethod.release();
345 }
346 }
347
348 if (saml1statement->getSubjectLocality()) {
349 const saml1::SubjectLocality* locality = saml1statement->getSubjectLocality();
350 // IPAddress
351 if (!m_subjectAddress.empty() && locality->getIPAddress() && *(locality->getIPAddress())) {
352 auto_ptr_char temp(locality->getIPAddress());
353 if (temp.get()) {
354 auto_ptr<SimpleAttribute> address(new SimpleAttribute(vector<string>(1, m_subjectAddress)));
355 address->getValues().push_back(temp.get());
356 attributes.push_back(address.get());
357 address.release();
358 }
359 }
360
361 // DNSAddress
362 if (!m_subjectDNS.empty() && locality->getDNSAddress() && *(locality->getDNSAddress())) {
363 auto_ptr_char temp(locality->getDNSAddress());
364 if (temp.get()) {
365 auto_ptr<SimpleAttribute> dns(new SimpleAttribute(vector<string>(1, m_subjectDNS)));
366 dns->getValues().push_back(temp.get());
367 attributes.push_back(dns.get());
368 dns.release();
369 }
370 }
371 }
372 }
373 }
374
getAttributeIds(vector<string> & attributes) const375 void AssertionExtractor::getAttributeIds(vector<string>& attributes) const
376 {
377 if (!m_authnAuthority.empty())
378 attributes.push_back(m_authnAuthority);
379 if (!m_authnClass.empty())
380 attributes.push_back(m_authnClass);
381 if (!m_authnDecl.empty())
382 attributes.push_back(m_authnDecl);
383 if (!m_authnInstant.empty())
384 attributes.push_back(m_authnInstant);
385 if (!m_issuer.empty())
386 attributes.push_back(m_issuer);
387 if (!m_notOnOrAfter.empty())
388 attributes.push_back(m_notOnOrAfter);
389 if (!m_sessionIndex.empty())
390 attributes.push_back(m_sessionIndex);
391 if (!m_sessionNotOnOrAfter.empty())
392 attributes.push_back(m_sessionNotOnOrAfter);
393 if (!m_subjectAddress.empty())
394 attributes.push_back(m_subjectAddress);
395 if (!m_subjectDNS.empty())
396 attributes.push_back(m_subjectDNS);
397 if (!m_consent.empty())
398 attributes.push_back(m_consent);
399 }
400