X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=apache%2Fmod_shib.cpp;h=9bd6c18f6956e13b01940462a8b55ba86198a836;hb=eab3df9a887298b7e35940a7a69c155832589457;hp=3899db4b27318d7d0913be94dd8673d036459430;hpb=a2c21612f1206704fec5522188859daafd2b6b1f;p=shibboleth%2Fcpp-sp.git diff --git a/apache/mod_shib.cpp b/apache/mod_shib.cpp index 3899db4..9bd6c18 100644 --- a/apache/mod_shib.cpp +++ b/apache/mod_shib.cpp @@ -136,6 +136,7 @@ namespace { struct shib_server_config { char* szScheme; + int bCompatValidUser; }; // creates the per-server configuration @@ -143,6 +144,7 @@ extern "C" void* create_shib_server_config(SH_AP_POOL* p, server_rec* s) { shib_server_config* sc=(shib_server_config*)ap_pcalloc(p,sizeof(shib_server_config)); sc->szScheme = nullptr; + sc->bCompatValidUser = -1; return sc; } @@ -160,6 +162,8 @@ extern "C" void* merge_shib_server_config (SH_AP_POOL* p, void* base, void* sub) else sc->szScheme=nullptr; + sc->bCompatValidUser = ((child->bCompatValidUser==-1) ? parent->bCompatValidUser : child->bCompatValidUser); + return sc; } @@ -341,7 +345,7 @@ public: shib_server_config* m_sc; shib_request_config* m_rc; - ShibTargetApache(request_rec* req) : AbstractSPRequest(SHIBSP_LOGCAT".Apache"), + ShibTargetApache(request_rec* req) : AbstractSPRequest(SHIBSP_LOGCAT ".Apache"), m_gotBody(false),m_firsttime(true), #if defined(SHIBSP_HAVE_GSSAPI) && !defined(SHIB_APACHE_13) m_gssname(GSS_C_NO_NAME), @@ -411,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(); @@ -594,19 +602,23 @@ public: m_req->content_type = ap_psprintf(m_req->pool, "%s", type); } void setResponseHeader(const char* name, const char* value) { - HTTPResponse::setResponseHeader(name, value); + HTTPResponse::setResponseHeader(name, value); + if (name) { #ifdef SHIB_DEFERRED_HEADERS - if (!m_rc) - // this happens on subrequests - m_rc = get_request_config(m_req); - if (m_handler) { - if (!m_rc->hdr_out) - m_rc->hdr_out = ap_make_table(m_req->pool, 5); - ap_table_add(m_rc->hdr_out, name, value); - } - else + if (!m_rc) { + // this happens on subrequests + m_rc = get_request_config(m_req); + } + if (m_handler) { + if (!m_rc->hdr_out) { + m_rc->hdr_out = ap_make_table(m_req->pool, 5); + } + ap_table_add(m_rc->hdr_out, name, value); + } + else #endif - ap_table_add(m_req->err_headers_out, name, value); + ap_table_add(m_req->err_headers_out, name, value); + } } long sendResponse(istream& in, long status) { if (status != XMLTOOLING_HTTP_STATUS_OK) @@ -809,8 +821,9 @@ extern "C" int shib_handler(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_handler found no per-request structure"); - return SERVER_ERROR; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, SH_AP_R(r), "shib_handler 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 @@ -868,8 +881,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 @@ -1154,7 +1168,7 @@ bool htAccessControl::checkAttribute(const SPRequest& request, const Attribute* auto_arrayptr trans(fromUTF8(v->c_str())); if (re->matches(trans.get())) { if (request.isPriorityEnabled(SPRequest::SPDebug)) - request.log(SPRequest::SPDebug, string("htaccess: expecting regexp ") + toMatch + ", got " + *v + ": acccepted"); + request.log(SPRequest::SPDebug, string("htaccess: expecting regexp ") + toMatch + ", got " + *v + ": accepted"); return true; } } @@ -1290,9 +1304,16 @@ AccessControl::aclresult_t htAccessControl::authorized(const SPRequest& request, 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); } @@ -1578,7 +1599,7 @@ extern "C" authz_status shib_shibboleth_check_authz(request_rec* r, const char* return AUTHZ_GRANTED; } -extern "C" authz_status shib_validuser_check_authz(request_rec* r, const char* require_line, const void*) +extern "C" authz_status shib_session_check_authz(request_rec* r, const char* require_line, const void*) { pair sta = shib_base_check_authz(r); if (!sta.first) @@ -1588,7 +1609,7 @@ extern "C" authz_status shib_validuser_check_authz(request_rec* r, const char* r Session* session = sta.first->getSession(false, true, false); Locker slocker(session, false); if (session) { - sta.first->log(SPRequest::SPDebug, "htaccess: accepting valid-user based on active session"); + sta.first->log(SPRequest::SPDebug, "htaccess: accepting shib-session/valid-user based on active session"); return AUTHZ_GRANTED; } } @@ -1596,13 +1617,36 @@ extern "C" authz_status shib_validuser_check_authz(request_rec* r, const char* r sta.first->log(SPRequest::SPWarn, string("htaccess: unable to obtain session for access control check: ") + e.what()); } + sta.first->log(SPRequest::SPDebug, "htaccess: denying shib-access/valid-user rule, no active session"); return AUTHZ_DENIED_NO_USER; } -extern "C" authz_status shib_user_check_authz(request_rec* r, const char* require_line, const void*) +extern "C" authz_status shib_validuser_check_authz(request_rec* r, const char* require_line, const void*) { - if (!r->user || !*(r->user)) + // 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 valid-user so that combined deployments can + // use valid-user for non-Shibboleth cases and shib-session 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_session_check_authz(r, require_line, nullptr); + } + + // Reproduce mod_authz_user version... + + if (!r->user) { return AUTHZ_DENIED_NO_USER; + } + + return AUTHZ_GRANTED; +} + +extern "C" authz_status shib_ext_user_check_authz(request_rec* r, const char* require_line, const void*) +{ pair sta = shib_base_check_authz(r); if (!sta.first) return sta.second; @@ -1613,6 +1657,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 sta = shib_base_check_authz(r); @@ -1724,6 +1805,14 @@ extern "C" const char* shib_set_server_string_slot(cmd_parms* parms, void*, cons return nullptr; } +extern "C" const char* shib_set_server_flag_slot(cmd_parms* parms, void*, int arg) +{ + char* base=(char*)ap_get_module_config(parms->server->module_config,&mod_shib); + size_t offset=(size_t)parms->info; + *((int*)(base + offset)) = arg; + return nullptr; +} + extern "C" const char* shib_ap_set_file_slot(cmd_parms* parms, #ifdef SHIB_APACHE_13 char* arg1, char* arg2 @@ -2077,7 +2166,9 @@ module MODULE_VAR_EXPORT mod_shib = { #ifdef SHIB_APACHE_24 extern "C" const authz_provider shib_authz_shibboleth_provider = { &shib_shibboleth_check_authz, nullptr }; 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 }; @@ -2121,7 +2212,9 @@ extern "C" void shib_register_hooks (apr_pool_t *p) #ifdef SHIB_APACHE_24 ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "shibboleth", AUTHZ_PROVIDER_VERSION, &shib_authz_shibboleth_provider, AP_AUTH_INTERNAL_PER_CONF); 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); @@ -2174,6 +2267,9 @@ static command_rec shib_cmds[] = { AP_INIT_FLAG("ShibRequestMapperAuthz", (config_fn_t)ap_set_flag_slot, (void *) offsetof (shib_dir_config, bRequestMapperAuthz), OR_AUTHCFG, "Support access control via shibboleth2.xml / RequestMapper"), + AP_INIT_FLAG("ShibCompatValidUser", (config_fn_t)shib_set_server_flag_slot, + (void *) offsetof (shib_server_config, bCompatValidUser), + RSRC_CONF, "Handle 'require valid-user' in mod_authz_user-compatible fashion (requiring username)"), #else AP_INIT_TAKE1("AuthGroupFile", (config_fn_t)shib_ap_set_file_slot, (void *) offsetof (shib_dir_config, szAuthGrpFile),