[cpp-sp] branch master updated: SSPCPP-614 - requireSessionWith cannot be disabled in sub location / path

Scott Cantor cantor.2 at osu.edu
Fri Mar 23 17:10:15 EDT 2018


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

scantor pushed a commit to branch master
in repository cpp-sp.

View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=9ed8e21768f446b1a1a2f90cbeb54ff575036460

The following commit(s) were added to refs/heads/master by this push:
       new  9ed8e21   SSPCPP-614 - requireSessionWith cannot be disabled in sub location / path
9ed8e21 is described below

commit 9ed8e21768f446b1a1a2f90cbeb54ff575036460
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Fri Mar 23 17:09:18 2018 -0400

    SSPCPP-614 - requireSessionWith cannot be disabled in sub location / path
    
    https://issues.shibboleth.net/jira/browse/SSPCPP-614
---
 apache/mod_shib.cpp                         | 228 +++++++++++++++-------------
 apache/mod_shib_20.cpp                      |   1 +
 apache/mod_shib_22.cpp                      |   1 +
 apache/mod_shib_24.cpp                      |   1 +
 nsapi_shib/nsapi_shib.cpp                   |  24 +--
 schemas/shibboleth-3.0-native-sp-config.xsd |   1 +
 shibsp/ServiceProvider.cpp                  |   2 +-
 shibsp/handler/impl/StatusHandler.cpp       |  15 +-
 shibsp/impl/XMLRequestMapper.cpp            |   6 +-
 shibsp/impl/XMLServiceProvider.cpp          |  27 ++--
 shibsp/util/DOMPropertySet.cpp              |  37 +++--
 shibsp/util/DOMPropertySet.h                |  10 +-
 shibsp/util/PropertySet.h                   |   7 -
 13 files changed, 185 insertions(+), 175 deletions(-)

diff --git a/apache/mod_shib.cpp b/apache/mod_shib.cpp
index 61e084e..0a1fd16 100644
--- a/apache/mod_shib.cpp
+++ b/apache/mod_shib.cpp
@@ -89,7 +89,7 @@
 
 #include <cstddef>
 #ifdef HAVE_UNISTD_H
-#include <unistd.h>		// for getpid()
+#include <unistd.h>        // for getpid()
 #endif
 
 using namespace shibsp;
