[shibboleth-sp2] 47/119: Backport PathRegex support, can't do queries.

Ferenc Wágner wferi-guest at moszumanska.debian.org
Tue Jan 26 21:29:49 UTC 2016


This is an automated email from the git hooks/post-receive script.

wferi-guest pushed a commit to annotated tag 1.3.1
in repository shibboleth-sp2.

commit e9e984841b14464eb968d4d2b8e385a27601df97
Author: Scott Cantor <cantor.2 at osu.edu>
Date:   Tue Sep 4 17:06:06 2007 +0000

    Backport PathRegex support, can't do queries.
---
 schemas/shibboleth-targetconfig-1.0.xsd |  51 ++++++++++++-
 shib-target/XMLRequestMapper.cpp        | 122 +++++++++++++++++++++++++-------
 2 files changed, 144 insertions(+), 29 deletions(-)

diff --git a/schemas/shibboleth-targetconfig-1.0.xsd b/schemas/shibboleth-targetconfig-1.0.xsd
index a0795db..7c7efb8 100644
--- a/schemas/shibboleth-targetconfig-1.0.xsd
+++ b/schemas/shibboleth-targetconfig-1.0.xsd
@@ -270,7 +270,10 @@
 					<element ref="conf:AccessControl"/>
 	            	<element ref="conf:AccessControlProvider"/>
 	            </choice>
-                <element ref="conf:Host" minOccurs="0" maxOccurs="unbounded"/>
+            	<choice minOccurs="0" maxOccurs="unbounded">
+            		<element ref="conf:Host"/>
+            		<element ref="conf:HostRegex"/>
+            	</choice>
             </sequence>
             <attribute name="applicationId" type="string" fixed="default"/>
          	<attributeGroup ref="conf:ContentSettings"/>
@@ -285,7 +288,10 @@
 					<element ref="conf:AccessControl"/>
 	            	<element ref="conf:AccessControlProvider"/>
 	            </choice>
-    			<element ref="conf:Path" minOccurs="0" maxOccurs="unbounded"/>
+    			<choice minOccurs="0" maxOccurs="unbounded">
+    				<element ref="conf:Path"/>
+    				<element ref="conf:PathRegex"/>
+    			</choice>
     		</sequence>
     		<attribute name="scheme" use="optional">
 			    <simpleType>
@@ -305,6 +311,26 @@
     	</complexType>
     </element>
 
+	<element name="HostRegex">
+		<complexType>
+			<sequence>
+				<choice minOccurs="0">
+					<element ref="conf:htaccess"/>
+					<element ref="conf:AccessControl"/>
+					<element ref="conf:AccessControlProvider"/>
+				</choice>
+				<choice minOccurs="0" maxOccurs="unbounded">
+					<element ref="conf:Path"/>
+					<element ref="conf:PathRegex"/>
+				</choice>
+			</sequence>
+			<attribute name="regex" type="conf:string" use="required"/>
+			<attribute name="ignoreCase" type="boolean" default="true"/>
+			<attribute name="applicationId" type="conf:string"/>
+			<attributeGroup ref="conf:ContentSettings"/>
+		</complexType>
+	</element>
+	
     <element name="Path">
         <complexType>
     		<sequence>
@@ -313,7 +339,10 @@
 					<element ref="conf:AccessControl"/>
 	            	<element ref="conf:AccessControlProvider"/>
 	            </choice>
-    			<element ref="conf:Path" minOccurs="0" maxOccurs="unbounded"/>
+    			<choice minOccurs="0" maxOccurs="unbounded">
+    				<element ref="conf:Path"/>
+    				<element ref="conf:PathRegex"/>
+    			</choice>
     		</sequence>
     		<attribute name="name" type="string" use="required"/>
     		<attribute name="applicationId" type="string" use="optional"/>
@@ -321,6 +350,22 @@
         </complexType>
     </element>
 
+	<element name="PathRegex">
+		<complexType>
+			<sequence>
+				<choice minOccurs="0">
+					<element ref="conf:htaccess"/>
+					<element ref="conf:AccessControl"/>
+					<element ref="conf:AccessControlProvider"/>
+				</choice>
+			</sequence>
+			<attribute name="regex" type="conf:string" use="required"/>
+			<attribute name="ignoreCase" type="boolean" default="true"/>
+			<attribute name="applicationId" type="conf:string"/>
+			<attributeGroup ref="conf:ContentSettings"/>
+		</complexType>
+	</element>
+	
 	<element name="Applications">
 		<annotation>
 			<documentation>Container for global target settings and application-specific overrides</documentation>
diff --git a/shib-target/XMLRequestMapper.cpp b/shib-target/XMLRequestMapper.cpp
index 7e2f776..069641e 100644
--- a/shib-target/XMLRequestMapper.cpp
+++ b/shib-target/XMLRequestMapper.cpp
@@ -24,11 +24,14 @@
 
 #include "internal.h"
 
