-/*\r
- * Copyright 2001-2007 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * XMLAttributeExtractor.cpp\r
- * \r
- * AttributeExtractor based on an XML mapping file.\r
- */\r
-\r
-#include "internal.h"\r
-#include "Application.h"\r
-#include "ServiceProvider.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/resolver/AttributeExtractor.h"\r
-#include "util/SPConstants.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-#include <saml/saml2/metadata/MetadataCredentialCriteria.h>\r
-#include <xmltooling/util/NDC.h>\r
-#include <xmltooling/util/ReloadableXMLFile.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml::saml2md;\r
-using namespace opensaml;\r
-using namespace xmltooling;\r
-using namespace log4cpp;\r
-using namespace std;\r
-using saml1::NameIdentifier;\r
-using saml2::NameID;\r
-using saml2::EncryptedAttribute;\r
-\r
-namespace shibsp {\r
-\r
-#if defined (_MSC_VER)\r
- #pragma warning( push )\r
- #pragma warning( disable : 4250 )\r
-#endif\r
-\r
- class XMLExtractorImpl\r
- {\r
- public:\r
- XMLExtractorImpl(const DOMElement* e, Category& log);\r
- ~XMLExtractorImpl() {\r
- for (attrmap_t::iterator i = m_attrMap.begin(); i!=m_attrMap.end(); ++i)\r
- delete i->second.first;\r
- if (m_document)\r
- m_document->release();\r
- }\r
-\r
- void setDocument(DOMDocument* doc) {\r
- m_document = doc;\r
- }\r
-\r
- void extractAttributes(\r
- const Application& application, const char* assertingParty, const NameIdentifier& nameid, multimap<string,Attribute*>& attributes\r
- ) const;\r
- void extractAttributes(\r
- const Application& application, const char* assertingParty, const NameID& nameid, multimap<string,Attribute*>& attributes\r
- ) const;\r
- void extractAttributes(\r
- const Application& application, const char* assertingParty, const saml1::Attribute& attr, multimap<string,Attribute*>& attributes\r
- ) const;\r
- void extractAttributes(\r
- const Application& application, const char* assertingParty, const saml2::Attribute& attr, multimap<string,Attribute*>& attributes\r
- ) const;\r
-\r
- private:\r
- Category& m_log;\r
- DOMDocument* m_document;\r
-#ifdef HAVE_GOOD_STL\r
- typedef map< pair<xstring,xstring>,pair<AttributeDecoder*,string> > attrmap_t;\r
-#else\r
- typedef map< pair<string,string>,pair<AttributeDecoder*,string> > attrmap_t;\r
-#endif\r
- attrmap_t m_attrMap;\r
- };\r
- \r
- class XMLExtractor : public AttributeExtractor, public ReloadableXMLFile\r
- {\r
- public:\r
- XMLExtractor(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor")), m_impl(NULL) {\r
- load();\r
- }\r
- ~XMLExtractor() {\r
- delete m_impl;\r
- }\r
- \r
- void extractAttributes(\r
- const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, multimap<string,Attribute*>& attributes\r
- ) const;\r
-\r
- protected:\r
- pair<bool,DOMElement*> load();\r
-\r
- private:\r
- XMLExtractorImpl* m_impl;\r
- };\r
-\r
-#if defined (_MSC_VER)\r
- #pragma warning( pop )\r
-#endif\r
-\r
- AttributeExtractor* SHIBSP_DLLLOCAL XMLAttributeExtractorFactory(const DOMElement* const & e)\r
- {\r
- return new XMLExtractor(e);\r
- }\r
- \r
- static const XMLCh _AttributeDecoder[] = UNICODE_LITERAL_16(A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);\r
- static const XMLCh Attributes[] = UNICODE_LITERAL_10(A,t,t,r,i,b,u,t,e,s);\r
- static const XMLCh _id[] = UNICODE_LITERAL_2(i,d);\r
- static const XMLCh _name[] = UNICODE_LITERAL_4(n,a,m,e);\r
- static const XMLCh nameFormat[] = UNICODE_LITERAL_10(n,a,m,e,F,o,r,m,a,t);\r
-};\r
-\r
+/*
+ * 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.
+ */
+
+/**
+ * XMLAttributeExtractor.cpp
+ *
+ * AttributeExtractor based on an XML mapping file.
+ */
+
+#include "internal.h"
+#include "Application.h"
+#include "ServiceProvider.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/resolver/AttributeExtractor.h"
+#include "util/SPConstants.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/ReloadableXMLFile.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+using saml1::NameIdentifier;
+using saml2::NameID;
+using saml2::EncryptedAttribute;
+
+namespace shibsp {
+
+#if defined (_MSC_VER)
+ #pragma warning( push )
+ #pragma warning( disable : 4250 )
+#endif
+
+ class XMLExtractorImpl
+ {
+ public:
+ XMLExtractorImpl(const DOMElement* e, Category& log);
+ ~XMLExtractorImpl() {
+ for (attrmap_t::iterator i = m_attrMap.begin(); i!=m_attrMap.end(); ++i)
+ delete i->second.first;
+ if (m_document)
+ m_document->release();
+ }
+
+ void setDocument(DOMDocument* doc) {
+ m_document = doc;
+ }
+
+ void extractAttributes(
+ const Application& application, const char* assertingParty, const NameIdentifier& nameid, multimap<string,Attribute*>& attributes
+ ) const;
+ void extractAttributes(
+ const Application& application, const char* assertingParty, const NameID& nameid, multimap<string,Attribute*>& attributes
+ ) const;
+ void extractAttributes(
+ const Application& application, const char* assertingParty, const saml1::Attribute& attr, multimap<string,Attribute*>& attributes
+ ) const;
+ void extractAttributes(
+ const Application& application, const char* assertingParty, const saml2::Attribute& attr, multimap<string,Attribute*>& attributes
+ ) const;
+
+ private:
+ Category& m_log;
+ DOMDocument* m_document;
+#ifdef HAVE_GOOD_STL
+ typedef map< pair<xstring,xstring>,pair<AttributeDecoder*,string> > attrmap_t;
+#else
+ typedef map< pair<string,string>,pair<AttributeDecoder*,string> > attrmap_t;
+#endif
+ attrmap_t m_attrMap;
+ };
+
+ class XMLExtractor : public AttributeExtractor, public ReloadableXMLFile
+ {
+ public:
+ XMLExtractor(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor")), m_impl(NULL) {
+ load();
+ }
+ ~XMLExtractor() {
+ delete m_impl;
+ }
+
+ void extractAttributes(
+ const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, multimap<string,Attribute*>& attributes
+ ) const;
+
+ protected:
+ pair<bool,DOMElement*> load();
+
+ private:
+ XMLExtractorImpl* m_impl;
+ };
+
+#if defined (_MSC_VER)
+ #pragma warning( pop )
+#endif
+
+ AttributeExtractor* SHIBSP_DLLLOCAL XMLAttributeExtractorFactory(const DOMElement* const & e)
+ {
+ return new XMLExtractor(e);
+ }
+
+ static const XMLCh _AttributeDecoder[] = UNICODE_LITERAL_16(A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
+ static const XMLCh Attributes[] = UNICODE_LITERAL_10(A,t,t,r,i,b,u,t,e,s);
+ static const XMLCh _id[] = UNICODE_LITERAL_2(i,d);
+ static const XMLCh _name[] = UNICODE_LITERAL_4(n,a,m,e);
+ static const XMLCh nameFormat[] = UNICODE_LITERAL_10(n,a,m,e,F,o,r,m,a,t);
+};
+
void SHIBSP_API shibsp::registerAttributeExtractors()
{
SPConfig::getConfig().AttributeExtractorManager.registerFactory(XML_ATTRIBUTE_EXTRACTOR, XMLAttributeExtractorFactory);
}
-\r
-XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log) : m_log(log), m_document(NULL)\r
-{\r
-#ifdef _DEBUG\r
- xmltooling::NDC ndc("XMLExtractorImpl");\r
-#endif\r
- \r
- if (!XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, Attributes))\r
- throw ConfigurationException("XML AttributeExtractor requires am:Attributes at root of configuration.");\r
-\r
- DOMElement* child = XMLHelper::getFirstChildElement(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);\r
- while (child) {\r
- // Check for missing name or id.\r
- const XMLCh* name = child->getAttributeNS(NULL, _name);\r
- if (!name || !*name) {\r
- m_log.warn("skipping Attribute with no name");\r
- child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);\r
- continue;\r
- }\r
-\r
- auto_ptr_char id(child->getAttributeNS(NULL, _id));\r
- if (!id.get() || !*id.get()) {\r
- m_log.warn("skipping Attribute with no id");\r
- child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);\r
- continue;\r
- }\r
-\r
- AttributeDecoder* decoder=NULL;\r
- try {\r
- DOMElement* dchild = XMLHelper::getFirstChildElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _AttributeDecoder);\r
- if (child) {\r
- auto_ptr<QName> q(XMLHelper::getXSIType(dchild));\r
- if (q.get())\r
- decoder = SPConfig::getConfig().AttributeDecoderManager.newPlugin(*q.get(), dchild);\r
- }\r
- if (!decoder)\r
- decoder = SPConfig::getConfig().AttributeDecoderManager.newPlugin(StringAttributeDecoderType, NULL);\r
- }\r
- catch (exception& ex) {\r
- m_log.error("skipping Attribute (%s), error building AttributeDecoder: %s", id.get(), ex.what());\r
- }\r
-\r
- if (!decoder) {\r
- child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);\r
- continue;\r
- }\r
-\r
- // Empty NameFormat implies the usual Shib URI naming defaults.\r
- const XMLCh* format = child->getAttributeNS(NULL, nameFormat);\r
- if (!format || XMLString::equals(format, shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI) ||\r
- XMLString::equals(format, saml2::Attribute::URI_REFERENCE))\r
- format = &chNull; // ignore default Format/Namespace values\r
-\r
- // Fetch/create the map entry and see if it's a duplicate rule.\r
-#ifdef HAVE_GOOD_STL\r
- pair<AttributeDecoder*,string>& decl = m_attrMap[make_pair(name,format)];\r
-#else\r
- auto_ptr_char n(name);\r
- auto_ptr_char f(format);\r
- pair<AttributeDecoder*,string>& decl = m_attrMap[make_pair(n.get(),f.get())];\r
-#endif\r
- if (decl.first) {\r
- m_log.warn("skipping duplicate Attribute declaration (same name and nameFormat)");\r
- delete decoder;\r
- child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);\r
- continue;\r
- }\r
-\r
- if (m_log.isInfoEnabled()) {\r
-#ifdef HAVE_GOOD_STL\r
- auto_ptr_char n(name);\r
- auto_ptr_char f(format);\r
-#endif\r
- m_log.info("creating declaration for Attribute %s%s%s", n.get(), *f.get() ? ", Format/Namespace:" : "", f.get());\r
- }\r
- \r
- decl.first = decoder;\r
- decl.second = id.get();\r
- \r
- child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);\r
- }\r
-}\r
-\r
-void XMLExtractorImpl::extractAttributes(\r
- const Application& application, const char* assertingParty, const NameIdentifier& nameid, multimap<string,Attribute*>& attributes\r
- ) const\r
-{\r
-#ifdef HAVE_GOOD_STL\r
- map< pair<xstring,xstring>,pair<AttributeDecoder*,string> >::const_iterator rule;\r
-#else\r
- map< pair<string,string>,pair<AttributeDecoder*,string> >::const_iterator rule;\r
-#endif\r
-\r
- const XMLCh* format = nameid.getFormat();\r
- if (!format || !*format)\r
- format = NameIdentifier::UNSPECIFIED;\r
-#ifdef HAVE_GOOD_STL\r
- if ((rule=m_attrMap.find(make_pair(format,xstring()))) != m_attrMap.end()) {\r
-#else\r
- auto_ptr_char temp(format);\r
- if ((rule=m_attrMap.find(make_pair(temp.get(),string()))) != m_attrMap.end()) {\r
-#endif\r
- attributes.insert(\r
- make_pair(\r
- rule->second.second,\r
- rule->second.first->decode(rule->second.second.c_str(), &nameid, assertingParty, application.getString("entityID").second)\r
- )\r
- );\r
- }\r
-}\r
-\r
-void XMLExtractorImpl::extractAttributes(\r
- const Application& application, const char* assertingParty, const NameID& nameid, multimap<string,Attribute*>& attributes\r
- ) const\r
-{\r
-#ifdef HAVE_GOOD_STL\r
- map< pair<xstring,xstring>,pair<AttributeDecoder*,string> >::const_iterator rule;\r
-#else\r
- map< pair<string,string>,pair<AttributeDecoder*,string> >::const_iterator rule;\r
-#endif\r
-\r
- const XMLCh* format = nameid.getFormat();\r
- if (!format || !*format)\r
- format = NameID::UNSPECIFIED;\r
-#ifdef HAVE_GOOD_STL\r
- if ((rule=m_attrMap.find(make_pair(format,xstring()))) != m_attrMap.end()) {\r
-#else\r
- auto_ptr_char temp(format);\r
- if ((rule=m_attrMap.find(make_pair(temp.get(),string()))) != m_attrMap.end()) {\r
-#endif\r
- attributes.insert(\r
- make_pair(\r
- rule->second.second,\r
- rule->second.first->decode(rule->second.second.c_str(), &nameid, assertingParty, application.getString("entityID").second)\r
- )\r
- );\r
- }\r
-}\r
-\r
-void XMLExtractorImpl::extractAttributes(\r
- const Application& application, const char* assertingParty, const saml1::Attribute& attr, multimap<string,Attribute*>& attributes\r
- ) const\r
-{\r
-#ifdef HAVE_GOOD_STL\r
- map< pair<xstring,xstring>,pair<AttributeDecoder*,string> >::const_iterator rule;\r
-#else\r
- map< pair<string,string>,pair<AttributeDecoder*,string> >::const_iterator rule;\r
-#endif\r
-\r
- const XMLCh* name = attr.getAttributeName();\r
- const XMLCh* format = attr.getAttributeNamespace();\r
- if (!name || !*name)\r
- return;\r
- if (!format || XMLString::equals(format, shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI))\r
- format = &chNull;\r
-#ifdef HAVE_GOOD_STL\r
- if ((rule=m_attrMap.find(make_pair(name,format))) != m_attrMap.end()) {\r
-#else\r
- auto_ptr_char temp1(name);\r
- auto_ptr_char temp2(format);\r
- if ((rule=m_attrMap.find(make_pair(temp1.get(),temp2.get()))) != m_attrMap.end()) {\r
-#endif\r
- attributes.insert(\r
- make_pair(\r
- rule->second.second,\r
- rule->second.first->decode(rule->second.second.c_str(), &attr, assertingParty, application.getString("entityID").second)\r
- )\r
- );\r
- }\r
-}\r
-\r
-void XMLExtractorImpl::extractAttributes(\r
- const Application& application, const char* assertingParty, const saml2::Attribute& attr, multimap<string,Attribute*>& attributes\r
- ) const\r
-{\r
-#ifdef HAVE_GOOD_STL\r
- map< pair<xstring,xstring>,pair<AttributeDecoder*,string> >::const_iterator rule;\r
-#else\r
- map< pair<string,string>,pair<AttributeDecoder*,string> >::const_iterator rule;\r
-#endif\r
-\r
- const XMLCh* name = attr.getName();\r
- const XMLCh* format = attr.getNameFormat();\r
- if (!name || !*name)\r
- return;\r
- if (!format || !*format)\r
- format = saml2::Attribute::UNSPECIFIED;\r
- else if (XMLString::equals(format, saml2::Attribute::URI_REFERENCE))\r
- format = &chNull;\r
-#ifdef HAVE_GOOD_STL\r
- if ((rule=m_attrMap.find(make_pair(name,format))) != m_attrMap.end()) {\r
-#else\r
- auto_ptr_char temp1(name);\r
- auto_ptr_char temp2(format);\r
- if ((rule=m_attrMap.find(make_pair(temp1.get(),temp2.get()))) != m_attrMap.end()) {\r
-#endif\r
- attributes.insert(\r
- make_pair(\r
- rule->second.second,\r
- rule->second.first->decode(rule->second.second.c_str(), &attr, assertingParty, application.getString("entityID").second)\r
- )\r
- );\r
- }\r
-}\r
-\r
-void XMLExtractor::extractAttributes(\r
- const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, multimap<string,Attribute*>& attributes\r
- ) const\r
-{\r
- // Check for assertions.\r
- if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), saml1::Assertion::LOCAL_NAME)) {\r
- const saml2::Assertion* token2 = dynamic_cast<const saml2::Assertion*>(&xmlObject);\r
- if (token2) {\r
- auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);\r
- const vector<saml2::AttributeStatement*>& statements = token2->getAttributeStatements();\r
- for (vector<saml2::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {\r
- const vector<saml2::Attribute*>& attrs = const_cast<const saml2::AttributeStatement*>(*s)->getAttributes();\r
- for (vector<saml2::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)\r
- m_impl->extractAttributes(application, assertingParty.get(), *(*a), attributes);\r
-\r
- const vector<saml2::EncryptedAttribute*>& encattrs = const_cast<const saml2::AttributeStatement*>(*s)->getEncryptedAttributes();\r
- for (vector<saml2::EncryptedAttribute*>::const_iterator ea = encattrs.begin(); ea!=encattrs.end(); ++ea)\r
- extractAttributes(application, issuer, *(*ea), attributes);\r
- }\r
- }\r
-\r
- const saml1::Assertion* token1 = dynamic_cast<const saml1::Assertion*>(&xmlObject);\r
- if (token1) {\r
- auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);\r
- const vector<saml1::AttributeStatement*>& statements = token1->getAttributeStatements();\r
- for (vector<saml1::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {\r
- const vector<saml1::Attribute*>& attrs = const_cast<const saml1::AttributeStatement*>(*s)->getAttributes();\r
- for (vector<saml1::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)\r
- m_impl->extractAttributes(application, assertingParty.get(), *(*a), attributes);\r
- }\r
- }\r
-\r
- throw AttributeExtractionException("Unable to extract attributes, unknown object type.");\r
- }\r
-\r
- // Check for attributes.\r
- if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), saml1::Attribute::LOCAL_NAME)) {\r
- auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);\r
-\r
- const saml2::Attribute* attr2 = dynamic_cast<const saml2::Attribute*>(&xmlObject);\r
- if (attr2)\r
- return m_impl->extractAttributes(application, assertingParty.get(), *attr2, attributes);\r
-\r
- const saml1::Attribute* attr1 = dynamic_cast<const saml1::Attribute*>(&xmlObject);\r
- if (attr1)\r
- return m_impl->extractAttributes(application, assertingParty.get(), *attr1, attributes);\r
-\r
- throw AttributeExtractionException("Unable to extract attributes, unknown object type.");\r
- }\r
-\r
- if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), EncryptedAttribute::LOCAL_NAME)) {\r
- const EncryptedAttribute* encattr = dynamic_cast<const EncryptedAttribute*>(&xmlObject);\r
- if (encattr) {\r
- const XMLCh* recipient = application.getXMLString("entityID").second;\r
- CredentialResolver* cr = application.getCredentialResolver();\r
- if (!cr) {\r
- m_log.warn("found encrypted attribute, but no CredentialResolver was available");\r
- return;\r
- }\r
-\r
- try {\r
- Locker credlocker(cr);\r
- if (issuer) {\r
- MetadataCredentialCriteria mcc(*issuer);\r
- auto_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient, &mcc));\r
- return extractAttributes(application, issuer, *(decrypted.get()), attributes);\r
- }\r
- else {\r
- auto_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient));\r
- return extractAttributes(application, issuer, *(decrypted.get()), attributes);\r
- }\r
- }\r
- catch (exception& ex) {\r
- m_log.error("caught exception decrypting Attribute: %s", ex.what());\r
- return;\r
- }\r
- }\r
- }\r
-\r
- // Check for NameIDs.\r
- const NameID* name2 = dynamic_cast<const NameID*>(&xmlObject);\r
- if (name2) {\r
- auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);\r
- return m_impl->extractAttributes(application, assertingParty.get(), *name2, attributes);\r
- }\r
-\r
- const NameIdentifier* name1 = dynamic_cast<const NameIdentifier*>(&xmlObject);\r
- if (name1) {\r
- auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);\r
- return m_impl->extractAttributes(application, assertingParty.get(), *name1, attributes);\r
- }\r
-\r
- throw AttributeExtractionException("Unable to extract attributes, unknown object type.");\r
-}\r
-\r
-pair<bool,DOMElement*> XMLExtractor::load()\r
-{\r
- // Load from source using base class.\r
- pair<bool,DOMElement*> raw = ReloadableXMLFile::load();\r
- \r
- // If we own it, wrap it.\r
- XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);\r
-\r
- XMLExtractorImpl* impl = new XMLExtractorImpl(raw.second, m_log);\r
- \r
- // If we held the document, transfer it to the impl. If we didn't, it's a no-op.\r
- impl->setDocument(docjanitor.release());\r
-\r
- delete m_impl;\r
- m_impl = impl;\r
-\r
- return make_pair(false,(DOMElement*)NULL);\r
-}\r
+
+XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log) : m_log(log), m_document(NULL)
+{
+#ifdef _DEBUG
+ xmltooling::NDC ndc("XMLExtractorImpl");
+#endif
+
+ if (!XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, Attributes))
+ throw ConfigurationException("XML AttributeExtractor requires am:Attributes at root of configuration.");
+
+ DOMElement* child = XMLHelper::getFirstChildElement(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
+ while (child) {
+ // Check for missing name or id.
+ const XMLCh* name = child->getAttributeNS(NULL, _name);
+ if (!name || !*name) {
+ m_log.warn("skipping Attribute with no name");
+ child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
+ continue;
+ }
+
+ auto_ptr_char id(child->getAttributeNS(NULL, _id));
+ if (!id.get() || !*id.get()) {
+ m_log.warn("skipping Attribute with no id");
+ child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
+ continue;
+ }
+
+ AttributeDecoder* decoder=NULL;
+ try {
+ DOMElement* dchild = XMLHelper::getFirstChildElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _AttributeDecoder);
+ if (dchild) {
+ auto_ptr<QName> q(XMLHelper::getXSIType(dchild));
+ if (q.get())
+ decoder = SPConfig::getConfig().AttributeDecoderManager.newPlugin(*q.get(), dchild);
+ }
+ if (!decoder)
+ decoder = SPConfig::getConfig().AttributeDecoderManager.newPlugin(StringAttributeDecoderType, NULL);
+ }
+ catch (exception& ex) {
+ m_log.error("skipping Attribute (%s), error building AttributeDecoder: %s", id.get(), ex.what());
+ }
+
+ if (!decoder) {
+ child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
+ continue;
+ }
+
+ // Empty NameFormat implies the usual Shib URI naming defaults.
+ const XMLCh* format = child->getAttributeNS(NULL, nameFormat);
+ if (!format || XMLString::equals(format, shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI) ||
+ XMLString::equals(format, saml2::Attribute::URI_REFERENCE))
+ format = &chNull; // ignore default Format/Namespace values
+
+ // Fetch/create the map entry and see if it's a duplicate rule.
+#ifdef HAVE_GOOD_STL
+ pair<AttributeDecoder*,string>& decl = m_attrMap[make_pair(name,format)];
+#else
+ auto_ptr_char n(name);
+ auto_ptr_char f(format);
+ pair<AttributeDecoder*,string>& decl = m_attrMap[make_pair(n.get(),f.get())];
+#endif
+ if (decl.first) {
+ m_log.warn("skipping duplicate Attribute mapping (same name and nameFormat)");
+ delete decoder;
+ child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
+ continue;
+ }
+
+ if (m_log.isInfoEnabled()) {
+#ifdef HAVE_GOOD_STL
+ auto_ptr_char n(name);
+ auto_ptr_char f(format);
+#endif
+ m_log.info("creating mapping for Attribute %s%s%s", n.get(), *f.get() ? ", Format/Namespace:" : "", f.get());
+ }
+
+ decl.first = decoder;
+ decl.second = id.get();
+
+ child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
+ }
+}
+
+void XMLExtractorImpl::extractAttributes(
+ const Application& application, const char* assertingParty, const NameIdentifier& nameid, multimap<string,Attribute*>& attributes
+ ) const
+{
+#ifdef HAVE_GOOD_STL
+ map< pair<xstring,xstring>,pair<AttributeDecoder*,string> >::const_iterator rule;
+#else
+ map< pair<string,string>,pair<AttributeDecoder*,string> >::const_iterator rule;
+#endif
+
+ const XMLCh* format = nameid.getFormat();
+ if (!format || !*format)
+ format = NameIdentifier::UNSPECIFIED;
+#ifdef HAVE_GOOD_STL
+ if ((rule=m_attrMap.find(make_pair(format,xstring()))) != m_attrMap.end()) {
+#else
+ auto_ptr_char temp(format);
+ if ((rule=m_attrMap.find(make_pair(temp.get(),string()))) != m_attrMap.end()) {
+#endif
+ attributes.insert(
+ make_pair(
+ rule->second.second,
+ rule->second.first->decode(rule->second.second.c_str(), &nameid, assertingParty, application.getString("entityID").second)
+ )
+ );
+ }
+}
+
+void XMLExtractorImpl::extractAttributes(
+ const Application& application, const char* assertingParty, const NameID& nameid, multimap<string,Attribute*>& attributes
+ ) const
+{
+#ifdef HAVE_GOOD_STL
+ map< pair<xstring,xstring>,pair<AttributeDecoder*,string> >::const_iterator rule;
+#else
+ map< pair<string,string>,pair<AttributeDecoder*,string> >::const_iterator rule;
+#endif
+
+ const XMLCh* format = nameid.getFormat();
+ if (!format || !*format)
+ format = NameID::UNSPECIFIED;
+#ifdef HAVE_GOOD_STL
+ if ((rule=m_attrMap.find(make_pair(format,xstring()))) != m_attrMap.end()) {
+#else
+ auto_ptr_char temp(format);
+ if ((rule=m_attrMap.find(make_pair(temp.get(),string()))) != m_attrMap.end()) {
+#endif
+ attributes.insert(
+ make_pair(
+ rule->second.second,
+ rule->second.first->decode(rule->second.second.c_str(), &nameid, assertingParty, application.getString("entityID").second)
+ )
+ );
+ }
+}
+
+void XMLExtractorImpl::extractAttributes(
+ const Application& application, const char* assertingParty, const saml1::Attribute& attr, multimap<string,Attribute*>& attributes
+ ) const
+{
+#ifdef HAVE_GOOD_STL
+ map< pair<xstring,xstring>,pair<AttributeDecoder*,string> >::const_iterator rule;
+#else
+ map< pair<string,string>,pair<AttributeDecoder*,string> >::const_iterator rule;
+#endif
+
+ const XMLCh* name = attr.getAttributeName();
+ const XMLCh* format = attr.getAttributeNamespace();
+ if (!name || !*name)
+ return;
+ if (!format || XMLString::equals(format, shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI))
+ format = &chNull;
+#ifdef HAVE_GOOD_STL
+ if ((rule=m_attrMap.find(make_pair(name,format))) != m_attrMap.end()) {
+#else
+ auto_ptr_char temp1(name);
+ auto_ptr_char temp2(format);
+ if ((rule=m_attrMap.find(make_pair(temp1.get(),temp2.get()))) != m_attrMap.end()) {
+#endif
+ attributes.insert(
+ make_pair(
+ rule->second.second,
+ rule->second.first->decode(rule->second.second.c_str(), &attr, assertingParty, application.getString("entityID").second)
+ )
+ );
+ }
+}
+
+void XMLExtractorImpl::extractAttributes(
+ const Application& application, const char* assertingParty, const saml2::Attribute& attr, multimap<string,Attribute*>& attributes
+ ) const
+{
+#ifdef HAVE_GOOD_STL
+ map< pair<xstring,xstring>,pair<AttributeDecoder*,string> >::const_iterator rule;
+#else
+ map< pair<string,string>,pair<AttributeDecoder*,string> >::const_iterator rule;
+#endif
+
+ const XMLCh* name = attr.getName();
+ const XMLCh* format = attr.getNameFormat();
+ if (!name || !*name)
+ return;
+ if (!format || !*format)
+ format = saml2::Attribute::UNSPECIFIED;
+ else if (XMLString::equals(format, saml2::Attribute::URI_REFERENCE))
+ format = &chNull;
+#ifdef HAVE_GOOD_STL
+ if ((rule=m_attrMap.find(make_pair(name,format))) != m_attrMap.end()) {
+#else
+ auto_ptr_char temp1(name);
+ auto_ptr_char temp2(format);
+ if ((rule=m_attrMap.find(make_pair(temp1.get(),temp2.get()))) != m_attrMap.end()) {
+#endif
+ attributes.insert(
+ make_pair(
+ rule->second.second,
+ rule->second.first->decode(rule->second.second.c_str(), &attr, assertingParty, application.getString("entityID").second)
+ )
+ );
+ }
+}
+
+void XMLExtractor::extractAttributes(
+ const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, multimap<string,Attribute*>& attributes
+ ) const
+{
+ // Check for assertions.
+ if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), saml1::Assertion::LOCAL_NAME)) {
+ const saml2::Assertion* token2 = dynamic_cast<const saml2::Assertion*>(&xmlObject);
+ if (token2) {
+ auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);
+ const vector<saml2::AttributeStatement*>& statements = token2->getAttributeStatements();
+ for (vector<saml2::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {
+ const vector<saml2::Attribute*>& attrs = const_cast<const saml2::AttributeStatement*>(*s)->getAttributes();
+ for (vector<saml2::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)
+ m_impl->extractAttributes(application, assertingParty.get(), *(*a), attributes);
+
+ const vector<saml2::EncryptedAttribute*>& encattrs = const_cast<const saml2::AttributeStatement*>(*s)->getEncryptedAttributes();
+ for (vector<saml2::EncryptedAttribute*>::const_iterator ea = encattrs.begin(); ea!=encattrs.end(); ++ea)
+ extractAttributes(application, issuer, *(*ea), attributes);
+ }
+ return;
+ }
+
+ const saml1::Assertion* token1 = dynamic_cast<const saml1::Assertion*>(&xmlObject);
+ if (token1) {
+ auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);
+ const vector<saml1::AttributeStatement*>& statements = token1->getAttributeStatements();
+ for (vector<saml1::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {
+ const vector<saml1::Attribute*>& attrs = const_cast<const saml1::AttributeStatement*>(*s)->getAttributes();
+ for (vector<saml1::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)
+ m_impl->extractAttributes(application, assertingParty.get(), *(*a), attributes);
+ }
+ return;
+ }
+
+ throw AttributeExtractionException("Unable to extract attributes, unknown object type.");
+ }
+
+ // Check for attributes.
+ if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), saml1::Attribute::LOCAL_NAME)) {
+ auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);
+
+ const saml2::Attribute* attr2 = dynamic_cast<const saml2::Attribute*>(&xmlObject);
+ if (attr2)
+ return m_impl->extractAttributes(application, assertingParty.get(), *attr2, attributes);
+
+ const saml1::Attribute* attr1 = dynamic_cast<const saml1::Attribute*>(&xmlObject);
+ if (attr1)
+ return m_impl->extractAttributes(application, assertingParty.get(), *attr1, attributes);
+
+ throw AttributeExtractionException("Unable to extract attributes, unknown object type.");
+ }
+
+ if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), EncryptedAttribute::LOCAL_NAME)) {
+ const EncryptedAttribute* encattr = dynamic_cast<const EncryptedAttribute*>(&xmlObject);
+ if (encattr) {
+ const XMLCh* recipient = application.getXMLString("entityID").second;
+ CredentialResolver* cr = application.getCredentialResolver();
+ if (!cr) {
+ m_log.warn("found encrypted attribute, but no CredentialResolver was available");
+ return;
+ }
+
+ try {
+ Locker credlocker(cr);
+ if (issuer) {
+ MetadataCredentialCriteria mcc(*issuer);
+ auto_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient, &mcc));
+ return extractAttributes(application, issuer, *(decrypted.get()), attributes);
+ }
+ else {
+ auto_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient));
+ return extractAttributes(application, issuer, *(decrypted.get()), attributes);
+ }
+ }
+ catch (exception& ex) {
+ m_log.error("caught exception decrypting Attribute: %s", ex.what());
+ return;
+ }
+ }
+ }
+
+ // Check for NameIDs.
+ const NameID* name2 = dynamic_cast<const NameID*>(&xmlObject);
+ if (name2) {
+ auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);
+ return m_impl->extractAttributes(application, assertingParty.get(), *name2, attributes);
+ }
+
+ const NameIdentifier* name1 = dynamic_cast<const NameIdentifier*>(&xmlObject);
+ if (name1) {
+ auto_ptr_char assertingParty(issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent())->getEntityID() : NULL);
+ return m_impl->extractAttributes(application, assertingParty.get(), *name1, attributes);
+ }
+
+ throw AttributeExtractionException("Unable to extract attributes, unknown object type.");
+}
+
+pair<bool,DOMElement*> XMLExtractor::load()
+{
+ // Load from source using base class.
+ pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
+
+ // If we own it, wrap it.
+ XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);
+
+ XMLExtractorImpl* impl = new XMLExtractorImpl(raw.second, m_log);
+
+ // If we held the document, transfer it to the impl. If we didn't, it's a no-op.
+ impl->setDocument(docjanitor.release());
+
+ delete m_impl;
+ m_impl = impl;
+
+ return make_pair(false,(DOMElement*)NULL);
+}