@@ -171,13 +171,14 @@ extern "C" void* merge_shib_server_config (SH_AP_POOL* p, void* base, void* sub)
 struct shib_dir_config
 {
     SH_AP_TABLE* tSettings; // generic table of extensible settings
+    SH_AP_TABLE* tUnsettings; // generic table of settings to "unset", i.e. default and block inheritance
 
     // RM Configuration
 #ifdef SHIB_APACHE_24
     int bRequestMapperAuthz;// support RequestMapper AccessControl plugins
 #else
     char* szAuthGrpFile;    // Auth GroupFile name
-	char* szAccessControl;	// path to "external" AccessControl plugin file
+    char* szAccessControl;    // path to "external" AccessControl plugin file
     int bRequireAll;        // all "known" require directives must match, otherwise OR logic
     int bAuthoritative;     // allow htaccess plugin to DECLINE when authz fails
     int bCompatWith24;      // support 2.4-reserved require logic for compatibility
@@ -201,11 +202,12 @@ extern "C" void* create_shib_dir_config (SH_AP_POOL* p, char* d)
 {
     shib_dir_config* dc=(shib_dir_config*)ap_pcalloc(p,sizeof(shib_dir_config));
     dc->tSettings = nullptr;
+    dc->tUnsettings = nullptr;
 #ifdef SHIB_APACHE_24
     dc->bRequestMapperAuthz = -1;
 #else
     dc->szAuthGrpFile = nullptr;
-	dc->szAccessControl = nullptr;
+    dc->szAccessControl = nullptr;
     dc->bRequireAll = -1;
     dc->bAuthoritative = -1;
     dc->bCompatWith24 = -1;
@@ -230,10 +232,25 @@ extern "C" void* merge_shib_dir_config (SH_AP_POOL* p, void* base, void* sub)
     shib_dir_config* parent=(shib_dir_config*)base;
     shib_dir_config* child=(shib_dir_config*)sub;
 
-    // The child supersedes any matching table settings in the parent.
+    // The child supersedes any matching table settings in the parent,
+    // and only parent settings not "unset" by the child are copied in.
     dc->tSettings = nullptr;
-    if (parent->tSettings)
-        dc->tSettings = ap_copy_table(p, parent->tSettings);
+    if (parent->tSettings) {
+        if (child->tUnsettings) {
+            const array_header* thdr = ap_table_elts(parent->tSettings);
+            const table_entry* tent = (const table_entry*)thdr->elts;
+            for (int i = 0; i < thdr->nelts; ++i) {
+                if (!ap_table_get(child->tUnsettings, tent[i].key)) {
+                    if (!dc->tSettings)
+                        dc->tSettings = ap_make_table(p, thdr->nelts);
+                    ap_table_set(dc->tSettings, tent[i].key, tent[i].val);
+                }
+            }
+        }
+        else {
+            dc->tSettings = ap_copy_table(p, parent->tSettings);
+        }
+    }
     if (child->tSettings) {
         if (dc->tSettings)
             ap_overlap_tables(dc->tSettings, child->tSettings, AP_OVERLAP_TABLES_SET);
@@ -241,19 +258,37 @@ extern "C" void* merge_shib_dir_config (SH_AP_POOL* p, void* base, void* sub)
             dc->tSettings = ap_copy_table(p, child->tSettings);
     }
 
+    // Unsetting is weird. We don't need to carry forward either the parent's
+    // or child's table for our own use because its only relevance is to block
+    // inheritance of the parent's settings during this specific merge. If another
+    // child is merged in, then *its* unset table will be applied to that merge, and
+    // so forth. So the merged result contains no explicit unsetters. Weird.
+    // EXCEPT: we need to merge and track all the unsets done as a group in order
+    // to block inheritance from the RequestMap, which is the "parent" for all
+    // settings.
+    dc->tUnsettings = nullptr;
+    if (parent->tUnsettings)
+        dc->tUnsettings = ap_copy_table(p, parent->tUnsettings);
+    if (child->tUnsettings) {
+        if (dc->tUnsettings)
+            ap_overlap_tables(dc->tUnsettings, child->tUnsettings, AP_OVERLAP_TABLES_SET);
+        else
+            dc->tUnsettings = ap_copy_table(p, child->tUnsettings);
+    }
+
 #ifdef SHIB_APACHE_24
     dc->bRequestMapperAuthz = ((child->bRequestMapperAuthz==-1) ? parent->bRequestMapperAuthz : child->bRequestMapperAuthz);
 #else
     if (child->szAuthGrpFile)
         dc->szAuthGrpFile=ap_pstrdup(p,child->szAuthGrpFile);
-    else if (parent->szAuthGrpFile)
+    else if (parent->szAuthGrpFile && (!child->tUnsettings || !apr_table_get(child->tUnsettings, "AuthGroupFile")))
         dc->szAuthGrpFile=ap_pstrdup(p,parent->szAuthGrpFile);
     else
         dc->szAuthGrpFile=nullptr;
 
-	if (child->szAccessControl)
+    if (child->szAccessControl)
         dc->szAccessControl=ap_pstrdup(p,child->szAccessControl);
-    else if (parent->szAccessControl)
+    else if (parent->szAccessControl && (!child->tUnsettings || !apr_table_get(child->tUnsettings, "ShibAccessControl")))
         dc->szAccessControl=ap_pstrdup(p,parent->szAccessControl);
     else
         dc->szAccessControl=nullptr;
@@ -261,29 +296,41 @@ extern "C" void* merge_shib_dir_config (SH_AP_POOL* p, void* base, void* sub)
 
     if (child->szApplicationId)
         dc->szApplicationId=ap_pstrdup(p,child->szApplicationId);
-    else if (parent->szApplicationId)
+    else if (parent->szApplicationId && (!child->tUnsettings || !apr_table_get(child->tUnsettings, "applicationId")))
         dc->szApplicationId=ap_pstrdup(p,parent->szApplicationId);
     else
         dc->szApplicationId=nullptr;
 
     if (child->szRequireWith)
         dc->szRequireWith=ap_pstrdup(p,child->szRequireWith);
-    else if (parent->szRequireWith)
+    else if (parent->szRequireWith && (!child->tUnsettings || !apr_table_get(child->tUnsettings, "requireSessionWith")))
         dc->szRequireWith=ap_pstrdup(p,parent->szRequireWith);
     else
         dc->szRequireWith=nullptr;
 
     if (child->szRedirectToSSL)
         dc->szRedirectToSSL=ap_pstrdup(p,child->szRedirectToSSL);
-    else if (parent->szRedirectToSSL)
+    else if (parent->szRedirectToSSL && (!child->tUnsettings || !apr_table_get(child->tUnsettings, "redirectToSSL")))
         dc->szRedirectToSSL=ap_pstrdup(p,parent->szRedirectToSSL);
     else
         dc->szRedirectToSSL=nullptr;
 
-    dc->bOff = ((child->bOff==-1) ? parent->bOff : child->bOff);
-    dc->bBasicHijack = ((child->bBasicHijack==-1) ? parent->bBasicHijack : child->bBasicHijack);
-    dc->bRequireSession = ((child->bRequireSession==-1) ? parent->bRequireSession : child->bRequireSession);
-    dc->bExportAssertion = ((child->bExportAssertion==-1) ? parent->bExportAssertion : child->bExportAssertion);
+    if (child->bRequireSession != -1)
+        dc->bRequireSession = child->bRequireSession;
+    else if (parent->bRequireSession != -1 && (!child->tUnsettings || !apr_table_get(child->tUnsettings, "requireSession")))
+        dc->bRequireSession = parent->bRequireSession;
+    else
+        dc->bRequireSession = -1;
+
+    if (child->bExportAssertion != -1)
+        dc->bExportAssertion = child->bExportAssertion;
+    else if (parent->bExportAssertion != -1 && (!child->tUnsettings || !apr_table_get(child->tUnsettings, "exportAssertion")))
+        dc->bExportAssertion = parent->bExportAssertion;
+    else
+        dc->bExportAssertion = -1;
+
+    dc->bOff = ((child->bOff == -1) ? parent->bOff : child->bOff);
+    dc->bBasicHijack = ((child->bBasicHijack == -1) ? parent->bBasicHijack : child->bBasicHijack);
 #ifndef SHIB_APACHE_24
     dc->bRequireAll = ((child->bRequireAll==-1) ? parent->bRequireAll : child->bRequireAll);
     dc->bAuthoritative = ((child->bAuthoritative==-1) ? parent->bAuthoritative : child->bAuthoritative);
@@ -963,24 +1010,24 @@ AccessControl* htAccessFactory(const xercesc::DOMElement* const & e)
 
 AccessControl::aclresult_t htAccessControl::doAccessControl(const ShibTargetApache& sta, const Session* session, const char* plugin) const
 {
-	aclresult_t result = shib_acl_false;
-	try {
+    aclresult_t result = shib_acl_false;
+    try {
         ifstream aclfile(plugin);
         if (!aclfile)
             throw ConfigurationException("Unable to open access control file ($1).", params(1, plugin));
         xercesc::DOMDocument* acldoc = XMLToolingConfig::getConfig().getParser().parse(aclfile);
-		XercesJanitor<xercesc::DOMDocument> docjanitor(acldoc);
-		static XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
+        XercesJanitor<xercesc::DOMDocument> docjanitor(acldoc);
+        static XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
         string t(XMLHelper::getAttrString(acldoc ? acldoc->getDocumentElement() : nullptr, nullptr, _type));
         if (t.empty())
             throw ConfigurationException("Missing type attribute in AccessControl plugin configuration.");
         scoped_ptr<AccessControl> aclplugin(SPConfig::getConfig().AccessControlManager.newPlugin(t.c_str(), acldoc->getDocumentElement()));
-		Locker acllock(aclplugin.get());
-		result = aclplugin->authorized(sta, session);
-	}
-	catch (std::exception& ex) {
-		sta.log(SPRequest::SPError, ex.what());
-	}
+        Locker acllock(aclplugin.get());
+        result = aclplugin->authorized(sta, session);
+    }
+    catch (std::exception& ex) {
+        sta.log(SPRequest::SPError, ex.what());
+    }
     return result;
 }
 
@@ -1247,8 +1294,8 @@ AccessControl::aclresult_t htAccessControl::authorized(const SPRequest& request,
     if (!reqs_arr)
         return shib_acl_indeterminate;  // should never happen
 
-	// Check for an "embedded" AccessControl plugin.
-	if (sta->m_dc->szAccessControl) {
+    // Check for an "embedded" AccessControl plugin.
+    if (sta->m_dc->szAccessControl) {
         aclresult_t result = doAccessControl(*sta, session, sta->m_dc->szAccessControl);
         if (result == shib_acl_true && sta->m_dc->bRequireAll != 1) {
             // If we're not insisting that all rules be met, then we're done.
@@ -1394,7 +1441,6 @@ public:
     pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=nullptr) const;
     pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=nullptr) const;
     pair<bool,int> getInt(const char* name, const char* ns=nullptr) const;
-    void getAll(map<string,const char*>& properties) const;
     const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIBSPCONFIG_NS) const;
     const xercesc::DOMElement* getElement() const;
 
@@ -1446,7 +1492,7 @@ pair<bool,bool> ApacheRequestMapper::getBool(const char* name, const char* ns) c
                 return make_pair(true, !strcmp(prop, "true") || !strcmp(prop, "1") || !strcmp(prop, "On"));
         }
     }
-    return s ? s->getBool(name,ns) : make_pair(false,false);
+    return s && (!sta->m_dc->tUnsettings || !ap_table_get(sta->m_dc->tUnsettings, name)) ? s->getBool(name,ns) : make_pair(false,false);
 }
 
 pair<bool,const char*> ApacheRequestMapper::getString(const char* name, const char* ns) const
