diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-11-13 07:53:10 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-11-13 07:53:10 +0000 |
commit | 3ac22b097d9a9e829ec45963a7c3a40dd12b40a1 (patch) | |
tree | ae26d54d061b8f61a1ee2513aa913e8a5e3a1277 /sca-cpp/trunk/modules | |
parent | 1b5f778e514d74d86eee83932b9d5948d7e6e316 (diff) |
Port to HTTPD 2.3.8. Add an auth module to make OpenID, OAuth 1/2 and HTTPD 2.3 Form auth modules play nice together.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1034693 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp/trunk/modules')
30 files changed, 771 insertions, 231 deletions
diff --git a/sca-cpp/trunk/modules/http/Makefile.am b/sca-cpp/trunk/modules/http/Makefile.am index 209c7358b7..08d7e1b49a 100644 --- a/sca-cpp/trunk/modules/http/Makefile.am +++ b/sca-cpp/trunk/modules/http/Makefile.am @@ -20,7 +20,7 @@ INCLUDES = -I${HTTPD_INCLUDE} incl_HEADERS = *.hpp incldir = $(prefix)/include/modules/http -dist_mod_SCRIPTS = httpd-conf httpd-addr httpd-start httpd-stop httpd-restart ssl-ca-conf ssl-cert-conf ssl-cert-find httpd-ssl-conf httpd-auth-conf proxy-conf proxy-ssl-conf proxy-member-conf proxy-ssl-member-conf vhost-conf vhost-ssl-conf tunnel-ssl-conf +dist_mod_SCRIPTS = httpd-conf httpd-addr httpd-start httpd-stop httpd-restart ssl-ca-conf ssl-cert-conf ssl-cert-find httpd-ssl-conf basic-auth-conf form-auth-conf open-auth-conf proxy-conf proxy-ssl-conf proxy-member-conf proxy-ssl-member-conf vhost-conf vhost-ssl-conf tunnel-ssl-conf moddir=$(prefix)/modules/http curl_test_SOURCES = curl-test.cpp @@ -32,18 +32,23 @@ curl_get_LDFLAGS = -lxml2 -lcurl -lmozjs curl_connect_SOURCES = curl-connect.cpp curl_connect_LDFLAGS = -lxml2 -lcurl -lmozjs -mod_LTLIBRARIES = libmod_tuscany_ssltunnel.la -noinst_DATA = libmod_tuscany_ssltunnel.so +mod_LTLIBRARIES = libmod_tuscany_ssltunnel.la libmod_tuscany_openauth.la +noinst_DATA = libmod_tuscany_ssltunnel.so libmod_tuscany_openauth.so libmod_tuscany_ssltunnel_la_SOURCES = mod-ssltunnel.cpp libmod_tuscany_ssltunnel_la_LDFLAGS = -lxml2 -lcurl -lmozjs libmod_tuscany_ssltunnel.so: ln -s .libs/libmod_tuscany_ssltunnel.so +libmod_tuscany_openauth_la_SOURCES = mod-openauth.cpp +libmod_tuscany_openauth_la_LDFLAGS = -lxml2 -lcurl -lmozjs +libmod_tuscany_openauth.so: + ln -s .libs/libmod_tuscany_openauth.so + mod_DATA = httpd.prefix httpd-apachectl.prefix httpd-modules.prefix curl.prefix nobase_dist_mod_DATA = conf/* -EXTRA_DIST = htdocs/index.html +EXTRA_DIST = htdocs/index.html htdocs/login/index.html htdocs/logout/index.html httpd.prefix: $(top_builddir)/config.status echo ${HTTPD_PREFIX} >httpd.prefix diff --git a/sca-cpp/trunk/modules/http/httpd-auth-conf b/sca-cpp/trunk/modules/http/basic-auth-conf index be117c008f..74f4a61959 100755 --- a/sca-cpp/trunk/modules/http/httpd-auth-conf +++ b/sca-cpp/trunk/modules/http/basic-auth-conf @@ -17,7 +17,7 @@ # specific language governing permissions and limitations # under the License. -# Generate a minimal HTTPD SSL configuration +# Generate a minimal HTTPD basic authentication configuration here=`readlink -f $0`; here=`dirname $here` mkdir -p $1 root=`readlink -f $1` @@ -28,13 +28,14 @@ host=`echo $conf | awk '{ print $6 }'` httpd_prefix=`cat $here/httpd.prefix` # Generate basic authentication configuration -cat >>$root/conf/vhost-ssl.conf <<EOF -# Generated by: httpd-auth-conf $* +cat >>$root/conf/auth.conf <<EOF +# Generated by: basic-auth-conf $* # Require clients to present a userid + password for HTTP # basic authentication <Location /> AuthType Basic AuthName "$host" +AuthBasicProvider file AuthUserFile "$root/conf/httpd.passwd" Require valid-user </Location> @@ -42,7 +43,8 @@ Require valid-user EOF # Create test users -$httpd_prefix/bin/htpasswd -bc $root/conf/httpd.passwd test test 2>/dev/null +touch $root/conf/httpd.passwd +$httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd test test 2>/dev/null $httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd admin admin 2>/dev/null $httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd foo foo 2>/dev/null $httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd bar bar 2>/dev/null diff --git a/sca-cpp/trunk/modules/http/form-auth-conf b/sca-cpp/trunk/modules/http/form-auth-conf new file mode 100755 index 0000000000..a58a800058 --- /dev/null +++ b/sca-cpp/trunk/modules/http/form-auth-conf @@ -0,0 +1,64 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Generate a minimal HTTPD form authentication configuration +here=`readlink -f $0`; here=`dirname $here` +mkdir -p $1 +root=`readlink -f $1` + +conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"` +host=`echo $conf | awk '{ print $6 }'` + +httpd_prefix=`cat $here/httpd.prefix` + +# Generate form authentication configuration +cat >>$root/conf/auth.conf <<EOF +# Generated by: form-auth-conf $* +# Require clients to present a userid + password through form-based +# authentication +<Location /> +AuthType Form +AuthName "$host" +AuthFormProvider file +AuthUserFile "$root/conf/httpd.passwd" +AuthFormLoginRequiredLocation /login +AuthFormLogoutLocation / +Session On +SessionCookieName TuscanyFormAuth path=/;secure=TRUE +#SessionCryptoPassphrase secret +Require valid-user +</Location> + +<Location /login/dologin> +SetHandler form-login-handler +</Location> + +<Location /logout/dologout> +SetHandler form-logout-handler +</Location> + +EOF + +# Create test users +touch $root/conf/httpd.passwd +$httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd test test 2>/dev/null +$httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd admin admin 2>/dev/null +$httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd foo foo 2>/dev/null +$httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd bar bar 2>/dev/null + diff --git a/sca-cpp/trunk/modules/http/htdocs/login/index.html b/sca-cpp/trunk/modules/http/htdocs/login/index.html new file mode 100644 index 0000000000..f3542f1524 --- /dev/null +++ b/sca-cpp/trunk/modules/http/htdocs/login/index.html @@ -0,0 +1,39 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + +<html><body><h1>Sign in</h1> + +<script type="text/javascript"> +function submitFormSignin() { + document.formSignin.httpd_location.value = '/'; + document.formSignin.submit(); +} +</script> + +<form name="formSignin" method="POST" action="/login/dologin"> +<table border="0"> +<tr><td>Username:</td><td><input type="text" name="httpd_username" value=""/></td></tr> +<tr><td>Password:</td><td><input type="password" name="httpd_password" value=""/></td></tr> +<tr><td><input type="button" onclick="submitFormSignin()" value="Sign in"/></td><td></td></tr> +</table> +<input type="hidden" name="httpd_location" value="/"/> +</form> + +</body> +</html> diff --git a/sca-cpp/trunk/modules/http/htdocs/logout/index.html b/sca-cpp/trunk/modules/http/htdocs/logout/index.html new file mode 100644 index 0000000000..1ac6e39a1c --- /dev/null +++ b/sca-cpp/trunk/modules/http/htdocs/logout/index.html @@ -0,0 +1,33 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + +<html><body> +<h1>Sign out</h1> + +<form name="signout" action="/login" method="GET"> +<script type="text/javascript"> +function submitSignout() { + document.cookie = 'TuscanyFormAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE'; + document.signout.submit(); + return true; +} +</script> +<input type="button" onclick="submitSignout()" value="Sign out"/> +</form> +</body></html> diff --git a/sca-cpp/trunk/modules/http/http.hpp b/sca-cpp/trunk/modules/http/http.hpp index db860aeee2..56331d7ee2 100644 --- a/sca-cpp/trunk/modules/http/http.hpp +++ b/sca-cpp/trunk/modules/http/http.hpp @@ -159,19 +159,19 @@ const failable<CURL*> setup(const string& url, const CURLSession& cs) { // Setup SSL options if (cs.ca != "") { - debug(cs.ca, "http::apply::ca"); + debug(cs.ca, "http::setup::ca"); curl_easy_setopt(ch, CURLOPT_CAINFO, c_str(cs.ca)); curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, true); curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, 2); } else curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, false); if (cs.cert != "") { - debug(cs.cert, "http::apply::cert"); + debug(cs.cert, "http::setup::cert"); curl_easy_setopt(ch, CURLOPT_SSLCERT, c_str(cs.cert)); curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM"); } if (cs.key != "") { - debug(cs.key, "http::apply::key"); + debug(cs.key, "http::setup::key"); curl_easy_setopt(ch, CURLOPT_SSLKEY, c_str(cs.key)); curl_easy_setopt(ch, CURLOPT_SSLKEYTYPE, "PEM"); } @@ -238,6 +238,8 @@ curl_slist* headers(curl_slist* cl, const list<string>& h) { } template<typename R> const failable<list<R> > apply(const list<list<string> >& hdr, const lambda<R(const string&, const R)>& reduce, const R& initial, const string& url, const string& verb, const CURLSession& cs) { + debug(url, "http::apply::url"); + debug(verb, "http::apply::verb"); // Setup the CURL session const failable<CURL*> fch = setup(url, cs); @@ -523,6 +525,7 @@ apr_pollfd_t* pollfd(apr_socket_t* s, const int e, const gc_pool& p) { * Connect to a URL. */ const failable<bool> connect(const string& url, CURLSession& cs) { + debug(url, "http::connect::url"); // Setup the CURL session const failable<CURL*> fch = setup(url, cs); diff --git a/sca-cpp/trunk/modules/http/httpd-conf b/sca-cpp/trunk/modules/http/httpd-conf index 8a6928d823..79a85c0961 100755 --- a/sca-cpp/trunk/modules/http/httpd-conf +++ b/sca-cpp/trunk/modules/http/httpd-conf @@ -52,19 +52,25 @@ PidFile $root/logs/httpd.pid # after mod_rewrite's hooks) LoadModule alias_module ${modules_prefix}/modules/mod_alias.so LoadModule authn_file_module ${modules_prefix}/modules/mod_authn_file.so -LoadModule authn_default_module ${modules_prefix}/modules/mod_authn_default.so +LoadModule authn_core_module ${modules_prefix}/modules/mod_authn_core.so LoadModule authz_host_module ${modules_prefix}/modules/mod_authz_host.so LoadModule authz_groupfile_module ${modules_prefix}/modules/mod_authz_groupfile.so LoadModule authz_user_module ${modules_prefix}/modules/mod_authz_user.so -LoadModule authz_default_module ${modules_prefix}/modules/mod_authz_default.so +LoadModule authz_core_module ${modules_prefix}/modules/mod_authz_core.so LoadModule auth_basic_module ${modules_prefix}/modules/mod_auth_basic.so +LoadModule auth_digest_module ${modules_prefix}/modules/mod_auth_digest.so +LoadModule auth_form_module ${modules_prefix}/modules/mod_auth_form.so +LoadModule request_module ${modules_prefix}/modules/mod_request.so +LoadModule deflate_module ${modules_prefix}/modules/mod_deflate.so LoadModule filter_module ${modules_prefix}/modules/mod_filter.so LoadModule proxy_module ${modules_prefix}/modules/mod_proxy.so LoadModule proxy_connect_module ${modules_prefix}/modules/mod_proxy_connect.so LoadModule proxy_http_module ${modules_prefix}/modules/mod_proxy_http.so LoadModule proxy_balancer_module ${modules_prefix}/modules/mod_proxy_balancer.so +LoadModule lbmethod_byrequests_module ${modules_prefix}/modules/mod_lbmethod_byrequests.so LoadModule headers_module ${modules_prefix}/modules/mod_headers.so LoadModule ssl_module ${modules_prefix}/modules/mod_ssl.so +LoadModule socache_shmcb_module ${modules_prefix}/modules/mod_socache_shmcb.so LoadModule rewrite_module ${modules_prefix}/modules/mod_rewrite.so LoadModule mime_module ${modules_prefix}/modules/mod_mime.so LoadModule status_module ${modules_prefix}/modules/mod_status.so @@ -79,8 +85,16 @@ LoadModule logio_module ${modules_prefix}/modules/mod_logio.so LoadModule usertrack_module ${modules_prefix}/modules/mod_usertrack.so LoadModule vhost_alias_module ${modules_prefix}/modules/mod_vhost_alias.so LoadModule cgi_module ${modules_prefix}/modules/mod_cgi.so +LoadModule unixd_module ${modules_prefix}/modules/mod_unixd.so +LoadModule session_module ${modules_prefix}/modules/mod_session.so +#LoadModule session_crypto_module ${modules_prefix}/modules/mod_session_crypto.so +LoadModule session_cookie_module ${modules_prefix}/modules/mod_session_cookie.so +LoadModule slotmem_shm_module ${modules_prefix}/modules/mod_slotmem_shm.so +LoadModule ratelimit_module ${modules_prefix}/modules/mod_ratelimit.so +LoadModule reqtimeout_module ${modules_prefix}/modules/mod_reqtimeout.so LoadModule mod_tuscany_ssltunnel $here/libmod_tuscany_ssltunnel.so +LoadModule mod_tuscany_openauth $here/libmod_tuscany_openauth.so # Basic security precautions User $user @@ -103,7 +117,6 @@ CookieTracking on CookieName TuscanyVisitorId # Configure Mime types -DefaultType text/plain TypesConfig $here/conf/mime.types # Set default document root @@ -114,26 +127,44 @@ DirectoryIndex index.html <Directory /> Options None AllowOverride None -Order deny,allow -Deny from all +Require all denied </Directory> -<FilesMatch "^\.ht"> -Order deny,allow -Deny from all -Satisfy Any -</FilesMatch> -# Allow access to document root -<Directory "$htdocs"> -Options FollowSymLinks -Allow from all -</Directory> +# Configure authentication +Include conf/auth.conf -# Allow access to root location -<Location /> -Options FollowSymLinks -Order deny,allow -Allow from all +# Allow access to public locations +<Location /login> +AuthType None +Require all granted +</Location> +<Location /logout> +AuthType None +Require all granted +</Location> +<Location /public> +AuthType None +Require all granted +</Location> +<Location /openid> +AuthType None +Require all granted +</Location> +<Location /ui> +AuthType None +Require all granted +</Location> +<Location /wiring> +AuthType None +Require all granted +</Location> +<Location /.well-known/host-meta> +AuthType None +Require all granted +</Location> +<Location /favicon.ico> +AuthType None +Require all granted </Location> # Listen on HTTP port @@ -152,6 +183,25 @@ Include conf/svhost.conf EOF +# Generate auth configuration +cat >$root/conf/auth.conf <<EOF +# Generated by: httpd-conf $* +# Authentication configuration + +# Allow access to document root +<Directory "$htdocs"> +Options FollowSymLinks +Require all granted +</Directory> + +# Allow access to root location +<Location /> +Options FollowSymLinks +Require all granted +</Location> + +EOF + # Generate vhost configuration cat >$root/conf/vhost.conf <<EOF # Generated by: httpd-conf $* diff --git a/sca-cpp/trunk/modules/http/httpd-ssl-conf b/sca-cpp/trunk/modules/http/httpd-ssl-conf index 5f1058ea75..94352ca344 100755 --- a/sca-cpp/trunk/modules/http/httpd-ssl-conf +++ b/sca-cpp/trunk/modules/http/httpd-ssl-conf @@ -51,7 +51,7 @@ AddType application/x-pkcs7-crl .crl SSLPassPhraseDialog builtin SSLSessionCache "shmcb:$root/logs/ssl_scache(512000)" SSLSessionCacheTimeout 300 -SSLMutex "file:$root/logs/ssl_mutex" +Mutex "file:$root/logs" ssl-cache SSLRandomSeed startup builtin SSLRandomSeed connect builtin @@ -68,7 +68,6 @@ Include conf/svhost-ssl.conf <Location /server-status> SetHandler server-status HostnameLookups on -Allow from all Require user admin </Location> @@ -114,10 +113,10 @@ UseCanonicalName Off SSLEngine on SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL BrowserMatch ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0 -SSLOptions -StrictRequire +OptRenegotiate +SSLOptions +StrictRequire +OptRenegotiate +FakeBasicAuth # Verify client certificates -SSLVerifyClient none +SSLVerifyClient optional SSLVerifyDepth 1 # Enable SSL proxy engine @@ -143,19 +142,13 @@ cat >>$root/conf/vhost-ssl.conf <<EOF <Location /> # Require clients to use SSL and authenticate SSLRequireSSL - -# Also accept other forms of authentication (e.g. HTTP basic -# authentication, or OpenID authentication) -Satisfy Any +SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128 EOF proxyconf=`cat $root/conf/vhost.conf | grep "# Generated by: proxy-conf"` if [ "$proxyconf" != "" ]; then cat >>$root/conf/vhost-ssl.conf <<EOF -# In an proxy, only require a 128+ cipher key -SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128 - # Forward received SSL client certificate info in proxied requests RewriteEngine on RewriteRule .* - [E=SSL_PROTOCOL:%{SSL:SSL_PROTOCOL}] @@ -184,18 +177,6 @@ RequestHeader set X-Forwarded-SSL-Client-DN-OU %{SSL_S_DN_OU}e env=SSL_S_DN_OU EOF else cat >>$root/conf/vhost-ssl.conf <<EOF -# In a server, require a 128+ cipher key and one of the following -# - another server's certificate issued by our certificate authority -# - a proxy certificate + forwarded info on the client request certificate, -# both signed by our certificate authority -# - OpenID authentication (set by mod_auth_openid in the auth_type) -# - another valid form of authentication as per the Satisfy directive -SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128 and ( \ -( %{SSL_CLIENT_I_DN_O} == "$org" and %{SSL_CLIENT_S_DN_OU} == "server" ) or \ -( %{SSL_CLIENT_I_DN_O} == "$org" and %{SSL_CLIENT_S_DN_OU} == "tunnel" ) or \ -( %{SSL_CLIENT_I_DN_O} == "$org" and %{SSL_CLIENT_S_DN_OU} == "proxy" and \ - %{HTTP:X-Forwarded-SSL-Issuer-DN-O} == "$org" and %{HTTP:X-Forwarded-SSL-Client-DN-OU} == "server" ) or \ -%{REQUEST_URI} =~ m/^.(login|logout|openid|public|ui).*$/ ) # Record received SSL client certificate info in environment vars RewriteEngine on @@ -270,3 +251,8 @@ SSLProxyMachineCertificateFile "$root/cert/$proxycert.pem" EOF +# Configure user for HTTP fake basic auth +cat >$root/conf/httpd.passwd <<EOF +/C=US/ST=CA/L=San Francisco/O=$host/OU=server/CN=$host:\$1\$OXLyS...\$Owx8s2/m9/gfkcRVXzgoE/ +EOF + diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp index 528404b8fc..02c9904ac3 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -31,14 +31,23 @@ #include <apr_lib.h> #define APR_WANT_STRFUNC #include <apr_want.h> +#include <apr_base64.h> #include <httpd.h> +// Hack to workaround compile error with HTTPD 2.3.8 +#define new new_ #include <http_config.h> +#undef new #include <http_core.h> #include <http_connection.h> #include <http_request.h> #include <http_protocol.h> +// Hack to workaround compile error with HTTPD 2.3.8 +#define aplog_module_index aplog_module_index = 0 #include <http_log.h> +#undef aplog_module_index +#undef APLOG_MODULE_INDEX +#define APLOG_MODULE_INDEX (aplog_module_index ? *aplog_module_index : APLOG_NO_MODULE) #include <http_main.h> #include <util_script.h> #include <util_md5.h> @@ -46,6 +55,8 @@ #include <http_log.h> #include <ap_mpm.h> #include <mod_core.h> +#include <ap_provider.h> +#include <mod_auth.h> #include "string.hpp" #include "stream.hpp" @@ -358,6 +369,7 @@ const failable<int> writeResult(const failable<list<string> >& ls, const string& * Report a request execution status. */ const int reportStatus(const failable<int>& rc) { + debug(rc, "httpd::reportStatus::rc"); if (!hasContent(rc)) return HTTP_INTERNAL_SERVER_ERROR; return content(rc); @@ -575,10 +587,11 @@ const failable<request_rec*, int> internalSubRequest(const string& nr_uri, reque * Return an HTTP external redirect request. */ const int externalRedirect(const string& uri, request_rec* r) { + debug(uri, "httpd::externalRedirect"); r->status = HTTP_MOVED_TEMPORARILY; apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(uri))); r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:/") + uri)); - return OK; + return HTTP_MOVED_TEMPORARILY; } /** @@ -642,6 +655,12 @@ int debugNote(unused void* r, const char* key, const char* value) { */ const bool debugRequest(request_rec* r, const string& msg) { cdebug << msg << ":" << endl; + cdebug << " unparsed uri: " << debugOptional(r->unparsed_uri) << endl; + cdebug << " uri: " << debugOptional(r->uri) << endl; + cdebug << " path info: " << debugOptional(r->path_info) << endl; + cdebug << " filename: " << debugOptional(r->filename) << endl; + cdebug << " uri tokens: " << pathTokens(r->uri) << endl; + cdebug << " args: " << debugOptional(r->args) << endl; cdebug << " server: " << debugOptional(r->server->server_hostname) << endl; cdebug << " protocol: " << debugOptional(r->protocol) << endl; cdebug << " method: " << debugOptional(r->method) << endl; @@ -649,16 +668,10 @@ const bool debugRequest(request_rec* r, const string& msg) { cdebug << " content type: " << contentType(r) << endl; cdebug << " content encoding: " << debugOptional(r->content_encoding) << endl; apr_table_do(debugHeader, r, r->headers_in, NULL); - cdebug << " unparsed uri: " << debugOptional(r->unparsed_uri) << endl; - cdebug << " uri: " << debugOptional(r->uri) << endl; - cdebug << " path info: " << debugOptional(r->path_info) << endl; - cdebug << " filename: " << debugOptional(r->filename) << endl; - cdebug << " uri tokens: " << pathTokens(r->uri) << endl; - cdebug << " args: " << debugOptional(r->args) << endl; cdebug << " user: " << debugOptional(r->user) << endl; cdebug << " auth type: " << debugOptional(r->ap_auth_type) << endl; apr_table_do(debugEnv, r, r->subprocess_env, NULL); - apr_table_do(debugEnv, r, r->notes, NULL); + apr_table_do(debugNote, r, r->notes, NULL); return true; } diff --git a/sca-cpp/trunk/modules/http/mod-openauth.cpp b/sca-cpp/trunk/modules/http/mod-openauth.cpp new file mode 100644 index 0000000000..b43624f08d --- /dev/null +++ b/sca-cpp/trunk/modules/http/mod-openauth.cpp @@ -0,0 +1,325 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +/** + * HTTPD module for Tuscany Open authentication. + * + * This module allows multiple authentication mechanisms to co-exist in a + * single Web site: + * - OAuth1 using Tuscany's mod-tuscany-oauth1 + * - OAuth2 using Tuscany's mod-tuscany-oauth2 + * - OpenID using mod_auth_openid + * - Form-based using HTTPD's mod_auth_form + * - SSL certificate using SSLFakeBasicAuth and mod_auth_basic + */ + +#include <sys/stat.h> + +#include "string.hpp" +#include "stream.hpp" +#include "list.hpp" +#include "tree.hpp" +#include "value.hpp" +#include "monad.hpp" +#include "httpd.hpp" +#include "http.hpp" +#include "openauth.hpp" + +extern "C" { +extern module AP_MODULE_DECLARE_DATA mod_tuscany_openauth; +} + +namespace tuscany { +namespace openauth { + +/** + * Server configuration. + */ +class ServerConf { +public: + ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s) { + } + + const gc_pool p; + server_rec* server; +}; + +/** + * Directory configuration. + */ +class DirConf { +public: + DirConf(apr_pool_t* p, char* d) : p(p), dir(d), enabled(false), login("") { + } + + const gc_pool p; + const char* dir; + bool enabled; + string login; +}; + +/** + * Return the user info from a form auth session cookie. + */ +const failable<value> userInfo(const value& sid, const string& realm) { + const list<list<value>> info = httpd::queryArgs(sid); + debug(info, "modopenauth::userInfo::info"); + const list<value> user = assoc<value>(realm + "-user", info); + if (isNil(user)) + return mkfailure<value>("Couldn't retrieve user id"); + const list<value> pw = assoc<value>(realm + "-pw", info); + if (isNil(pw)) + return mkfailure<value>("Couldn't retrieve password"); + return value(mklist<value>(mklist<value>("realm", realm), mklist<value>("id", cadr(user)), mklist<value>("password", cadr(pw)))); +} + +/** + * Return the user info from a basic auth header. + */ +const failable<value> userInfo(const char* header, const string& realm, request_rec* r) { + debug(header, "modopenauth::userInfo::header"); + if (strcasecmp(ap_getword(r->pool, &header, ' '), "Basic")) + return mkfailure<value>("Wrong authentication scheme"); + + while (apr_isspace(*header)) + header++; + char *decoded_line = (char*)apr_palloc(r->pool, apr_base64_decode_len(header) + 1); + int length = apr_base64_decode(decoded_line, header); + decoded_line[length] = '\0'; + + const string user(ap_getword_nulls(r->pool, const_cast<const char**>(&decoded_line), ':')); + const string pw(decoded_line); + + return value(mklist<value>(mklist<value>("realm", realm), mklist<value>("id", user), mklist<value>("password", pw))); +} + +/** + * Handle an authenticated request. + */ +const failable<int> authenticated(const list<list<value> >& info, request_rec* r) { + debug(info, "modopenauth::authenticated::info"); + + // Store user info in the request + const list<value> realm = assoc<value>("realm", info); + if (isNil(realm) || isNil(cdr(realm))) + return mkfailure<int>("Couldn't retrieve realm"); + apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "REALM"), apr_pstrdup(r->pool, c_str(cadr(realm)))); + + const list<value> id = assoc<value>("id", info); + if (isNil(id) || isNil(cdr(id))) + return mkfailure<int>("Couldn't retrieve user id"); + 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)))); + return OK; +} + +/** + * Run the authnz hooks to try to authenticate a request. + */ +const failable<int> checkAuthnz(const string& user, const string& pw, request_rec* r) { + const authn_provider* provider = (const authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION); + if (!provider || !provider->check_password) + return mkfailure<int>("No Authn provider configured"); + apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, AUTHN_DEFAULT_PROVIDER); + const authn_status auth_result = provider->check_password(r, c_str(user), c_str(pw)); + apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE); + if (auth_result != AUTH_GRANTED) + return mkfailure<int>("Authentication failure for: " + user); + return OK; +} + +/** + * Check user authentication. + */ +static int checkAuthn(request_rec *r) { + // Decline if we're not enabled or AuthType is not set to Open + const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth); + if (!dc.enabled) + return DECLINED; + const char* atype = ap_auth_type(r); + if (atype == NULL || strcasecmp(atype, "Open")) + return DECLINED; + + gc_scoped_pool pool(r->pool); + httpdDebugRequest(r, "modopenauth::checkAuthn::input"); + + // Get session id from the request + const maybe<string> sid = sessionID(r); + 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_") + return DECLINED; + + // Retrieve the auth realm + const char* aname = ap_auth_name(r); + if (aname == NULL) + return httpd::reportStatus(mkfailure<int>("Missing AuthName")); + + // Extract user info from the session id + const failable<value> info = userInfo(content(sid), aname); + if (hasContent(info)) { + + // Try to authenticate the request + const value cinfo = content(info); + const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", cinfo)), cadr(assoc<value>("password", cinfo)), r); + if (!hasContent(authz)) { + + // Authentication failed, redirect to login page + r->ap_auth_type = const_cast<char*>(atype); + return httpd::reportStatus(login(dc.login, r)); + } + + // Successfully authenticated, store the user info in the request + r->ap_auth_type = const_cast<char*>(atype); + return httpd::reportStatus(authenticated(cinfo, 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) { + + // Retrieve the auth realm + const char* aname = ap_auth_name(r); + if (aname == NULL) + return httpd::reportStatus(mkfailure<int>("Missing AuthName")); + + // Extract user info from the session id + const failable<value> info = userInfo(header, aname, r); + if (hasContent(info)) { + + // Try to authenticate the request + const value cinfo = content(info); + const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", cinfo)), cadr(assoc<value>("password", cinfo)), r); + if (!hasContent(authz)) { + + // Authentication failed, redirect to login page + r->ap_auth_type = const_cast<char*>(atype); + return httpd::reportStatus(login(dc.login, r)); + } + + // Successfully authenticated, store the user info in the request + r->ap_auth_type = const_cast<char*>(atype); + return httpd::reportStatus(authenticated(cinfo, r)); + } + } + + // Get the request args + const list<list<value> > args = httpd::queryArgs(r); + + // Decline if the request is for another authentication provider + if (!isNil(assoc<value>("openid_identifier", args))) + return DECLINED; + if (!isNil(assoc<value>("mod_oauth1_step", args))) + return DECLINED; + if (!isNil(assoc<value>("mod_oauth2_step", args))) + return DECLINED; + + // Redirect to the login page + r->ap_auth_type = const_cast<char*>(atype); + return httpd::reportStatus(login(dc.login, r)); +} + +/** + * Process the module configuration. + */ +int postConfigMerge(ServerConf& mainsc, server_rec* 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); + ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_openauth); + debug(httpd::serverName(s), "modopenauth::postConfig::serverName"); + + // Merge server configurations + return postConfigMerge(sc, s); +} + +/** + * 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_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; + + // Merge the updated configuration into the virtual hosts + postConfigMerge(sc, s->next); +} + +/** + * Configuration commands. + */ +const char* confEnabled(cmd_parms *cmd, void *c, const int arg) { + gc_scoped_pool pool(cmd->pool); + DirConf& dc = httpd::dirConf<DirConf>(c); + dc.enabled = (bool)arg; + return NULL; +} +const char* confLogin(cmd_parms *cmd, void *c, const char* arg) { + gc_scoped_pool pool(cmd->pool); + DirConf& dc = httpd::dirConf<DirConf>(c); + dc.login = arg; + return NULL; +} + +/** + * HTTP server module declaration. + */ +const command_rec commands[] = { + AP_INIT_FLAG("AuthOpenAuth", (const char*(*)())confEnabled, NULL, OR_AUTHCFG, "Tuscany Open Auth authentication On | Off"), + AP_INIT_TAKE1("AuthOpenAuthLoginPage", (const char*(*)())confLogin, NULL, OR_AUTHCFG, "Tuscany Open Auth login page"), + {NULL, NULL, NULL, 0, NO_ARGS, NULL} +}; + +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_check_authn(checkAuthn, NULL, NULL, APR_HOOK_MIDDLE, AP_AUTH_INTERNAL_PER_CONF); +} + +} +} + +extern "C" { + +module AP_MODULE_DECLARE_DATA mod_tuscany_openauth = { + STANDARD20_MODULE_STUFF, + // dir config and merger + tuscany::httpd::makeDirConf<tuscany::openauth::DirConf>, NULL, + // server config and merger + tuscany::httpd::makeServerConf<tuscany::openauth::ServerConf>, NULL, + // commands and hooks + tuscany::openauth::commands, tuscany::openauth::registerHooks +}; + +} diff --git a/sca-cpp/trunk/modules/http/open-auth-conf b/sca-cpp/trunk/modules/http/open-auth-conf new file mode 100755 index 0000000000..f2304a0b86 --- /dev/null +++ b/sca-cpp/trunk/modules/http/open-auth-conf @@ -0,0 +1,66 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Generate a minimal HTTPD form authentication configuration +here=`readlink -f $0`; here=`dirname $here` +mkdir -p $1 +root=`readlink -f $1` + +conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"` +host=`echo $conf | awk '{ print $6 }'` + +httpd_prefix=`cat $here/httpd.prefix` + +# Generate form authentication configuration +cat >>$root/conf/auth.conf <<EOF +# Generated by: open-auth-conf $* +# Enable Tuscany open authentication +<Location /> +AuthType Open +AuthName "$host" +AuthOpenAuth On +AuthOpenAuthLoginPage /login +AuthUserFile "$root/conf/httpd.passwd" +Require valid-user +</Location> + +# Use HTTPD form-based authentication +<Location /login/dologin> +AuthType Form +AuthName "$host" +AuthFormProvider file +AuthUserFile "$root/conf/httpd.passwd" +AuthFormLoginRequiredLocation /login +AuthFormLogoutLocation / +Session On +SessionCookieName TuscanyOpenAuth path=/;secure=TRUE +#SessionCryptoPassphrase secret +Require valid-user +SetHandler form-login-handler +</Location> + +EOF + +# Create test users +touch $root/conf/httpd.passwd +$httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd test test 2>/dev/null +$httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd admin admin 2>/dev/null +$httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd foo foo 2>/dev/null +$httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd bar bar 2>/dev/null + diff --git a/sca-cpp/trunk/modules/oauth/oauth.hpp b/sca-cpp/trunk/modules/http/openauth.hpp index cea16e035f..53250b4732 100644 --- a/sca-cpp/trunk/modules/oauth/oauth.hpp +++ b/sca-cpp/trunk/modules/http/openauth.hpp @@ -19,11 +19,11 @@ /* $Rev$ $Date$ */ -#ifndef tuscany_oauth_hpp -#define tuscany_oauth_hpp +#ifndef tuscany_openauth_hpp +#define tuscany_openauth_hpp /** - * OAuth support utility functions. + * Tuscany Open auth support utility functions. */ #include "string.hpp" @@ -35,10 +35,9 @@ #include "../json/json.hpp" #include "../http/httpd.hpp" #include "../http/http.hpp" -#include "../../components/cache/memcache.hpp" namespace tuscany { -namespace oauth { +namespace openauth { /** * Return the session id from a request. @@ -51,30 +50,27 @@ const char* cookieName(const char* cs) { const maybe<string> sessionID(const list<string> c) { if (isNil(c)) return maybe<string>(); - const list<string> kv = tokenize("=", cookieName(c_str(car(c)))); - if (!isNil(kv) && !isNil(cdr(kv))) { - if (car(kv) == "TuscanyOpenAuth") - return cadr(kv); + const string cn = cookieName(c_str(car(c))); + const int i = find(cn, "="); + if (i < length(cn)) { + const list<string> kv = mklist<string>(substr(cn, 0, i), substr(cn, i+1)); + if (!isNil(kv) && !isNil(cdr(kv))) { + if (car(kv) == "TuscanyOpenAuth") + return cadr(kv); + } } return sessionID(cdr(c)); } const maybe<string> sessionID(const request_rec* r) { const char* c = apr_table_get(r->headers_in, "Cookie"); - debug(c, "oauth::sessionid::cookies"); + debug(c, "openauth::sessionid::cookies"); if (c == NULL) return maybe<string>(); return sessionID(tokenize(";", c)); } /** - * Return the user info for a session. - */ -const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) { - return memcache::get(mklist<value>("tuscanyOpenAuth", sid), mc); -} - -/** * Convert a session id to a cookie string. */ const string cookie(const string& sid) { @@ -82,7 +78,7 @@ const string cookie(const string& sid) { char exp[32]; strftime(exp, 32, "%a, %d-%b-%Y %H:%M:%S GMT", gmtime(&t)); const string c = string("TuscanyOpenAuth=") + sid + string(";path=/;expires=" + string(exp)) + ";secure=TRUE"; - debug(c, "oauth::cookie"); + debug(c, "openauth::cookie"); return c; } @@ -92,11 +88,11 @@ const string cookie(const string& sid) { const failable<int> login(const string& page, request_rec* r) { const list<list<value> > largs = mklist<list<value> >(mklist<value>("openauth_referrer", httpd::escape(httpd::url(r->uri, r)))); const string loc = httpd::url(page, r) + string("?") + httpd::queryString(largs); - debug(loc, "oauth::login::uri"); + debug(loc, "openauth::login::uri"); return httpd::externalRedirect(loc, r); } } } -#endif /* tuscany_oauth_hpp */ +#endif /* tuscany_openauth_hpp */ diff --git a/sca-cpp/trunk/modules/http/proxy-conf b/sca-cpp/trunk/modules/http/proxy-conf index ff312041f5..e9abe8435f 100755 --- a/sca-cpp/trunk/modules/http/proxy-conf +++ b/sca-cpp/trunk/modules/http/proxy-conf @@ -33,8 +33,7 @@ ProxyStatus On ProxyPass / balancer://cluster/ <Proxy balancer://cluster> -Order deny,allow -Allow from all +Require all granted ProxySet lbmethod=byrequests </Proxy> diff --git a/sca-cpp/trunk/modules/http/proxy-ssl-conf b/sca-cpp/trunk/modules/http/proxy-ssl-conf index 8f8d51c7a4..12340f9921 100755 --- a/sca-cpp/trunk/modules/http/proxy-ssl-conf +++ b/sca-cpp/trunk/modules/http/proxy-ssl-conf @@ -34,8 +34,7 @@ ProxyPass /balancer-manager ! ProxyPass / balancer://sslcluster/ <Proxy balancer://sslcluster> -Order deny,allow -Allow from all +Require all granted ProxySet lbmethod=byrequests </Proxy> @@ -43,8 +42,6 @@ ProxySet lbmethod=byrequests <Location /balancer-manager> SetHandler balancer-manager HostnameLookups on -Deny from all -Allow from all Require user admin </Location> diff --git a/sca-cpp/trunk/modules/oauth/htdocs/index.html b/sca-cpp/trunk/modules/oauth/htdocs/index.html index e8cdd2f26b..fc8ce922f1 100644 --- a/sca-cpp/trunk/modules/oauth/htdocs/index.html +++ b/sca-cpp/trunk/modules/oauth/htdocs/index.html @@ -19,7 +19,7 @@ <html> <head> -<script type="text/javascript" src="/js/ref.js"></script> +<script type="text/javascript" src="/wiring/ref.js"></script> <script type="text/javascript"> var protected = component("Protected"); var userInfo = defun(reference(protected, "userInfo"), "getuser", "getemail", "getnickname", "getfullname", "getfirstname", "getlastname", "getrealm"); diff --git a/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html b/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html index 10773c4538..d0b4f94d55 100644 --- a/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html +++ b/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html @@ -17,9 +17,14 @@ under the License. --> -<html><body><h1>Sign in with an OpenID or OAuth provider</h1> +<html><body><h1>Sign in with a Form, an OpenID provider or an OAuth provider</h1> <script type="text/javascript"> +function submitFormSignin() { + document.formSignin.httpd_location.value = '/'; + document.formSignin.submit(); +} + function queryParams() { qp = new Array(); qs = window.location.search.substring(1).split('&'); @@ -133,6 +138,17 @@ function withTwitter() { } </script> +<form name="formSignin" method="POST" action="/login/dologin"> +<p>Sign in with your user id and password<br/> +<table border="0"> +<tr><td>Username:</td><td><input type="text" name="httpd_username" value=""/></td></tr> +<tr><td>Password:</td><td><input type="password" name="httpd_password" value=""/></td></tr> +<tr><td><input type="button" onclick="submitFormSignin()" value="Sign in"/></td><td></td></tr> +</table> +</p> +<input type="hidden" name="httpd_location" value="/"/> +</form> + <form name="fields"> <p>Sign in with your Google account<br/><input type="button" onclick="submitOpenIDSignin(withGoogle)" value="Sign in"/></p> <p>Sign in with your Yahoo account<br/><input type="button" onclick="submitOpenIDSignin(withYahoo)" value="Sign in"/></p> diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp index 22fdd0cce3..a417935c0a 100644 --- a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp +++ b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp @@ -39,8 +39,8 @@ extern "C" { #include "../json/json.hpp" #include "../http/httpd.hpp" #include "../http/http.hpp" +#include "../http/openauth.hpp" #include "../../components/cache/memcache.hpp" -#include "oauth.hpp" extern "C" { extern module AP_MODULE_DECLARE_DATA mod_tuscany_oauth1; @@ -83,20 +83,10 @@ public: }; /** - * Check user authentication. + * Return the user info for a session. */ -static int checkUserID(request_rec *r) { - // Decline if we're not enabled or AuthType is not set to Open - const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth1); - if (!dc.enabled) - return DECLINED; - const char* atype = ap_auth_type(r); - if (atype == NULL || strcasecmp(atype, "Open")) - return DECLINED; - - gc_scoped_pool pool(r->pool); - httpdDebugRequest(r, "modoauth1::checkUserID::input"); - return OK; +const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) { + return memcache::get(mklist<value>("tuscanyOpenAuth", sid), mc); } /** @@ -135,10 +125,7 @@ const failable<int> authenticated(const list<list<value> >& info, request_rec* r const list<value> lastname = assoc<value>("last-name", info); if (!isNil(lastname) && !isNil(cdr(lastname))) apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "LASTNAME"), apr_pstrdup(r->pool, c_str(cadr(lastname)))); - - if(r->ap_auth_type == NULL) - r->ap_auth_type = const_cast<char*>("OAuth"); - return DECLINED; + return OK; } /** @@ -391,47 +378,47 @@ const failable<int> access_token(const list<list<value> >& args, request_rec* r, return mkfailure<int>(reason(prc)); // Send session ID to the client in a cookie - apr_table_set(r->err_headers_out, "Set-Cookie", c_str(oauth::cookie(sid))); + apr_table_set(r->err_headers_out, "Set-Cookie", c_str(openauth::cookie(sid))); return httpd::externalRedirect(httpd::url(r->uri, r), r); } /** - * Handle a request. + * Check user authentication. */ -int handler(request_rec* r) { - // Decline if we're not enabled or if the user is already - // authenticated by another module +static int checkAuthn(request_rec *r) { + // Decline if we're not enabled or AuthType is not set to Open const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth1); - if(!dc.enabled) + if (!dc.enabled) return DECLINED; - if (r->user != NULL || apr_table_get(r->subprocess_env, "SSL_REMOTE_USER") != NULL) + const char* atype = ap_auth_type(r); + if (atype == NULL || strcasecmp(atype, "Open")) return DECLINED; gc_scoped_pool pool(r->pool); - httpdDebugRequest(r, "modoauth1::handler::input"); + httpdDebugRequest(r, "modoauth1::checkAuthn::input"); const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth1); // Get session id from the request - const maybe<string> sid = oauth::sessionID(r); + const maybe<string> sid = openauth::sessionID(r); if (hasContent(sid)) { // Decline if the session id was not created by this module if (substr(content(sid), 0, 7) != "OAuth1_") return DECLINED; // If we're authenticated store the user info in the request - const failable<value> info = oauth::userInfo(content(sid), sc.mc); - if (hasContent(info)) + const failable<value> info = userInfo(content(sid), sc.mc); + if (hasContent(info)) { + r->ap_auth_type = const_cast<char*>(atype); return httpd::reportStatus(authenticated(content(info), r)); + } } // Get the request args const list<list<value> > args = httpd::queryArgs(r); - // Decline if the request is for OpenID authentication + // Decline if the request is for another authentication provider if (!isNil(assoc<value>("openid_identifier", args))) return DECLINED; - - // Decline if the request is for OAuth2 authentication if (!isNil(assoc<value>("mod_oauth2_step", args))) return DECLINED; @@ -441,15 +428,20 @@ int handler(request_rec* r) { const value step = !isNil(sl) && !isNil(cdr(sl))? cadr(sl) : ""; // Handle OAuth authorize request step - if (step == "authorize") + if (step == "authorize") { + r->ap_auth_type = const_cast<char*>(atype); return httpd::reportStatus(authorize(args, r, sc)); + } // Handle OAuth access_token request step - if (step == "access_token") + if (step == "access_token") { + r->ap_auth_type = const_cast<char*>(atype); return httpd::reportStatus(access_token(args, r, sc)); + } // Redirect to the login page - return httpd::reportStatus(oauth::login(dc.login, r)); + r->ap_auth_type = const_cast<char*>(atype); + return httpd::reportStatus(openauth::login(dc.login, r)); } /** @@ -567,8 +559,7 @@ const command_rec commands[] = { 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_check_user_id(checkUserID, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_handler(handler, NULL, NULL, APR_HOOK_FIRST); + ap_hook_check_authn(checkAuthn, NULL, NULL, APR_HOOK_MIDDLE, AP_AUTH_INTERNAL_PER_CONF); } } diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp index bb96fcb916..b52967977e 100644 --- a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp +++ b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp @@ -33,8 +33,8 @@ #include "monad.hpp" #include "../http/httpd.hpp" #include "../http/http.hpp" +#include "../http/openauth.hpp" #include "../../components/cache/memcache.hpp" -#include "oauth.hpp" extern "C" { extern module AP_MODULE_DECLARE_DATA mod_tuscany_oauth2; @@ -77,20 +77,10 @@ public: }; /** - * Check user authentication. + * Return the user info for a session. */ -static int checkUserID(request_rec *r) { - // 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); - if (atype == NULL || strcasecmp(atype, "Open")) - return DECLINED; - - gc_scoped_pool pool(r->pool); - httpdDebugRequest(r, "modoauth2::checkUserID::input"); - return OK; +const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) { + return memcache::get(mklist<value>("tuscanyOpenAuth", sid), mc); } /** @@ -99,6 +89,12 @@ static int checkUserID(request_rec *r) { const failable<int> authenticated(const list<list<value> >& info, request_rec* r) { debug(info, "modoauth2::authenticated::info"); + // Store user info in the request + const list<value> realm = assoc<value>("realm", info); + if (isNil(realm) || isNil(cdr(realm))) + return mkfailure<int>("Couldn't retrieve realm"); + apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "REALM"), apr_pstrdup(r->pool, c_str(cadr(realm)))); + const list<value> id = assoc<value>("id", info); if (isNil(id) || isNil(cdr(id))) return mkfailure<int>("Couldn't retrieve user id"); @@ -122,9 +118,7 @@ const failable<int> authenticated(const list<list<value> >& info, request_rec* r if (!isNil(lastname) && !isNil(cdr(lastname))) apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "LASTNAME"), apr_pstrdup(r->pool, c_str(cadr(lastname)))); - if(r->ap_auth_type == NULL) - r->ap_auth_type = const_cast<char*>("OAuth"); - return DECLINED; + return OK; } /** @@ -236,47 +230,47 @@ const failable<int> access_token(const list<list<value> >& args, request_rec* r, return mkfailure<int>(reason(prc)); // Send session ID to the client in a cookie - apr_table_set(r->err_headers_out, "Set-Cookie", c_str(oauth::cookie(sid))); + apr_table_set(r->err_headers_out, "Set-Cookie", c_str(openauth::cookie(sid))); return httpd::externalRedirect(httpd::url(r->uri, r), r); } /** - * Handle a request. + * Check user authentication. */ -int handler(request_rec* r) { - // Decline if we're not enabled or if the user is already - // authenticated by another module +static int checkAuthn(request_rec *r) { + // 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) + if (!dc.enabled) return DECLINED; - if (r->user != NULL || apr_table_get(r->subprocess_env, "SSL_REMOTE_USER") != NULL) + const char* atype = ap_auth_type(r); + if (atype == NULL || strcasecmp(atype, "Open")) return DECLINED; gc_scoped_pool pool(r->pool); - httpdDebugRequest(r, "modoauth2::handler::input"); + httpdDebugRequest(r, "modoauth2::checkAuthn::input"); const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth2); // Get session id from the request - const maybe<string> sid = oauth::sessionID(r); + const maybe<string> sid = openauth::sessionID(r); if (hasContent(sid)) { // Decline if the session id was not created by this module if (substr(content(sid), 0, 7) != "OAuth2_") return DECLINED; // If we're authenticated store the user info in the request - const failable<value> info = oauth::userInfo(content(sid), sc.mc); - if (hasContent(info)) + const failable<value> info = userInfo(content(sid), sc.mc); + if (hasContent(info)) { + r->ap_auth_type = const_cast<char*>(atype); return httpd::reportStatus(authenticated(content(info), r)); + } } // Get the request args const list<list<value> > args = httpd::queryArgs(r); - // Decline if the request is for OpenID authentication + // Decline if the request is for another authentication provider if (!isNil(assoc<value>("openid_identifier", args))) return DECLINED; - - // Decline if the request is for OAuth1 authentication if (!isNil(assoc<value>("mod_oauth1_step", args))) return DECLINED; @@ -286,15 +280,20 @@ int handler(request_rec* r) { const value step = !isNil(sl) && !isNil(cdr(sl))? cadr(sl) : ""; // Handle OAuth authorize request step - if (step == "authorize") + if (step == "authorize") { + r->ap_auth_type = const_cast<char*>(atype); return httpd::reportStatus(authorize(args, r, sc)); + } // Handle OAuth access_token request step - if (step == "access_token") + if (step == "access_token") { + r->ap_auth_type = const_cast<char*>(atype); return httpd::reportStatus(access_token(args, r, sc)); + } // Redirect to the login page - return httpd::reportStatus(oauth::login(dc.login, r)); + r->ap_auth_type = const_cast<char*>(atype); + return httpd::reportStatus(openauth::login(dc.login, r)); } /** @@ -412,8 +411,7 @@ const command_rec commands[] = { 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_check_user_id(checkUserID, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_handler(handler, NULL, NULL, APR_HOOK_FIRST); + ap_hook_check_authn(checkAuthn, NULL, NULL, APR_HOOK_MIDDLE, AP_AUTH_INTERNAL_PER_CONF); } } diff --git a/sca-cpp/trunk/modules/oauth/oauth-conf b/sca-cpp/trunk/modules/oauth/oauth-conf index 91ae1916c7..4ac231a55b 100755 --- a/sca-cpp/trunk/modules/oauth/oauth-conf +++ b/sca-cpp/trunk/modules/oauth/oauth-conf @@ -26,7 +26,7 @@ conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"` host=`echo $conf | awk '{ print $6 }'` # Configure HTTPD mod_tuscany_oauth module -cat >>$root/conf/httpd.conf <<EOF +cat >>$root/conf/auth.conf <<EOF # Generated by: oauth-conf $* # Load support for OAuth authentication LoadModule mod_tuscany_oauth1 $here/libmod_tuscany_oauth1.so @@ -35,22 +35,10 @@ LoadModule mod_tuscany_oauth2 $here/libmod_tuscany_oauth2.so # Enable OAuth authentication <Location /> AuthType Open +AuthName "$host" AuthOAuth On AuthOAuthLoginPage /login -</Location> - -# Enable unauthenticated access to public areas -<Location /login> -AuthOAuth Off -</Location> -<Location /logout> -AuthOAuth Off -</Location> -<Location /public> -AuthOAuth Off -</Location> -<Location /ui> -AuthOAuth Off +Require valid-user </Location> # Configure OAuth App keys @@ -65,14 +53,3 @@ cat >$root/cert/oauth-keys.conf <<EOF EOF -cat >>$root/conf/vhost-ssl.conf <<EOF -# Generated by: oauth-conf $* -# Require OAuth authentication -<Location /> -AuthType Open -AuthName "$host" -Require valid-user -</Location> - -EOF - diff --git a/sca-cpp/trunk/modules/oauth/oauth-memcached-conf b/sca-cpp/trunk/modules/oauth/oauth-memcached-conf index 6634511d61..23a82a0486 100755 --- a/sca-cpp/trunk/modules/oauth/oauth-memcached-conf +++ b/sca-cpp/trunk/modules/oauth/oauth-memcached-conf @@ -24,7 +24,7 @@ host=$2 port=$3 # Configure HTTPD mod_tuscany_oauth module cache -cat >>$root/conf/httpd.conf <<EOF +cat >>$root/conf/auth.conf <<EOF # Generated by: oauth-memcached-conf $* AddAuthOAuthMemcached $host:$port diff --git a/sca-cpp/trunk/modules/oauth/start-mixed-test b/sca-cpp/trunk/modules/oauth/start-mixed-test index e838e9bb83..c368c29ed2 100755 --- a/sca-cpp/trunk/modules/oauth/start-mixed-test +++ b/sca-cpp/trunk/modules/oauth/start-mixed-test @@ -44,6 +44,8 @@ here=`readlink -f $0`; here=`dirname $here` ../openid/openid-memcached-conf tmp localhost 11212 ../openid/openid-memcached-conf tmp localhost 11213 +../http/open-auth-conf tmp + ../../modules/server/server-conf tmp ../../modules/server/scheme-conf tmp cat >>tmp/conf/httpd.conf <<EOF @@ -51,6 +53,7 @@ SCAContribution `pwd`/ SCAComposite oauth.composite Alias /login/index.html $here/htdocs/login/mixed.html + EOF ../../modules/http/httpd-start tmp diff --git a/sca-cpp/trunk/modules/oauth/start-test b/sca-cpp/trunk/modules/oauth/start-test index 8c59009102..8fd9d01302 100755 --- a/sca-cpp/trunk/modules/oauth/start-test +++ b/sca-cpp/trunk/modules/oauth/start-test @@ -21,14 +21,14 @@ ../../components/cache/memcached-start 11212 ../../components/cache/memcached-start 11213 -../../modules/http/ssl-ca-conf tmp jsdelfino.com -../../modules/http/ssl-cert-conf tmp jsdelfino.com -../../modules/http/httpd-conf tmp jsdelfino.com 8090/80 htdocs +../../modules/http/ssl-ca-conf tmp localhost +../../modules/http/ssl-cert-conf tmp localhost +../../modules/http/httpd-conf tmp localhost 8090/80 htdocs ../../modules/http/httpd-ssl-conf tmp 8453/443 ./oauth-conf tmp -./oauth-memcached-conf tmp jsdelfino.com 11212 -./oauth-memcached-conf tmp jsdelfino.com 11213 +./oauth-memcached-conf tmp localhost 11212 +./oauth-memcached-conf tmp localhost 11213 # Configure your app keys here ./oauth1-appkey-conf tmp twitter.com app2345 secret7890 diff --git a/sca-cpp/trunk/modules/openid/htdocs/index.html b/sca-cpp/trunk/modules/openid/htdocs/index.html index cdc65a4e37..e42e347671 100644 --- a/sca-cpp/trunk/modules/openid/htdocs/index.html +++ b/sca-cpp/trunk/modules/openid/htdocs/index.html @@ -19,7 +19,7 @@ <html> <head> -<script type="text/javascript" src="/js/ref.js"></script> +<script type="text/javascript" src="/wiring/ref.js"></script> <script type="text/javascript"> var protected = component("Protected"); var userInfo = defun(reference(protected, "userInfo"), "getuser", "getemail", "getrealm"); diff --git a/sca-cpp/trunk/modules/openid/openid-conf b/sca-cpp/trunk/modules/openid/openid-conf index 839b58b554..1d208784de 100755 --- a/sca-cpp/trunk/modules/openid/openid-conf +++ b/sca-cpp/trunk/modules/openid/openid-conf @@ -26,8 +26,8 @@ conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"` host=`echo $conf | awk '{ print $6 }'` openid_prefix=`cat $here/openid.prefix` -# Configure HTTPD mod_auth_openid module -cat >>$root/conf/httpd.conf <<EOF +# Configure OpenID authentication +cat >>$root/conf/auth.conf <<EOF # Generated by: openid-conf $* # Load support for OpenID authentication LoadModule authopenid_module $openid_prefix/modules/mod_auth_openid.so @@ -35,6 +35,8 @@ LoadModule authopenid_module $openid_prefix/modules/mod_auth_openid.so # Enable OpenID authentication <Location /> AuthType Open +AuthName "$host" +Require valid-user AuthOpenIDEnabled On AuthOpenIDCookiePath / AuthOpenIDCookieName TuscanyOpenAuth @@ -47,30 +49,5 @@ AuthOpenIDAXAdd FIRSTNAME http://axschema.org/namePerson/first AuthOpenIDAXAdd LASTNAME http://axschema.org/namePerson/last </Location> -# Enable unauthenticated access to public areas -<Location /login> -AuthOpenIDEnabled Off -</Location> -<Location /logout> -AuthOpenIDEnabled Off -</Location> -<Location /public> -AuthOpenIDEnabled Off -</Location> -<Location /ui> -AuthOpenIDEnabled Off -</Location> - -EOF - -cat >>$root/conf/vhost-ssl.conf <<EOF -# Generated by: openid-conf $* -# Require OpenID authentication -<Location /> -AuthType Open -AuthName "$host" -Require valid-user -</Location> - EOF diff --git a/sca-cpp/trunk/modules/openid/openid-memcached-conf b/sca-cpp/trunk/modules/openid/openid-memcached-conf index 776631dab8..1717b3ce92 100755 --- a/sca-cpp/trunk/modules/openid/openid-memcached-conf +++ b/sca-cpp/trunk/modules/openid/openid-memcached-conf @@ -24,7 +24,7 @@ host=$2 port=$3 # Configure HTTPD mod_auth_openid module cache -cat >>$root/conf/httpd.conf <<EOF +cat >>$root/conf/auth.conf <<EOF # Generated by: openid-cache-conf $* AddAuthOpenIDMemcached $host:$port diff --git a/sca-cpp/trunk/modules/openid/openid-step2-conf b/sca-cpp/trunk/modules/openid/openid-step2-conf index 30fdc4846e..d91becf7a4 100755 --- a/sca-cpp/trunk/modules/openid/openid-step2-conf +++ b/sca-cpp/trunk/modules/openid/openid-step2-conf @@ -26,19 +26,17 @@ conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"` host=`echo $conf | awk '{ print $6 }'` # Configure HTTPD to serve OpenID XRDS and LRDD documents -cat >>$root/conf/httpd.conf <<EOF +cat >>$root/conf/auth.conf <<EOF # Generated by: openid-step2-conf $* # Serve OpenID XRDS document Alias /openid $root/conf/openid.xrds <Location /openid> -AuthOpenIDEnabled Off ForceType application/xrds+xml </Location> # Serve OpenID LRDD document Alias /.well-known/host-meta $root/conf/openid.lrdd <Location /.well-known/host-meta> -AuthOpenIDEnabled Off ForceType text/plain </Location> diff --git a/sca-cpp/trunk/modules/python/eval.hpp b/sca-cpp/trunk/modules/python/eval.hpp index 9b75945cf2..0ff68a6a1d 100644 --- a/sca-cpp/trunk/modules/python/eval.hpp +++ b/sca-cpp/trunk/modules/python/eval.hpp @@ -135,8 +135,10 @@ PyObject* pyLambda_getattr(PyObject *self, PyObject *attrname) { if (substr(name, 0, 1) == "_") return PyObject_GenericGetAttr(self, attrname); - if (name == "eval") + if (name == "eval") { + Py_INCREF(self); return self; + } const pyLambda* pyl = (pyLambda*)self; debug(name, "python::getattr::name"); diff --git a/sca-cpp/trunk/modules/server/Makefile.am b/sca-cpp/trunk/modules/server/Makefile.am index 349e372a74..efe8874ecb 100644 --- a/sca-cpp/trunk/modules/server/Makefile.am +++ b/sca-cpp/trunk/modules/server/Makefile.am @@ -23,9 +23,9 @@ incldir = $(prefix)/include/modules/server dist_mod_SCRIPTS = cpp-conf scheme-conf server-conf moddir = $(prefix)/modules/server -nobase_dist_mod_DATA = htdocs/js/*.js +nobase_dist_mod_DATA = htdocs/wiring/*.js -EXTRA_DIST = domain-test.composite client-test.scm server-test.scm htdocs/*.xml htdocs/*.txt htdocs/*.html htdocs/js/*.js +EXTRA_DIST = domain-test.composite client-test.scm server-test.scm htdocs/*.xml htdocs/*.txt htdocs/*.html htdocs/wiring/*.js mod_LTLIBRARIES = libmod_tuscany_eval.la libmod_tuscany_wiring.la noinst_DATA = libmod_tuscany_eval.so libmod_tuscany_wiring.so diff --git a/sca-cpp/trunk/modules/server/htdocs/js/ref.js b/sca-cpp/trunk/modules/server/htdocs/wiring/ref.js index 95a84c01a5..95a84c01a5 100644 --- a/sca-cpp/trunk/modules/server/htdocs/js/ref.js +++ b/sca-cpp/trunk/modules/server/htdocs/wiring/ref.js diff --git a/sca-cpp/trunk/modules/server/server-conf b/sca-cpp/trunk/modules/server/server-conf index 5c1c1bc9fc..e790a147e0 100755 --- a/sca-cpp/trunk/modules/server/server-conf +++ b/sca-cpp/trunk/modules/server/server-conf @@ -50,7 +50,7 @@ LoadModule mod_tuscany_wiring $here/libmod_tuscany_wiring.so SCAWiringServerName $servername # Serve HTTP binding JavaScript client code -Alias /js/ref.js $here/htdocs/js/ref.js +Alias /wiring/ref.js $here/htdocs/wiring/ref.js EOF |