-using namespace std;
-using namespace saml;
-using namespace shibboleth;
-using namespace shibtarget;
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xercesc/util/regx/RegularExpression.hpp>
+
 using namespace shibtarget::logging;
+using namespace shibtarget;
+using namespace shibboleth;
+using namespace saml;
+using namespace std;
 
 namespace shibtarget {
 
@@ -48,7 +51,9 @@ namespace shibtarget {
         const IPropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:target:config:1.0") const;
         
         // Provides filter to exclude special config elements.
-        short acceptNode(const DOMNode* node) const;
+        short acceptNode(const DOMNode* node) const {
+            return FILTER_REJECT;
+        }
 
         const Override* locate(const char* path) const;
         IAccessControl* getAC() const { return (m_acl ? m_acl : (m_base ? m_base->getAC() : NULL)); }
@@ -57,6 +62,7 @@ namespace shibtarget {
         void loadACL(const DOMElement* e, Category& log);
         
         map<string,Override*> m_map;
+        vector< pair<RegularExpression*,Override*> > m_regexps;
     
     private:
         const Override* m_base;
@@ -91,6 +97,12 @@ namespace shibtarget {
         virtual ReloadableXMLFileImpl* newImplementation(const char* pathname, bool first=true) const;
         virtual ReloadableXMLFileImpl* newImplementation(const DOMElement* e, bool first=true) const;
     };
+
+    static const XMLCh HostRegex[] =    { chLatin_H, chLatin_o, chLatin_s, chLatin_t, chLatin_R, chLatin_e, chLatin_g, chLatin_e, chLatin_x, chNull };
+    static const XMLCh ignoreCase[] =   { chLatin_i, chLatin_g, chLatin_n, chLatin_o, chLatin_r, chLatin_e, chLatin_C, chLatin_a, chLatin_s, chLatin_e, chNull };
+    static const XMLCh ignoreOption[] = { chLatin_i, chNull };
+    static const XMLCh PathRegex[] =    { chLatin_P, chLatin_a, chLatin_t, chLatin_h, chLatin_R, chLatin_e, chLatin_g, chLatin_e, chLatin_x, chNull };
+    static const XMLCh regex[] =        { chLatin_r, chLatin_e, chLatin_g, chLatin_e, chLatin_x, chNull };
 }
 
 IPlugIn* XMLRequestMapFactory(const DOMElement* e)
@@ -100,21 +112,6 @@ IPlugIn* XMLRequestMapFactory(const DOMElement* e)
     return m.release();
 }
 
-short Override::acceptNode(const DOMNode* node) const
-{
-    if (XMLString::compareString(node->getNamespaceURI(),shibtarget::XML::SHIBTARGET_NS))
-        return FILTER_ACCEPT;
-    const XMLCh* name=node->getLocalName();
-    if (!XMLString::compareString(name,SHIBT_L(Host)) ||
-        !XMLString::compareString(name,SHIBT_L(Path)) ||
-        !XMLString::compareString(name,SHIBT_L(AccessControl)) ||
-        !XMLString::compareString(name,SHIBT_L(htaccess)) ||
-        !XMLString::compareString(name,SHIBT_L(AccessControlProvider)))
-        return FILTER_REJECT;
-
-    return FILTER_ACCEPT;
-}
-
 void Override::loadACL(const DOMElement* e, Category& log)
 {
     IPlugIn* plugin=NULL;
@@ -126,14 +123,14 @@ void Override::loadACL(const DOMElement* e, Category& log)
     else {
         acl=saml::XML::getFirstChildElement(e,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(AccessControl));
         if (acl) {
-            log.info("building XML-based Access Control provider...");
+            log.info("building XML-based AccessControl provider...");
             plugin=SAMLConfig::getConfig().getPlugMgr().newPlugin(shibtarget::XML::XMLAccessControlType,acl);
         }
         else {
             acl=saml::XML::getFirstChildElement(e,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(AccessControlProvider));
             if (acl) {
                 auto_ptr_char type(acl->getAttributeNS(NULL,SHIBT_L(type)));
-                log.info("building Access Control provider of type %s...",type.get());
+                log.info("building AccessControl provider of type %s...",type.get());
                 plugin=SAMLConfig::getConfig().getPlugMgr().newPlugin(type.get(),acl);
             }
         }
@@ -144,7 +141,7 @@ void Override::loadACL(const DOMElement* e, Category& log)
             m_acl=acl;
         else {
             delete plugin;
-            log.fatal("plugin was not an Access Control provider");
+            log.fatal("plugin was not an AccessControl provider");
             throw UnsupportedExtensionException("plugin was not an Access Control provider");
         }
     }
@@ -228,9 +225,46 @@ Override::Override(const DOMElement* e, Category& log, const Override* base) : m
             
             path=saml::XML::getNextSiblingElement(path,shibtarget::XML::SHIBTARGET_NS,SHIBT_L(Path));
         }
+
+        if (!XMLString::equals(e->getLocalName(), PathRegex)) {
+            // Handle nested PathRegexs.
+            path = saml::XML::getFirstChildElement(e,shibtarget::XML::SHIBTARGET_NS,PathRegex);
+            for (int i=1; path; ++i, path=saml::XML::getNextSiblingElement(path,shibtarget::XML::SHIBTARGET_NS,PathRegex)) {
+                const XMLCh* n=path->getAttributeNS(NULL,regex);
+                if (!n || !*n) {
+                    log.warn("skipping PathRegex element (%d) with empty regex attribute",i);
+                    continue;
+                }
+
+                auto_ptr<Override> o(new Override(path,log,this));
+
+                const XMLCh* flag=path->getAttributeNS(NULL,ignoreCase);
+                try {
+                    auto_ptr<RegularExpression> re(
+                        new RegularExpression(n, (flag && (*flag==chLatin_f || *flag==chDigit_0)) ? &chNull : ignoreOption)
+                        );
+                    m_regexps.push_back(make_pair(re.release(), o.release()));
+                }
+                catch (XMLException& ex) {
+                    auto_ptr_char tmp(ex.getMessage());
+                    log.error("caught exception while parsing PathRegex regular expression (%d): %s", i, tmp.get());
+                    throw ConfigurationException("Invalid regular expression in PathRegex element.");
+                }
+
+                if (log.isDebugEnabled())
+                    log.debug("added <PathRegex> mapping (%s)", m_regexps.back().second->getString("regex").second);
+            }
+        }
     }
     catch (...) {
-        this->~Override();
+        delete m_acl;
+
+        for (map<string,Override*>::iterator m=m_map.begin(); m!=m_map.end(); m++)
+            delete m->second;
+        for (vector< pair<RegularExpression*,Override*> >::iterator i = m_regexps.begin(); i != m_regexps.end(); ++i) {
+            delete i->first;
+            delete i->second;
+        }
         throw;
     }
 }