@@ -1476,13 +1522,14 @@ pair<bool,const char*> ApacheRequestMapper::getString(const char* name, const ch
                 return make_pair(true, prop);
         }
     }
-    return s ? s->getString(name,ns) : pair<bool,const char*>(false,nullptr);
+    return s && (!sta->m_dc->tUnsettings || !ap_table_get(sta->m_dc->tUnsettings, name)) ? s->getString(name,ns) : pair<bool,const char*>(false,nullptr);
 }
 
 pair<bool,const XMLCh*> ApacheRequestMapper::getXMLString(const char* name, const char* ns) const
 {
+    const ShibTargetApache* sta = reinterpret_cast<const ShibTargetApache*>(m_staKey->getData());
     const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
-    return s ? s->getXMLString(name,ns) : pair<bool,const XMLCh*>(false,nullptr);
+    return s && (!sta->m_dc->tUnsettings || !ap_table_get(sta->m_dc->tUnsettings, name)) ? s->getXMLString(name,ns) : pair<bool,const XMLCh*>(false,nullptr);
 }
 
 pair<bool,unsigned int> ApacheRequestMapper::getUnsignedInt(const char* name, const char* ns) const
@@ -1499,7 +1546,7 @@ pair<bool,unsigned int> ApacheRequestMapper::getUnsignedInt(const char* name, co
                 return pair<bool,unsigned int>(true, atoi(prop));
         }
     }
-    return s ? s->getUnsignedInt(name,ns) : pair<bool,unsigned int>(false,0);
+    return s && (!sta->m_dc->tUnsettings || !ap_table_get(sta->m_dc->tUnsettings, name)) ? s->getUnsignedInt(name,ns) : pair<bool,unsigned int>(false,0);
 }
 
 pair<bool,int> ApacheRequestMapper::getInt(const char* name, const char* ns) const
@@ -1516,46 +1563,7 @@ pair<bool,int> ApacheRequestMapper::getInt(const char* name, const char* ns) con
                 return make_pair(true, atoi(prop));
         }
     }
-    return s ? s->getInt(name,ns) : pair<bool,int>(false,0);
-}
-
-static int _rm_get_all_table_walk(void *v, const char *key, const char *value)
-{
-    reinterpret_cast<map<string,const char*>*>(v)->insert(pair<string,const char*>(key, value));
-    return 1;
-}
-
-void ApacheRequestMapper::getAll(map<string,const char*>& properties) const
-{
-    const ShibTargetApache* sta=reinterpret_cast<const ShibTargetApache*>(m_staKey->getData());
-    const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
-
-    if (s)
-        s->getAll(properties);
-    if (!sta)
-        return;
-
-    const char* auth_type=ap_auth_type(sta->m_req);
-    if (auth_type) {
-        // Check for Basic Hijack
-        if (!strcasecmp(auth_type, "basic") && sta->m_dc->bBasicHijack == 1)
-            auth_type = "shibboleth";
-        properties["authType"] = auth_type;
-    }
-
-    if (sta->m_dc->szApplicationId)
-        properties["applicationId"] = sta->m_dc->szApplicationId;
-    if (sta->m_dc->szRequireWith)
-        properties["requireSessionWith"] = sta->m_dc->szRequireWith;
-    if (sta->m_dc->szRedirectToSSL)
-        properties["redirectToSSL"] = sta->m_dc->szRedirectToSSL;
-    if (sta->m_dc->bRequireSession != 0)
-        properties["requireSession"] = (sta->m_dc->bRequireSession==1) ? "true" : "false";
-    if (sta->m_dc->bExportAssertion != 0)
-        properties["exportAssertion"] = (sta->m_dc->bExportAssertion==1) ? "true" : "false";
-
-    if (sta->m_dc->tSettings)
-        ap_table_do(_rm_get_all_table_walk, &properties, sta->m_dc->tSettings, NULL);
+    return s && (!sta->m_dc->tUnsettings || !ap_table_get(sta->m_dc->tUnsettings, name)) ? s->getInt(name,ns) : pair<bool,int>(false,0);
 }
 
 const PropertySet* ApacheRequestMapper::getPropertySet(const char* name, const char* ns) const
