#include <xmltooling/util/ReloadableXMLFile.h>\r
#include <xmltooling/util/XMLHelper.h>\r
#include <xercesc/util/XMLUniDefs.hpp>\r
+#include <xercesc/util/regx/RegularExpression.hpp>\r
\r
#ifndef HAVE_STRCASECMP\r
# define strcasecmp _stricmp\r
vector <string> m_vals;\r
};\r
\r
+ class RuleRegex : public AccessControl\r
+ {\r
+ public:\r
+ RuleRegex(const DOMElement* e);\r
+ ~RuleRegex() {\r
+ delete m_re;\r
+ }\r
+ \r
+ Lockable* lock() {return this;}\r
+ void unlock() {}\r
+\r
+ aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
+ \r
+ private:\r
+ string m_alias;\r
+ auto_arrayptr<char> m_exp;\r
+ RegularExpression* m_re;\r
+ };\r
+ \r
class Operator : public AccessControl\r
{\r
public:\r
return new XMLAccessControl(e);\r
}\r
\r
- static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);\r
+ static const XMLCh _AccessControl[] = UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);\r
+ static const XMLCh ignoreCase[] = UNICODE_LITERAL_10(i,g,n,o,r,e,C,a,s,e);\r
+ static const XMLCh ignoreOption[] = UNICODE_LITERAL_1(i);\r
+ static const XMLCh _list[] = UNICODE_LITERAL_4(l,i,s,t);\r
static const XMLCh require[] = UNICODE_LITERAL_7(r,e,q,u,i,r,e);\r
static const XMLCh NOT[] = UNICODE_LITERAL_3(N,O,T);\r
static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D);\r
static const XMLCh OR[] = UNICODE_LITERAL_2(O,R);\r
static const XMLCh _Rule[] = UNICODE_LITERAL_4(R,u,l,e);\r
+ static const XMLCh _RuleRegex[] = UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x);\r
}\r
\r
void SHIBSP_API shibsp::registerAccessControls()\r
\r
Rule::Rule(const DOMElement* e)\r
{\r
- xmltooling::auto_ptr_char req(e->getAttributeNS(NULL,require));\r
+ auto_ptr_char req(e->getAttributeNS(NULL,require));\r
if (!req.get() || !*req.get())\r
throw ConfigurationException("Access control rule missing require attribute");\r
m_alias=req.get();\r
+\r
+ auto_arrayptr<char> vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL));\r
+ if (!vals.get())\r
+ return;\r
+ \r
+ const XMLCh* flag = e->getAttributeNS(NULL,_list);\r
+ if (flag && (*flag == chLatin_f || *flag == chDigit_0)) {\r
+ if (*vals.get())\r
+ m_vals.push_back(vals.get());\r
+ return;\r
+ }\r
\r
- xmltooling::auto_ptr_char vals(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL);\r
#ifdef HAVE_STRTOK_R\r
char* pos=NULL;\r
- const char* token=strtok_r(const_cast<char*>(vals.get()),"/",&pos);\r
+ const char* token=strtok_r(const_cast<char*>(vals.get())," ",&pos);\r
#else\r
- const char* token=strtok(const_cast<char*>(vals.get()),"/");\r
+ const char* token=strtok(const_cast<char*>(vals.get())," ");\r
#endif\r
while (token) {\r
m_vals.push_back(token);\r
#ifdef HAVE_STRTOK_R\r
- token=strtok_r(NULL,"/",&pos);\r
+ token=strtok_r(NULL," ",&pos);\r
#else\r
- token=strtok(NULL,"/");\r
+ token=strtok(NULL," ");\r
#endif\r
}\r
}\r
return shib_acl_false;\r
}\r
\r
+ if (m_alias == "valid-user") {\r
+ if (session) {\r
+ request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");\r
+ return shib_acl_true;\r
+ }\r
+ return shib_acl_false;\r
+ }\r
+ if (m_alias == "user") {\r
+ for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {\r
+ if (*i == request.getRemoteUser()) {\r
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted");\r
+ return shib_acl_true;\r
+ }\r
+ }\r
+ return shib_acl_false;\r
+ }\r
+ else if (m_alias == "authnContextClassRef") {\r
+ const char* ref = session->getAuthnContextClassRef();\r
+ for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {\r
+ if (!strcmp(i->c_str(),ref)) {\r
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted");\r
+ return shib_acl_true;\r
+ }\r
+ }\r
+ return shib_acl_false;\r
+ }\r
+ else if (m_alias == "authnContextDeclRef") {\r
+ const char* ref = session->getAuthnContextDeclRef();\r
+ for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {\r
+ if (!strcmp(i->c_str(),ref)) {\r
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted");\r
+ return shib_acl_true;\r
+ }\r
+ }\r
+ return shib_acl_false;\r
+ }\r
+\r
// Find the attribute(s) matching the require rule.\r
pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =\r
session->getIndexedAttributes().equal_range(m_alias);\r
for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {\r
for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {\r
if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) {\r
- request.log(SPRequest::SPDebug, string("AccessControl plugin expecting ") + *j + ", authz granted");\r
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted");\r
return shib_acl_true;\r
}\r
}\r
return shib_acl_false;\r
}\r
\r
+RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL))\r
+{\r
+ auto_ptr_char req(e->getAttributeNS(NULL,require));\r
+ if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get())\r
+ throw ConfigurationException("Access control rule missing require attribute or element content.");\r
+ m_alias=req.get();\r
+ \r
+ const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase);\r
+ bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1));\r
+ try {\r
+ m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull)); \r
+ }\r
+ catch (XMLException& ex) {\r
+ auto_ptr_char tmp(ex.getMessage());\r
+ throw ConfigurationException("Caught exception while parsing RuleRegex regular expression: $1", params(1,tmp.get()));\r
+ }\r
+}\r
+\r
+AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const Session* session) const\r
+{\r
+ // Map alias in rule to the attribute.\r
+ if (!session) {\r
+ request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");\r
+ return shib_acl_false;\r
+ }\r
+ \r
+ if (m_alias == "valid-user") {\r
+ if (session) {\r
+ request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");\r
+ return shib_acl_true;\r
+ }\r
+ return shib_acl_false;\r
+ }\r
+\r
+ try {\r
+ if (m_alias == "user") {\r
+ if (m_re->matches(request.getRemoteUser().c_str())) {\r
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + m_exp.get() + "), authz granted");\r
+ return shib_acl_true;\r
+ }\r
+ return shib_acl_false;\r
+ }\r
+ else if (m_alias == "authnContextClassRef") {\r
+ if (session->getAuthnContextClassRef() && m_re->matches(session->getAuthnContextClassRef())) {\r
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + m_exp.get() + "), authz granted");\r
+ return shib_acl_true;\r
+ }\r
+ return shib_acl_false;\r
+ }\r
+ else if (m_alias == "authnContextDeclRef") {\r
+ if (session->getAuthnContextDeclRef() && m_re->matches(session->getAuthnContextDeclRef())) {\r
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + m_exp.get() + "), authz granted");\r
+ return shib_acl_true;\r
+ }\r
+ return shib_acl_false;\r
+ }\r
+\r
+ // Find the attribute(s) matching the require rule.\r
+ pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =\r
+ session->getIndexedAttributes().equal_range(m_alias);\r
+ if (attrs.first == attrs.second) {\r
+ request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");\r
+ return shib_acl_false;\r
+ }\r
+\r
+ for (; attrs.first != attrs.second; ++attrs.first) {\r
+ // Now we have to intersect the attribute's values against the regular expression.\r
+ const vector<string>& vals = attrs.first->second->getSerializedValues();\r
+ for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {\r
+ if (m_re->matches(j->c_str())) {\r
+ request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted");\r
+ return shib_acl_true;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ catch (XMLException& ex) {\r
+ auto_ptr_char tmp(ex.getMessage());\r
+ request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get());\r
+ }\r
+ \r
+ return shib_acl_false;\r
+}\r
+\r
Operator::Operator(const DOMElement* e)\r
{\r
if (XMLString::equals(e->getLocalName(),NOT))\r
e=XMLHelper::getFirstChildElement(e);\r
if (XMLString::equals(e->getLocalName(),_Rule))\r
m_operands.push_back(new Rule(e));\r
+ else if (XMLString::equals(e->getLocalName(),_RuleRegex))\r
+ m_operands.push_back(new RuleRegex(e));\r
else\r
m_operands.push_back(new Operator(e));\r
\r
while (e) {\r
if (XMLString::equals(e->getLocalName(),_Rule))\r
m_operands.push_back(new Rule(e));\r
+ else if (XMLString::equals(e->getLocalName(),_RuleRegex))\r
+ m_operands.push_back(new RuleRegex(e));\r
else\r
m_operands.push_back(new Operator(e));\r
e=XMLHelper::getNextSiblingElement(e);\r
AccessControl* authz;\r
if (XMLString::equals(raw.second->getLocalName(),_Rule))\r
authz=new Rule(raw.second);\r
+ else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex))\r
+ authz=new RuleRegex(raw.second);\r
else\r
authz=new Operator(raw.second);\r
\r