@@ -238,8 +272,12 @@ Override::Override(const DOMElement* e, Category& log, const Override* base) : m
 Override::~Override()
 {
     delete m_acl;
-    for (map<string,Override*>::iterator i=m_map.begin(); i!=m_map.end(); i++)
+    for (map<string,Override*>::iterator m=m_map.begin(); m!=m_map.end(); m++)
+        delete m->second;
+    for (vector< pair<RegularExpression*,Override*> >::iterator i = m_regexps.begin(); i != m_regexps.end(); ++i) {
+        delete i->first;
         delete i->second;
+    }
 }
 
 pair<bool,bool> Override::getBool(const char* name, const char* ns) const
@@ -292,6 +330,14 @@ const IPropertySet* Override::getPropertySet(const char* name, const char* ns) c
 
 const Override* Override::locate(const char* path) const
 {
+    // This function is confusing because it's *not* recursive.
+    // The whole path is tokenized and mapped in a loop, so the
+    // path parameter starts with the entire request path and
+    // we can skip the leading slash as irrelevant.
+    if (*path == '/')
+        path++;
+
+    // Now we copy the path, chop the query string, and lower case it.
     char* dup=strdup(path);
     char* sep=strchr(dup,'?');
     if (sep)
@@ -299,8 +345,10 @@ const Override* Override::locate(const char* path) const
     for (char* pch=dup; *pch; pch++)
         *pch=tolower(*pch);
         
+    // Default is for the current object to provide settings.
     const Override* o=this;
     
+    // Tokenize the path by segment and try and map each segment.
 #ifdef HAVE_STRTOK_R
     char* pos=NULL;
     const char* token=strtok_r(dup,"/",&pos);
@@ -311,8 +359,16 @@ const Override* Override::locate(const char* path) const
     {
         map<string,Override*>::const_iterator i=o->m_map.find(token);
         if (i==o->m_map.end())
-            break;
+            break;  // Once there's no match, we've consumed as much of the path as possible here.
+        // We found a match, so reset the settings pointer.
         o=i->second;
+
+        // We descended a step down the path, so we need to advance the original
+        // parameter for the regex step later.
+        path += strlen(token);
+        if (*path == '/')
+            path++;
+        
 #ifdef HAVE_STRTOK_R
         token=strtok_r(NULL,"/",&pos);
 #else
@@ -321,6 +377,20 @@ const Override* Override::locate(const char* path) const
     }
 
     free(dup);
+
+    // If there's anything left, we try for a regex match on the rest of the path minus the query string.
+    if (*path) {
+        string path2(path);
+        path2 = path2.substr(0,path2.find('?'));
+
+        for (vector< pair<RegularExpression*,Override*> >::const_iterator re = o->m_regexps.begin(); re != o->m_regexps.end(); ++re) {
+            if (re->first->matches(path2.c_str())) {
+                o = re->second;
+                break;
+            }
+        }
+    }
+    
     return o;
 }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-shibboleth/shibboleth-sp2.git



More information about the Pkg-shibboleth-devel mailing list