@@ -1677,7 +1685,7 @@ extern "C" authz_status shib_user_check_authz(request_rec* r, const char* requir
     if (!r->user) {
         return AUTHZ_DENIED_NO_USER;
     }
- 	
+     
     const char* t = require_line;
     const char *w;
     while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
@@ -1685,12 +1693,12 @@ extern "C" authz_status shib_user_check_authz(request_rec* r, const char* requir
             return AUTHZ_GRANTED;
         }
     }
- 	
+     
     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01663)
         "access to %s failed, reason: user '%s' does not meet "
         "'require'ments for user to be allowed access",
         r->uri, r->user);
- 	
+     
     return AUTHZ_DENIED;
 }
 
@@ -1815,11 +1823,11 @@ extern "C" const char* shib_set_server_flag_slot(cmd_parms* parms, void*, int ar
 
 extern "C" const char* shib_ap_set_file_slot(cmd_parms* parms,
 #ifdef SHIB_APACHE_13
-					     char* arg1, char* arg2
+                         char* arg1, char* arg2
 #else
-					     void* arg1, const char* arg2
+                         void* arg1, const char* arg2
 #endif
-					     )
+                         )
 {
   ap_set_file_slot(parms, arg1, arg2);
   return DECLINE_CMD;
@@ -1833,6 +1841,14 @@ extern "C" const char* shib_table_set(cmd_parms* parms, shib_dir_config* dc, con
     return nullptr;
 }
 
+extern "C" const char* shib_table_unset(cmd_parms* parms, shib_dir_config* dc, const char* arg1)
+{
+    if (!dc->tUnsettings)
+        dc->tUnsettings = ap_make_table(parms->pool, 4);
+    ap_table_set(dc->tUnsettings, arg1, "");
+    return nullptr;
+}
+
 #ifndef SHIB_APACHE_24
 extern "C" const char* shib_set_acl_slot(cmd_parms* params, shib_dir_config* dc, char* arg)
 {
@@ -2083,6 +2099,8 @@ static command_rec shire_cmds[] = {
 
   {"ShibRequestSetting", (config_fn_t)shib_table_set, nullptr,
    OR_AUTHCFG, TAKE2, "Set arbitrary Shibboleth request property for content"},
+  {"ShibRequestUnset", (config_fn_t)shib_table_unset, nullptr,
+   OR_AUTHCFG, TAKE1, "Unset an arbitrary Shibboleth request property (blocking inheritance)" },
 
   {"ShibAccessControl", (config_fn_t)shib_set_acl_slot, nullptr,
    OR_AUTHCFG, TAKE1, "Set arbitrary Shibboleth access control plugin for content"},
@@ -2092,22 +2110,22 @@ static command_rec shire_cmds[] = {
    OR_AUTHCFG, FLAG, "Disable all Shib module activity here to save processing effort"},
   {"ShibApplicationId", (config_fn_t)ap_set_string_slot,
    (void *) XtOffsetOf (shib_dir_config, szApplicationId),
-   OR_AUTHCFG, TAKE1, "Set Shibboleth applicationId property for content"},
+   OR_AUTHCFG, TAKE1, "(DEPRECATED) Set Shibboleth applicationId property for content"},
   {"ShibBasicHijack", (config_fn_t)ap_set_flag_slot,
    (void *) XtOffsetOf (shib_dir_config, bBasicHijack),
    OR_AUTHCFG, FLAG, "(DEPRECATED) Respond to AuthType Basic and convert to shibboleth"},
   {"ShibRequireSession", (config_fn_t)ap_set_flag_slot,
    (void *) XtOffsetOf (shib_dir_config, bRequireSession),
-   OR_AUTHCFG, FLAG, "Initiates a new session if one does not exist"},
+   OR_AUTHCFG, FLAG, "(DEPRECATED) Initiates a new session if one does not exist"},
   {"ShibRequireSessionWith", (config_fn_t)ap_set_string_slot,
    (void *) XtOffsetOf (shib_dir_config, szRequireWith),
-   OR_AUTHCFG, TAKE1, "Initiates a new session if one does not exist using a specific SessionInitiator"},
+   OR_AUTHCFG, TAKE1, "(DEPRECATED) Initiates a new session if one does not exist using a specific SessionInitiator"},
   {"ShibExportAssertion", (config_fn_t)ap_set_flag_slot,
    (void *) XtOffsetOf (shib_dir_config, bExportAssertion),
-   OR_AUTHCFG, FLAG, "Export SAML attribute assertion(s) to Shib-Attributes header"},
+   OR_AUTHCFG, FLAG, "(DEPRECATED) Export SAML attribute assertion(s) to Shib-Attributes header"},
   {"ShibRedirectToSSL", (config_fn_t)ap_set_string_slot,
    (void *) XtOffsetOf (shib_dir_config, szRedirectToSSL),
-   OR_AUTHCFG, TAKE1, "Redirect non-SSL requests to designated port" },
+   OR_AUTHCFG, TAKE1, "(DEPRECATED) Redirect non-SSL requests to designated port" },
   {"AuthGroupFile", (config_fn_t)shib_ap_set_file_slot,
    (void *) XtOffsetOf (shib_dir_config, szAuthGrpFile),
    OR_AUTHCFG, TAKE1, "text file containing group names and member user IDs"},
