SSPCPP-616 - clean up concatenated string literals
[shibboleth/cpp-sp.git] / shibsp / attribute / resolver / impl / DelegationAttributeExtractor.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  * DelegationAttributeExtractor.cpp
23  *
24  * AttributeExtractor for DelegationRestriction information.
25  */
26
27 #include "internal.h"
28 #include "Application.h"
29 #include "ServiceProvider.h"
30 #include "attribute/ExtensibleAttribute.h"
31 #include "attribute/resolver/AttributeExtractor.h"
32 #include "util/SPConstants.h"
33
34 #include <boost/shared_ptr.hpp>
35 #include <boost/iterator/indirect_iterator.hpp>
36 #include <saml/saml2/core/Assertions.h>
37 #include <saml/saml2/metadata/Metadata.h>
38 #include <saml/saml2/metadata/MetadataCredentialCriteria.h>
39 #include <xmltooling/security/CredentialResolver.h>
40 #include <xmltooling/util/DateTime.h>
41 #include <xmltooling/util/XMLHelper.h>
42 #include <xercesc/util/XMLUniDefs.hpp>
43
44 using namespace shibsp;
45 using namespace opensaml::saml2md;
46 using namespace opensaml;
47 using namespace xmltooling;
48 using namespace boost;
49 using namespace std;
50
51 namespace shibsp {
52
53 #if defined (_MSC_VER)
54     #pragma warning( push )
55     #pragma warning( disable : 4250 )
56 #endif
57
58     class DelegationExtractor : public AttributeExtractor
59     {
60     public:
61         DelegationExtractor(const DOMElement* e);
62         ~DelegationExtractor() {}
63
64         Lockable* lock() {
65             return this;
66         }
67
68         void unlock() {
69         }
70
71         void extractAttributes(
72             const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
73             ) const;
74
75         void getAttributeIds(std::vector<std::string>& attributes) const {
76             attributes.push_back(m_attributeId);
77         }
78
79     private:
80         string m_attributeId,m_formatter;
81     };
82
83 #if defined (_MSC_VER)
84     #pragma warning( pop )
85 #endif
86
87     AttributeExtractor* SHIBSP_DLLLOCAL DelegationAttributeExtractorFactory(const DOMElement* const & e)
88     {
89         return new DelegationExtractor(e);
90     }
91
92     static const XMLCh attributeId[] =  UNICODE_LITERAL_11(a,t,t,r,i,b,u,t,e,I,d);
93     static const XMLCh formatter[] =    UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
94 };
95
96 DelegationExtractor::DelegationExtractor(const DOMElement* e)
97     : m_attributeId(XMLHelper::getAttrString(e, "delegate", attributeId)),
98         m_formatter(XMLHelper::getAttrString(e, "$Name", formatter))
99 {
100 }
101
102 void DelegationExtractor::extractAttributes(
103     const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
104     ) const
105 {
106     const saml2::Assertion* assertion = dynamic_cast<const saml2::Assertion*>(&xmlObject);
107     if (!assertion || !assertion->getConditions())
108         return;
109
110     Category& log = Category::getInstance(SHIBSP_LOGCAT ".AttributeExtractor.Delegation");
111
112     const vector<saml2::Condition*>& conditions = const_cast<const saml2::Conditions*>(assertion->getConditions())->getConditions();
113     for (vector<saml2::Condition*>::const_iterator c = conditions.begin(); c != conditions.end(); ++c) {
114         const saml2::DelegationRestrictionType* drt = dynamic_cast<const saml2::DelegationRestrictionType*>(*c);
115         if (drt) {
116             auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(vector<string>(1,m_attributeId), m_formatter.c_str()));
117
118             const vector<saml2::Delegate*>& dels = drt->getDelegates();
119             for (indirect_iterator<vector<saml2::Delegate*>::const_iterator> d = make_indirect_iterator(dels.begin());
120                     d != make_indirect_iterator(dels.end()); ++d) {
121                 if (d->getBaseID()) {
122                     log.error("delegate identified by saml:BaseID cannot be processed into an attribute value");
123                     continue;
124                 }
125
126                 saml2::NameID* n = nullptr;
127                 boost::shared_ptr<saml2::NameID> namewrapper;
128                 if (d->getEncryptedID()) {
129                     CredentialResolver* cr = application.getCredentialResolver();
130                     if (!cr) {
131                         log.warn("found encrypted Delegate, but no CredentialResolver was available");
132                     }
133
134                     try {
135                         const XMLCh* recipient = application.getRelyingParty(
136                             issuer ? dynamic_cast<EntityDescriptor*>(issuer->getParent()) : nullptr
137                             )->getXMLString("entityID").second;
138                         Locker credlocker(cr);
139                         if (issuer) {
140                             MetadataCredentialCriteria mcc(*issuer);
141                             boost::shared_ptr<XMLObject> decrypted(d->getEncryptedID()->decrypt(*cr, recipient, &mcc));
142                             namewrapper = dynamic_pointer_cast<saml2::NameID>(decrypted);
143                             n = namewrapper.get();
144                         }
145                         else {
146                             boost::shared_ptr<XMLObject> decrypted(d->getEncryptedID()->decrypt(*cr, recipient));
147                             namewrapper = dynamic_pointer_cast<saml2::NameID>(decrypted);
148                             n = namewrapper.get();
149                         }
150                         if (n && log.isDebugEnabled())
151                             log.debugStream() << "decrypted Delegate: " << *n << logging::eol;
152                     }
153                     catch (std::exception& ex) {
154                         log.error("caught exception decrypting Delegate: %s", ex.what());
155                     }
156                 }
157                 else {
158                     n = d->getNameID();
159                 }
160
161                 if (n) {
162                     DDF val = DDF(nullptr).structure();
163                     if (d->getConfirmationMethod()) {
164                         auto_ptr_char temp(d->getConfirmationMethod());
165                         val.addmember("ConfirmationMethod").string(temp.get());
166                     }
167                     if (d->getDelegationInstant()) {
168                         auto_ptr_char temp(d->getDelegationInstant()->getRawData());
169                         val.addmember("DelegationInstant").string(temp.get());
170                     }
171
172                     auto_arrayptr<char> name(toUTF8(n->getName()));
173                     if (name.get() && *name.get()) {
174                         val.addmember("Name").string(name.get());
175                         auto_arrayptr<char> format(toUTF8(n->getFormat()));
176                         if (format.get())
177                             val.addmember("Format").string(format.get());
178
179                         auto_arrayptr<char> nq(toUTF8(n->getNameQualifier()));
180                         if (nq.get())
181                             val.addmember("NameQualifier").string(nq.get());
182
183                         auto_arrayptr<char> spnq(toUTF8(n->getSPNameQualifier()));
184                         if (spnq.get())
185                             val.addmember("SPNameQualifier").string(spnq.get());
186
187                         auto_arrayptr<char> sppid(toUTF8(n->getSPProvidedID()));
188                         if (sppid.get())
189                             val.addmember("SPProvidedID").string(sppid.get());
190                     }
191
192                     if (val.integer())
193                         attr->getValues().add(val);
194                     else
195                         val.destroy();
196                 }
197             }
198
199             attributes.push_back(attr.get());
200             attr.release();
201         }
202     }
203 }