summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/modules/http/mod-openauth.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/trunk/modules/http/mod-openauth.cpp')
-rw-r--r--sca-cpp/trunk/modules/http/mod-openauth.cpp269
1 files changed, 160 insertions, 109 deletions
diff --git a/sca-cpp/trunk/modules/http/mod-openauth.cpp b/sca-cpp/trunk/modules/http/mod-openauth.cpp
index 2e308ecedb..797e8c10b5 100644
--- a/sca-cpp/trunk/modules/http/mod-openauth.cpp
+++ b/sca-cpp/trunk/modules/http/mod-openauth.cpp
@@ -57,11 +57,11 @@ namespace openauth {
*/
class ServerConf {
public:
- ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s) {
+ ServerConf(apr_pool_t* const p, server_rec* const s) : p(p), server(s) {
}
const gc_pool p;
- server_rec* server;
+ server_rec* const server;
};
/**
@@ -71,11 +71,11 @@ class AuthnProviderConf {
public:
AuthnProviderConf() : name(), provider(NULL) {
}
- AuthnProviderConf(const string name, const authn_provider* provider) : name(name), provider(provider) {
+ AuthnProviderConf(const string name, const authn_provider* const provider) : name(name), provider(provider) {
}
- string name;
- const authn_provider* provider;
+ const string name;
+ const authn_provider* const provider;
};
/**
@@ -83,14 +83,14 @@ public:
*/
class DirConf {
public:
- DirConf(apr_pool_t* p, char* d) : p(p), dir(d), enabled(false), login("") {
+ DirConf(apr_pool_t* const p, const char* d) : p(p), dir(d), enabled(false), login(emptyString) {
}
const gc_pool p;
- const char* dir;
+ const char* const dir;
bool enabled;
- string login;
- list<AuthnProviderConf> apcs;
+ gc_mutable_ref<string> login;
+ gc_mutable_ref<list<AuthnProviderConf> > apcs;
};
#ifdef WANT_MAINTAINER_LOG
@@ -98,17 +98,17 @@ public:
/**
* Log session entries.
*/
-int debugSessionEntry(unused void* r, const char* key, const char* value) {
+int debugSessionEntry(unused void* r, const char* const key, const char* const value) {
cdebug << " session key: " << key << ", value: " << value << endl;
return 1;
}
-const bool debugSession(request_rec* r, session_rec* z) {
+const bool debugSession(request_rec* const r, const session_rec* const z) {
apr_table_do(debugSessionEntry, r, z->entries, NULL);
return true;
}
-#define debug_authSession(r, z) if (debug_islogging()) openauth::debugSession(r, z)
+#define debug_authSession(r, z) if(debug_islogging()) openauth::debugSession(r, z)
#else
@@ -117,28 +117,35 @@ const bool debugSession(request_rec* r, session_rec* z) {
#endif
/**
+ * Session hook functions.
+ */
+static int (*ap_session_load_fn) (request_rec * r, session_rec ** z) = NULL;
+static apr_status_t (*ap_session_get_fn) (request_rec * r, session_rec * z, const char *key, const char **value) = NULL;
+static apr_status_t (*ap_session_set_fn)(request_rec * r, session_rec * z, const char *key, const char *value) = NULL;
+
+/**
* Run the authnz hooks to authenticate a request.
*/
-const failable<int> checkAuthnzProviders(const string& user, const string& pw, request_rec* r, const list<AuthnProviderConf>& apcs) {
- if (isNil(apcs))
- return mkfailure<int>("Authentication failure for: " + user);
+const failable<int> checkAuthnzProviders(const string& user, const string& pw, request_rec* const r, const list<AuthnProviderConf>& apcs) {
+ if(isNil(apcs))
+ return mkfailure<int>("Authentication failure for: " + user, HTTP_UNAUTHORIZED);
const AuthnProviderConf apc = car<AuthnProviderConf>(apcs);
- if (apc.provider == NULL || !apc.provider->check_password)
+ if(apc.provider == NULL || !apc.provider->check_password)
return checkAuthnzProviders(user, pw, r, cdr(apcs));
apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, c_str(apc.name));
const authn_status auth_result = apc.provider->check_password(r, c_str(user), c_str(pw));
apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE);
- if (auth_result != AUTH_GRANTED)
+ if(auth_result != AUTH_GRANTED)
return checkAuthnzProviders(user, pw, r, cdr(apcs));
return OK;
}
-const failable<int> checkAuthnz(const string& user, const string& pw, request_rec* r, const DirConf& dc) {
- if (substr(user, 0, 1) == "/" && pw == "password")
+const failable<int> checkAuthnz(const string& user, const string& pw, request_rec* const r, const DirConf& dc) {
+ if(substr(user, 0, 1) == "/" && pw == "password")
return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED);
- if (isNil(dc.apcs)) {
+ if(isNil((const list<AuthnProviderConf>)dc.apcs)) {
const authn_provider* provider = (const authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION);
return checkAuthnzProviders(user, pw, r, mklist<AuthnProviderConf>(AuthnProviderConf(AUTHN_DEFAULT_PROVIDER, provider)));
}
@@ -148,54 +155,47 @@ const failable<int> checkAuthnz(const string& user, const string& pw, request_re
/**
* Return the user info from a form auth encrypted session cookie.
*/
-static int (*ap_session_load_fn) (request_rec * r, session_rec ** z) = NULL;
-static int (*ap_session_get_fn) (request_rec * r, session_rec * z, const char *key, const char **value) = NULL;
-
-const failable<value> userInfoFromSession(const string& realm, request_rec* r) {
+const failable<value> userInfoFromSession(const string& realm, request_rec* const r) {
debug("modopenauth::userInfoFromSession");
- if (ap_session_load_fn == NULL)
- ap_session_load_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_load);
session_rec *z = NULL;
ap_session_load_fn(r, &z);
- if (z == NULL)
- return mkfailure<value>("Couldn't retrieve user session");
+ if(z == NULL)
+ return mkfailure<value>("Couldn't retrieve user session", HTTP_UNAUTHORIZED);
debug_authSession(r, z);
- if (ap_session_get_fn == NULL)
- ap_session_get_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_get);
const char* user = NULL;
ap_session_get_fn(r, z, c_str(realm + "-user"), &user);
- if (user == NULL)
- return mkfailure<value>("Couldn't retrieve user id");
+ if(user == NULL)
+ return mkfailure<value>("Couldn't retrieve user id", HTTP_UNAUTHORIZED);
const char* pw = NULL;
ap_session_get_fn(r, z, c_str(realm + "-pw"), &pw);
- if (pw == NULL)
- return mkfailure<value>("Couldn't retrieve password");
+ if(pw == NULL)
+ return mkfailure<value>("Couldn't retrieve password", HTTP_UNAUTHORIZED);
return value(mklist<value>(mklist<value>("realm", realm), mklist<value>("id", string(user)), mklist<value>("password", string(pw))));
}
/**
* Return the user info from a form auth session cookie.
*/
-const failable<value> userInfoFromCookie(const value& sid, const string& realm, request_rec* r) {
+const failable<value> userInfoFromCookie(const value& sid, const string& realm, request_rec* const r) {
const list<list<value>> info = httpd::queryArgs(sid);
debug(info, "modopenauth::userInfoFromCookie::info");
const list<value> user = assoc<value>(realm + "-user", info);
- if (isNil(user))
+ if(isNil(user))
return userInfoFromSession(realm, r);
const list<value> pw = assoc<value>(realm + "-pw", info);
- if (isNil(pw))
- return mkfailure<value>("Couldn't retrieve password");
+ if(isNil(pw))
+ return mkfailure<value>("Couldn't retrieve password", HTTP_UNAUTHORIZED);
return value(mklist<value>(mklist<value>("realm", realm), mklist<value>("id", cadr(user)), mklist<value>("password", cadr(pw))));
}
/**
* Return the user info from a basic auth header.
*/
-const failable<value> userInfoFromHeader(const char* header, const string& realm, request_rec* r) {
+const failable<value> userInfoFromHeader(const char* header, const string& realm, request_rec* const r) {
debug(header, "modopenauth::userInfoFromHeader::header");
- if (strcasecmp(ap_getword(r->pool, &header, ' '), "Basic"))
- return mkfailure<value>("Wrong authentication scheme");
+ if(strcasecmp(ap_getword(r->pool, &header, ' '), "Basic"))
+ return mkfailure<value>("Wrong authentication scheme", HTTP_UNAUTHORIZED);
while (apr_isspace(*header))
header++;
@@ -212,18 +212,18 @@ const failable<value> userInfoFromHeader(const char* header, const string& realm
/**
* Handle an authenticated request.
*/
-const failable<int> authenticated(const list<list<value> >& info, request_rec* r) {
+const failable<int> authenticated(const list<list<value> >& info, request_rec* const r) {
debug(info, "modopenauth::authenticated::info");
// Store user info in the request
const list<value> realm = assoc<value>("realm", info);
- if (isNil(realm) || isNil(cdr(realm)))
- return mkfailure<int>("Couldn't retrieve realm");
+ if(isNil(realm) || isNil(cdr(realm)))
+ return mkfailure<int>("Couldn't retrieve realm", HTTP_UNAUTHORIZED);
apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "REALM"), apr_pstrdup(r->pool, c_str(cadr(realm))));
const list<value> id = assoc<value>("id", info);
- if (isNil(id) || isNil(cdr(id)))
- return mkfailure<int>("Couldn't retrieve user id");
+ if(isNil(id) || isNil(cdr(id)))
+ return mkfailure<int>("Couldn't retrieve user id", HTTP_UNAUTHORIZED);
r->user = apr_pstrdup(r->pool, c_str(cadr(id)));
apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "NICKNAME"), apr_pstrdup(r->pool, c_str(cadr(id))));
@@ -233,127 +233,113 @@ const failable<int> authenticated(const list<list<value> >& info, request_rec* r
/**
* Check user authentication.
*/
-static int checkAuthn(request_rec *r) {
- gc_scoped_pool pool(r->pool);
+static int checkAuthn(request_rec* const r) {
+ const gc_scoped_pool sp(r->pool);
// Decline if we're not enabled or AuthType is not set to Open
const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
- if (!dc.enabled)
+ if(!dc.enabled)
return DECLINED;
const char* atype = ap_auth_type(r);
- if (atype == NULL || strcasecmp(atype, "Open"))
- return DECLINED;
debug_httpdRequest(r, "modopenauth::checkAuthn::input");
debug(atype, "modopenauth::checkAuthn::auth_type");
+ if(atype == NULL || strcasecmp(atype, "Open"))
+ return DECLINED;
+ debug(atype, "modopenauth::checkAuthn::auth_type");
// Get the request args
const list<list<value> > args = httpd::queryArgs(r);
// Get session id from the request
const maybe<string> sid = sessionID(r, "TuscanyOpenAuth");
- if (hasContent(sid)) {
+ if(hasContent(sid)) {
// Decline if the session id was not created by this module
const string stype = substr(content(sid), 0, 7);
- if (stype == "OAuth2_" || stype == "OAuth1_" || stype == "OpenID_")
+ if(stype == "OAuth2_" || stype == "OAuth1_" || stype == "OpenID_")
return DECLINED;
// Retrieve the auth realm
const char* aname = ap_auth_name(r);
- if (aname == NULL)
- return httpd::reportStatus(mkfailure<int>("Missing AuthName"));
+ if(aname == NULL)
+ return reportStatus(mkfailure<int>("Missing AuthName", HTTP_UNAUTHORIZED), dc.login, nilValue, r);
// Extract user info from the session id
const failable<value> userinfo = userInfoFromCookie(content(sid), aname, r);
- if (hasContent(userinfo)) {
+ if(hasContent(userinfo)) {
// Try to authenticate the request
const value uinfo = content(userinfo);
const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", uinfo)), cadr(assoc<value>("password", uinfo)), r, dc);
- if (!hasContent(authz)) {
+ if(!hasContent(authz)) {
// Authentication failed, redirect to login page
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(login(dc.login, value(), 1, r));
+ return reportStatus(authz, dc.login, 1, r);
}
// Successfully authenticated, store the user info in the request
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authenticated(uinfo, r));
+ return reportStatus(authenticated(uinfo, r), dc.login, nilValue, r);
}
}
// Get basic auth header from the request
- const char* header = apr_table_get(r->headers_in, (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization" : "Authorization");
- if (header != NULL) {
+ const char* const header = apr_table_get(r->headers_in, (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization" : "Authorization");
+ if(header != NULL) {
// Retrieve the auth realm
- const char* aname = ap_auth_name(r);
- if (aname == NULL)
- return httpd::reportStatus(mkfailure<int>("Missing AuthName"));
+ const char* const aname = ap_auth_name(r);
+ if(aname == NULL)
+ return reportStatus(mkfailure<int>("Missing AuthName", HTTP_UNAUTHORIZED), dc.login, nilValue, r);
// Extract user info from the session id
const failable<value> info = userInfoFromHeader(header, aname, r);
- if (hasContent(info)) {
+ if(hasContent(info)) {
// Try to authenticate the request
const value uinfo = content(info);
const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", uinfo)), cadr(assoc<value>("password", uinfo)), r, dc);
- if (!hasContent(authz)) {
+ if(!hasContent(authz)) {
// Authentication failed, redirect to login page
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(login(dc.login, value(), 1, r));
+ return reportStatus(authz, dc.login, 1, r);
}
// Successfully authenticated, store the user info in the request
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authenticated(uinfo, r));
+ return reportStatus(authenticated(uinfo, r), dc.login, nilValue, r);
}
}
// Decline if the request is for another authentication provider
- if (!isNil(assoc<value>("openid_identifier", args)))
+ if(!isNil(assoc<value>("openid_identifier", args)))
return DECLINED;
// Redirect to the login page, unless we have a session id from another module
- if (hasContent(sessionID(r, "TuscanyOpenIDAuth")) ||
+ if(hasContent(sessionID(r, "TuscanyOpenIDAuth")) ||
hasContent(sessionID(r, "TuscanyOAuth1")) ||
hasContent(sessionID(r, "TuscanyOAuth2")))
return DECLINED;
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(login(dc.login, value(), value(), r));
+ return httpd::reportStatus(login(dc.login, nilValue, nilValue, r));
}
/**
- * Save the auth session cookie in the response.
- */
-static int sessionCookieSave(request_rec* r, session_rec* z) {
- gc_scoped_pool pool(r->pool);
-
- const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
- if (!dc.enabled)
- return DECLINED;
-
- debug(c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))), "modopenauth::setcookie");
- apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))));
- return OK;
-}
-
-/**
- * Load the auth session cookie from the request. Similar
+ * Load the auth session cookie from the request.
*/
-static int sessionCookieLoad(request_rec* r, session_rec** z) {
- gc_scoped_pool pool(r->pool);
+static int sessionCookieLoad(request_rec* const r, session_rec** const z) {
+ const gc_scoped_pool sp(r->pool);
const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
- if (!dc.enabled)
+ if(!dc.enabled)
return DECLINED;
// First look in the notes
- const char* note = apr_pstrcat(r->pool, "mod_openauth", "TuscanyOpenAuth", NULL);
+ const char* const note = apr_pstrcat(r->pool, "mod_openauth", "TuscanyOpenAuth", NULL);
session_rec* zz = (session_rec*)(void*)apr_table_get(r->notes, note);
- if (zz != NULL) {
+ if(zz != NULL) {
*z = zz;
return OK;
}
@@ -376,22 +362,86 @@ static int sessionCookieLoad(request_rec* r, session_rec** z) {
}
/**
+ * Save the auth session cookie in the response.
+ */
+static int sessionCookieSave(request_rec* const r, session_rec* const z) {
+ const gc_scoped_pool sp(r->pool);
+
+ const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
+ if(!dc.enabled)
+ return DECLINED;
+ if(z->encoded == NULL || *(z->encoded) == '\0') {
+ const maybe<string> sid = sessionID(r, "TuscanyOpenAuth");
+ if(!hasContent(sid))
+ return OK;
+ }
+
+ debug(c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))), "modopenauth::sessioncookiesave::setcookie");
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))));
+ return OK;
+}
+
+/**
+ * Logout request handler.
+ */
+int logoutHandler(request_rec* const r) {
+ if(r->handler == NULL || strcmp(r->handler, "mod_tuscany_openauth_logout"))
+ return DECLINED;
+
+ const gc_scoped_pool sp(r->pool);
+ debug_httpdRequest(r, "modopenauth::handler::input");
+ const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
+ if(!dc.enabled)
+ return DECLINED;
+
+ // Clear the current session
+ if(hasContent(sessionID(r, "TuscanyOpenAuth"))) {
+ const char* const authname = ap_auth_name(r);
+ session_rec* z = NULL;
+ ap_session_load_fn(r, &z);
+ if(z != NULL && authname != NULL) {
+ ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-user", NULL), NULL);
+ ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-pw", NULL), NULL);
+ ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-site", NULL), NULL);
+ } else
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", emptyString, httpd::hostName(r))));
+ }
+ if(hasContent(sessionID(r, "TuscanyOpenIDAuth")))
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenIDAuth", emptyString, httpd::hostName(r))));
+ if(hasContent(sessionID(r, "TuscanyOAuth1")))
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOAuth1", emptyString, httpd::hostName(r))));
+ if(hasContent(sessionID(r, "TuscanyOAuth2")))
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOAuth2", emptyString, httpd::hostName(r))));
+
+ // Redirect to the login page
+ return httpd::reportStatus(login(dc.login, "/", nilValue, r));
+}
+
+/**
* Process the module configuration.
*/
-int postConfigMerge(ServerConf& mainsc, server_rec* s) {
- if (s == NULL)
+int postConfigMerge(const ServerConf& mainsc, server_rec* const s) {
+ if(s == NULL)
return OK;
debug(httpd::serverName(s), "modopenauth::postConfigMerge::serverName");
return postConfigMerge(mainsc, s->next);
}
-int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, server_rec* s) {
- gc_scoped_pool pool(p);
+int postConfig(apr_pool_t* const p, unused apr_pool_t* const plog, unused apr_pool_t* const ptemp, server_rec* const s) {
+ const gc_scoped_pool sp(p);
- ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_openauth);
+ const ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_openauth);
debug(httpd::serverName(s), "modopenauth::postConfig::serverName");
+ // Retrieve session hook functions
+ if(ap_session_load_fn == NULL)
+ ap_session_load_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_load);
+ if(ap_session_get_fn == NULL)
+ ap_session_get_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_get);
+ if(ap_session_set_fn == NULL)
+ ap_session_set_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_set);
+
// Merge server configurations
return postConfigMerge(sc, s);
}
@@ -399,15 +449,15 @@ int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp,
/**
* Child process initialization.
*/
-void childInit(apr_pool_t* p, server_rec* s) {
- gc_scoped_pool pool(p);
+void childInit(apr_pool_t* const p, server_rec* const s) {
+ const gc_scoped_pool sp(p);
- ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_openauth);
+ const ServerConf* const psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_openauth);
if(psc == NULL) {
cfailure << "[Tuscany] Due to one or more errors mod_tuscany_openauth loading failed. Causing apache to stop loading." << endl;
exit(APEXIT_CHILDFATAL);
}
- ServerConf& sc = *psc;
+ const ServerConf& sc = *psc;
// Merge the updated configuration into the virtual hosts
postConfigMerge(sc, s->next);
@@ -416,27 +466,27 @@ void childInit(apr_pool_t* p, server_rec* s) {
/**
* Configuration commands.
*/
-const char* confEnabled(cmd_parms *cmd, void *c, const int arg) {
- gc_scoped_pool pool(cmd->pool);
+char* confEnabled(cmd_parms* cmd, void *c, const int arg) {
+ const gc_scoped_pool sp(cmd->pool);
DirConf& dc = httpd::dirConf<DirConf>(c);
dc.enabled = (bool)arg;
return NULL;
}
-const char* confLogin(cmd_parms *cmd, void *c, const char* arg) {
- gc_scoped_pool pool(cmd->pool);
+char* confLogin(cmd_parms *cmd, void *c, const char* arg) {
+ const gc_scoped_pool sp(cmd->pool);
DirConf& dc = httpd::dirConf<DirConf>(c);
dc.login = arg;
return NULL;
}
-const char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) {
- gc_scoped_pool pool(cmd->pool);
+char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) {
+ const gc_scoped_pool sp(cmd->pool);
DirConf& dc = httpd::dirConf<DirConf>(c);
// Lookup and cache the Authn provider
const authn_provider* provider = (authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, arg, AUTHN_PROVIDER_VERSION);
- if (provider == NULL)
+ if(provider == NULL)
return apr_psprintf(cmd->pool, "Unknown Authn provider: %s", arg);
- if (!provider->check_password)
+ if(!provider->check_password)
return apr_psprintf(cmd->pool, "The '%s' Authn provider doesn't support password authentication", arg);
dc.apcs = append<AuthnProviderConf>(dc.apcs, mklist<AuthnProviderConf>(AuthnProviderConf(arg, provider)));
return NULL;
@@ -458,6 +508,7 @@ void registerHooks(unused apr_pool_t *p) {
ap_hook_check_authn(checkAuthn, NULL, NULL, APR_HOOK_MIDDLE, AP_AUTH_INTERNAL_PER_CONF);
ap_hook_session_load(sessionCookieLoad, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_session_save(sessionCookieSave, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_handler(logoutHandler, NULL, NULL, APR_HOOK_MIDDLE);
}
}