@@ -2142,23 +2160,23 @@ handler_rec shib_handlers[] = {
 module MODULE_VAR_EXPORT mod_shib = {
     STANDARD_MODULE_STUFF,
     nullptr,                        /* initializer */
-    create_shib_dir_config,	/* dir config creater */
-    merge_shib_dir_config,	/* dir merger --- default is to override */
+    create_shib_dir_config,    /* dir config creater */
+    merge_shib_dir_config,    /* dir merger --- default is to override */
     create_shib_server_config, /* server config */
     merge_shib_server_config,   /* merge server config */
-    shire_cmds,			/* command table */
-    shib_handlers,		/* handlers */
-    nullptr,			/* filename translation */
-    shib_check_user,		/* check_user_id */
-    shib_auth_checker,		/* check auth */
-    nullptr,			/* check access */
-    nullptr,			/* type_checker */
-    shib_fixups,		/* fixups */
-    nullptr,			/* logger */
-    nullptr,			/* header parser */
-    shib_child_init,		/* child_init */
-    shib_child_exit,		/* child_exit */
-    shib_post_read		/* post read-request */
+    shire_cmds,            /* command table */
+    shib_handlers,        /* handlers */
+    nullptr,            /* filename translation */
+    shib_check_user,        /* check_user_id */
+    shib_auth_checker,        /* check auth */
+    nullptr,            /* check access */
+    nullptr,            /* type_checker */
+    shib_fixups,        /* fixups */
+    nullptr,            /* logger */
+    nullptr,            /* header parser */
+    shib_child_init,        /* child_init */
+    shib_child_exit,        /* child_exit */
+    shib_post_read        /* post read-request */
 };
 
 #else
@@ -2241,28 +2259,30 @@ static command_rec shib_cmds[] = {
 
     AP_INIT_TAKE2("ShibRequestSetting", (config_fn_t)shib_table_set, nullptr,
         OR_AUTHCFG, "Set arbitrary Shibboleth request property for content"),
+    AP_INIT_TAKE1("ShibRequestUnset", (config_fn_t)shib_table_unset, nullptr,
+        OR_AUTHCFG, "Unset an arbitrary Shibboleth request property (blocking inheritance)"),
 
     AP_INIT_FLAG("ShibDisable", (config_fn_t)ap_set_flag_slot,
         (void *) offsetof (shib_dir_config, bOff),
         OR_AUTHCFG, "Disable all Shib module activity here to save processing effort"),
     AP_INIT_TAKE1("ShibApplicationId", (config_fn_t)ap_set_string_slot,
         (void *) offsetof (shib_dir_config, szApplicationId),
-        OR_AUTHCFG, "Set Shibboleth applicationId property for content"),
+        OR_AUTHCFG, "(DEPRECATED) Set Shibboleth applicationId property for content"),
     AP_INIT_FLAG("ShibBasicHijack", (config_fn_t)ap_set_flag_slot,
         (void *) offsetof (shib_dir_config, bBasicHijack),
         OR_AUTHCFG, "(DEPRECATED) Respond to AuthType Basic and convert to shibboleth"),
     AP_INIT_FLAG("ShibRequireSession", (config_fn_t)ap_set_flag_slot,
         (void *) offsetof (shib_dir_config, bRequireSession),
-        OR_AUTHCFG, "Initiates a new session if one does not exist"),
+        OR_AUTHCFG, "(DEPRECATED) Initiates a new session if one does not exist"),
     AP_INIT_TAKE1("ShibRequireSessionWith", (config_fn_t)ap_set_string_slot,
         (void *) offsetof (shib_dir_config, szRequireWith),
-        OR_AUTHCFG, "Initiates a new session if one does not exist using a specific SessionInitiator"),
+        OR_AUTHCFG, "(DEPRECATED) Initiates a new session if one does not exist using a specific SessionInitiator"),
     AP_INIT_FLAG("ShibExportAssertion", (config_fn_t)ap_set_flag_slot,
         (void *) offsetof (shib_dir_config, bExportAssertion),
-        OR_AUTHCFG, "Export SAML attribute assertion(s) to Shib-Attributes header"),
+        OR_AUTHCFG, "(DEPRECATED) Export SAML attribute assertion(s) to Shib-Attributes header"),
     AP_INIT_TAKE1("ShibRedirectToSSL", (config_fn_t)ap_set_string_slot,
         (void *) offsetof (shib_dir_config, szRedirectToSSL),
-        OR_AUTHCFG, "Redirect non-SSL requests to designated port"),
+        OR_AUTHCFG, "(DEPRECATED) Redirect non-SSL requests to designated port"),
 #ifdef SHIB_APACHE_24
     AP_INIT_FLAG("ShibRequestMapperAuthz", (config_fn_t)ap_set_flag_slot,
         (void *) offsetof (shib_dir_config, bRequestMapperAuthz),
diff --git a/apache/mod_shib_20.cpp b/apache/mod_shib_20.cpp
index a9b38de..9f25e7a 100644
--- a/apache/mod_shib_20.cpp
+++ b/apache/mod_shib_20.cpp
@@ -32,6 +32,7 @@
 #define SH_AP_TABLE apr_table_t
 #define SH_AP_CONFIGFILE ap_configfile_t
 #define array_header apr_array_header_t
+#define table_entry apr_table_entry_t
 
 #define SH_AP_R(r) 0,r
 #define SH_AP_USER(r) r->user
diff --git a/apache/mod_shib_22.cpp b/apache/mod_shib_22.cpp
index e6e25e0..7e7ea23 100644
--- a/apache/mod_shib_22.cpp
+++ b/apache/mod_shib_22.cpp
@@ -32,6 +32,7 @@
 #define SH_AP_TABLE apr_table_t
 #define SH_AP_CONFIGFILE ap_configfile_t
 #define array_header apr_array_header_t
+#define table_entry apr_table_entry_t
 
 #define SH_AP_R(r) 0,r
 #define SH_AP_USER(r) r->user
diff --git a/apache/mod_shib_24.cpp b/apache/mod_shib_24.cpp
index ddd5c65..73cd070 100644
--- a/apache/mod_shib_24.cpp
+++ b/apache/mod_shib_24.cpp
@@ -32,6 +32,7 @@
 #define SH_AP_TABLE apr_table_t
 #define SH_AP_CONFIGFILE ap_configfile_t
 #define array_header apr_array_header_t
+#define table_entry apr_table_entry_t
 
 #define SH_AP_R(r) 0,r
 #define SH_AP_USER(r) r->user
diff --git a/nsapi_shib/nsapi_shib.cpp b/nsapi_shib/nsapi_shib.cpp
index 200fd07..b07cb01 100644
--- a/nsapi_shib/nsapi_shib.cpp
+++ b/nsapi_shib/nsapi_shib.cpp
@@ -570,7 +570,6 @@ public:
     pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=nullptr) const;
     pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=nullptr) const;
     pair<bool,int> getInt(const char* name, const char* ns=nullptr) const;
