2 * Copyright 2001-2007 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 XMLCh format[] = UNICODE_LITERAL_6(f,o,r,m,a,t);
38 static XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
39 static const XMLCh Scope[] = UNICODE_LITERAL_5(S,c,o,p,e);
40 static const XMLCh scopeDelimeter[] = UNICODE_LITERAL_14(s,c,o,p,e,D,e,l,i,m,e,t,e,r);
42 class SHIBSP_DLLLOCAL NameIDFromScopedAttributeDecoder : virtual public AttributeDecoder
45 NameIDFromScopedAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_delimeter('@'),
46 m_format(e ? e->getAttributeNS(NULL,format) : NULL), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL) {
47 if (e && e->hasAttributeNS(NULL,scopeDelimeter)) {
48 auto_ptr_char d(e->getAttributeNS(NULL,scopeDelimeter));
49 m_delimeter = *(d.get());
52 ~NameIDFromScopedAttributeDecoder() {}
54 shibsp::Attribute* decode(
55 const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
60 auto_ptr_char m_format;
61 auto_ptr_char m_formatter;
64 AttributeDecoder* SHIBSP_DLLLOCAL NameIDFromScopedAttributeDecoderFactory(const DOMElement* const & e)
66 return new NameIDFromScopedAttributeDecoder(e);
70 shibsp::Attribute* NameIDFromScopedAttributeDecoder::decode(
71 const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
77 const XMLCh* xmlscope;
78 xmltooling::QName scopeqname(NULL,Scope);
79 auto_ptr<NameIDAttribute> nameid(
80 new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER)
82 nameid->setCaseSensitive(m_caseSensitive);
83 vector<NameIDAttribute::Value>& dest = nameid->getValues();
84 vector<XMLObject*>::const_iterator v,stop;
86 Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameIDFromScoped");
88 if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {
89 const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);
91 const vector<XMLObject*>& values = saml2attr->getAttributeValues();
94 if (log.isDebugEnabled()) {
95 auto_ptr_char n(saml2attr->getName());
97 "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
98 ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
103 const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);
105 const vector<XMLObject*>& values = saml1attr->getAttributeValues();
108 if (log.isDebugEnabled()) {
109 auto_ptr_char n(saml1attr->getAttributeName());
111 "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
112 ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
117 log.warn("XMLObject type not recognized by NameIDFromScopedAttributeDecoder, no values returned");
122 for (; v!=stop; ++v) {
123 if (!(*v)->hasChildren()) {
124 val = toUTF8((*v)->getTextContent());
126 dest.push_back(NameIDAttribute::Value());
127 NameIDAttribute::Value& destval = dest.back();
128 const AttributeExtensibleXMLObject* aexo=dynamic_cast<const AttributeExtensibleXMLObject*>(*v);
129 xmlscope = aexo ? aexo->getAttribute(scopeqname) : NULL;
130 if (!xmlscope || !*xmlscope) {
131 // Terminate the value at the scope delimiter.
132 if (scope = strchr(val, m_delimeter))
135 destval.m_Name = val;
136 if (m_format.get() && *m_format.get())
137 destval.m_Format = m_format.get();
139 destval.m_NameQualifier = assertingParty;
141 destval.m_SPNameQualifier = relyingParty;
144 log.warn("skipping empty AttributeValue");
149 log.warn("skipping complex AttributeValue");
153 return dest.empty() ? NULL : nameid.release();
156 log.warn("XMLObject type not recognized by NameIDFromScopedAttributeDecoder, no values returned");