VS10 solution files, convert from NULL macro to nullptr.
[shibboleth/sp.git] / shibsp / attribute / resolver / impl / KeyDescriptorAttributeExtractor.cpp
1 /*
2  *  Copyright 2009-2010 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  * KeyDescriptorAttributeExtractor.cpp
19  *
20  * AttributeExtractor for KeyDescriptor information.
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "Application.h"
26 #include "attribute/AttributeDecoder.h"
27 #include "attribute/SimpleAttribute.h"
28 #include "attribute/resolver/AttributeExtractor.h"
29
30 #include <saml/saml2/metadata/Metadata.h>
31 #include <saml/saml2/metadata/MetadataCredentialCriteria.h>
32 #include <saml/saml2/metadata/MetadataProvider.h>
33 #include <xmltooling/security/Credential.h>
34 #include <xmltooling/security/SecurityHelper.h>
35 #include <xmltooling/util/XMLHelper.h>
36 #include <xercesc/util/XMLUniDefs.hpp>
37
38 using namespace shibsp;
39 using namespace opensaml::saml2md;
40 using namespace opensaml;
41 using namespace xmltooling;
42 using namespace std;
43
44 namespace shibsp {
45
46 #if defined (_MSC_VER)
47     #pragma warning( push )
48     #pragma warning( disable : 4250 )
49 #endif
50
51     class KeyDescriptorExtractor : public AttributeExtractor
52     {
53     public:
54         KeyDescriptorExtractor(const DOMElement* e);
55         ~KeyDescriptorExtractor() {}
56
57         Lockable* lock() {
58             return this;
59         }
60
61         void unlock() {
62         }
63
64         void extractAttributes(
65             const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
66             ) const;
67
68         void getAttributeIds(std::vector<std::string>& attributes) const {
69             if (!m_hashId.empty())
70                 attributes.push_back(m_hashId.front());
71             if (!m_signingId.empty())
72                 attributes.push_back(m_signingId.front());
73             if (!m_encryptionId.empty())
74                 attributes.push_back(m_encryptionId.front());
75         }
76
77     private:
78         auto_ptr_char m_hashAlg;
79         vector<string> m_hashId;
80         vector<string> m_signingId;
81         vector<string> m_encryptionId;
82     };
83
84 #if defined (_MSC_VER)
85     #pragma warning( pop )
86 #endif
87
88     AttributeExtractor* SHIBSP_DLLLOCAL KeyDescriptorAttributeExtractorFactory(const DOMElement* const & e)
89     {
90         return new KeyDescriptorExtractor(e);
91     }
92
93     static const XMLCh encryptionId[] = UNICODE_LITERAL_12(e,n,c,r,y,p,t,i,o,n,I,d);
94     static const XMLCh hashId[] =       UNICODE_LITERAL_6(h,a,s,h,I,d);
95     static const XMLCh hashAlg[] =      UNICODE_LITERAL_7(h,a,s,h,A,l,g);
96     static const XMLCh signingId[] =    UNICODE_LITERAL_9(s,i,g,n,i,n,g,I,d);
97 };
98
99 KeyDescriptorExtractor::KeyDescriptorExtractor(const DOMElement* e) : m_hashAlg(e ? e->getAttributeNS(nullptr, hashAlg) : nullptr)
100 {
101     if (e) {
102         const XMLCh* a = e->getAttributeNS(nullptr, hashId);
103         if (a && *a) {
104             auto_ptr_char temp(a);
105             m_hashId.push_back(temp.get());
106         }
107         a = e->getAttributeNS(nullptr, signingId);
108         if (a && *a) {
109             auto_ptr_char temp(a);
110             m_signingId.push_back(temp.get());
111         }
112         a = e->getAttributeNS(nullptr, encryptionId);
113         if (a && *a) {
114             auto_ptr_char temp(a);
115             m_encryptionId.push_back(temp.get());
116         }
117     }
118     if (m_hashId.empty() && m_signingId.empty() && m_encryptionId.empty())
119         throw ConfigurationException("KeyDescriptor AttributeExtractor requires hashId, signingId, or encryptionId property.");
120 }
121
122 void KeyDescriptorExtractor::extractAttributes(
123     const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
124     ) const
125 {
126     const RoleDescriptor* role = dynamic_cast<const RoleDescriptor*>(&xmlObject);
127     if (!role)
128         return;
129
130     vector<const Credential*> creds;
131     MetadataCredentialCriteria mcc(*role);
132
133     if (!m_signingId.empty() || !m_hashId.empty()) {
134         mcc.setUsage(Credential::SIGNING_CREDENTIAL);
135         if (application.getMetadataProvider()->resolve(creds, &mcc)) {
136             if (!m_hashId.empty()) {
137                 const char* alg = m_hashAlg.get();
138                 if (!alg || !*alg)
139                     alg = "SHA1";
140                 auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_hashId));
141                 vector<string>& vals = attr->getValues();
142                 for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
143                     if (vals.empty() || !vals.back().empty())
144                         vals.push_back(string());
145                     vals.back() = SecurityHelper::getDEREncoding(*(*c), alg);
146                 }
147                 if (vals.back().empty())
148                     vals.pop_back();
149                 if (!vals.empty())
150                     attributes.push_back(attr.release());
151             }
152             if (!m_signingId.empty()) {
153                 auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_signingId));
154                 vector<string>& vals = attr->getValues();
155                 for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
156                     if (vals.empty() || !vals.back().empty())
157                         vals.push_back(string());
158                     vals.back() = SecurityHelper::getDEREncoding(*(*c));
159                 }
160                 if (vals.back().empty())
161                     vals.pop_back();
162                 if (!vals.empty())
163                     attributes.push_back(attr.release());
164             }
165             creds.clear();
166         }
167     }
168
169     if (!m_encryptionId.empty()) {
170         mcc.setUsage(Credential::ENCRYPTION_CREDENTIAL);
171         if (application.getMetadataProvider()->resolve(creds, &mcc)) {
172             auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_encryptionId));
173             vector<string>& vals = attr->getValues();
174             for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
175                 if (vals.empty() || !vals.back().empty())
176                     vals.push_back(string());
177                 vals.back() = SecurityHelper::getDEREncoding(*(*c));
178             }
179             if (vals.back().empty())
180                 vals.pop_back();
181             if (!vals.empty())
182                 attributes.push_back(attr.release());
183         }
184     }
185 }