diff options
Diffstat (limited to '')
-rwxr-xr-x | sca-cpp/trunk/modules/http/form-auth-conf | 12 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/http/htdocs/login/index.html | 2 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/http/htdocs/logout/index.html | 2 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/http/http.hpp | 1 | ||||
-rwxr-xr-x | sca-cpp/trunk/modules/http/httpd-conf | 10 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/http/httpd.hpp | 8 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/http/mod-openauth.cpp | 15 | ||||
-rwxr-xr-x | sca-cpp/trunk/modules/http/open-auth-conf | 10 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/http/openauth.hpp | 26 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/oauth/htdocs/login/index.html | 14 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html | 18 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/oauth/htdocs/logout/index.html | 12 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/oauth/mod-oauth1.cpp | 22 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/oauth/mod-oauth2.cpp | 22 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/openid/htdocs/login/index.html | 12 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/openid/htdocs/logout/index.html | 12 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/server/mod-eval.hpp | 45 |
17 files changed, 153 insertions, 90 deletions
diff --git a/sca-cpp/trunk/modules/http/form-auth-conf b/sca-cpp/trunk/modules/http/form-auth-conf index ba2f99dbf1..6a68da3972 100755 --- a/sca-cpp/trunk/modules/http/form-auth-conf +++ b/sca-cpp/trunk/modules/http/form-auth-conf @@ -44,6 +44,14 @@ else sslsuffix="-ssl" fi +# Configure session crypto +cat >>$root/conf/httpd.conf <<EOF +# Configure session crypto +SessionCryptoPassphrase $pw +SessionCryptoDriver openssl + +EOF + # Disallow public access to server resources cat >$root/conf/noauth$sslsuffix.conf <<EOF # Generated by: form-auth-conf $* @@ -64,8 +72,8 @@ AuthnCacheProvideFor $providers AuthnCacheContext / AuthFormLoginRequiredLocation /login/ Session On -SessionCookieName TuscanyFormAuth domain=.$host; path=/; secure; httponly -SessionCryptoPassphrase $pw +SessionCookieName TuscanyFormAuth domain=.$host; max-age=604800; path=/; secure; httponly +SessionMaxAge 0 Require valid-user </Location> diff --git a/sca-cpp/trunk/modules/http/htdocs/login/index.html b/sca-cpp/trunk/modules/http/htdocs/login/index.html index fd3bc21889..636a385f5c 100644 --- a/sca-cpp/trunk/modules/http/htdocs/login/index.html +++ b/sca-cpp/trunk/modules/http/htdocs/login/index.html @@ -32,7 +32,7 @@ <script type="text/javascript"> function submitFormSignin() { - clearauthcookie(); + clearAuthCookie(); document.formSignin.httpd_location.value = '/'; document.formSignin.submit(); } diff --git a/sca-cpp/trunk/modules/http/htdocs/logout/index.html b/sca-cpp/trunk/modules/http/htdocs/logout/index.html index 218dd5d52c..1dd09fd56c 100644 --- a/sca-cpp/trunk/modules/http/htdocs/logout/index.html +++ b/sca-cpp/trunk/modules/http/htdocs/logout/index.html @@ -33,7 +33,7 @@ <form name="signout" action="/login" method="GET"> <script type="text/javascript"> function submitSignout() { - clearauthcookie(); + clearAuthCookie(); document.signout.submit(); return true; } diff --git a/sca-cpp/trunk/modules/http/http.hpp b/sca-cpp/trunk/modules/http/http.hpp index 04b0d4e490..c5e3bdcb4b 100644 --- a/sca-cpp/trunk/modules/http/http.hpp +++ b/sca-cpp/trunk/modules/http/http.hpp @@ -423,6 +423,7 @@ template<typename R> const failable<list<R> > apply(const list<list<string> >& h // Set the request headers curl_slist* hl = headers(NULL, car(hdr)); hl = curl_slist_append(hl, "X-Accept: text/x-scheme; charset=utf-8"); + hl = curl_slist_append(hl, "X-Cache-Control: no-cache"); curl_easy_setopt(ch, CURLOPT_HTTPHEADER, hl); // Convert request body to a string diff --git a/sca-cpp/trunk/modules/http/httpd-conf b/sca-cpp/trunk/modules/http/httpd-conf index 3f96304ae8..8a029eaec2 100755 --- a/sca-cpp/trunk/modules/http/httpd-conf +++ b/sca-cpp/trunk/modules/http/httpd-conf @@ -74,7 +74,7 @@ ServerSignature Off ServerTokens Prod Timeout 45 RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500 -LimitRequestBody 1048576 +LimitRequestBody 8388608 HostNameLookups Off #MaxKeepAliveRequests 25 #MaxConnectionsPerChild 100 @@ -93,9 +93,9 @@ AddCharset utf-8 .html .js .css # Configure cache control <Directory /> -ExpiresActive On -ExpiresDefault A604800 -Header onsuccess merge Cache-Control public env=!private-cache +SetEnvIf X-Cache-Control no-cache x-no-cache +Header merge Cache-Control max-age=604800 env=!x-no-cache +Header merge Cache-Control public env=!x-no-cache </Directory> # Enable Linux Kernel sendfile @@ -262,8 +262,6 @@ cat >$root/conf/pubauth.conf <<EOF AuthType None Session Off Require all granted -# Mark login page with a header -Header set X-Login open-auth </Location> <Location /login/dologin> Session Off diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp index bf06ed5d91..8bd74f3403 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -418,9 +418,7 @@ const failable<int> writeResult(const failable<list<string> >& ls, const string& const string ob(str(os)); // Make sure browsers come back and check for updated dynamic content - apr_table_set(r->headers_out, "Cache-Control", "must-revalidate, max-age=0"); - apr_table_set(r->headers_out, "Expires", "Tue, 01 Jan 1980 00:00:00 GMT"); - apr_table_set(r->subprocess_env, "private-cache", "1"); + apr_table_setn(r->headers_out, "Cache-Control", "must-revalidate, max-age=0"); // Compute and return an Etag for the returned content const string etag(ap_md5_binary(r->pool, (const unsigned char*)c_str(ob), (int)length(ob))); @@ -698,8 +696,8 @@ const int externalRedirect(const string& uri, request_rec* const r) { debug(uri, "httpd::externalRedirect"); r->status = HTTP_MOVED_TEMPORARILY; apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(uri))); - apr_table_setn(r->headers_out, "Cache-Control", "no-store"); - apr_table_addn(r->err_headers_out, "Cache-Control", "no-store"); + apr_table_setn(r->headers_out, "Cache-Control", "no-cache, no-store, must-revalidate, max-age=0"); + apr_table_setn(r->err_headers_out, "Cache-Control", "no-cache, no-store, must-revalidate, max-age=0"); r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:/") + uri)); return HTTP_MOVED_TEMPORARILY; } diff --git a/sca-cpp/trunk/modules/http/mod-openauth.cpp b/sca-cpp/trunk/modules/http/mod-openauth.cpp index 3adc488301..1a45473caf 100644 --- a/sca-cpp/trunk/modules/http/mod-openauth.cpp +++ b/sca-cpp/trunk/modules/http/mod-openauth.cpp @@ -28,6 +28,7 @@ * - OAuth2 using Tuscany's mod-tuscany-oauth2 * - OpenID using mod_auth_openid * - Form-based using HTTPD's mod_auth_form + * - HTTP basic auth using mod_auth_basic * - SSL certificate using SSLFakeBasicAuth and mod_auth_basic */ @@ -142,7 +143,7 @@ const failable<int> checkAuthnzProviders(const string& user, const string& pw, r } const failable<int> checkAuthnz(const string& user, const string& pw, request_rec* const r, const DirConf& dc) { - if(substr(user, 0, 1) == "/" && pw == "password") + if(substr(user, 0, 1) == "/") return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED); if(isNull((const list<AuthnProviderConf>)dc.apcs)) { @@ -224,9 +225,17 @@ const failable<int> authenticated(const list<value>& info, request_rec* const r) const list<value> id = assoc<value>("id", info); if(isNull(id) || isNull(cdr(id))) return mkfailure<int>("Couldn't retrieve user id", HTTP_UNAUTHORIZED); - r->user = apr_pstrdup(r->pool, c_str(cadr(id))); + const string sid = cadr(id); + if (find(sid, '@') != length(sid)) + apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "EMAIL"), apr_pstrdup(r->pool, c_str(sid))); + r->user = apr_pstrdup(r->pool, c_str(sid)); - apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "NICKNAME"), apr_pstrdup(r->pool, c_str(cadr(id)))); + // Update the request user field with the authorized user id returned by the authnz hooks + const char* auser = apr_table_get(r->subprocess_env, "AUTHZ_USER"); + if (auser != NULL) + r->user = apr_pstrdup(r->pool, auser); + + apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "NICKNAME"), apr_pstrdup(r->pool, r->user)); return OK; } diff --git a/sca-cpp/trunk/modules/http/open-auth-conf b/sca-cpp/trunk/modules/http/open-auth-conf index 5a8db92972..a93eb98011 100755 --- a/sca-cpp/trunk/modules/http/open-auth-conf +++ b/sca-cpp/trunk/modules/http/open-auth-conf @@ -59,6 +59,14 @@ LoadModule mod_tuscany_openauth $here/libmod_tuscany_openauth$libsuffix EOF +# Configure session crypto +cat >>$root/conf/httpd.conf <<EOF +# Configure session crypto +SessionCryptoPassphrase $pw +SessionCryptoDriver openssl + +EOF + # Disallow public access to server resources cat >$root/conf/noauth$sslsuffix.conf <<EOF # Generated by: open-auth-conf $* @@ -78,7 +86,7 @@ AuthnCacheProvideFor $providers AuthnCacheContext / AuthOpenAuthLoginPage /login/ Session On -SessionCryptoPassphrase $pw +SessionMaxAge 0 AuthOpenAuth On Require valid-user </Location> diff --git a/sca-cpp/trunk/modules/http/openauth.hpp b/sca-cpp/trunk/modules/http/openauth.hpp index 70c6f658ad..d448311cca 100644 --- a/sca-cpp/trunk/modules/http/openauth.hpp +++ b/sca-cpp/trunk/modules/http/openauth.hpp @@ -72,6 +72,16 @@ const maybe<string> sessionID(const request_rec* const r, const string& key) { } /** + * Convert a number of seconds to an expiration date. + */ +const string expires(const int s) { + const time_t t = time(NULL) + s; + char exp[32]; + strftime(exp, 32, "%a, %d-%b-%Y %H:%M:%S GMT", gmtime(&t)); + return string(exp); +} + +/** * Convert a session id to a cookie string. */ const string cookie(const string& key, const string& sid, const string& domain) { @@ -80,10 +90,8 @@ const string cookie(const string& key, const string& sid, const string& domain) debug(c, "openauth::cookie"); return c; } - const time_t t = time(NULL) + 86400; - char exp[32]; - strftime(exp, 32, "%a, %d-%b-%Y %H:%M:%S GMT", gmtime(&t)); - const string c = key + string("=") + sid + "; expires=" + string(exp) + "; domain=." + httpd::realm(domain) + "; path=/; secure; httponly"; + const string exp = "604800"; + const string c = key + string("=") + sid + (length(exp) != 0? string("; max-age=") + exp : emptyString) + "; domain=." + httpd::realm(domain) + "; path=/; secure; httponly"; debug(c, "openauth::cookie"); return c; } @@ -92,6 +100,16 @@ const string cookie(const string& key, const string& sid, const string& domain) * Redirect to the configured login page. */ const failable<int> login(const string& page, const value& ref, const value& attempt, request_rec* const r) { + + // Don't redirect non-cacheable requests, just respond with an uncacheable 403 response + const char* cc = apr_table_get(r->headers_in, "X-Cache-Control"); + if(cc != NULL && !strcmp(cc, "no-cache")) { + apr_table_setn(r->headers_out, "Cache-Control", "no-cache, no-store, must-revalidate, max-age=0"); + apr_table_setn(r->err_headers_out, "Cache-Control", "no-cache, no-store, must-revalidate, max-age=0"); + return HTTP_FORBIDDEN; + } + + // Redirect to the login page const list<value> rarg = ref == string("/")? nilListValue : mklist<value>(mklist<value>("openauth_referrer", httpd::escape(httpd::url(isNull(ref)? r->uri : ref, r)))); const list<value> aarg = isNull(attempt)? nilListValue : mklist<value>(mklist<value>("openauth_attempt", attempt)); const list<value> largs = append(rarg, aarg); diff --git a/sca-cpp/trunk/modules/oauth/htdocs/login/index.html b/sca-cpp/trunk/modules/oauth/htdocs/login/index.html index 0740afd8b3..bf5e196bae 100644 --- a/sca-cpp/trunk/modules/oauth/htdocs/login/index.html +++ b/sca-cpp/trunk/modules/oauth/htdocs/login/index.html @@ -55,17 +55,17 @@ if (typeof(oauthReferrer()) == 'undefined') { document.location = '/'; } -function clearauthcookie() { - document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; +function clearAuthCookie() { + document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; return true; } function submitSignin2(w) { parms = w(); - clearauthcookie(); + clearAuthCookie(); document.signin2.oauth2_authorize.value = parms[0]; document.signin2.oauth2_access_token.value = parms[1]; document.signin2.oauth2_client_id.value = parms[2]; @@ -89,7 +89,7 @@ function withGithub() { function submitSignin1(w) { parms = w(); - clearauthcookie(); + clearAuthCookie(); document.signin1.oauth1_request_token.value = parms[0]; document.signin1.oauth1_authorize.value = parms[1]; document.signin1.oauth1_access_token.value = parms[2]; diff --git a/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html b/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html index fdf2b64a3f..ef5afcdc7e 100644 --- a/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html +++ b/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html @@ -29,16 +29,16 @@ <h1>Sign in with a Form, an OpenID provider or an OAuth provider</h1> <script type="text/javascript"> -function clearauthcookie() { - document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; +function clearAuthCookie() { + document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; return true; } function submitFormSignin() { - clearauthcookie(); + clearAuthCookie(); document.formSignin.httpd_location.value = '/'; document.formSignin.submit(); } @@ -69,7 +69,7 @@ if (typeof(openauthReferrer()) == 'undefined') { } function submitOpenIDSignin(w) { - clearauthcookie(); + clearAuthCookie(); document.openIDSignin.openid_identifier.value = w(); document.openIDSignin.action = openauthReferrer(); document.openIDSignin.submit(); @@ -117,7 +117,7 @@ function withXRDSEndpoint() { function submitOAuth2Signin(w) { parms = w(); - clearauthcookie(); + clearAuthCookie(); document.oauth2Signin.oauth2_authorize.value = parms[0]; document.oauth2Signin.oauth2_access_token.value = parms[1]; document.oauth2Signin.oauth2_client_id.value = parms[2]; @@ -141,7 +141,7 @@ function withGithub() { function submitOAuth1Signin(w) { parms = w(); - clearauthcookie(); + clearAuthCookie(); document.oauth1Signin.oauth1_request_token.value = parms[0]; document.oauth1Signin.oauth1_authorize.value = parms[1]; document.oauth1Signin.oauth1_access_token.value = parms[2]; diff --git a/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html b/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html index 8cf786043b..437d39e882 100644 --- a/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html +++ b/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html @@ -31,16 +31,16 @@ <form name="signout" action="/login" method="GET"> <script type="text/javascript"> -function clearauthcookie() { - document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; +function clearAuthCookie() { + document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; return true; } function submitSignout() { - clearauthcookie(); + clearAuthCookie(); document.signout.submit(); return true; } diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp index b1786d1098..e34c0c2359 100644 --- a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp +++ b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp @@ -139,7 +139,7 @@ const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) /** * Handle an authenticated request. */ -const failable<int> authenticated(const list<value>& userinfo, const bool check, request_rec* const r, const list<value>& scopeattrs, const list<AuthnProviderConf>& apcs) { +const failable<int> authenticated(const list<value>& userinfo, request_rec* const r, const list<value>& scopeattrs, const list<AuthnProviderConf>& apcs) { debug(userinfo, "modoauth2::authenticated::userinfo"); if (isNull(scopeattrs)) { @@ -156,8 +156,15 @@ const failable<int> authenticated(const list<value>& userinfo, const bool check, r->user = apr_pstrdup(r->pool, c_str(cadr(id))); // Run the authnz hooks to check the authenticated user - if (check) - return checkAuthnz(r->user == NULL? emptyString : r->user, r, apcs); + const failable<int> arc = checkAuthnz(r->user == NULL? emptyString : r->user, r, apcs); + if (!hasContent(arc)) + return arc; + + // Update the request user field with the authorized user id returned by the authnz hooks + const char* auser = apr_table_get(r->subprocess_env, "AUTHZ_USER"); + if (auser != NULL) + r->user = apr_pstrdup(r->pool, auser); + return OK; } @@ -172,7 +179,7 @@ const failable<int> authenticated(const list<value>& userinfo, const bool check, else apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, c_str(car(a))), apr_pstrdup(r->pool, c_str(cadr(v)))); } - return authenticated(userinfo, check, r, cdr(scopeattrs), apcs); + return authenticated(userinfo, r, cdr(scopeattrs), apcs); } /** @@ -293,8 +300,7 @@ const failable<int> authorize(const list<value>& args, request_rec* const r, con /** * Extract user info from a profile/info response. - * TODO This currently only works for Twitter, Foursquare and LinkedIn. - * User profile parsing needs to be made configurable. + * TODO Make this configurable */ const failable<list<value> > profileUserInfo(const value& cid, const string& info) { const string b = substr(info, 0, 1); @@ -424,7 +430,7 @@ const failable<int> accessToken(const list<value>& args, request_rec* r, const l return mkfailure<int>(userinfo); // Validate the authenticated user - const failable<int> authrc = authenticated(content(userinfo), true, r, scopeattrs, apcs); + const failable<int> authrc = authenticated(content(userinfo), r, scopeattrs, apcs); if (!hasContent(authrc)) return authrc; @@ -471,7 +477,7 @@ static int checkAuthn(request_rec *r) { if (!hasContent(userinfo)) return openauth::reportStatus(mkfailure<int>(reason(userinfo), HTTP_UNAUTHORIZED), dc.login, nilValue, r); r->ap_auth_type = const_cast<char*>(atype); - return openauth::reportStatus(authenticated(content(userinfo), false, r, dc.scopeattrs, dc.apcs), dc.login, nilValue, r); + return openauth::reportStatus(authenticated(content(userinfo), r, dc.scopeattrs, dc.apcs), dc.login, nilValue, r); } // Get the request args diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp index 0a4405ce2e..c5de134926 100644 --- a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp +++ b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp @@ -133,7 +133,7 @@ const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) /** * Handle an authenticated request. */ -const failable<int> authenticated(const list<value>& userinfo, const bool check, request_rec* const r, const list<value>& scopeattrs, const list<AuthnProviderConf>& apcs) { +const failable<int> authenticated(const list<value>& userinfo, request_rec* const r, const list<value>& scopeattrs, const list<AuthnProviderConf>& apcs) { debug(userinfo, "modoauth2::authenticated::userinfo"); if (isNull(scopeattrs)) { @@ -150,8 +150,15 @@ const failable<int> authenticated(const list<value>& userinfo, const bool check, r->user = apr_pstrdup(r->pool, c_str(cadr(id))); // Run the authnz hooks to check the authenticated user - if (check) - return checkAuthnz(r->user == NULL? emptyString : r->user, r, apcs); + const failable<int> arc = checkAuthnz(r->user == NULL? emptyString : r->user, r, apcs); + if (!hasContent(arc)) + return arc; + + // Update the request user field with the authorized user id returned by the authnz hooks + const char* auser = apr_table_get(r->subprocess_env, "AUTHZ_USER"); + if (auser != NULL) + r->user = apr_pstrdup(r->pool, auser); + return OK; } @@ -166,7 +173,7 @@ const failable<int> authenticated(const list<value>& userinfo, const bool check, else apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, c_str(car(a))), apr_pstrdup(r->pool, c_str(cadr(v)))); } - return authenticated(userinfo, check, r, cdr(scopeattrs), apcs); + return authenticated(userinfo, r, cdr(scopeattrs), apcs); } /** @@ -219,8 +226,7 @@ const failable<int> authorize(const list<value>& args, request_rec* const r, con /** * Extract user info from a profile/info response. - * TODO This currently only works for Facebook and Gowalla. - * User profile parsing needs to be made configurable. + * TODO Make this configurable. */ const failable<list<value> > profileUserInfo(const value& cid, const list<value>& info) { return cons<value>(mklist<value>("realm", cid), info); @@ -299,7 +305,7 @@ const failable<int> accessToken(const list<value>& args, request_rec* r, const l return mkfailure<int>(userinfo); // Validate the authenticated user - const failable<int> authrc = authenticated(content(userinfo), true, r, scopeattrs, apcs); + const failable<int> authrc = authenticated(content(userinfo), r, scopeattrs, apcs); if (!hasContent(authrc)) return authrc; @@ -346,7 +352,7 @@ static int checkAuthn(request_rec *r) { if (!hasContent(userinfo)) return openauth::reportStatus(mkfailure<int>(reason(userinfo), HTTP_UNAUTHORIZED), dc.login, nilValue, r); r->ap_auth_type = const_cast<char*>(atype); - return openauth::reportStatus(authenticated(content(userinfo), false, r, dc.scopeattrs, dc.apcs), dc.login, nilValue, r); + return openauth::reportStatus(authenticated(content(userinfo), r, dc.scopeattrs, dc.apcs), dc.login, nilValue, r); } // Get the request args diff --git a/sca-cpp/trunk/modules/openid/htdocs/login/index.html b/sca-cpp/trunk/modules/openid/htdocs/login/index.html index 00b0bfd038..d2f364c91b 100644 --- a/sca-cpp/trunk/modules/openid/htdocs/login/index.html +++ b/sca-cpp/trunk/modules/openid/htdocs/login/index.html @@ -55,16 +55,16 @@ if (typeof(openidReferrer()) == 'undefined') { document.location = '/'; } -function clearauthcookie() { - document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; +function clearAuthCookie() { + document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; return true; } function submitSignin(w) { - clearauthcookie(); + clearAuthCookie(); document.signin.openid_identifier.value = w(); document.signin.action = openidReferrer(); document.signin.submit(); diff --git a/sca-cpp/trunk/modules/openid/htdocs/logout/index.html b/sca-cpp/trunk/modules/openid/htdocs/logout/index.html index 8cf786043b..437d39e882 100644 --- a/sca-cpp/trunk/modules/openid/htdocs/logout/index.html +++ b/sca-cpp/trunk/modules/openid/htdocs/logout/index.html @@ -31,16 +31,16 @@ <form name="signout" action="/login" method="GET"> <script type="text/javascript"> -function clearauthcookie() { - document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; +function clearAuthCookie() { + document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainName(window.location.hostname) + '; path=/'; return true; } function submitSignout() { - clearauthcookie(); + clearAuthCookie(); document.signout.submit(); return true; } diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp index 204459e127..5c46f1c224 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.hpp +++ b/sca-cpp/trunk/modules/server/mod-eval.hpp @@ -1266,14 +1266,14 @@ int handler(request_rec* r) { /** * Call an authenticator component to check a user's password. */ -authn_status checkPassword(request_rec* r, const char* u, const char* p) { +authn_status checkAuthnz(request_rec* r, const char* u, const char* p) { const gc_scoped_pool sp(r->pool); // Prevent FakeBasicAuth spoofing const string user = u; - const string password = p; - debug(user, "modeval::checkPassword::user"); - if (substr(user, 0, 1) != "/" && find(user, "/") != length(user) && password == "password") { + debug(user, "modeval::checkAuthnz::user"); + const bool extauth = find(user, "/") != length(user); + if (extauth && substr(user, 0, 1) != "/") { mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED); return AUTH_DENIED; } @@ -1286,35 +1286,46 @@ authn_status checkPassword(request_rec* r, const char* u, const char* p) { } // Retrieve the user's password hash - const list<value> uid = pathValues(user); + const list<value> uid = extauth? cdr(pathValues(user)) : pathValues(user); const failable<value> val = failableResult(((value)sc.vhostc.authenticator)(cons<value>("get", mklist<value>(uid)))); - if (!hasContent(val)) { + if (!hasContent(val) || isNull(content(val))) { mkfailure<int>(string("SCA authentication check user failed, user not found: ") + user, rcode(val), user != "admin"); return AUTH_USER_NOT_FOUND; } - const value hval = content(val); - const list<value> hcontent = isList(hval) && !isNull(hval) && isList(car<value>(hval)) && !isNull(car<value>(hval))? assoc<value>(value("content"), cdr<value>(car<value>(hval))) : nilListValue; - const list<value> hassoc = isNull(hcontent)? nilListValue : assoc<value>(value("hash"), cdr<value>(hcontent)); - if (isNull(hassoc)) { + debug(content(val), "modeval::checkAuthnz::val"); + + const value authn = cdr<value>(car<value>(content(val))); + const list<value> acontent = assoc<value>(value("content"), authn); + const list<value> aauthn = isNull(acontent)? nilListValue : assoc<value>(value("authn"), cdr<value>(acontent)); + const list<value> ahash = isNull(aauthn)? nilListValue : assoc<value>(value("hash"), cdr<value>(aauthn)); + if (isNull(ahash)) { mkfailure<int>(string("SCA authentication check user failed, hash not found: ") + user, -1, user != "admin"); return AUTH_USER_NOT_FOUND; } - const string hash = cadr<value>(hassoc); - if (length(hash) == 0) { + const string uhash = cadr<value>(ahash); + if (length(uhash) == 0) { mkfailure<int>(string("SCA authentication check user failed: ") + user); return AUTH_USER_NOT_FOUND; } - // Cache the hash in the auth cache provider, if available - if (authnCacheStore != NULL) - authnCacheStore(r, "component", u, NULL, c_str(hash)); + // Use a fixed hash of the string 'password' for externally authenticated users as they + // don't present an actual password + const string hash = extauth? "$apr1$OPUrN0Kr$/tc96p1r6LdmvB0mly6gg0" : uhash; - // Validate the presented password against the hash + // Validate the password against the hash const apr_status_t rv = apr_password_validate(p, c_str(hash)); if (rv != APR_SUCCESS) { mkfailure<int>(string("SCA authentication user password check failed: ") + user); return AUTH_DENIED; } + + // Update the user field of the request with the authenticated user + const list<value> auser = assoc<value>(value("user"), cdr<value>(aauthn)); + if (!isNull(auser)) { + debug(c_str(cadr(auser)), "modeval::checkAuthnz::auth_user"); + apr_table_set(r->subprocess_env, "AUTHZ_USER", apr_pstrdup(r->pool, c_str(cadr(auser)))); + } + return AUTH_GRANTED; } @@ -1569,7 +1580,7 @@ const command_rec commands[] = { const authn_provider AuthnProvider = { - &checkPassword, + &checkAuthnz, NULL }; |