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.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * shibsp/attribute/Attribute.cpp
24 * A resolved attribute.
28 #include "exceptions.h"
30 #include "attribute/SimpleAttribute.h"
32 # include "attribute/AttributeDecoder.h"
34 #include "util/SPConstants.h"
36 #include <xmltooling/XMLObject.h>
37 #include <xmltooling/security/SecurityHelper.h>
38 #include <xmltooling/util/XMLHelper.h>
39 #include <xercesc/util/XMLUniDefs.hpp>
41 using namespace shibsp;
42 using namespace xmltooling;
46 SHIBSP_DLLLOCAL Attribute* SimpleAttributeFactory(DDF& in);
47 SHIBSP_DLLLOCAL Attribute* ScopedAttributeFactory(DDF& in);
48 SHIBSP_DLLLOCAL Attribute* NameIDAttributeFactory(DDF& in);
49 SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in);
50 SHIBSP_DLLLOCAL Attribute* XMLAttributeFactory(DDF& in);
51 SHIBSP_DLLLOCAL Attribute* BinaryAttributeFactory(DDF& in);
54 SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory StringAttributeDecoderFactory;
55 SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory ScopedAttributeDecoderFactory;
56 SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory NameIDAttributeDecoderFactory;
57 SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory NameIDFromScopedAttributeDecoderFactory;
58 SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory KeyInfoAttributeDecoderFactory;
59 SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory DOMAttributeDecoderFactory;
60 SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory XMLAttributeDecoderFactory;
61 SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory Base64AttributeDecoderFactory;
63 static const XMLCh _StringAttributeDecoder[] = UNICODE_LITERAL_22(S,t,r,i,n,g,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
64 static const XMLCh _ScopedAttributeDecoder[] = UNICODE_LITERAL_22(S,c,o,p,e,d,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
65 static const XMLCh _NameIDAttributeDecoder[] = UNICODE_LITERAL_22(N,a,m,e,I,D,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
66 static const XMLCh _NameIDFromScopedAttributeDecoder[] = UNICODE_LITERAL_32(N,a,m,e,I,D,F,r,o,m,S,c,o,p,e,d,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
67 static const XMLCh _KeyInfoAttributeDecoder[] =UNICODE_LITERAL_23(K,e,y,I,n,f,o,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
68 static const XMLCh _DOMAttributeDecoder[] = UNICODE_LITERAL_19(D,O,M,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
69 static const XMLCh _XMLAttributeDecoder[] = UNICODE_LITERAL_19(X,M,L,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
70 static const XMLCh _Base64AttributeDecoder[] = {
71 chLatin_B, chLatin_a, chLatin_s, chLatin_e, chDigit_6, chDigit_4,
72 chLatin_A, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,
73 chLatin_D, chLatin_e, chLatin_c, chLatin_o, chLatin_d, chLatin_e, chLatin_r, chNull
76 static const XMLCh caseSensitive[] = UNICODE_LITERAL_13(c,a,s,e,S,e,n,s,i,t,i,v,e);
77 static const XMLCh hashAlg[] = UNICODE_LITERAL_7(h,a,s,h,A,l,g);
78 static const XMLCh internal[] = UNICODE_LITERAL_8(i,n,t,e,r,n,a,l);
79 static const XMLCh langAware[] = UNICODE_LITERAL_9(l,a,n,g,A,w,a,r,e);
84 xmltooling::QName shibsp::StringAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _StringAttributeDecoder);
85 xmltooling::QName shibsp::ScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _ScopedAttributeDecoder);
86 xmltooling::QName shibsp::NameIDAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDAttributeDecoder);
87 xmltooling::QName shibsp::NameIDFromScopedAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _NameIDFromScopedAttributeDecoder);
88 xmltooling::QName shibsp::KeyInfoAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _KeyInfoAttributeDecoder);
89 xmltooling::QName shibsp::DOMAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _DOMAttributeDecoder);
90 xmltooling::QName shibsp::XMLAttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _XMLAttributeDecoder);
91 xmltooling::QName shibsp::Base64AttributeDecoderType(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _Base64AttributeDecoder);
93 void shibsp::registerAttributeDecoders()
95 SPConfig& conf = SPConfig::getConfig();
96 conf.AttributeDecoderManager.registerFactory(StringAttributeDecoderType, StringAttributeDecoderFactory);
97 conf.AttributeDecoderManager.registerFactory(ScopedAttributeDecoderType, ScopedAttributeDecoderFactory);
98 conf.AttributeDecoderManager.registerFactory(NameIDAttributeDecoderType, NameIDAttributeDecoderFactory);
99 conf.AttributeDecoderManager.registerFactory(NameIDFromScopedAttributeDecoderType, NameIDFromScopedAttributeDecoderFactory);
100 conf.AttributeDecoderManager.registerFactory(KeyInfoAttributeDecoderType, KeyInfoAttributeDecoderFactory);
101 conf.AttributeDecoderManager.registerFactory(DOMAttributeDecoderType, DOMAttributeDecoderFactory);
102 conf.AttributeDecoderManager.registerFactory(XMLAttributeDecoderType, XMLAttributeDecoderFactory);
103 conf.AttributeDecoderManager.registerFactory(Base64AttributeDecoderType, Base64AttributeDecoderFactory);
106 AttributeDecoder::AttributeDecoder(const DOMElement *e)
107 : m_caseSensitive(XMLHelper::getAttrBool(e, true, caseSensitive)),
108 m_internal(XMLHelper::getAttrBool(e, false, internal)),
109 m_langAware(XMLHelper::getAttrBool(e, false, langAware)),
110 m_hashAlg(XMLHelper::getAttrString(e, nullptr, hashAlg))
114 AttributeDecoder::~AttributeDecoder()
118 Attribute* AttributeDecoder::decode(
119 const GenericRequest* request,
120 const std::vector<std::string>& ids,
121 const xmltooling::XMLObject* xmlObject,
122 const char* assertingParty,
123 const char* relyingParty
126 // Default call into deprecated method.
127 return decode(ids, xmlObject, assertingParty, relyingParty);
130 Attribute* AttributeDecoder::decode(
131 const std::vector<std::string>& ids,
132 const xmltooling::XMLObject* xmlObject,
133 const char* assertingParty,
134 const char* relyingParty
137 // Default for deprecated method.
141 Attribute* AttributeDecoder::_decode(Attribute* attr) const
144 attr->setCaseSensitive(m_caseSensitive);
145 attr->setInternal(m_internal);
147 if (!m_hashAlg.empty()) {
148 // We turn the values into strings using the supplied hash algorithm and return a SimpleAttribute instead.
149 auto_ptr<SimpleAttribute> simple(new SimpleAttribute(attr->getAliases()));
150 simple->setCaseSensitive(false);
151 simple->setInternal(m_internal);
152 vector<string>& newdest = simple->getValues();
153 const vector<string>& serialized = attr->getSerializedValues();
154 for (vector<string>::const_iterator ser = serialized.begin(); ser != serialized.end(); ++ser) {
155 newdest.push_back(SecurityHelper::doHash(m_hashAlg.c_str(), ser->data(), ser->length()));
156 if (newdest.back().empty())
160 return newdest.empty() ? nullptr : simple.release();
167 pair<vector<XMLObject*>::const_iterator,vector<XMLObject*>::const_iterator> AttributeDecoder::valueRange(
168 const GenericRequest* request, const vector<XMLObject*>& objects
171 if (!m_langAware || !request || objects.empty()) {
172 return make_pair(objects.begin(), objects.end());
174 else if (request && request->startLangMatching()) {
176 for (vector<XMLObject*>::const_iterator i = objects.begin(); i != objects.end(); ++i) {
177 if (request->matchLang((*i)->getLang())) {
178 return make_pair(i, i + 1);
181 } while (request->continueLangMatching());
184 return make_pair(objects.begin(), objects.begin() + 1);
188 void shibsp::registerAttributeFactories()
190 Attribute::registerFactory("", SimpleAttributeFactory);
191 Attribute::registerFactory("Simple", SimpleAttributeFactory);
192 Attribute::registerFactory("Binary", BinaryAttributeFactory);
193 Attribute::registerFactory("Scoped", ScopedAttributeFactory);
194 Attribute::registerFactory("NameID", NameIDAttributeFactory);
195 Attribute::registerFactory("Extensible", ExtensibleAttributeFactory);
196 Attribute::registerFactory("XML", XMLAttributeFactory);
199 map<string,Attribute::AttributeFactory*> Attribute::m_factoryMap;
201 void Attribute::registerFactory(const char* type, AttributeFactory* factory)
203 m_factoryMap[type] = factory;
206 void Attribute::deregisterFactory(const char* type)
208 m_factoryMap.erase(type);
211 void Attribute::deregisterFactories()
213 m_factoryMap.clear();
216 Attribute::Attribute(const vector<string>& ids) : m_id(ids), m_caseSensitive(true), m_internal(false)
220 Attribute::Attribute(DDF& in) : m_caseSensitive(in["case_insensitive"].isnull()), m_internal(!in["internal"].isnull())
222 const char* id = in.first().name();
226 throw AttributeException("No id found in marshalled attribute content.");
227 DDF aliases = in["aliases"];
228 if (aliases.islist()) {
229 DDF alias = aliases.first();
230 while (alias.isstring()) {
231 m_id.push_back(alias.string());
232 alias = aliases.next();
237 Attribute::~Attribute()
241 const char* Attribute::getId() const
243 return m_id.front().c_str();
246 const vector<string>& Attribute::getAliases() const
251 vector<string>& Attribute::getAliases()
256 void Attribute::setCaseSensitive(bool caseSensitive)
258 m_caseSensitive = caseSensitive;
261 void Attribute::setInternal(bool internal)
263 m_internal = internal;
266 bool Attribute::isCaseSensitive() const
268 return m_caseSensitive;
271 bool Attribute::isInternal() const
276 size_t Attribute::valueCount() const
278 return m_serialized.size();
281 const vector<string>& Attribute::getSerializedValues() const
286 const char* Attribute::getString(size_t index) const
288 return m_serialized[index].c_str();
291 const char* Attribute::getScope(size_t index) const
296 void Attribute::removeValue(size_t index)
298 if (index < m_serialized.size())
299 m_serialized.erase(m_serialized.begin() + index);
302 DDF Attribute::marshall() const
305 ddf.structure().addmember(m_id.front().c_str()).list();
306 if (!m_caseSensitive)
307 ddf.addmember("case_insensitive");
309 ddf.addmember("internal");
310 if (m_id.size() > 1) {
312 DDF aliases = ddf.addmember("aliases").list();
313 for (std::vector<std::string>::const_iterator a = m_id.begin() + 1; a != m_id.end(); ++a) {
314 alias = DDF(nullptr).string(a->c_str());
321 Attribute* Attribute::unmarshall(DDF& in)
323 map<string,AttributeFactory*>::const_iterator i = m_factoryMap.find(in.name() ? in.name() : "");
324 if (i == m_factoryMap.end())
325 throw AttributeException("No registered factory for Attribute of type ($1).", params(1,in.name()));
326 return (i->second)(in);