-    void getAll(map<string,const char*>& properties) const;
     const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIBSPCONFIG_NS) const;
     const xercesc::DOMElement* getElement() const;
 
@@ -606,8 +605,8 @@ pair<bool,bool> SunRequestMapper::getBool(const char* name, const char* ns) cons
     if (stn && !ns && name) {
         // Override boolean properties.
         const char* param=pblock_findval(name,stn->m_pb);
-        if (param && (!strcmp(param,"1") || !strcasecmp(param,"true")))
-            return make_pair(true,true);
+		if (param)
+			return make_pair(true, !strcmp(param, "1") || !strcasecmp(param, "true"));
     }
     return s ? s->getBool(name,ns) : make_pair(false,false);
 }
@@ -667,25 +666,6 @@ pair<bool,int> SunRequestMapper::getInt(const char* name, const char* ns) const
     return s ? s->getInt(name,ns) : pair<bool,int>(false,0);
 }
 
-void SunRequestMapper::getAll(map<string,const char*>& properties) const
-{
-    const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
-    const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
-    if (s)
-        s->getAll(properties);
-    if (!stn)
-        return;
-    properties["authType"] = "shibboleth";
-    const pb_entry* entry;
-    for (int i=0; i<stn->m_pb->hsize; ++i) {
-        entry = stn->m_pb->ht[i];
-        while (entry) {
-            properties[entry->param->name] = entry->param->value;
-            entry = entry->next;
-        }
-    }
-}
-
 const PropertySet* SunRequestMapper::getPropertySet(const char* name, const char* ns) const
 {
     const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
diff --git a/schemas/shibboleth-3.0-native-sp-config.xsd b/schemas/shibboleth-3.0-native-sp-config.xsd
index d874c13..ae0473a 100644
--- a/schemas/shibboleth-3.0-native-sp-config.xsd
+++ b/schemas/shibboleth-3.0-native-sp-config.xsd
@@ -292,6 +292,7 @@
     <attribute name="acsIndex" type="unsignedShort"/>
     <attribute name="REMOTE_ADDR" type="conf:string"/>
     <attribute name="encoding" type="conf:string"/>
+    <attribute name="unset" type="conf:listOfStrings"/>
     <anyAttribute namespace="##other" processContents="lax"/>
   </attributeGroup>
 
diff --git a/shibsp/ServiceProvider.cpp b/shibsp/ServiceProvider.cpp
index 2d07614..bc975fe 100644
--- a/shibsp/ServiceProvider.cpp
+++ b/shibsp/ServiceProvider.cpp
@@ -429,7 +429,7 @@ pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handl
                 initiator=app->getSessionInitiatorById(requireSessionWith.second);
                 if (!initiator) {
                     throw ConfigurationException(
-                        "No session initiator found with id ($1), check requireSessionWith command.", params(1, requireSessionWith.second)
+                        "No session initiator found with id ($1), check requireSessionWith setting.", params(1, requireSessionWith.second)
                         );
                 }
             }
diff --git a/shibsp/handler/impl/StatusHandler.cpp b/shibsp/handler/impl/StatusHandler.cpp
index bdb56c0..2128636 100644
--- a/shibsp/handler/impl/StatusHandler.cpp
+++ b/shibsp/handler/impl/StatusHandler.cpp
@@ -270,9 +270,6 @@ pair<bool,long> StatusHandler::run(SPRequest& request, bool isHandler) const
         // RequestMap query, so handle it inproc.
         DummyRequest dummy(target);
         RequestMapper::Settings settings = request.getApplication().getServiceProvider().getRequestMapper()->getSettings(dummy);
-        map<string,const char*> props;
-        settings.first->getAll(props);
-
         XMLDateTime now(time(nullptr), false);
         now.parseDateTime();
         auto_ptr_char timestamp(now.getFormattedString());
@@ -286,10 +283,14 @@ pair<bool,long> StatusHandler::run(SPRequest& request, bool isHandler) const
                 << "' OpenSAML-C='" << gOpenSAMLDotVersionStr
 #endif
                 << "' Shibboleth='" << PACKAGE_VERSION << "'/>";
-            systemInfo(msg) << "<RequestSettings";
-            for (map<string,const char*>::const_iterator p = props.begin(); p != props.end(); ++p)
-                msg << ' ' << p->first << "='" << p->second << "'";
-            msg << '>' << target << "</RequestSettings>";
+            const char* setting = request.getParameter("setting");
+                systemInfo(msg) << "<RequestSettings";
+                if (setting) {
+                    pair<bool, const char*> prop = settings.first->getString(setting);
+                    if (prop.first)
+                        msg << ' ' << setting << "='" << prop.second << "'";
+                }
+                msg << '>' << target << "</RequestSettings>";
             msg << "<Status><OK/></Status>";
         msg << "</StatusHandler>";
         return make_pair(true, request.sendResponse(msg));
