X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=shibsp%2Fattribute%2FNameIDAttributeDecoder.cpp;h=d3a198ba7759c1cc5a8d044c732335425614983f;hb=c51bfd77603cf0ddb0b5e374c35586a8435895d6;hp=19ea010e7db282d5a3e6a01b74d90b742e91b2a9;hpb=aebe94d53162cb5e0a50da51c7fa434e866072b6;p=shibboleth%2Fcpp-sp.git diff --git a/shibsp/attribute/NameIDAttributeDecoder.cpp b/shibsp/attribute/NameIDAttributeDecoder.cpp index 19ea010..d3a198b 100644 --- a/shibsp/attribute/NameIDAttributeDecoder.cpp +++ b/shibsp/attribute/NameIDAttributeDecoder.cpp @@ -1,221 +1,249 @@ -/* - * Copyright 2001-2007 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * NameIDAttributeDecoder.cpp - * - * Decodes SAML into NameIDAttributes - */ - -#include "internal.h" -#include "attribute/AttributeDecoder.h" -#include "attribute/NameIDAttribute.h" - -#include -#include - -using namespace shibsp; -using namespace opensaml::saml1; -using namespace opensaml::saml2; -using namespace xmltooling; -using namespace std; - -namespace shibsp { - static XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r); - - class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder - { - public: - NameIDAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL) {} - ~NameIDAttributeDecoder() {} - - shibsp::Attribute* decode( - const char* id, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - - private: - void extract( - const NameIDType* n, vector& dest, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - void extract( - const NameIdentifier* n, vector& dest, const char* assertingParty=NULL, const char* relyingParty=NULL - ) const; - auto_ptr_char m_formatter; - }; - - AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e) - { - return new NameIDAttributeDecoder(e); - } -}; - -shibsp::Attribute* NameIDAttributeDecoder::decode( - const char* id, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty - ) const -{ - auto_ptr nameid( - new NameIDAttribute(id, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER) - ); - nameid->setCaseSensitive(m_caseSensitive); - vector& dest = nameid->getValues(); - vector::const_iterator v,stop; - - Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder"); - - if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) { - const opensaml::saml2::Attribute* saml2attr = dynamic_cast(xmlObject); - if (saml2attr) { - const vector& values = saml2attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml2attr->getName()); - log.debug("decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", id, n.get() ? n.get() : "unnamed", values.size()); - } - } - else { - const opensaml::saml1::Attribute* saml1attr = dynamic_cast(xmlObject); - if (saml1attr) { - const vector& values = saml1attr->getAttributeValues(); - v = values.begin(); - stop = values.end(); - if (log.isDebugEnabled()) { - auto_ptr_char n(saml1attr->getAttributeName()); - log.debug("decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", id, n.get() ? n.get() : "unnamed", values.size()); - } - } - else { - log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned"); - return NULL; - } - } - - for (; v!=stop; ++v) { - const NameIDType* n2 = dynamic_cast(*v); - if (n2) - extract(n2, dest); - else { - const NameIdentifier* n1=dynamic_cast(*v); - if (n1) - extract(n1, dest); - else if ((*v)->hasChildren()) { - const list& values = (*v)->getOrderedChildren(); - for (list::const_iterator vv = values.begin(); vv!=values.end(); ++vv) { - if (n2=dynamic_cast(*vv)) - extract(n2, dest); - else if (n1=dynamic_cast(*vv)) - extract(n1, dest); - else - log.warn("skipping AttributeValue without a recognizable NameID/NameIdentifier"); - } - } - } - } - - return dest.empty() ? NULL : nameid.release(); - } - - const NameIDType* saml2name = dynamic_cast(xmlObject); - if (saml2name) { - if (log.isDebugEnabled()) { - auto_ptr_char f(saml2name->getFormat()); - log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", id, f.get() ? f.get() : "unspecified"); - } - extract(saml2name, dest); - } - else { - const NameIdentifier* saml1name = dynamic_cast(xmlObject); - if (saml1name) { - if (log.isDebugEnabled()) { - auto_ptr_char f(saml1name->getFormat()); - log.debug("decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", id, f.get() ? f.get() : "unspecified"); - } - extract(saml1name, dest); - } - else { - log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned"); - return NULL; - } - } - - return dest.empty() ? NULL : nameid.release(); -} - -void NameIDAttributeDecoder::extract( - const NameIDType* n, vector& dest, const char* assertingParty, const char* relyingParty - ) const -{ - char* name = toUTF8(n->getName()); - if (name && *name) { - dest.push_back(NameIDAttribute::Value()); - NameIDAttribute::Value& val = dest.back(); - val.m_Name = name; - char* str = toUTF8(n->getFormat()); - if (str) { - val.m_Format = str; - delete[] str; - } - - str = toUTF8(n->getNameQualifier()); - if (str && *str) - val.m_NameQualifier = str; - else if (assertingParty) - val.m_NameQualifier = assertingParty; - delete[] str; - - str = toUTF8(n->getSPNameQualifier()); - if (str && *str) - val.m_SPNameQualifier = str; - else if (relyingParty) - val.m_SPNameQualifier = relyingParty; - delete[] str; - - str = toUTF8(n->getSPProvidedID()); - if (str) { - val.m_SPProvidedID = str; - delete[] str; - } - } - delete[] name; -} - -void NameIDAttributeDecoder::extract( - const NameIdentifier* n, vector& dest, const char* assertingParty, const char* relyingParty - ) const -{ - char* name = toUTF8(n->getName()); - if (name && *name) { - dest.push_back(NameIDAttribute::Value()); - NameIDAttribute::Value& val = dest.back(); - val.m_Name = name; - char* str = toUTF8(n->getFormat()); - if (str) { - val.m_Format = str; - delete[] str; - } - - str = toUTF8(n->getNameQualifier()); - if (str && *str) - val.m_NameQualifier = str; - else if (assertingParty) - val.m_NameQualifier = assertingParty; - delete[] str; - - if (relyingParty) - val.m_SPNameQualifier = relyingParty; - } - delete[] name; -} +/** + * Licensed to the University Corporation for Advanced Internet + * Development, Inc. (UCAID) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + * + * UCAID licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the + * License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ + +/** + * NameIDAttributeDecoder.cpp + * + * Decodes SAML into NameIDAttributes. + */ + +#include "internal.h" +#include "attribute/AttributeDecoder.h" +#include "attribute/NameIDAttribute.h" + +#include +#include + +using namespace shibsp; +using namespace opensaml::saml1; +using namespace opensaml::saml2; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r); + static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s); + + class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder + { + public: + NameIDAttributeDecoder(const DOMElement* e) + : AttributeDecoder(e), + m_formatter(XMLHelper::getAttrString(e, nullptr, formatter)), + m_defaultQualifiers(XMLHelper::getAttrBool(e, false, defaultQualifiers)) { + } + ~NameIDAttributeDecoder() {} + + // deprecated method + shibsp::Attribute* decode( + const vector& ids, const XMLObject* xmlObject, const char* assertingParty=nullptr, const char* relyingParty=nullptr + ) const { + return decode(nullptr, ids, xmlObject, assertingParty, relyingParty); + } + + shibsp::Attribute* decode( + const GenericRequest*, const vector&, const XMLObject*, const char* assertingParty=nullptr, const char* relyingParty=nullptr + ) const; + + private: + void extract( + const NameIDType* n, vector& dest, const char* assertingParty, const char* relyingParty + ) const; + void extract( + const NameIdentifier* n, vector& dest, const char* assertingParty, const char* relyingParty + ) const; + string m_formatter; + bool m_defaultQualifiers; + }; + + AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e) + { + return new NameIDAttributeDecoder(e); + } +}; + +shibsp::Attribute* NameIDAttributeDecoder::decode( + const GenericRequest*, const vector& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty + ) const +{ + auto_ptr nameid( + new NameIDAttribute(ids, (!m_formatter.empty()) ? m_formatter.c_str() : DEFAULT_NAMEID_FORMATTER, m_hashAlg.c_str()) + ); + vector& dest = nameid->getValues(); + vector::const_iterator v,stop; + + Category& log = Category::getInstance(SHIBSP_LOGCAT ".AttributeDecoder.NameID"); + + if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) { + const opensaml::saml2::Attribute* saml2attr = dynamic_cast(xmlObject); + if (saml2attr) { + const vector& values = saml2attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml2attr->getName()); + log.debug( + "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + const opensaml::saml1::Attribute* saml1attr = dynamic_cast(xmlObject); + if (saml1attr) { + const vector& values = saml1attr->getAttributeValues(); + v = values.begin(); + stop = values.end(); + if (log.isDebugEnabled()) { + auto_ptr_char n(saml1attr->getAttributeName()); + log.debug( + "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)", + ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size() + ); + } + } + else { + log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned"); + return nullptr; + } + } + + for (; v != stop; ++v) { + const NameIDType* n2 = dynamic_cast(*v); + if (n2) { + log.debug("decoding AttributeValue element of saml2:NameIDType type"); + extract(n2, dest, assertingParty, relyingParty); + } + else { + const NameIdentifier* n1=dynamic_cast(*v); + if (n1) { + log.debug("decoding AttributeValue element of saml1:NameIdentifier type"); + extract(n1, dest, assertingParty, relyingParty); + } + else if ((*v)->hasChildren()) { + const list& values = (*v)->getOrderedChildren(); + for (list::const_iterator vv = values.begin(); vv!=values.end(); ++vv) { + if (n2=dynamic_cast(*vv)) { + log.debug("decoding saml2:NameID child element of AttributeValue"); + extract(n2, dest, assertingParty, relyingParty); + } + else if (n1=dynamic_cast(*vv)) { + log.debug("decoding saml1:NameIdentifier child element of AttributeValue"); + extract(n1, dest, assertingParty, relyingParty); + } + else { + log.warn("skipping AttributeValue child element not recognizable as NameID/NameIdentifier"); + } + } + } + else { + log.warn("AttributeValue was not of a supported type and contains no child elements"); + } + } + } + + return dest.empty() ? nullptr : nameid.release(); + } + + const NameIDType* saml2name = dynamic_cast(xmlObject); + if (saml2name) { + if (log.isDebugEnabled()) { + auto_ptr_char f(saml2name->getFormat()); + log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified"); + } + extract(saml2name, dest, assertingParty, relyingParty); + } + else { + const NameIdentifier* saml1name = dynamic_cast(xmlObject); + if (saml1name) { + if (log.isDebugEnabled()) { + auto_ptr_char f(saml1name->getFormat()); + log.debug( + "decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)", + ids.front().c_str(), f.get() ? f.get() : "unspecified" + ); + } + extract(saml1name, dest, assertingParty, relyingParty); + } + else { + log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned"); + return nullptr; + } + } + + return dest.empty() ? nullptr : nameid.release(); +} + +void NameIDAttributeDecoder::extract( + const NameIDType* n, vector& dest, const char* assertingParty, const char* relyingParty + ) const +{ + auto_arrayptr name(toUTF8(n->getName())); + if (name.get() && *name.get()) { + dest.push_back(NameIDAttribute::Value()); + NameIDAttribute::Value& val = dest.back(); + val.m_Name = name.get(); + + auto_arrayptr format(toUTF8(n->getFormat())); + if (format.get()) + val.m_Format = format.get(); + + auto_arrayptr nameQualifier(toUTF8(n->getNameQualifier())); + if (nameQualifier.get() && *nameQualifier.get()) + val.m_NameQualifier = nameQualifier.get(); + else if (m_defaultQualifiers && assertingParty) + val.m_NameQualifier = assertingParty; + + auto_arrayptr spNameQualifier(toUTF8(n->getSPNameQualifier())); + if (spNameQualifier.get() && *spNameQualifier.get()) + val.m_SPNameQualifier = spNameQualifier.get(); + else if (m_defaultQualifiers && relyingParty) + val.m_SPNameQualifier = relyingParty; + + auto_arrayptr spProvidedID(toUTF8(n->getSPProvidedID())); + if (spProvidedID.get()) + val.m_SPProvidedID = spProvidedID.get(); + } +} + +void NameIDAttributeDecoder::extract( + const NameIdentifier* n, vector& dest, const char* assertingParty, const char* relyingParty + ) const +{ + auto_arrayptr name(toUTF8(n->getName())); + if (name.get() && *name.get()) { + dest.push_back(NameIDAttribute::Value()); + NameIDAttribute::Value& val = dest.back(); + val.m_Name = name.get(); + + auto_arrayptr format(toUTF8(n->getFormat())); + if (format.get()) + val.m_Format = format.get(); + + auto_arrayptr nameQualifier(toUTF8(n->getNameQualifier())); + if (nameQualifier.get() && *nameQualifier.get()) + val.m_NameQualifier = nameQualifier.get(); + else if (m_defaultQualifiers && assertingParty) + val.m_NameQualifier = assertingParty; + + if (m_defaultQualifiers && relyingParty) + val.m_SPNameQualifier = relyingParty; + } +}