2 * Copyright 2001-2010 Internet2
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * NameIDFromNameIDFromScopedAttributeDecoder.cpp
20 * Decodes SAML "scoped" attributes into NameIDAttributes.
24 #include "attribute/AttributeDecoder.h"
25 #include "attribute/NameIDAttribute.h"
27 #include <saml/saml1/core/Assertions.h>
28 #include <saml/saml2/core/Assertions.h>
30 using namespace shibsp;
31 using namespace opensaml::saml1;
32 using namespace opensaml::saml2;
33 using namespace xmltooling;
37 static const XMLCh defaultQualifiers[] =UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s);
38 static const XMLCh format[] = UNICODE_LITERAL_6(f,o,r,m,a,t);
39 static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
40 static const XMLCh Scope[] = UNICODE_LITERAL_5(S,c,o,p,e);
41 static const XMLCh scopeDelimeter[] = UNICODE_LITERAL_14(s,c,o,p,e,D,e,l,i,m,e,t,e,r);
43 class SHIBSP_DLLLOCAL NameIDFromScopedAttributeDecoder : virtual public AttributeDecoder
46 NameIDFromScopedAttributeDecoder(const DOMElement* e)
47 : AttributeDecoder(e),
49 m_format(XMLHelper::getAttrString(e, nullptr, format)),
50 m_formatter(XMLHelper::getAttrString(e, nullptr, formatter)),
51 m_defaultQualifiers(XMLHelper::getAttrBool(e, false, defaultQualifiers)) {
52 if (e && e->hasAttributeNS(nullptr,scopeDelimeter)) {
53 auto_ptr_char d(e->getAttributeNS(nullptr,scopeDelimeter));
54 m_delimeter = *(d.get());
57 ~NameIDFromScopedAttributeDecoder() {}
59 shibsp::Attribute* decode(
60 const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=nullptr, const char* relyingParty=nullptr
65 string m_format,m_formatter;
66 bool m_defaultQualifiers;
69 AttributeDecoder* SHIBSP_DLLLOCAL NameIDFromScopedAttributeDecoderFactory(const DOMElement* const & e)
71 return new NameIDFromScopedAttributeDecoder(e);
75 shibsp::Attribute* NameIDFromScopedAttributeDecoder::decode(
76 const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
82 const XMLCh* xmlscope;
83 xmltooling::QName scopeqname(nullptr,Scope);
84 auto_ptr<NameIDAttribute> nameid(
85 new NameIDAttribute(ids, (!m_formatter.empty()) ? m_formatter.c_str() : DEFAULT_NAMEID_FORMATTER)
87 vector<NameIDAttribute::Value>& dest = nameid->getValues();
88 vector<XMLObject*>::const_iterator v,stop;
90 Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameIDFromScoped");
92 if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {
93 const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);
95 const vector<XMLObject*>& values = saml2attr->getAttributeValues();
98 if (log.isDebugEnabled()) {
99 auto_ptr_char n(saml2attr->getName());
101 "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
102 ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
107 const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);
109 const vector<XMLObject*>& values = saml1attr->getAttributeValues();
112 if (log.isDebugEnabled()) {
113 auto_ptr_char n(saml1attr->getAttributeName());
115 "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
116 ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
121 log.warn("XMLObject type not recognized by NameIDFromScopedAttributeDecoder, no values returned");
126 for (; v!=stop; ++v) {
127 if (!(*v)->hasChildren()) {
128 val = toUTF8((*v)->getTextContent());
130 dest.push_back(NameIDAttribute::Value());
131 NameIDAttribute::Value& destval = dest.back();
132 const AttributeExtensibleXMLObject* aexo=dynamic_cast<const AttributeExtensibleXMLObject*>(*v);
133 xmlscope = aexo ? aexo->getAttribute(scopeqname) : nullptr;
134 if (!xmlscope || !*xmlscope) {
135 // Terminate the value at the scope delimiter.
136 if (scope = strchr(val, m_delimeter))
139 destval.m_Name = val;
140 destval.m_Format = m_format;
141 if (m_defaultQualifiers && assertingParty)
142 destval.m_NameQualifier = assertingParty;
143 if (m_defaultQualifiers && relyingParty)
144 destval.m_SPNameQualifier = relyingParty;
147 log.warn("skipping empty AttributeValue");
152 log.warn("skipping complex AttributeValue");
156 return dest.empty() ? nullptr : _decode(nameid.release());
159 log.warn("XMLObject type not recognized by NameIDFromScopedAttributeDecoder, no values returned");