diff --git a/shibsp/impl/XMLRequestMapper.cpp b/shibsp/impl/XMLRequestMapper.cpp
index ae3dae0..1ba6e29 100644
--- a/shibsp/impl/XMLRequestMapper.cpp
+++ b/shibsp/impl/XMLRequestMapper.cpp
@@ -217,7 +217,8 @@ Override::Override(bool unicodeAware, const DOMElement* e, Category& log, const
     : m_unicodeAware(unicodeAware)
 {
     // Load the property set.
-    load(e, nullptr, this);
+    xmltooling::QName unsetter(nullptr, "unset");
+    load(e, nullptr, this, nullptr, &unsetter);
     setParent(base);
 
     // Load any AccessControl provider.
@@ -475,7 +476,8 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
     }
 
     // Load the property set.
-    load(e, nullptr, this);
+    xmltooling::QName unsetter(nullptr, "unset");
+    load(e, nullptr, this, nullptr, &unsetter);
 
     // Inject "default" app ID if not explicit.
     if (!getString("applicationId").first)
diff --git a/shibsp/impl/XMLServiceProvider.cpp b/shibsp/impl/XMLServiceProvider.cpp
index 3882fc6..96b3824 100644
--- a/shibsp/impl/XMLServiceProvider.cpp
+++ b/shibsp/impl/XMLServiceProvider.cpp
@@ -368,7 +368,6 @@ namespace {
         pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=nullptr) const {return m_impl->getXMLString(name,ns);}
         pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=nullptr) const {return m_impl->getUnsignedInt(name,ns);}
         pair<bool,int> getInt(const char* name, const char* ns=nullptr) const {return m_impl->getInt(name,ns);}
-        void getAll(map<string,const char*>& properties) const {return m_impl->getAll(properties);}
         const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIBSPCONFIG_NS) const {return m_impl->getPropertySet(name,ns);}
         const DOMElement* getElement() const {return m_impl->getElement();}
 
