https://issues.shibboleth.net/jira/browse/SSPCPP-584
[shibboleth/cpp-sp.git] / apache / mod_shib.cpp
index 02b68a5..311297b 100644 (file)
@@ -415,7 +415,11 @@ public:
     return type ? type : "";
   }
   long getContentLength() const {
-      return m_gotBody ? m_body.length() : m_req->remaining;
+      // Apache won't expose content length until the body's read.
+      if (!m_gotBody) {
+          getRequestBody();
+      }
+      return m_body.length();
   }
   string getRemoteAddr() const {
     string ret = AbstractSPRequest::getRemoteAddr();
@@ -873,8 +877,9 @@ extern "C" int shib_auth_checker(request_rec* r)
 #else
         shib_request_config* rc = (shib_request_config*)ap_get_module_config(r->request_config, &mod_shib);
         if (!rc || !rc->sta) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(r), "shib_auth_checker found no per-request structure");
-            return SERVER_ERROR;
+            ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, SH_AP_R(r), "shib_auth_checker found no per-request structure");
+            shib_post_read(r);  // ensures objects are created if post_read hook didn't run
+            rc = (shib_request_config*)ap_get_module_config(r->request_config, &mod_shib);
         }
         ShibTargetApache* psta = rc->sta;
 #endif
@@ -1291,13 +1296,20 @@ AccessControl::aclresult_t htAccessControl::authorized(const SPRequest& request,
                 status = true;
             }
         }
-        else if ((!strcmp(w,"valid-user") || !strcmp(w,"shib-session")) && session) {
-            request.log(SPRequest::SPDebug, "htaccess: accepting shib-session/valid-user based on active session");
+        else if (!strcmp(w,"valid-user") && session) {
+            request.log(SPRequest::SPDebug, "htaccess: accepting valid-user based on active session");
+            status = true;
+        }
+        else if (sta->m_dc->bCompatWith24 == 1 && !strcmp(w,"shib-session") && session) {
+            request.log(SPRequest::SPDebug, "htaccess: accepting shib-session based on active session");
             status = true;
         }
         else if (!strcmp(w,"user") && !remote_user.empty()) {
             status = (doUser(*sta, t) == shib_acl_true);
         }
+        else if (sta->m_dc->bCompatWith24 == 1 && !strcmp(w,"shib-user") && !remote_user.empty()) {
+            status = (doUser(*sta, t) == shib_acl_true);
+        }
         else if (!strcmp(w,"group")  && !remote_user.empty()) {
             status = (doGroup(*sta, t) == shib_acl_true);
         }
@@ -1620,17 +1632,17 @@ extern "C" authz_status shib_validuser_check_authz(request_rec* r, const char* r
         return shib_session_check_authz(r, require_line, nullptr);
     }
 
-    if (!r->user || !*r->user) {
+    // Reproduce mod_authz_user version...
+
+    if (!r->user) {
         return AUTHZ_DENIED_NO_USER;
     }
 
     return AUTHZ_GRANTED;
 }
 
-extern "C" authz_status shib_user_check_authz(request_rec* r, const char* require_line, const void*)
+extern "C" authz_status shib_ext_user_check_authz(request_rec* r, const char* require_line, const void*)
 {
-    if (!r->user || !*(r->user))
-        return AUTHZ_DENIED_NO_USER;
     pair<ShibTargetApache*,authz_status> sta = shib_base_check_authz(r);
     if (!sta.first)
         return sta.second;
@@ -1641,6 +1653,43 @@ extern "C" authz_status shib_user_check_authz(request_rec* r, const char* requir
     return AUTHZ_DENIED;
 }
 
+extern "C" authz_status shib_user_check_authz(request_rec* r, const char* require_line, const void*)
+{
+    // Shouldn't have actually ever hooked this, and now we're in conflict with mod_authz_user over the meaning.
+    // For now, added a command to restore "normal" semantics for user rules so that combined deployments can
+    // use user for non-Shibboleth cases and shib-user for the Shibboleth semantic.
+
+    // In future, we may want to expose the AuthType set to honor down at this level so we can differentiate
+    // based on AuthType. Unfortunately we allow overriding the AuthType to honor and we don't have access to
+    // that setting from the ServiceProvider class..
+
+    shib_server_config* sc = (shib_server_config*)ap_get_module_config(r->server->module_config, &mod_shib);
+    if (sc->bCompatValidUser != 1) {
+        return shib_ext_user_check_authz(r, require_line, nullptr);
+    }
+
+    // Reproduce mod_authz_user version...
+
+    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]) {
+        if (!strcmp(r->user, w)) {
+            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;
+}
+
 extern "C" authz_status shib_acclass_check_authz(request_rec* r, const char* require_line, const void*)
 {
     pair<ShibTargetApache*,authz_status> sta = shib_base_check_authz(r);
@@ -2115,6 +2164,7 @@ extern "C" const authz_provider shib_authz_shibboleth_provider = { &shib_shibbol
 extern "C" const authz_provider shib_authz_validuser_provider = { &shib_validuser_check_authz, nullptr };
 extern "C" const authz_provider shib_authz_session_provider = { &shib_session_check_authz, nullptr };
 extern "C" const authz_provider shib_authz_user_provider = { &shib_user_check_authz, nullptr };
+extern "C" const authz_provider shib_authz_ext_user_provider = { &shib_ext_user_check_authz, nullptr };
 extern "C" const authz_provider shib_authz_acclass_provider = { &shib_acclass_check_authz, nullptr };
 extern "C" const authz_provider shib_authz_acdecl_provider = { &shib_acdecl_check_authz, nullptr };
 extern "C" const authz_provider shib_authz_attr_provider = { &shib_attr_check_authz, nullptr };
@@ -2160,6 +2210,7 @@ extern "C" void shib_register_hooks (apr_pool_t *p)
     ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "valid-user", AUTHZ_PROVIDER_VERSION, &shib_authz_validuser_provider, AP_AUTH_INTERNAL_PER_CONF);
     ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "shib-session", AUTHZ_PROVIDER_VERSION, &shib_authz_session_provider, AP_AUTH_INTERNAL_PER_CONF);
     ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "user", AUTHZ_PROVIDER_VERSION, &shib_authz_user_provider, AP_AUTH_INTERNAL_PER_CONF);
+    ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "shib-user", AUTHZ_PROVIDER_VERSION, &shib_authz_ext_user_provider, AP_AUTH_INTERNAL_PER_CONF);
     ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "authnContextClassRef", AUTHZ_PROVIDER_VERSION, &shib_authz_acclass_provider, AP_AUTH_INTERNAL_PER_CONF);
     ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "authnContextDeclRef", AUTHZ_PROVIDER_VERSION, &shib_authz_acdecl_provider, AP_AUTH_INTERNAL_PER_CONF);
     ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "shib-attr", AUTHZ_PROVIDER_VERSION, &shib_authz_attr_provider, AP_AUTH_INTERNAL_PER_CONF);