Modified: tuscany/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp?rev=1361915&r1=1361914&r2=1361915&view=diff ============================================================================== --- tuscany/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp (original) +++ tuscany/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp Mon Jul 16 06:47:49 2012 @@ -65,6 +65,20 @@ public: }; /** + * Authentication provider configuration. + */ +class AuthnProviderConf { +public: + AuthnProviderConf() : name(), provider(NULL) { + } + AuthnProviderConf(const string name, const authn_provider* provider) : name(name), provider(provider) { + } + + string name; + const authn_provider* provider; +}; + +/** * Directory configuration. */ class DirConf { @@ -77,9 +91,39 @@ public: bool enabled; string login; list<list<value> > scopeattrs; + list<AuthnProviderConf> apcs; }; /** + * Run the authnz hooks to authenticate a request. + */ +const failable<int> checkAuthnzProviders(const string& user, request_rec* 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) + return checkAuthnzProviders(user, 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(string("/oauth2/") + user), "password"); + apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE); + if (auth_result != AUTH_GRANTED) + return checkAuthnzProviders(user, r, cdr(apcs)); + return OK; +} + +const failable<int> checkAuthnz(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) { + if (substr(user, 0, 1) == "/") + return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED); + + if (isNil(apcs)) { + const authn_provider* provider = (const authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION); + return checkAuthnzProviders(user, r, mklist<AuthnProviderConf>(AuthnProviderConf(AUTHN_DEFAULT_PROVIDER, provider))); + } + return checkAuthnzProviders(user, r, apcs); +} + +/** * Return the user info for a session. */ const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) { @@ -89,13 +133,13 @@ const failable<value> userInfo(const val /** * Handle an authenticated request. */ -const failable<int> authenticated(const list<list<value> >& attrs, const list<list<value> >& info, request_rec* r) { - debug(info, "modoauth2::authenticated::info"); +const failable<int> authenticated(const list<list<value> >& userinfo, const bool check, request_rec* r, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs) { + debug(userinfo, "modoauth2::authenticated::userinfo"); - if (isNil(attrs)) { + if (isNil(scopeattrs)) { // Store user id in an environment variable - const list<value> id = assoc<value>("id", info); + const list<value> id = assoc<value>("id", userinfo); if (isNil(id) || isNil(cdr(id))) return mkfailure<int>("Couldn't retrieve user id"); apr_table_set(r->subprocess_env, "OAUTH2_ID", apr_pstrdup(r->pool, c_str(cadr(id)))); @@ -104,12 +148,16 @@ const failable<int> authenticated(const // OAuth id attribute to it if (r->user == NULL || r->user[0] == '\0') 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? "" : r->user, r, apcs); return OK; } - // Store each configure OAuth scope attribute in an environment variable - const list<value> a = car(attrs); - const list<value> v = assoc<value>(cadr(a), info); + // Store each configured OAuth scope attribute in an environment variable + const list<value> a = car(scopeattrs); + const list<value> v = assoc<value>(cadr(a), userinfo); if (!isNil(v) && !isNil(cdr(v))) { // Map the REMOTE_USER attribute to the request user field @@ -118,7 +166,7 @@ const failable<int> authenticated(const 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(cdr(attrs), info, r); + return authenticated(userinfo, check, r, cdr(scopeattrs), apcs); } /** @@ -181,7 +229,8 @@ const failable<list<value> > profileUser /** * Handle an access_token request. */ -const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const perthread_ptr<http::CURLSession>& cs, const memcache::MemCached& mc) { +const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const perthread_ptr<http::CURLSession>& cs, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs, const memcache::MemCached& mc) { + // Extract access_token URI, client ID and authorization code parameters const list<value> state = assoc<value>("state", args); if (isNil(state) || isNil(cdr(state))) @@ -245,17 +294,22 @@ const failable<int> accessToken(const li debug(content(profres), "modoauth2::access_token::info"); // Retrieve the user info from the profile - const failable<list<value> > iv = profileUserInfo(cadr(cid), content(profres)); - if (!hasContent(iv)) - return mkfailure<int>(iv); + const failable<list<value> > userinfo = profileUserInfo(cadr(cid), content(profres)); + if (!hasContent(userinfo)) + return mkfailure<int>(userinfo); + + // Validate the authenticated user + const failable<int> authrc = authenticated(content(userinfo), true, r, scopeattrs, apcs); + if (!hasContent(authrc)) + return authrc; - // Store user info in memcached keyed by session ID + // Store user info in memcached keyed by a session ID const value sid = string("OAuth2_") + mkrand(); - const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth2", sid), content(iv), mc); + const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth2", sid), content(userinfo), mc); if (!hasContent(prc)) return mkfailure<int>(prc); - // Send session ID to the client in a cookie + // Send the session ID to the client in a cookie debug(c_str(openauth::cookie("TuscanyOAuth2", sid, httpd::hostName(r))), "modoauth2::access_token::setcookie"); apr_table_set(r->err_headers_out, "Set-Cookie", c_str(openauth::cookie("TuscanyOAuth2", sid, httpd::hostName(r)))); return httpd::externalRedirect(httpd::url(httpd::unescape(cadr(ref)), r), r); @@ -265,20 +319,19 @@ const failable<int> accessToken(const li * Check user authentication. */ static int checkAuthn(request_rec *r) { + gc_scoped_pool pool(r->pool); + // Decline if we're not enabled or AuthType is not set to Open const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth2); if (!dc.enabled) return DECLINED; const char* atype = ap_auth_type(r); - debug(atype, "modopenauth::checkAuthn::auth_type"); if (atype == NULL || strcasecmp(atype, "Open")) return DECLINED; - - // Create a scoped memory pool - gc_scoped_pool pool(r->pool); + debug_httpdRequest(r, "modoauth2::checkAuthn::input"); + debug(atype, "modopenauth::checkAuthn::auth_type"); // Get the server configuration - debug_httpdRequest(r, "modoauth2::checkAuthn::input"); const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth2); // Get session id from the request @@ -288,24 +341,33 @@ static int checkAuthn(request_rec *r) { if (substr(content(sid), 0, 7) != "OAuth2_") return DECLINED; - // If we're authenticated store the user info in the request - const failable<value> info = userInfo(content(sid), sc.mc); - if (hasContent(info)) { - r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(authenticated(dc.scopeattrs, content(info), r)); - } + // Extract the user info from the auth session + const failable<value> userinfo = userInfo(content(sid), sc.mc); + if (!hasContent(userinfo)) + return httpd::reportStatus(mkfailure<int>(userinfo)); + r->ap_auth_type = const_cast<char*>(atype); + return httpd::reportStatus(authenticated(content(userinfo), false, r, dc.scopeattrs, dc.apcs)); } + // Get the request args + const list<list<value> > args = httpd::queryArgs(r); + // Handle OAuth authorize request step if (string(r->uri) == "/oauth2/authorize/") { r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(authorize(httpd::queryArgs(r), r, sc.appkeys)); + return httpd::reportStatus(authorize(args, r, sc.appkeys)); } // Handle OAuth access_token request step if (string(r->uri) == "/oauth2/access_token/") { r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(accessToken(httpd::queryArgs(r), r, sc.appkeys, sc.cs, sc.mc)); + const failable<int> authrc = accessToken(args, r, sc.appkeys, sc.cs, dc.scopeattrs, dc.apcs, sc.mc); + + // Redirect to the login page if user is not authorized + if (!hasContent(authrc) && rcode(authrc) == HTTP_UNAUTHORIZED) + return httpd::reportStatus(openauth::login(dc.login, string("/"), 1, r)); + + return httpd::reportStatus(authrc); } // Redirect to the login page, unless we have a session id or an authorization @@ -316,10 +378,11 @@ static int checkAuthn(request_rec *r) { hasContent(openauth::sessionID(r, "TuscanyOpenAuth")) || hasContent(openauth::sessionID(r, "TuscanyOAuth1"))) return DECLINED; - if ((substr(string(r->uri), 0, 8) == "/oauth1/") || !isNil(assoc<value>("openid_identifier", httpd::queryArgs(r)))) + if ((substr(string(r->uri), 0, 8) == "/oauth1/") || !isNil(assoc<value>("openid_identifier", args))) return DECLINED; + r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(openauth::login(dc.login, r)); + return httpd::reportStatus(openauth::login(dc.login, value(), value(), r)); } /** @@ -344,6 +407,7 @@ int postConfigMerge(ServerConf& mainsc, int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, server_rec* s) { gc_scoped_pool pool(p); + ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_oauth2); debug(httpd::serverName(s), "modoauth2::postConfig::serverName"); @@ -360,7 +424,7 @@ public: } const gc_ptr<http::CURLSession> operator()() const { - return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, ""); + return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, "", 0); } private: @@ -374,6 +438,7 @@ private: */ void childInit(apr_pool_t* p, server_rec* s) { gc_scoped_pool pool(p); + ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_oauth2); if(psc == NULL) { cfailure << "[Tuscany] Due to one or more errors mod_tuscany_oauth2 loading failed. Causing apache to stop loading." << endl; @@ -445,11 +510,25 @@ const char* confScopeAttr(cmd_parms *cmd dc.scopeattrs = cons<list<value> >(mklist<value>(arg1, arg2), dc.scopeattrs); return NULL; } +const char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) { + gc_scoped_pool pool(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) + return apr_psprintf(cmd->pool, "Unknown Authn provider: %s", arg); + 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; +} /** * HTTP server module declaration. */ const command_rec commands[] = { + AP_INIT_ITERATE("AuthOAuthProvider", (const char*(*)())confAuthnProvider, NULL, OR_AUTHCFG, "Auth providers for a directory or location"), AP_INIT_TAKE3("AddAuthOAuth2AppKey", (const char*(*)())confAppKey, NULL, RSRC_CONF, "OAuth 2.0 name app-id app-key"), AP_INIT_ITERATE("AddAuthOAuthMemcached", (const char*(*)())confMemcached, NULL, RSRC_CONF, "Memcached server host:port"), AP_INIT_FLAG("AuthOAuth", (const char*(*)())confEnabled, NULL, OR_AUTHCFG, "OAuth 2.0 authentication On | Off"),
Modified: tuscany/sca-cpp/trunk/modules/oauth/oauth-conf URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/oauth/oauth-conf?rev=1361915&r1=1361914&r2=1361915&view=diff ============================================================================== --- tuscany/sca-cpp/trunk/modules/oauth/oauth-conf (original) +++ tuscany/sca-cpp/trunk/modules/oauth/oauth-conf Mon Jul 16 06:47:49 2012 @@ -39,18 +39,23 @@ else sslsuffix="-ssl" fi +if [ "$2" = "" ]; then + providers="file" +else + providers="$2 file" +fi + # Configure HTTPD mod_tuscany_oauth module cat >>$root/conf/modules.conf <<EOF # Generated by: oauth-conf $* # Load support for OAuth authentication -LoadModule mod_tuscany_oauth1 $here/libmod_tuscany_oauth1$libsuffix LoadModule mod_tuscany_oauth2 $here/libmod_tuscany_oauth2$libsuffix EOF # Disallow public access to server resources cat >$root/conf/noauth$sslsuffix.conf <<EOF -# Generated by: oauth-auth-conf $* +# Generated by: oauth-conf $* # Disallow public access to server resources EOF @@ -62,9 +67,12 @@ cat >>$root/conf/locauth$sslsuffix.conf <Location /> AuthType Open AuthName "$host" +AuthOAuthProvider socache $providers +AuthnCacheProvideFor $providers +AuthnCacheContext / Require valid-user AuthOAuth On -AuthOAuthLoginPage /login +AuthOAuthLoginPage /login/ AddAuthOAuth2ScopeAttr REALM realm AddAuthOAuth2ScopeAttr REMOTE_USER email AddAuthOAuth2ScopeAttr EMAIL email @@ -72,13 +80,7 @@ AddAuthOAuth2ScopeAttr NICKNAME name AddAuthOAuth2ScopeAttr FULLNAME name AddAuthOAuth2ScopeAttr FIRSTNAME first_name AddAuthOAuth2ScopeAttr LASTNAME last_name -AddAuthOAuth1ScopeAttr REALM realm -AddAuthOAuth1ScopeAttr REMOTE_USER email -AddAuthOAuth1ScopeAttr EMAIL email -AddAuthOAuth1ScopeAttr NICKNAME screen_name AddAuthOAuth2ScopeAttr FULLNAME name -AddAuthOAuth1ScopeAttr FIRSTNAME first-name -AddAuthOAuth1ScopeAttr LASTNAME last-name </Location> EOF Copied: tuscany/sca-cpp/trunk/modules/oauth/oauth12-conf (from r1361914, tuscany/sca-cpp/trunk/modules/oauth/oauth-conf) URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/oauth/oauth12-conf?p2=tuscany/sca-cpp/trunk/modules/oauth/oauth12-conf&p1=tuscany/sca-cpp/trunk/modules/oauth/oauth-conf&r1=1361914&r2=1361915&rev=1361915&view=diff ============================================================================== --- tuscany/sca-cpp/trunk/modules/oauth/oauth-conf (original) +++ tuscany/sca-cpp/trunk/modules/oauth/oauth12-conf Mon Jul 16 06:47:49 2012 @@ -39,9 +39,15 @@ else sslsuffix="-ssl" fi +if [ "$2" = "" ]; then + providers="file" +else + providers="$2 file" +fi + # Configure HTTPD mod_tuscany_oauth module cat >>$root/conf/modules.conf <<EOF -# Generated by: oauth-conf $* +# Generated by: oauth12-conf $* # Load support for OAuth authentication LoadModule mod_tuscany_oauth1 $here/libmod_tuscany_oauth1$libsuffix LoadModule mod_tuscany_oauth2 $here/libmod_tuscany_oauth2$libsuffix @@ -50,21 +56,24 @@ EOF # Disallow public access to server resources cat >$root/conf/noauth$sslsuffix.conf <<EOF -# Generated by: oauth-auth-conf $* +# Generated by: oauth12-conf $* # Disallow public access to server resources EOF # Configure OAuth authentication cat >>$root/conf/locauth$sslsuffix.conf <<EOF -# Generated by: oauth-conf $* +# Generated by: oauth12-conf $* # Enable OAuth authentication <Location /> AuthType Open AuthName "$host" +AuthOAuthProvider socache $providers +AuthnCacheProvideFor $providers +AuthnCacheContext / Require valid-user AuthOAuth On -AuthOAuthLoginPage /login +AuthOAuthLoginPage /login/ AddAuthOAuth2ScopeAttr REALM realm AddAuthOAuth2ScopeAttr REMOTE_USER email AddAuthOAuth2ScopeAttr EMAIL email @@ -91,7 +100,7 @@ EOF mkdir -p $root/cert cat >$root/cert/oauth-keys.conf <<EOF -# Generated by: oauth-conf $* +# Generated by: oauth12-conf $* # OAuth App keys EOF Modified: tuscany/sca-cpp/trunk/modules/oauth/start-mixed-test URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/oauth/start-mixed-test?rev=1361915&r1=1361914&r2=1361915&view=diff ============================================================================== --- tuscany/sca-cpp/trunk/modules/oauth/start-mixed-test (original) +++ tuscany/sca-cpp/trunk/modules/oauth/start-mixed-test Mon Jul 16 06:47:49 2012 @@ -38,7 +38,7 @@ rm -rf tmp ../openid/openid-memcached-conf tmp www.example.com 11212 ../openid/openid-memcached-conf tmp www.example.com 11213 -./oauth-conf tmp +./oauth12-conf tmp ./oauth-memcached-conf tmp www.example.com 11212 ./oauth-memcached-conf tmp www.example.com 11213 @@ -48,13 +48,16 @@ rm -rf tmp ./oauth2-appkey-conf tmp facebook.com app1234 secret6789 ./oauth2-appkey-conf tmp github.com app5678 secret8901 -../http/open-auth-conf tmp -../http/passwd-auth-conf tmp foo foo +../../modules/http/open-auth-conf tmp -# For this test to work you need to add your form, oauth and open id ids -# to the authorized user group +# For this test to work you need to add your oauth and openid user ids to +# the password file with a dummy 'password' password, and to the group +# of authorized users +../../modules/http/passwd-auth-conf tmp foo foo ../../modules/http/group-auth-conf tmp foo +../../modules/http/passwd-auth-conf tmp /openid/123456 password ../../modules/http/group-auth-conf tmp 123456 +../../modules/http/passwd-auth-conf tmp /oauth2/[email protected] password ../../modules/http/group-auth-conf tmp [email protected] ../../modules/server/server-conf tmp Modified: tuscany/sca-cpp/trunk/modules/oauth/start-test URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/oauth/start-test?rev=1361915&r1=1361914&r2=1361915&view=diff ============================================================================== --- tuscany/sca-cpp/trunk/modules/oauth/start-test (original) +++ tuscany/sca-cpp/trunk/modules/oauth/start-test Mon Jul 16 06:47:49 2012 @@ -33,7 +33,7 @@ rm -rf tmp ../../modules/http/httpd-conf tmp www.example.com 8090 htdocs ../../modules/http/httpd-ssl-conf tmp 8453 -./oauth-conf tmp +./oauth12-conf tmp ./oauth-memcached-conf tmp www.example.com 11212 ./oauth-memcached-conf tmp www.example.com 11213 @@ -44,7 +44,9 @@ rm -rf tmp ./oauth2-appkey-conf tmp github.com app5678 secret8901 # For this test to work you need to add your oauth user id to the -# authorized user group +# password file with a dummy 'password' password, and to the group +# of authorized users +../../modules/http/passwd-auth-conf tmp /oauth2/[email protected] password ../../modules/http/group-auth-conf tmp [email protected] ../../modules/server/server-conf tmp Modified: tuscany/sca-cpp/trunk/modules/openid/openid-conf URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/openid/openid-conf?rev=1361915&r1=1361914&r2=1361915&view=diff ============================================================================== --- tuscany/sca-cpp/trunk/modules/openid/openid-conf (original) +++ tuscany/sca-cpp/trunk/modules/openid/openid-conf Mon Jul 16 06:47:49 2012 @@ -33,6 +33,12 @@ else sslsuffix="-ssl" fi +if [ "$2" = "" ]; then + providers="file" +else + providers="$2" +fi + # Configure HTTPD mod_auth_openid module cat >>$root/conf/modules.conf <<EOF # Generated by: openid-conf $* @@ -55,6 +61,9 @@ cat >>$root/conf/locauth$sslsuffix.conf <Location /> AuthType Open AuthName "$host" +#AuthOpenIDProvider socache $providers +#AuthnCacheProvideFor $providers +#AuthnCacheContext / Require valid-user AuthOpenIDEnabled On AuthOpenIDCookiePath / Modified: tuscany/sca-cpp/trunk/modules/openid/start-test URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/openid/start-test?rev=1361915&r1=1361914&r2=1361915&view=diff ============================================================================== --- tuscany/sca-cpp/trunk/modules/openid/start-test (original) +++ tuscany/sca-cpp/trunk/modules/openid/start-test Mon Jul 16 06:47:49 2012 @@ -32,8 +32,10 @@ rm -rf tmp ./openid-memcached-conf tmp localhost 11213 ./openid-step2-conf tmp -# For this test to work you need to add your openid (or email address if -# available from your openid attributes to the the authorized user group +# For this test to work you need to add your openid user id to the +# password file with a dummy 'password' password, and to the group +# of authorized users +../../modules/http/passwd-auth-conf tmp /openid/[email protected] password ../../modules/http/group-auth-conf tmp [email protected] ../../modules/server/server-conf tmp Modified: tuscany/sca-cpp/trunk/modules/server/mod-eval.hpp URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/server/mod-eval.hpp?rev=1361915&r1=1361914&r2=1361915&view=diff ============================================================================== --- tuscany/sca-cpp/trunk/modules/server/mod-eval.hpp (original) +++ tuscany/sca-cpp/trunk/modules/server/mod-eval.hpp Mon Jul 16 06:47:49 2012 @@ -43,6 +43,10 @@ #include "../http/http.hpp" #include "../http/httpd.hpp" +#include "apr_md5.h" +#include "ap_provider.h" +#include "mod_auth.h" + extern "C" { extern module AP_MODULE_DECLARE_DATA mod_tuscany_eval; } @@ -75,8 +79,10 @@ public: string domain; string contribPath; string composName; - string providerName; - value provider; + string contributorName; + value contributor; + string authenticatorName; + value authenticator; }; /** @@ -115,7 +121,7 @@ public: ServerConf() { } - ServerConf(apr_pool_t* p, const server_rec* s) : p(p), server(s) { + ServerConf(apr_pool_t* p, const server_rec* s) : p(p), server(s), timeout(0) { } const gc_pool p; @@ -123,6 +129,7 @@ public: lambda<value(const list<value>&)> lifecycle; ContribConf contribc; SSLConf sslc; + int timeout; VhostConf vhostc; Composite compos; }; @@ -145,7 +152,12 @@ public: }; /** - * Convert a result represented as a content + failure pair to a + * Authentication cache store function. + */ +static APR_OPTIONAL_FN_TYPE(ap_authn_cache_store) *authnCacheStore = NULL; + +/** + * Convert a result represented as a (content reason? code?) tuple to a * failable monad. */ const failable<value> failableResult(const list<value>& v) { @@ -177,9 +189,9 @@ public: /** * Make an HTTP proxy lambda to an absolute URI */ -const value mkhttpProxy(const string& uri, const gc_pool& p) { +const value mkhttpProxy(const string& uri, const int timeout, const gc_pool& p) { debug(uri, "modeval::mkhttpProxy::uri"); - return lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", p)); + return lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", timeout, p)); } /** @@ -187,7 +199,7 @@ const value mkhttpProxy(const string& ur */ class implProxy { public: - implProxy(const value& name, const list<value>& impls, const SSLConf& sslc) : name(name), impls(impls), sslc(sslc) { + implProxy(const value& name, const list<value>& impls, const SSLConf& sslc, const int timeout) : name(name), impls(impls), sslc(sslc), timeout(timeout) { } const value callImpl(const value& cname, const list<value>& aparams) const { @@ -229,7 +241,7 @@ public: ostringstream appuri; appuri << httpd::scheme(currentRequest) << "://" << substr(uri, 6) << "." << http::topDomain(httpd::hostName(currentRequest)) << ":" << httpd::port(currentRequest) << "/"; debug(str(appuri), "modeval::implProxy::httpproxy::appuri"); - const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(str(appuri), sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), p)); + const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(str(appuri), sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), timeout, p)); return px(aparams); } @@ -237,13 +249,13 @@ public: // only if the target is in the same top level domain if (http::topDomain(http::hostName(uri, p)) == http::topDomain(httpd::hostName(currentRequest))) { debug(uri, "modeval::implProxy::httpproxy::samedomain"); - const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), p)); + const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), timeout, p)); return px(aparams); } // No SSL certificate or cookie on a cross domain call debug(uri, "modeval::implProxy::httpproxy::crossdomain"); - const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", p)); + const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", timeout, p)); return px(aparams); } @@ -259,11 +271,12 @@ private: const value name; const list<value>& impls; const SSLConf& sslc; + const int timeout; }; -const value mkimplProxy(const value& name, const list<value>& impls, const SSLConf& sslc) { +const value mkimplProxy(const value& name, const list<value>& impls, const SSLConf& sslc, const int timeout) { debug(name, "modeval::implProxy::impl"); - return lambda<value(const list<value>&)>(implProxy(name, impls, sslc)); + return lambda<value(const list<value>&)>(implProxy(name, impls, sslc, timeout)); } /** @@ -303,7 +316,7 @@ const value mkunwiredProxy(const string& /** * Convert a list of component references to a list of proxy lambdas. */ -const value mkrefProxy(const value& ref, const list<value>& impls, const SSLConf& sslc, const gc_pool& p) { +const value mkrefProxy(const value& ref, const list<value>& impls, const SSLConf& sslc, const int timeout, const gc_pool& p) { const value target = scdl::target(ref); const bool wbyimpl = scdl::wiredByImpl(ref); debug(ref, "modeval::mkrefProxy::ref"); @@ -312,18 +325,18 @@ const value mkrefProxy(const value& ref, // Use an HTTP proxy or an internal proxy to the component implementation if (wbyimpl) - return mkimplProxy(value(), impls, sslc); + return mkimplProxy(value(), impls, sslc, timeout); if (isNil(target)) return mkunwiredProxy(scdl::name(ref)); if (http::isAbsolute(target)) - return mkhttpProxy(target, p); - return mkimplProxy(car(pathValues(target)), impls, sslc); + return mkhttpProxy(target, timeout, p); + return mkimplProxy(car(pathValues(target)), impls, sslc, timeout); } -const list<value> refProxies(const list<value>& refs, const list<value>& impls, const SSLConf& sslc, const gc_pool& p) { +const list<value> refProxies(const list<value>& refs, const list<value>& impls, const SSLConf& sslc, const int timeout, const gc_pool& p) { if (isNil(refs)) return refs; - return cons(mkrefProxy(car(refs), impls, sslc, p), refProxies(cdr(refs), impls, sslc, p)); + return cons(mkrefProxy(car(refs), impls, sslc, timeout, p), refProxies(cdr(refs), impls, sslc, timeout, p)); } /** @@ -422,15 +435,29 @@ struct realmPropProxy { const char* env = apr_table_get(currentRequest->subprocess_env, "REALM"); if (env == NULL) return v; - const char* realm = strncmp(env, "www.", 4) == 0? env + 4 : env; - if (*realm == '\0') + const string realm = httpd::realm(string(env)); + if (length(realm) == 0) return v; - const value r = string(realm); + const value r = realm; debug(r, "modeval::realmPropProxy::value"); return r; } }; +struct timeoutPropProxy { + const value v; + timeoutPropProxy(const value& v) : v(atoi(c_str((string)v))) { + } + const value operator()(unused const list<value>& params) const { + if (currentRequest == NULL) + return v; + const ServerConf& sc = httpd::serverConf<ServerConf>(currentRequest, &mod_tuscany_eval); + const value r = sc.timeout; + debug(r, "modeval::timeoutPropProxy::value"); + return r; + } +}; + struct userPropProxy { const value v; userPropProxy(const value& v) : v(v) { @@ -461,6 +488,8 @@ const value mkpropProxy(const value& pro return lambda<value(const list<value>&)>(userPropProxy(v)); if (n == "realm") return lambda<value(const list<value>&)>(realmPropProxy(v)); + if (n == "timeout") + return lambda<value(const list<value>&)>(timeoutPropProxy(v)); if (n == "email") return lambda<value(const list<value>&)>(envPropProxy("EMAIL", v)); if (n == "nickname") @@ -499,7 +528,7 @@ struct implementationFailure { } }; -const value evalComponent(const string& contribPath, const value& comp, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const gc_pool& p) { +const value evalComponent(const string& contribPath, const value& comp, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const int timeout, const gc_pool& p) { extern const failable<lambda<value(const list<value>&)> > evalImplementation(const string& cpath, const value& impl, const list<value>& px, const lambda<value(const list<value>&)>& lifecycle); const value impl = scdl::implementation(comp); @@ -507,7 +536,7 @@ const value evalComponent(const string& debug(impl, "modeval::evalComponent::impl"); // Convert component references to configured proxy lambdas - const list<value> rpx(refProxies(scdl::references(comp), impls, sslc, p)); + const list<value> rpx(refProxies(scdl::references(comp), impls, sslc, timeout, p)); // Convert component properties to configured proxy lambdas const list<value> ppx(propProxies(scdl::properties(comp))); @@ -522,12 +551,12 @@ const value evalComponent(const string& /** * Return a list of component-name + configured-implementation pairs. */ -const list<value> componentToImplementationAssoc(const list<value>& c, const string& contribPath, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const gc_pool& p) { +const list<value> componentToImplementationAssoc(const list<value>& c, const string& contribPath, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const int timeout, const gc_pool& p) { if (isNil(c)) return c; return cons<value>(mklist<value>(scdl::name(car(c)), - evalComponent(contribPath, car(c), impls, lifecycle, sslc, p)), - componentToImplementationAssoc(cdr(c), contribPath, impls, lifecycle, sslc, p)); + evalComponent(contribPath, car(c), impls, lifecycle, sslc, timeout, p)), + componentToImplementationAssoc(cdr(c), contribPath, impls, lifecycle, sslc, timeout, p)); } /** @@ -541,16 +570,17 @@ const failable<list<value> > readCompone } /** - * Get the components returned by a provider. + * Get the components returned by a contributor. */ -const failable<list<value> > getComponents(const lambda<value(const list<value>&)>& provider, const string& name) { - const failable<value> val = failableResult(provider(cons<value>("get", mklist<value>(mklist<value>(name))))); +const failable<list<value> > getComponents(const lambda<value(const list<value>&)>& contributor, const string& name) { + const failable<value> val = failableResult(contributor(cons<value>("get", mklist<value>(mklist<value>(name))))); if (!hasContent(val)) return mkfailure<list<value> >(val); - const list<value> c = assoc<value>(value("content"), (list<list<value> >)cdr<value>(content(val))); + const list<value> c = assoc<value>(value("composite"), assoc<value>(value("content"), (list<list<value> >)cdr<value>(car<value>(content(val))))); + debug(c, "modeval::getComponents::comp"); if (isNil(c)) return mkfailure<list<value> >(string("Could not get composite: ") + name); - const failable<list<string> > x = writeXML(car<value>(valuesToElements(mklist<value>(mklist<value>(cadr(c)))))); + const failable<list<string> > x = writeXML(car<value>(valuesToElements(mklist<value>(mklist<value>(c))))); if (!hasContent(x)) return mkfailure<list<value> >(x); return scdl::components(readXML(content(x))); @@ -631,16 +661,16 @@ const list<value> uriToComponentAssoc(co /** * Configure the components declared in the deployed composite. */ -const failable<Composite> confComponents(const string& contribPath, const string& composName, const value& provider, const string& vhost, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const gc_pool& p) { +const failable<Composite> confComponents(const string& contribPath, const string& composName, const value& contributor, const string& vhost, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const int timeout, const gc_pool& p) { debug(contribPath, "modeval::confComponents::contribPath"); debug(composName, "modeval::confComponents::composName"); - debug(provider, "modeval::confComponents::provider"); + debug(contributor, "modeval::confComponents::contributor"); debug(vhost, "modeval::confComponents::vhost"); debug(impls, "modeval::confComponents::impls"); - const failable<list<value> > fcomps = isNil(provider)? + const failable<list<value> > fcomps = isNil(contributor)? readComponents(scdl::resourcePath(length(vhost) != 0? contribPath + vhost + "/" : contribPath, composName)) : - getComponents(provider, vhost); + getComponents(contributor, vhost); if (!hasContent(fcomps)) return mkfailure<Composite>(fcomps); @@ -654,8 +684,8 @@ const failable<Composite> confComponents debug(flatten(svcs), "modeval::confComponents::svcs"); const list<value> cimpls = mkbtree(sort(componentToImplementationAssoc(comps, - isNil(provider)? length(vhost) != 0? contribPath + vhost + "/" : contribPath : contribPath, - impls, lifecycle, sslc, p))); + isNil(contributor)? length(vhost) != 0? contribPath + vhost + "/" : contribPath : contribPath, + impls, lifecycle, sslc, timeout, p))); debug(flatten(cimpls), "modeval::confComponents::impls"); return Composite(refs, svcs, cimpls); @@ -720,6 +750,10 @@ const failable<int> get(const list<value const value c = content(val); debug(c, "modeval::get::content"); + // Return a nil value as a not found status + if (!isList(c) && isNil(c)) + return HTTP_NOT_FOUND; + // Check if the client requested a specific format const list<value> fmt = assoc<value>("format", args); @@ -735,6 +769,7 @@ const failable<int> get(const list<value debug(lc, "modeval::get::symbol"); return httpd::writeResult(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8", r); } + const list<value> lc = mklist<value>(mklist<value>("value", c)); debug(lc, "modeval::get::value"); return httpd::writeResult(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8", r); @@ -1041,9 +1076,9 @@ const int translateRequest(request_rec* // Attempt to map a request targeting the main host to an actual file if (isNil(vpath)) { - const failable<request_rec*, int> fnr = httpd::internalSubRequest(r->uri, r); + const failable<request_rec*> fnr = httpd::internalSubRequest(r->uri, r); if (!hasContent(fnr)) - return HTTP_INTERNAL_SERVER_ERROR; + return rcode(fnr); request_rec* nr = content(fnr); nr->uri = r->filename; const int tr = ap_core_translate(nr); @@ -1082,7 +1117,6 @@ int translate(request_rec *r) { if(r->method_number != M_GET && r->method_number != M_POST && r->method_number != M_PUT && r->method_number != M_DELETE) return DECLINED; - // Create a scoped memory pool gc_scoped_pool pool(r->pool); debug_httpdRequest(r, "modeval::translate::input"); @@ -1103,9 +1137,9 @@ int translate(request_rec *r) { // If the request is targeting a virtual host, configure the components // in that virtual host - if (length(sc.vhostc.domain) != 0 && (length(sc.vhostc.contribPath) != 0 || !isNil(sc.vhostc.provider)) && httpd::isVhostRequest(sc.server, sc.vhostc.domain, r)) { + if (length(sc.vhostc.domain) != 0 && (length(sc.vhostc.contribPath) != 0 || !isNil(sc.vhostc.contributor)) && httpd::isVhostRequest(sc.server, sc.vhostc.domain, r)) { const string vname = http::subDomain(httpd::hostName(r)); - const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.provider, vname, reqc.impls, sc.lifecycle, sc.sslc, sc.p); + const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.contributor, vname, reqc.impls, sc.lifecycle, sc.sslc, sc.timeout, sc.p); if (!hasContent(fvcompos)) return DECLINED; const Composite vcompos = content(fvcompos); @@ -1124,9 +1158,9 @@ int translate(request_rec *r) { return rc; // Attempt to map the first segment of the request path to a virtual host - if (length(prefix) != 0 && (length(sc.vhostc.contribPath) != 0 || !isNil(sc.vhostc.provider))) { + if (length(prefix) != 0 && (length(sc.vhostc.contribPath) != 0 || !isNil(sc.vhostc.contributor))) { const string vname = prefix; - const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.provider, vname, reqc.impls, sc.lifecycle, sc.sslc, sc.p); + const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.contributor, vname, reqc.impls, sc.lifecycle, sc.sslc, sc.timeout, sc.p); if (!hasContent(fvcompos)) return DECLINED; const Composite vcompos = content(fvcompos); @@ -1150,9 +1184,9 @@ const int handleRequest(const list<value mkfailure<int>(string("Couldn't find component implementation: ") + cadr(rpath)); return HTTP_NOT_FOUND; } + const lambda<value(const list<value>&)> l(cadr<value>(impl)); // Handle HTTP method - const lambda<value(const list<value>&)> l(cadr<value>(impl)); if (r->header_only) return OK; if(r->method_number == M_GET) @@ -1182,7 +1216,7 @@ int handler(request_rec *r) { if(strcmp(r->handler, "mod_tuscany_eval")) return DECLINED; - // Create a scoped memory pool and a scope for the current request + // Create a scope for the current request gc_scoped_pool pool(r->pool); ScopedRequest sr(r); @@ -1228,6 +1262,61 @@ 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) { + gc_scoped_pool pool(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") { + mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED); + return AUTH_DENIED; + } + + // Get the server configuration + const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_eval); + if (isNil(sc.vhostc.authenticator)) { + mkfailure<int>("SCA authenticator not configured"); + return AUTH_GENERAL_ERROR; + } + + // Retrieve the user's password hash + const list<value> uid = pathValues(user); + const failable<value> val = failableResult(sc.vhostc.authenticator(cons<value>("get", mklist<value>(uid)))); + if (!hasContent(val)) { + mkfailure<int>(string("SCA authentication check user failed, user not found: ") + user); + return AUTH_USER_NOT_FOUND; + } + const value hval = content(val); + const list<value> hcontent = isList(hval) && !isNil(hval) && isList(car<value>(hval)) && !isNil(car<value>(hval))? assoc<value>(value("content"), cdr<value>(car<value>(hval))) : list<value>(); + const list<value> hassoc = isNil(hcontent)? list<value>() : assoc<value>(value("hash"), cdr<value>(hcontent)); + if (isNil(hassoc)) { + mkfailure<int>(string("SCA authentication check user failed, hash not found: ") + user); + return AUTH_USER_NOT_FOUND; + } + const string hash = cadr<value>(hassoc); + if (length(hash) == 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)); + + // Validate the presented 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; + } + return AUTH_GRANTED; +} + +/** * Cleanup callback, called when the server is stopped or restarted. */ apr_status_t serverCleanup(void* v) { @@ -1262,6 +1351,7 @@ const int postConfigMerge(const ServerCo if (sc.sslc.ca == "") sc.sslc.ca = mainsc.sslc.ca; if (sc.sslc.cert == "") sc.sslc.cert = mainsc.sslc.cert; if (sc.sslc.key == "") sc.sslc.key = mainsc.sslc.key; + sc.timeout = mainsc.timeout; sc.compos = mainsc.compos; return postConfigMerge(mainsc, s->next); } @@ -1311,7 +1401,7 @@ int postConfig(apr_pool_t *p, unused apr } // Configure the deployed components - const failable<Composite> compos = confComponents(sc.contribc.contribPath, sc.contribc.composName, value(), "", sc.compos.impls, sc.lifecycle, sc.sslc, sc.p); + const failable<Composite> compos = confComponents(sc.contribc.contribPath, sc.contribc.composName, value(), "", sc.compos.impls, sc.lifecycle, sc.sslc, sc.timeout, sc.p); if (!hasContent(compos)) { cfailure << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl; return -1; @@ -1326,28 +1416,49 @@ int postConfig(apr_pool_t *p, unused apr } /** + * Exit after a failure. + */ +void failureExitChild() { + cfailure << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl; + exit(APEXIT_CHILDFATAL); +} + +/** * Child process initialization. */ void childInit(apr_pool_t* p, server_rec* s) { gc_scoped_pool pool(p); + ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_eval); - if(psc == NULL) { - cfailure << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl; - exit(APEXIT_CHILDFATAL); - } + if(psc == NULL) + failureExitChild(); ServerConf& sc = *psc; // Start the components in the child process const failable<list<value> > fsimpls = startComponents(sc.compos.impls); - if (!hasContent(fsimpls)) { - cfailure << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl; - exit(APEXIT_CHILDFATAL); - } + if (!hasContent(fsimpls)) + failureExitChild(); sc.compos.impls = content(fsimpls); - // Create a proxy for the vhost provider if needed - if (length(sc.vhostc.providerName) != 0) - sc.vhostc.provider = mkimplProxy(sc.vhostc.providerName, sc.compos.impls, sc.sslc); + // Get the vhost contributor component implementation lambda + if (length(sc.vhostc.contributorName) != 0) { + const list<value> impl(assoctree<value>(sc.vhostc.contributorName, sc.compos.impls)); + if (isNil(impl)) { + mkfailure<int>(string("Couldn't find contributor component implementation: ") + sc.vhostc.contributorName); + failureExitChild(); + } + sc.vhostc.contributor = cadr<value>(impl); + } + + // Get the vhost authenticator component implementation lambda + if (length(sc.vhostc.authenticatorName) != 0) { + const list<value> impl(assoctree<value>(sc.vhostc.authenticatorName, sc.compos.impls)); + if (isNil(impl)) { + mkfailure<int>(string("Couldn't find authenticator component implementation: ") + sc.vhostc.authenticatorName); + failureExitChild(); + } + sc.vhostc.authenticator = cadr<value>(impl); + } // Merge the updated configuration into the virtual hosts postConfigMerge(sc, s->next); @@ -1383,10 +1494,10 @@ const char* confVirtualContribution(cmd_ sc.vhostc.contribPath = arg; return NULL; } -const char* confVirtualprovider(cmd_parms *cmd, unused void *c, const char *arg) { +const char* confVirtualContributor(cmd_parms *cmd, unused void *c, const char *arg) { gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); - sc.vhostc.providerName = arg; + sc.vhostc.contributorName = arg; return NULL; } const char* confVirtualComposite(cmd_parms *cmd, unused void *c, const char *arg) { @@ -1395,6 +1506,12 @@ const char* confVirtualComposite(cmd_par sc.vhostc.composName = arg; return NULL; } +const char* confAuthenticator(cmd_parms *cmd, unused void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); + ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); + sc.vhostc.authenticatorName = arg; + return NULL; +} const char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) { gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); @@ -1413,6 +1530,12 @@ const char* confCertKeyFile(cmd_parms *c sc.sslc.key = arg; return NULL; } +const char* confTimeout(cmd_parms *cmd, unused void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); + ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); + sc.timeout = atoi(arg); + return NULL; +} const char* confEnv(unused cmd_parms *cmd, unused void *c, const char *name, const char *value) { gc_scoped_pool pool(cmd->pool); setenv(name, value != NULL? value : "", 1); @@ -1427,20 +1550,33 @@ const command_rec commands[] = { AP_INIT_TAKE1("SCAComposite", (const char*(*)())confComposite, NULL, RSRC_CONF, "SCA composite location"), AP_INIT_TAKE1("SCAVirtualDomain", (const char*(*)())confVirtualDomain, NULL, RSRC_CONF, "SCA virtual host domain"), AP_INIT_TAKE1("SCAVirtualContribution", (const char*(*)())confVirtualContribution, NULL, RSRC_CONF, "SCA virtual host contribution path"), - AP_INIT_TAKE1("SCAVirtualContributor", (const char*(*)())confVirtualprovider, NULL, RSRC_CONF, "SCA virtual host provider component"), + AP_INIT_TAKE1("SCAVirtualContributor", (const char*(*)())confVirtualContributor, NULL, RSRC_CONF, "SCA virtual host contributor component"), AP_INIT_TAKE1("SCAVirtualComposite", (const char*(*)())confVirtualComposite, NULL, RSRC_CONF, "SCA virtual composite location"), + AP_INIT_TAKE1("SCAAuthenticator", (const char*(*)())confAuthenticator, NULL, RSRC_CONF, "SCA authenticator component"), AP_INIT_TAKE12("SCASetEnv", (const char*(*)())confEnv, NULL, OR_FILEINFO, "Environment variable name and optional value"), AP_INIT_TAKE1("SCAWiringSSLCACertificateFile", (const char*(*)())confCAFile, NULL, RSRC_CONF, "SCA wiring SSL CA certificate file"), AP_INIT_TAKE1("SCAWiringSSLCertificateFile", (const char*(*)())confCertFile, NULL, RSRC_CONF, "SCA wiring SSL certificate file"), AP_INIT_TAKE1("SCAWiringSSLCertificateKeyFile", (const char*(*)())confCertKeyFile, NULL, RSRC_CONF, "SCA wiring SSL certificate key file"), + AP_INIT_TAKE1("SCAWiringTimeout", (const char*(*)())confTimeout, NULL, RSRC_CONF, "SCA wiring timeout"), {NULL, NULL, NULL, 0, NO_ARGS, NULL} }; +const authn_provider AuthnProvider = { + &checkPassword, + NULL +}; + +void retrieveAuthnCacheStore() { + authnCacheStore = APR_RETRIEVE_OPTIONAL_FN(ap_authn_cache_store); +} + void registerHooks(unused apr_pool_t *p) { ap_hook_post_config(postConfig, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_child_init(childInit, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_handler(handler, NULL, NULL, APR_HOOK_MIDDLE); + ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "component", AUTHN_PROVIDER_VERSION, &AuthnProvider, AP_AUTH_INTERNAL_PER_CONF); + ap_hook_optional_fn_retrieve(retrieveAuthnCacheStore, NULL, NULL, APR_HOOK_MIDDLE); } } Modified: tuscany/sca-cpp/trunk/samples/store-cluster/tunnel-ssl-conf URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/samples/store-cluster/tunnel-ssl-conf?rev=1361915&r1=1361914&r2=1361915&view=diff ============================================================================== --- tuscany/sca-cpp/trunk/samples/store-cluster/tunnel-ssl-conf (original) +++ tuscany/sca-cpp/trunk/samples/store-cluster/tunnel-ssl-conf Mon Jul 16 06:47:49 2012 @@ -28,5 +28,6 @@ set -x ../../modules/http/httpd-event-conf $root tar -C tmp/ssl -c `../../modules/http/ssl-cert-find tmp/ssl` | tar -C $root -x ../../modules/http/httpd-ssl-conf $root $sslport +../../modules/http/httpd-tunnel-ssl-conf $root ../../modules/http/cert-auth-conf $root
