attributes.insert(attributes.end(), m_attributeIds.begin(), m_attributeIds.end());
}
+ void generateMetadata(SPSSODescriptor& role) const;
+
private:
Category& m_log;
DOMDocument* m_document;
-#ifdef HAVE_GOOD_STL
typedef map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > > attrmap_t;
-#else
- typedef map< pair<string,string>,pair< AttributeDecoder*,vector<string> > > attrmap_t;
-#endif
attrmap_t m_attrMap;
vector<string> m_attributeIds;
+ vector< pair< pair<xstring,xstring>,bool > > m_requestedAttrs;
// settings for embedded assertions in metadata
string m_policyId;
m_impl->getAttributeIds(attributes);
}
+ void generateMetadata(SPSSODescriptor& role) const {
+ if (m_impl)
+ m_impl->generateMetadata(role);
+ }
+
protected:
pair<bool,DOMElement*> background_load();
static const XMLCh _AttributeFilter[] = UNICODE_LITERAL_15(A,t,t,r,i,b,u,t,e,F,i,l,t,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 isRequested[] = UNICODE_LITERAL_11(i,s,R,e,q,u,e,s,t,e,d);
static const XMLCh _MetadataProvider[] = UNICODE_LITERAL_16(M,e,t,a,d,a,t,a,P,r,o,v,i,d,e,r);
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);
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*,vector<string> >& decl = m_attrMap[pair<xstring,xstring>(name,format)];
-#else
- auto_ptr_char n(name);
- auto_ptr_char f(format);
- pair< AttributeDecoder*,vector<string> >& decl = m_attrMap[pair<string,string>(n.get(),f.get())];
-#endif
if (decl.first) {
m_log.warn("skipping duplicate Attribute mapping (same name and nameFormat)");
delete decoder;
}
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.second.push_back(id.get());
m_attributeIds.push_back(id.get());
+ // Check for isRequired/isRequested.
+ bool requested = XMLHelper::getAttrBool(child, false, isRequested);
+ bool required = XMLHelper::getAttrBool(child, false, RequestedAttribute::ISREQUIRED_ATTRIB_NAME);
+ if (required || requested)
+ m_requestedAttrs.push_back(make_pair(make_pair(name,format), required));
+
name = child->getAttributeNS(nullptr, _aliases);
if (name && *name) {
auto_ptr_char aliases(name);
m_attrLock = RWLock::create();
}
+void XMLExtractorImpl::generateMetadata(SPSSODescriptor& role) const
+{
+ if (m_requestedAttrs.empty())
+ return;
+ int index = 1;
+ const vector<AttributeConsumingService*>& svcs = const_cast<const SPSSODescriptor*>(&role)->getAttributeConsumingServices();
+ for (vector<AttributeConsumingService*>::const_iterator s =svcs.begin(); s != svcs.end(); ++s) {
+ pair<bool,int> i = (*s)->getIndex();
+ if (i.first && index == i.second)
+ index = i.second + 1;
+ }
+ AttributeConsumingService* svc = AttributeConsumingServiceBuilder::buildAttributeConsumingService();
+ role.getAttributeConsumingServices().push_back(svc);
+ svc->setIndex(index);
+ ServiceName* sn = ServiceNameBuilder::buildServiceName();
+ svc->getServiceNames().push_back(sn);
+ sn->setName(dynamic_cast<EntityDescriptor*>(role.getParent())->getEntityID());
+ static const XMLCh english[] = UNICODE_LITERAL_2(e,n);
+ sn->setLang(english);
+
+ for (vector< pair< pair<xstring,xstring>,bool > >::const_iterator i = m_requestedAttrs.begin(); i != m_requestedAttrs.end(); ++i) {
+ RequestedAttribute* req = RequestedAttributeBuilder::buildRequestedAttribute();
+ svc->getRequestedAttributes().push_back(req);
+ req->setName(i->first.first.c_str());
+ if (i->first.second.empty())
+ req->setNameFormat(saml2::Attribute::URI_REFERENCE);
+ else
+ req->setNameFormat(i->first.second.c_str());
+ if (i->second)
+ req->isRequired(true);
+ }
+}
+
void XMLExtractorImpl::extractAttributes(
const Application& application,
const char* assertingParty,
vector<Attribute*>& attributes
) const
{
-#ifdef HAVE_GOOD_STL
map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-#else
- map< pair<string,string>,pair< AttributeDecoder*,vector<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(pair<xstring,xstring>(format,xstring()))) != m_attrMap.end()) {
-#else
- auto_ptr_char temp(format);
- if ((rule=m_attrMap.find(pair<string,string>(temp.get(),string()))) != m_attrMap.end()) {
-#endif
Attribute* a = rule->second.first->decode(rule->second.second, &nameid, assertingParty, relyingParty);
if (a)
attributes.push_back(a);
}
else if (m_log.isDebugEnabled()) {
-#ifdef HAVE_GOOD_STL
auto_ptr_char temp(format);
-#endif
m_log.debug("skipping unmapped NameIdentifier with format (%s)", temp.get());
}
}
vector<Attribute*>& attributes
) const
{
-#ifdef HAVE_GOOD_STL
map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-#else
- map< pair<string,string>,pair< AttributeDecoder*,vector<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(pair<xstring,xstring>(format,xstring()))) != m_attrMap.end()) {
-#else
- auto_ptr_char temp(format);
- if ((rule=m_attrMap.find(pair<string,string>(temp.get(),string()))) != m_attrMap.end()) {
-#endif
Attribute* a = rule->second.first->decode(rule->second.second, &nameid, assertingParty, relyingParty);
if (a)
attributes.push_back(a);
}
else if (m_log.isDebugEnabled()) {
-#ifdef HAVE_GOOD_STL
auto_ptr_char temp(format);
-#endif
m_log.debug("skipping unmapped NameID with format (%s)", temp.get());
}
}
vector<Attribute*>& attributes
) const
{
-#ifdef HAVE_GOOD_STL
map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-#else
- map< pair<string,string>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-#endif
const XMLCh* name = attr.getAttributeName();
const XMLCh* format = attr.getAttributeNamespace();
return;
if (!format || XMLString::equals(format, shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI))
format = &chNull;
-#ifdef HAVE_GOOD_STL
if ((rule=m_attrMap.find(pair<xstring,xstring>(name,format))) != m_attrMap.end()) {
-#else
- auto_ptr_char temp1(name);
- auto_ptr_char temp2(format);
- if ((rule=m_attrMap.find(pair<string,string>(temp1.get(),temp2.get()))) != m_attrMap.end()) {
-#endif
Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty);
if (a)
attributes.push_back(a);
}
else if (m_log.isInfoEnabled()) {
-#ifdef HAVE_GOOD_STL
auto_ptr_char temp1(name);
auto_ptr_char temp2(format);
-#endif
m_log.info("skipping unmapped SAML 1.x Attribute with Name: %s%s%s", temp1.get(), *temp2.get() ? ", Namespace:" : "", temp2.get());
}
}
vector<Attribute*>& attributes
) const
{
-#ifdef HAVE_GOOD_STL
map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-#else
- map< pair<string,string>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-#endif
const XMLCh* name = attr.getName();
const XMLCh* format = attr.getNameFormat();
else if (XMLString::equals(format, saml2::Attribute::URI_REFERENCE))
format = &chNull;
-#ifdef HAVE_GOOD_STL
if ((rule=m_attrMap.find(pair<xstring,xstring>(name,format))) != m_attrMap.end()) {
-#else
- auto_ptr_char temp1(name);
- auto_ptr_char temp2(format);
- if ((rule=m_attrMap.find(pair<string,string>(temp1.get(),temp2.get()))) != m_attrMap.end()) {
-#endif
Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty);
if (a) {
attributes.push_back(a);
}
else if (XMLString::equals(format, saml2::Attribute::UNSPECIFIED)) {
// As a fallback, if the format is "unspecified", null out the value and re-map.
-#ifdef HAVE_GOOD_STL
if ((rule=m_attrMap.find(pair<xstring,xstring>(name,xstring()))) != m_attrMap.end()) {
-#else
- if ((rule=m_attrMap.find(pair<string,string>(temp1.get(),string()))) != m_attrMap.end()) {
-#endif
Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty);
if (a) {
attributes.push_back(a);
}
if (m_log.isInfoEnabled()) {
-#ifdef HAVE_GOOD_STL
auto_ptr_char temp1(name);
auto_ptr_char temp2(format);
-#endif
m_log.info("skipping unmapped SAML 2.0 Attribute with Name: %s%s%s", temp1.get(), *temp2.get() ? ", Format:" : "", temp2.get());
}
}
#include "handler/RemotedHandler.h"
#ifndef SHIBSP_LITE
+# include "attribute/resolver/AttributeExtractor.h"
# include "metadata/MetadataProviderCriteria.h"
# include <saml/exceptions.h>
# include <saml/SAMLConfig.h>
{
public:
MetadataGenerator(const DOMElement* e, const char* appId);
- virtual ~MetadataGenerator() {}
+ virtual ~MetadataGenerator() {
+#ifndef SHIBSP_LITE
+ delete m_uiinfo;
+ delete m_org;
+ delete m_entityAttrs;
+ for_each(m_contacts.begin(), m_contacts.end(), xmltooling::cleanup<ContactPerson>());
+ for_each(m_reqAttrs.begin(), m_reqAttrs.end(), xmltooling::cleanup<RequestedAttribute>());
+ for_each(m_attrConsumers.begin(), m_attrConsumers.end(), xmltooling::cleanup<AttributeConsumingService>());
+#endif
+ }
pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
void receive(DDF& in, ostream& out);
string m_salt;
short m_http,m_https;
vector<string> m_bases;
+ UIInfo* m_uiinfo;
+ Organization* m_org;
+ EntityAttributes* m_entityAttrs;
+ vector<ContactPerson*> m_contacts;
+ vector<RequestedAttribute*> m_reqAttrs;
+ vector<AttributeConsumingService*> m_attrConsumers;
#endif
};
MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId)
: AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".MetadataGenerator"), &g_Blocker)
#ifndef SHIBSP_LITE
- ,m_http(0), m_https(0)
+ ,m_http(0), m_https(0), m_uiinfo(nullptr), m_org(nullptr), m_entityAttrs(nullptr)
#endif
{
string address(appId);
if (flag.first)
m_https = flag.second ? 1 : -1;
- e = XMLHelper::getFirstChildElement(e, EndpointBase);
+ e = XMLHelper::getFirstChildElement(e);
while (e) {
- if (e->hasChildNodes()) {
+ if (XMLString::equals(e->getLocalName(), EndpointBase) && e->hasChildNodes()) {
auto_ptr_char base(e->getFirstChild()->getNodeValue());
if (base.get() && *base.get())
m_bases.push_back(base.get());
}
- e = XMLHelper::getNextSiblingElement(e, EndpointBase);
+ else {
+ // Try and parse the object.
+ auto_ptr<XMLObject> child(XMLObjectBuilder::buildOneFromElement(const_cast<DOMElement*>(e)));
+ ContactPerson* cp = dynamic_cast<ContactPerson*>(child.get());
+ if (cp) {
+ child.release();
+ m_contacts.push_back(cp);
+ }
+ else {
+ RequestedAttribute* req = dynamic_cast<RequestedAttribute*>(child.get());
+ if (req) {
+ child.release();
+ m_reqAttrs.push_back(req);
+ }
+ else {
+ AttributeConsumingService* acs = dynamic_cast<AttributeConsumingService*>(child.get());
+ if (acs) {
+ child.release();
+ m_attrConsumers.push_back(acs);
+ }
+ else {
+ UIInfo* info = dynamic_cast<UIInfo*>(child.get());
+ if (info) {
+ if (!m_uiinfo) {
+ child.release();
+ m_uiinfo = info;
+ }
+ else {
+ m_log.warn("skipping duplicate UIInfo element");
+ }
+ }
+ else {
+ Organization* org = dynamic_cast<Organization*>(child.get());
+ if (org) {
+ if (!m_org) {
+ child.release();
+ m_org = org;
+ }
+ else {
+ m_log.warn("skipping duplicate Organization element");
+ }
+ }
+ else {
+ EntityAttributes* ea = dynamic_cast<EntityAttributes*>(child.get());
+ if (ea) {
+ if (!m_entityAttrs) {
+ child.release();
+ m_entityAttrs = ea;
+ }
+ else {
+ m_log.warn("skipping duplicate EntityAttributes element");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ e = XMLHelper::getNextSiblingElement(e);
}
#endif
}
entity->setValidUntil(time(nullptr) + cache.second);
entity->setEntityID(relyingParty->getXMLString("entityID").second);
+ if (m_org && !entity->getOrganization())
+ entity->setOrganization(m_org->cloneOrganization());
+
+ for (vector<ContactPerson*>::const_iterator cp = m_contacts.begin(); cp != m_contacts.end(); ++cp)
+ entity->getContactPersons().push_back((*cp)->cloneContactPerson());
+
+ if (m_entityAttrs) {
+ if (!entity->getExtensions())
+ entity->setExtensions(ExtensionsBuilder::buildExtensions());
+ entity->getExtensions()->getUnknownXMLObjects().push_back(m_entityAttrs->cloneEntityAttributes());
+ }
+
SPSSODescriptor* role;
if (entity->getSPSSODescriptors().empty()) {
role = SPSSODescriptorBuilder::buildSPSSODescriptor();
role = entity->getSPSSODescriptors().front();
}
+ if (m_uiinfo) {
+ if (!role->getExtensions())
+ role->setExtensions(ExtensionsBuilder::buildExtensions());
+ role->getExtensions()->getUnknownXMLObjects().push_back(m_uiinfo->cloneUIInfo());
+ }
+
+ for (vector<AttributeConsumingService*>::const_iterator acs = m_attrConsumers.begin(); acs != m_attrConsumers.end(); ++acs)
+ role->getAttributeConsumingServices().push_back((*acs)->cloneAttributeConsumingService());
+
+ if (!m_reqAttrs.empty()) {
+ int index = 1;
+ const vector<AttributeConsumingService*>& svcs = const_cast<const SPSSODescriptor*>(role)->getAttributeConsumingServices();
+ for (vector<AttributeConsumingService*>::const_iterator s =svcs.begin(); s != svcs.end(); ++s) {
+ pair<bool,int> i = (*s)->getIndex();
+ if (i.first && index == i.second)
+ index = i.second + 1;
+ }
+ AttributeConsumingService* svc = AttributeConsumingServiceBuilder::buildAttributeConsumingService();
+ role->getAttributeConsumingServices().push_back(svc);
+ svc->setIndex(index);
+ ServiceName* sn = ServiceNameBuilder::buildServiceName();
+ svc->getServiceNames().push_back(sn);
+ sn->setName(entity->getEntityID());
+ static const XMLCh english[] = UNICODE_LITERAL_2(e,n);
+ sn->setLang(english);
+ for (vector<RequestedAttribute*>::const_iterator req = m_reqAttrs.begin(); req != m_reqAttrs.end(); ++req)
+ svc->getRequestedAttributes().push_back((*req)->cloneRequestedAttribute());
+ }
+
// Policy flags.
prop = relyingParty->getString("signing");
if (prop.first && (!strcmp(prop.second,"true") || !strcmp(prop.second,"front")))
}
}
+ AttributeExtractor* extractor = application.getAttributeExtractor();
+ if (extractor) {
+ Locker extlocker(extractor);
+ extractor->generateMetadata(*role);
+ }
+
CredentialResolver* credResolver=application.getCredentialResolver();
if (credResolver) {
Locker credLocker(credResolver);