New "extensible" DDF-backed attribute type, and a delegation extractor using it.
[shibboleth/cpp-sp.git] / shibsp / attribute / resolver / impl / DelegationAttributeExtractor.cpp
1 /*
2  *  Copyright 2009 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 /**
18  * DelegationAttributeExtractor.cpp
19  *
20  * AttributeExtractor for DelegationRestriction information.
21  */
22
23 #include "internal.h"
24 #include "Application.h"
25 #include "ServiceProvider.h"
26 #include "attribute/ExtensibleAttribute.h"
27 #include "attribute/resolver/AttributeExtractor.h"
28 #include "util/SPConstants.h"
29
30 #include <saml/saml2/core/Assertions.h>
31 #include <saml/saml2/metadata/MetadataCredentialCriteria.h>
32 #include <xmltooling/util/XMLHelper.h>
33 #include <xercesc/util/XMLUniDefs.hpp>
34
35 using namespace shibsp;
36 using namespace opensaml::saml2md;
37 using namespace opensaml;
38 using namespace xmltooling;
39 using namespace std;
40
41 namespace shibsp {
42
43 #if defined (_MSC_VER)
44     #pragma warning( push )
45     #pragma warning( disable : 4250 )
46 #endif
47
48     class DelegationExtractor : public AttributeExtractor
49     {
50     public:
51         DelegationExtractor(const DOMElement* e);
52         ~DelegationExtractor() {}
53
54         Lockable* lock() {
55             return this;
56         }
57
58         void unlock() {
59         }
60
61         void extractAttributes(
62             const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
63             ) const;
64
65         void getAttributeIds(std::vector<std::string>& attributes) const {
66             attributes.push_back(m_attributeId);
67         }
68
69     private:
70         string m_attributeId,m_formatter;
71     };
72
73 #if defined (_MSC_VER)
74     #pragma warning( pop )
75 #endif
76
77     AttributeExtractor* SHIBSP_DLLLOCAL DelegationAttributeExtractorFactory(const DOMElement* const & e)
78     {
79         return new DelegationExtractor(e);
80     }
81
82     static const XMLCh attributeId[] =  UNICODE_LITERAL_11(a,t,t,r,i,b,u,t,e,I,d);
83     static const XMLCh formatter[] =    UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
84 };
85
86 DelegationExtractor::DelegationExtractor(const DOMElement* e) : m_attributeId("delegate"), m_formatter("$Name")
87 {
88     if (e) {
89         const XMLCh* a = e->getAttributeNS(NULL, attributeId);
90         if (a && *a) {
91             auto_ptr_char temp(a);
92             m_attributeId = temp.get();
93         }
94         a = e->getAttributeNS(NULL, formatter);
95         if (a && *a) {
96             auto_ptr_char temp(a);
97             m_formatter = temp.get();
98         }
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     const vector<saml2::Condition*>& conditions = const_cast<const saml2::Conditions*>(assertion->getConditions())->getConditions();
111     for (vector<saml2::Condition*>::const_iterator c = conditions.begin(); c != conditions.end(); ++c) {
112         const saml2::DelegationRestrictionType* drt = dynamic_cast<const saml2::DelegationRestrictionType*>(*c);
113         if (drt) {
114             auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(vector<string>(1,m_attributeId), m_formatter.c_str()));
115
116             const vector<saml2::Delegate*>& dels = drt->getDelegates();
117             for (vector<saml2::Delegate*>::const_iterator d = dels.begin(); d != dels.end(); ++d) {
118                 if ((*d)->getBaseID()) {
119                     Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.Delegation").error(
120                         "delegate identified by saml:BaseID cannot be processed into an attribute value"
121                         );
122                     continue;
123                 }
124
125                 saml2::NameID* n = NULL;
126                 if ((*d)->getEncryptedID()) {
127                     // TODO: add decryption
128                 }
129                 else {
130                     n = (*d)->getNameID();
131                 }
132                 if (n) {
133                     DDF val = DDF(NULL).structure();
134                     if ((*d)->getConfirmationMethod()) {
135                         auto_ptr_char temp((*d)->getConfirmationMethod());
136                         val.addmember("ConfirmationMethod").string(temp.get());
137                     }
138                     if ((*d)->getDelegationInstant()) {
139                         auto_ptr_char temp((*d)->getDelegationInstant()->getRawData());
140                         val.addmember("DelegationInstant").string(temp.get());
141                     }
142
143                     auto_arrayptr<char> name(toUTF8(n->getName()));\r
144                     if (name.get() && *name.get()) {\r
145                         val.addmember("Name").string(name.get());\r
146                         char* str = toUTF8(n->getFormat());\r
147                         if (str && *str)\r
148                             val.addmember("Format").string(str);\r
149                         delete[] str;\r
150 \r
151                         str = toUTF8(n->getNameQualifier());\r
152                         if (str && *str)\r
153                             val.addmember("NameQualifier").string(str);\r
154                         delete[] str;\r
155 \r
156                         str = toUTF8(n->getSPNameQualifier());\r
157                         if (str && *str)\r
158                             val.addmember("SPNameQualifier").string(str);\r
159                         delete[] str;\r
160 \r
161                         str = toUTF8(n->getSPProvidedID());\r
162                         if (str && *str)\r
163                             val.addmember("SPProvidedID").string(str);\r
164                         delete[] str;\r
165                     }\r
166
167                     if (n != (*d)->getNameID())
168                         delete n;
169
170                     if (val.integer())
171                         attr->getValues().add(val);
172                     else
173                         val.destroy();
174                 }
175             }
176
177             attributes.push_back(attr.release());
178         }
179     }
180 }