const XMLCh XML::Literals::xpath[] =
{ chLatin_x, chLatin_p, chLatin_a, chLatin_t, chLatin_h, chNull };
-
-const XMLCh XML::Literals::url[] = { chLatin_u, chLatin_r, chLatin_l, chNull };
-
-const XMLCh XML::Literals::AccessControl[] =
-{ chLatin_A, chLatin_c, chLatin_c, chLatin_e, chLatin_s, chLatin_s,
- chLatin_C, chLatin_o, chLatin_n, chLatin_t, chLatin_r, chLatin_o, chLatin_l, chNull
-};
-
-const XMLCh XML::Literals::AND[] =
-{ chLatin_A, chLatin_N, chLatin_D, chNull };
-
-const XMLCh XML::Literals::NOT[] =
-{ chLatin_N, chLatin_O, chLatin_T, chNull };
-
-const XMLCh XML::Literals::OR[] =
-{ chLatin_O, chLatin_R, chNull };
-
-const XMLCh XML::Literals::require[] =
-{ chLatin_r, chLatin_e, chLatin_q, chLatin_u, chLatin_i, chLatin_r, chLatin_e, chNull };
-
-const XMLCh XML::Literals::Rule[] =
-{ chLatin_R, chLatin_u, chLatin_l, chLatin_e, chNull };
#include <algorithm>
#include <shib-target/shib-target.h>
-#include <log4cpp/Category.hh>
+#include <xmltooling/util/ReloadableXMLFile.h>
+#include <xmltooling/util/XMLHelper.h>
#ifndef HAVE_STRCASECMP
# define strcasecmp _stricmp
#endif
+using namespace shibsp;
+using namespace shibtarget;
using namespace saml;
using namespace shibboleth;
-using namespace shibtarget;
+using namespace xmltooling;
using namespace std;
-using namespace log4cpp;
namespace {
struct IAuthz {
vector<IAuthz*> m_operands;
};
- class XMLAccessControlImpl : public ReloadableXMLFileImpl
- {
- public:
- XMLAccessControlImpl(const char* pathname) : ReloadableXMLFileImpl(pathname) { init(); }
- XMLAccessControlImpl(const DOMElement* e) : ReloadableXMLFileImpl(e) { init(); }
- void init();
- ~XMLAccessControlImpl() {delete m_rootAuthz;}
-
- IAuthz* m_rootAuthz;
- };
+#if defined (_MSC_VER)
+ #pragma warning( push )
+ #pragma warning( disable : 4250 )
+#endif
- class XMLAccessControl : public IAccessControl, public ReloadableXMLFile
+ class XMLAccessControl : public IAccessControl, public xmltooling::ReloadableXMLFile
{
public:
- XMLAccessControl(const DOMElement* e) : ReloadableXMLFile(e) {}
- ~XMLAccessControl() {}
+ XMLAccessControl(const DOMElement* e) : xmltooling::ReloadableXMLFile(e), m_rootAuthz(NULL) {
+ load(); // guarantees an exception or the policy is loaded
+ }
+
+ ~XMLAccessControl() {
+ delete m_rootAuthz;
+ }
- virtual bool authorized(ShibTarget* st, ISessionCacheEntry* entry) const;
+ bool authorized(ShibTarget* st, ISessionCacheEntry* entry) const;
protected:
- virtual ReloadableXMLFileImpl* newImplementation(const char* pathname, bool first=true) const;
- virtual ReloadableXMLFileImpl* newImplementation(const DOMElement* e, bool first=true) const;
+ pair<bool,DOMElement*> load();
+
+ private:
+ IAuthz* m_rootAuthz;
};
+
+#if defined (_MSC_VER)
+ #pragma warning( pop )
+#endif
+
+ static const XMLCh AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);
+ static const XMLCh require[] = UNICODE_LITERAL_7(r,e,q,u,i,r,e);
+ static const XMLCh NOT[] = UNICODE_LITERAL_3(N,O,T);
+ static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D);
+ static const XMLCh OR[] = UNICODE_LITERAL_2(O,R);
+ static const XMLCh _Rule[] = UNICODE_LITERAL_4(R,u,l,e);
}
IPlugIn* XMLAccessControlFactory(const DOMElement* e)
{
- auto_ptr<XMLAccessControl> a(new XMLAccessControl(e));
- a->getImplementation();
- return a.release();
+ return new XMLAccessControl(e);
}
Rule::Rule(const DOMElement* e)
{
- auto_ptr_char req(e->getAttributeNS(NULL,SHIB_L(require)));
+ xmltooling::auto_ptr_char req(e->getAttributeNS(NULL,require));
if (!req.get() || !*req.get())
- throw MalformedException("Access control rule missing require attribute");
+ throw ConfigurationException("Access control rule missing require attribute");
m_alias=req.get();
- auto_ptr_char vals(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL);
+ xmltooling::auto_ptr_char vals(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL);
#ifdef HAVE_STRTOK_R
char* pos=NULL;
const char* token=strtok_r(const_cast<char*>(vals.get()),"/",&pos);
Operator::Operator(const DOMElement* e)
{
- if (saml::XML::isElementNamed(e,shibtarget::XML::SHIBTARGET_NS,SHIB_L(NOT)))
+ if (XMLString::equals(e->getLocalName(),NOT))
m_op=OP_NOT;
- else if (saml::XML::isElementNamed(e,shibtarget::XML::SHIBTARGET_NS,SHIB_L(AND)))
+ else if (XMLString::equals(e->getLocalName(),AND))
m_op=OP_AND;
- else if (saml::XML::isElementNamed(e,shibtarget::XML::SHIBTARGET_NS,SHIB_L(OR)))
+ else if (XMLString::equals(e->getLocalName(),OR))
m_op=OP_OR;
else
- throw MalformedException("Unrecognized operator in access control rule");
+ throw ConfigurationException("Unrecognized operator in access control rule");
try {
- e=saml::XML::getFirstChildElement(e);
- if (saml::XML::isElementNamed(e,shibtarget::XML::SHIBTARGET_NS,SHIB_L(Rule)))
+ e=XMLHelper::getFirstChildElement(e);
+ if (XMLString::equals(e->getLocalName(),_Rule))
m_operands.push_back(new Rule(e));
else
m_operands.push_back(new Operator(e));
if (m_op==OP_NOT)
return;
- e=saml::XML::getNextSiblingElement(e);
+ e=XMLHelper::getNextSiblingElement(e);
while (e) {
- if (saml::XML::isElementNamed(e,shibtarget::XML::SHIBTARGET_NS,SHIB_L(Rule)))
+ if (XMLString::equals(e->getLocalName(),_Rule))
m_operands.push_back(new Rule(e));
else
m_operands.push_back(new Operator(e));
- e=saml::XML::getNextSiblingElement(e);
+ e=XMLHelper::getNextSiblingElement(e);
}
}
- catch (SAMLException&) {
- this->~Operator();
+ catch (exception&) {
+ for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<IAuthz>());
throw;
}
}
return false;
}
-void XMLAccessControlImpl::init()
+pair<bool,DOMElement*> XMLAccessControl::load()
{
-#ifdef _DEBUG
- xmltooling::NDC ndc("init");
-#endif
- Category* log=&Category::getInstance(XMLPROVIDERS_LOGCAT".AccessControl");
-
- try {
- // We need to move below the AccessControl root element if the policy is in a separate file.
- // Unlike most of the plugins, an inline policy will end up handing us the first inline
- // content element, and not the outer wrapper.
- const DOMElement* rootElement=ReloadableXMLFileImpl::m_root;
- if (saml::XML::isElementNamed(rootElement,shibtarget::XML::SHIBTARGET_NS,SHIB_L(AccessControl)))
- rootElement = saml::XML::getFirstChildElement(rootElement);
-
- if (saml::XML::isElementNamed(rootElement,shibtarget::XML::SHIBTARGET_NS,SHIB_L(Rule)))
- m_rootAuthz=new Rule(rootElement);
- else
- m_rootAuthz=new Operator(rootElement);
- }
- catch (SAMLException& e) {
- log->errorStream() << "Error while parsing access control configuration: " << e.what() << CategoryStream::ENDLINE;
- throw;
- }
-#ifndef _DEBUG
- catch (...)
- {
- log->error("Unexpected error while parsing access control configuration");
- throw;
- }
-#endif
-}
+ // 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);
-ReloadableXMLFileImpl* XMLAccessControl::newImplementation(const char* pathname, bool first) const
-{
- return new XMLAccessControlImpl(pathname);
-}
+ // Check for AccessControl wrapper and drop a level.
+ if (XMLString::equals(raw.second->getLocalName(),AccessControl))
+ raw.second = XMLHelper::getFirstChildElement(raw.second);
+
+ IAuthz* authz;
+ if (XMLString::equals(raw.second->getLocalName(),_Rule))
+ authz=new Rule(raw.second);
+ else
+ authz=new Operator(raw.second);
-ReloadableXMLFileImpl* XMLAccessControl::newImplementation(const DOMElement* e, bool first) const
-{
- return new XMLAccessControlImpl(e);
+ delete m_rootAuthz;
+ m_rootAuthz = authz;
+ return make_pair(false,(DOMElement*)NULL);
}
bool XMLAccessControl::authorized(ShibTarget* st, ISessionCacheEntry* entry) const
{
- return static_cast<XMLAccessControlImpl*>(getImplementation())->m_rootAuthz->authorized(st,entry);
+ return m_rootAuthz ? m_rootAuthz->authorized(st,entry) : false;
}