From 86b1de85536e93c59a25702a5a2d3e384202ffd2 Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Tue, 11 Dec 2012 04:03:29 +0000 Subject: More changes to port to C++11, adjust to use the new JSON support, and cleanup rest of the modules. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1419987 13f79535-47bb-0310-9956-ffa450edef68 --- sca-cpp/trunk/modules/http/mod-openauth.cpp | 269 +++++++++++++++++----------- 1 file changed, 160 insertions(+), 109 deletions(-) (limited to 'sca-cpp/trunk/modules/http/mod-openauth.cpp') 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 apcs; + gc_mutable_ref login; + gc_mutable_ref > 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 @@ -116,29 +116,36 @@ 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 checkAuthnzProviders(const string& user, const string& pw, request_rec* r, const list& apcs) { - if (isNil(apcs)) - return mkfailure("Authentication failure for: " + user); +const failable checkAuthnzProviders(const string& user, const string& pw, request_rec* const r, const list& apcs) { + if(isNil(apcs)) + return mkfailure("Authentication failure for: " + user, HTTP_UNAUTHORIZED); const AuthnProviderConf apc = car(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 checkAuthnz(const string& user, const string& pw, request_rec* r, const DirConf& dc) { - if (substr(user, 0, 1) == "/" && pw == "password") +const failable checkAuthnz(const string& user, const string& pw, request_rec* const r, const DirConf& dc) { + if(substr(user, 0, 1) == "/" && pw == "password") return mkfailure(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED); - if (isNil(dc.apcs)) { + if(isNil((const list)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(AUTHN_DEFAULT_PROVIDER, provider))); } @@ -148,54 +155,47 @@ const failable 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 userInfoFromSession(const string& realm, request_rec* r) { +const failable 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("Couldn't retrieve user session"); + if(z == NULL) + return mkfailure("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("Couldn't retrieve user id"); + if(user == NULL) + return mkfailure("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("Couldn't retrieve password"); + if(pw == NULL) + return mkfailure("Couldn't retrieve password", HTTP_UNAUTHORIZED); return value(mklist(mklist("realm", realm), mklist("id", string(user)), mklist("password", string(pw)))); } /** * Return the user info from a form auth session cookie. */ -const failable userInfoFromCookie(const value& sid, const string& realm, request_rec* r) { +const failable userInfoFromCookie(const value& sid, const string& realm, request_rec* const r) { const list> info = httpd::queryArgs(sid); debug(info, "modopenauth::userInfoFromCookie::info"); const list user = assoc(realm + "-user", info); - if (isNil(user)) + if(isNil(user)) return userInfoFromSession(realm, r); const list pw = assoc(realm + "-pw", info); - if (isNil(pw)) - return mkfailure("Couldn't retrieve password"); + if(isNil(pw)) + return mkfailure("Couldn't retrieve password", HTTP_UNAUTHORIZED); return value(mklist(mklist("realm", realm), mklist("id", cadr(user)), mklist("password", cadr(pw)))); } /** * Return the user info from a basic auth header. */ -const failable userInfoFromHeader(const char* header, const string& realm, request_rec* r) { +const failable 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("Wrong authentication scheme"); + if(strcasecmp(ap_getword(r->pool, &header, ' '), "Basic")) + return mkfailure("Wrong authentication scheme", HTTP_UNAUTHORIZED); while (apr_isspace(*header)) header++; @@ -212,18 +212,18 @@ const failable userInfoFromHeader(const char* header, const string& realm /** * Handle an authenticated request. */ -const failable authenticated(const list >& info, request_rec* r) { +const failable authenticated(const list >& info, request_rec* const r) { debug(info, "modopenauth::authenticated::info"); // Store user info in the request const list realm = assoc("realm", info); - if (isNil(realm) || isNil(cdr(realm))) - return mkfailure("Couldn't retrieve realm"); + if(isNil(realm) || isNil(cdr(realm))) + return mkfailure("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 id = assoc("id", info); - if (isNil(id) || isNil(cdr(id))) - return mkfailure("Couldn't retrieve user id"); + if(isNil(id) || isNil(cdr(id))) + return mkfailure("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 authenticated(const list >& 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(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 > args = httpd::queryArgs(r); // Get session id from the request const maybe 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("Missing AuthName")); + if(aname == NULL) + return reportStatus(mkfailure("Missing AuthName", HTTP_UNAUTHORIZED), dc.login, nilValue, r); // Extract user info from the session id const failable userinfo = userInfoFromCookie(content(sid), aname, r); - if (hasContent(userinfo)) { + if(hasContent(userinfo)) { // Try to authenticate the request const value uinfo = content(userinfo); const failable authz = checkAuthnz(cadr(assoc("id", uinfo)), cadr(assoc("password", uinfo)), r, dc); - if (!hasContent(authz)) { + if(!hasContent(authz)) { // Authentication failed, redirect to login page r->ap_auth_type = const_cast(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(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("Missing AuthName")); + const char* const aname = ap_auth_name(r); + if(aname == NULL) + return reportStatus(mkfailure("Missing AuthName", HTTP_UNAUTHORIZED), dc.login, nilValue, r); // Extract user info from the session id const failable info = userInfoFromHeader(header, aname, r); - if (hasContent(info)) { + if(hasContent(info)) { // Try to authenticate the request const value uinfo = content(info); const failable authz = checkAuthnz(cadr(assoc("id", uinfo)), cadr(assoc("password", uinfo)), r, dc); - if (!hasContent(authz)) { + if(!hasContent(authz)) { // Authentication failed, redirect to login page r->ap_auth_type = const_cast(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(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("openid_identifier", args))) + if(!isNil(assoc("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(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(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(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; } @@ -375,23 +361,87 @@ static int sessionCookieLoad(request_rec* r, session_rec** z) { return OK; } +/** + * 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(r, &mod_tuscany_openauth); + if(!dc.enabled) + return DECLINED; + if(z->encoded == NULL || *(z->encoded) == '\0') { + const maybe 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(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(s, &mod_tuscany_openauth); + const ServerConf& sc = httpd::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(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(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(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(dc.apcs, mklist(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); } } -- cgit v1.2.3