@@ -471,7 +470,7 @@ namespace {
     static const XMLCh Binding[] =              UNICODE_LITERAL_7(B,i,n,d,i,n,g);
     static const XMLCh Channel[]=               UNICODE_LITERAL_7(C,h,a,n,n,e,l);
     static const XMLCh _CredentialResolver[] =  UNICODE_LITERAL_18(C,r,e,d,e,n,t,i,a,l,R,e,s,o,l,v,e,r);
-	static const XMLCh _DataSealer[] =			UNICODE_LITERAL_10(D,a,t,a,S,e,a,l,e,r);
+    static const XMLCh _DataSealer[] =            UNICODE_LITERAL_10(D,a,t,a,S,e,a,l,e,r);
     static const XMLCh _default[] =             UNICODE_LITERAL_7(d,e,f,a,u,l,t);
     static const XMLCh _Extensions[] =          UNICODE_LITERAL_10(E,x,t,e,n,s,i,o,n,s);
     static const XMLCh _fatal[] =               UNICODE_LITERAL_5(f,a,t,a,l);
@@ -1829,7 +1828,7 @@ DOMNodeFilter::FilterAction XMLConfigImpl::acceptNode(const DOMNode* node) const
     const XMLCh* name=node->getLocalName();
     if (XMLString::equals(name,ApplicationDefaults) ||
         XMLString::equals(name,_ArtifactMap) ||
-		XMLString::equals(name, _DataSealer) ||
+        XMLString::equals(name, _DataSealer) ||
         XMLString::equals(name,_Extensions) ||
         XMLString::equals(name,Listener) ||
         XMLString::equals(name,_ProtocolProvider) ||
@@ -2127,17 +2126,17 @@ XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer,
             outer->m_listener->regListener("get::PostData", outer);
         }
 
-		if (child = XMLHelper::getFirstChildElement(e, _DataSealer)) {
-			string t(XMLHelper::getAttrString(child, nullptr, _type));
-			if (!t.empty()) {
-				log.info("building DataSealer of type %s...", t.c_str());
-				auto_ptr<DataSealerKeyStrategy> strategy(XMLToolingConfig::getConfig().DataSealerKeyStrategyManager.newPlugin(t, child));
-				auto_ptr<DataSealer> sealer(new DataSealer(strategy.get()));
-				strategy.release();
-				XMLToolingConfig::getConfig().setDataSealer(sealer.get());
-				sealer.release();
-			}
-		}
+        if (child = XMLHelper::getFirstChildElement(e, _DataSealer)) {
+            string t(XMLHelper::getAttrString(child, nullptr, _type));
+            if (!t.empty()) {
+                log.info("building DataSealer of type %s...", t.c_str());
+                auto_ptr<DataSealerKeyStrategy> strategy(XMLToolingConfig::getConfig().DataSealerKeyStrategyManager.newPlugin(t, child));
+                auto_ptr<DataSealer> sealer(new DataSealer(strategy.get()));
+                strategy.release();
+                XMLToolingConfig::getConfig().setDataSealer(sealer.get());
+                sealer.release();
+            }
+        }
 #endif
         if (conf.isEnabled(SPConfig::Caching))
             doCaching(e, outer, log);
diff --git a/shibsp/util/DOMPropertySet.cpp b/shibsp/util/DOMPropertySet.cpp
index 58d9f4e..d51fb9c 100644
--- a/shibsp/util/DOMPropertySet.cpp
+++ b/shibsp/util/DOMPropertySet.cpp
@@ -29,8 +29,10 @@
 
 #include <algorithm>
 #include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/XMLConstants.h>
+#include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
 using namespace xmltooling;
@@ -103,7 +105,8 @@ void DOMPropertySet::load(
     const DOMElement* e,
     Category* log,
     DOMNodeFilter* filter,
-    const Remapper* remapper
+    const Remapper* remapper,
+    const xmltooling::QName* unsetter
     )
 {
 #ifdef _DEBUG
@@ -119,8 +122,16 @@ void DOMPropertySet::load(
     DOMNamedNodeMap* attrs=m_root->getAttributes();
     for (XMLSize_t i=0; i<attrs->getLength(); i++) {
         DOMNode* a=attrs->item(i);
-        if (!XMLString::compareString(a->getNamespaceURI(),xmlconstants::XMLNS_NS))
+        if (!XMLString::compareString(a->getNamespaceURI(), xmlconstants::XMLNS_NS)) {
             continue;
+        }
+        else if (unsetter && XMLHelper::isNodeNamed(a, unsetter->getNamespaceURI(), unsetter->getLocalPart())) {
+            auto_ptr_char val(a->getNodeValue());
+            string dup(val.get());
+            split(m_unset, dup, is_space(), algorithm::token_compress_on);
+            continue;
+        }
+
         char* val=XMLString::transcode(a->getNodeValue());
         if (val && *val) {
             auto_ptr_char ns(a->getNamespaceURI());
@@ -196,10 +207,12 @@ pair<bool,bool> DOMPropertySet::getBool(const char* name, const char* ns) const
     else
         i=m_map.find(name);
 
+
     if (i!=m_map.end())
         return make_pair(true,(!strcmp(i->second.first,"true") || !strcmp(i->second.first,"1")));
-    else if (m_parent)
-        return m_parent->getBool(name,ns);
+    else if (m_parent && m_unset.find(ns ? (string("{") + ns + '}' + name) : name) == m_unset.end()) {
+        return m_parent->getBool(name, ns);
+    }
     return make_pair(false,false);
 }
 
@@ -215,7 +228,7 @@ pair<bool,const char*> DOMPropertySet::getString(const char* name, const char* n
 
     if (i!=m_map.end())
         return pair<bool,const char*>(true,i->second.first);
-    else if (m_parent)
+    else if (m_parent && m_unset.find(ns ? (string("{") + ns + '}' + name) : name) == m_unset.end())
         return m_parent->getString(name,ns);
     return pair<bool,const char*>(false,nullptr);
 }
@@ -231,7 +244,7 @@ pair<bool,const XMLCh*> DOMPropertySet::getXMLString(const char* name, const cha
 
     if (i!=m_map.end())
         return make_pair(true,i->second.second);
-    else if (m_parent)
+    else if (m_parent && m_unset.find(ns ? (string("{") + ns + '}' + name) : name) == m_unset.end())
         return m_parent->getXMLString(name,ns);
     return pair<bool,const XMLCh*>(false,nullptr);
 }
@@ -253,7 +266,7 @@ pair<bool,unsigned int> DOMPropertySet::getUnsignedInt(const char* name, const c
             return pair<bool,unsigned int>(false,0);
         }
     }
-    else if (m_parent)
+    else if (m_parent && m_unset.find(ns ? (string("{") + ns + '}' + name) : name) == m_unset.end())
         return m_parent->getUnsignedInt(name,ns);
     return pair<bool,unsigned int>(false,0);
 }
@@ -269,19 +282,11 @@ pair<bool,int> DOMPropertySet::getInt(const char* name, const char* ns) const
 
     if (i!=m_map.end())
         return pair<bool,int>(true,atoi(i->second.first));
-    else if (m_parent)
+    else if (m_parent && m_unset.find(ns ? (string("{") + ns + '}' + name) : name) == m_unset.end())
         return m_parent->getInt(name,ns);
     return pair<bool,int>(false,0);
 }
 
-void DOMPropertySet::getAll(std::map<std::string,const char*>& properties) const
-{
-    if (m_parent)
-        m_parent->getAll(properties);
-    for (map< string,pair<char*,const XMLCh*> >::const_iterator i = m_map.begin(); i != m_map.end(); ++i)
-        properties[i->first] = i->second.first;
-}
-
 const PropertySet* DOMPropertySet::getPropertySet(const char* name, const char* ns) const
 {
     map< string,boost::shared_ptr<DOMPropertySet> >::const_iterator i;
diff --git a/shibsp/util/DOMPropertySet.h b/shibsp/util/DOMPropertySet.h
index 016e65c..748a87a 100644
--- a/shibsp/util/DOMPropertySet.h
+++ b/shibsp/util/DOMPropertySet.h
@@ -32,6 +32,10 @@
 #include <boost/shared_ptr.hpp>
 #include <xmltooling/logging.h>
 
+namespace xmltooling {
+	class QName;
+}
+
 namespace shibsp {
 
     /**
@@ -51,7 +55,6 @@ namespace shibsp {
         std::pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=nullptr) const;
         std::pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=nullptr) const;
         std::pair<bool,int> getInt(const char* name, const char* ns=nullptr) const;
-        void getAll(std::map<std::string,const char*>& properties) const;
         const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIBSPCONFIG_NS) const;
         const xercesc::DOMElement* getElement() const;
 
@@ -105,12 +108,14 @@ namespace shibsp {
          * @param log       optional log object for tracing
          * @param filter    optional filter controls what child elements to include as nested PropertySets
          * @param remapper  optional mapper of property rename rules for legacy property support
+		 * @param unsetter  optional name of a property containing a list of property names to "unset"
          */
         void load(
             const xercesc::DOMElement* e,
             xmltooling::logging::Category* log=nullptr,
             xercesc::DOMNodeFilter* filter=nullptr,
-            const Remapper* remapper=nullptr
+            const Remapper* remapper=nullptr,
+			const xmltooling::QName* unsetter=nullptr
             );
 
     protected:
@@ -128,6 +133,7 @@ namespace shibsp {
         const PropertySet* m_parent;
         const xercesc::DOMElement* m_root;
         std::map<std::string,std::pair<char*,const XMLCh*> > m_map;
+		std::set<std::string> m_unset;
         std::map< std::string,boost::shared_ptr<DOMPropertySet> > m_nested;
         std::vector<xmltooling::xstring> m_injected;
     };
diff --git a/shibsp/util/PropertySet.h b/shibsp/util/PropertySet.h
index 68cee60..c6562d6 100644
--- a/shibsp/util/PropertySet.h
+++ b/shibsp/util/PropertySet.h
@@ -106,13 +106,6 @@ namespace shibsp {
         virtual std::pair<bool,int> getInt(const char* name, const char* ns=nullptr) const=0;
 
         /**
-         * Returns a map of all known properties in string form.
-         *
-         * @param properties    map to populate
-         */
-        virtual void getAll(std::map<std::string,const char*>& properties) const=0;
-
-        /**
          * Returns a nested property set.
          * 
          * @param name  nested property set name

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list