From 3ac22b097d9a9e829ec45963a7c3a40dd12b40a1 Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Sat, 13 Nov 2010 07:53:10 +0000 Subject: 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 --- sca-cpp/trunk/modules/http/Makefile.am | 13 +- sca-cpp/trunk/modules/http/basic-auth-conf | 51 ++++ sca-cpp/trunk/modules/http/form-auth-conf | 64 ++++ sca-cpp/trunk/modules/http/htdocs/login/index.html | 39 +++ .../trunk/modules/http/htdocs/logout/index.html | 33 +++ sca-cpp/trunk/modules/http/http.hpp | 9 +- sca-cpp/trunk/modules/http/httpd-auth-conf | 49 ---- sca-cpp/trunk/modules/http/httpd-conf | 90 ++++-- sca-cpp/trunk/modules/http/httpd-ssl-conf | 32 +- sca-cpp/trunk/modules/http/httpd.hpp | 29 +- sca-cpp/trunk/modules/http/mod-openauth.cpp | 325 +++++++++++++++++++++ sca-cpp/trunk/modules/http/open-auth-conf | 66 +++++ sca-cpp/trunk/modules/http/openauth.hpp | 98 +++++++ sca-cpp/trunk/modules/http/proxy-conf | 3 +- sca-cpp/trunk/modules/http/proxy-ssl-conf | 5 +- 15 files changed, 793 insertions(+), 113 deletions(-) create mode 100755 sca-cpp/trunk/modules/http/basic-auth-conf create mode 100755 sca-cpp/trunk/modules/http/form-auth-conf create mode 100644 sca-cpp/trunk/modules/http/htdocs/login/index.html create mode 100644 sca-cpp/trunk/modules/http/htdocs/logout/index.html delete mode 100755 sca-cpp/trunk/modules/http/httpd-auth-conf create mode 100644 sca-cpp/trunk/modules/http/mod-openauth.cpp create mode 100755 sca-cpp/trunk/modules/http/open-auth-conf create mode 100644 sca-cpp/trunk/modules/http/openauth.hpp (limited to 'sca-cpp/trunk/modules/http') 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/basic-auth-conf b/sca-cpp/trunk/modules/http/basic-auth-conf new file mode 100755 index 0000000000..74f4a61959 --- /dev/null +++ b/sca-cpp/trunk/modules/http/basic-auth-conf @@ -0,0 +1,51 @@ +#!/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 basic 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 basic authentication configuration +cat >>$root/conf/auth.conf < +AuthType Basic +AuthName "$host" +AuthBasicProvider file +AuthUserFile "$root/conf/httpd.passwd" +Require valid-user + + +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/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 < +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 + + + +SetHandler form-login-handler + + + +SetHandler form-logout-handler + + +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 @@ + + +

Sign in

+ + + +
+ + + + +
Username:
Password:
+ +
+ + + 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 @@ + + + +

Sign out

+ +
+ + +
+ 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 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& h) { } template const failable > apply(const list >& hdr, const lambda& 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 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 connect(const string& url, CURLSession& cs) { + debug(url, "http::connect::url"); // Setup the CURL session const failable fch = setup(url, cs); diff --git a/sca-cpp/trunk/modules/http/httpd-auth-conf b/sca-cpp/trunk/modules/http/httpd-auth-conf deleted file mode 100755 index be117c008f..0000000000 --- a/sca-cpp/trunk/modules/http/httpd-auth-conf +++ /dev/null @@ -1,49 +0,0 @@ -#!/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 SSL 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 basic authentication configuration -cat >>$root/conf/vhost-ssl.conf < -AuthType Basic -AuthName "$host" -AuthUserFile "$root/conf/httpd.passwd" -Require valid-user - - -EOF - -# Create test users -$httpd_prefix/bin/htpasswd -bc $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/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 Options None AllowOverride None -Order deny,allow -Deny from all +Require all denied - -Order deny,allow -Deny from all -Satisfy Any - -# Allow access to document root - -Options FollowSymLinks -Allow from all - +# Configure authentication +Include conf/auth.conf -# Allow access to root location - -Options FollowSymLinks -Order deny,allow -Allow from all +# Allow access to public locations + +AuthType None +Require all granted + + +AuthType None +Require all granted + + +AuthType None +Require all granted + + +AuthType None +Require all granted + + +AuthType None +Require all granted + + +AuthType None +Require all granted + + +AuthType None +Require all granted + + +AuthType None +Require all granted # Listen on HTTP port @@ -152,6 +183,25 @@ Include conf/svhost.conf EOF +# Generate auth configuration +cat >$root/conf/auth.conf < +Options FollowSymLinks +Require all granted + + +# Allow access to root location + +Options FollowSymLinks +Require all granted + + +EOF + # Generate vhost configuration cat >$root/conf/vhost.conf < SetHandler server-status HostnameLookups on -Allow from all Require user admin @@ -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 < # 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 <= 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 <= 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 < #define APR_WANT_STRFUNC #include +#include #include +// Hack to workaround compile error with HTTPD 2.3.8 +#define new new_ #include +#undef new #include #include #include #include +// Hack to workaround compile error with HTTPD 2.3.8 +#define aplog_module_index aplog_module_index = 0 #include +#undef aplog_module_index +#undef APLOG_MODULE_INDEX +#define APLOG_MODULE_INDEX (aplog_module_index ? *aplog_module_index : APLOG_NO_MODULE) #include #include #include @@ -46,6 +55,8 @@ #include #include #include +#include +#include #include "string.hpp" #include "stream.hpp" @@ -358,6 +369,7 @@ const failable writeResult(const failable >& ls, const string& * Report a request execution status. */ const int reportStatus(const failable& rc) { + debug(rc, "httpd::reportStatus::rc"); if (!hasContent(rc)) return HTTP_INTERNAL_SERVER_ERROR; return content(rc); @@ -575,10 +587,11 @@ const failable 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 + +#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 userInfo(const value& sid, const string& realm) { + const list> info = httpd::queryArgs(sid); + debug(info, "modopenauth::userInfo::info"); + const list user = assoc(realm + "-user", info); + if (isNil(user)) + return mkfailure("Couldn't retrieve user id"); + const list pw = assoc(realm + "-pw", info); + if (isNil(pw)) + return mkfailure("Couldn't retrieve password"); + return value(mklist(mklist("realm", realm), mklist("id", cadr(user)), mklist("password", cadr(pw)))); +} + +/** + * Return the user info from a basic auth header. + */ +const failable 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("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(&decoded_line), ':')); + const string pw(decoded_line); + + return value(mklist(mklist("realm", realm), mklist("id", user), mklist("password", pw))); +} + +/** + * Handle an authenticated request. + */ +const failable authenticated(const list >& info, request_rec* r) { + debug(info, "modopenauth::authenticated::info"); + + // Store user info in the request + const list realm = assoc("realm", info); + if (isNil(realm) || isNil(cdr(realm))) + return mkfailure("Couldn't retrieve realm"); + apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "REALM"), apr_pstrdup(r->pool, c_str(cadr(realm)))); + + const list id = assoc("id", info); + if (isNil(id) || isNil(cdr(id))) + return mkfailure("Couldn't retrieve user id"); + 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 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("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("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(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 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("Missing AuthName")); + + // Extract user info from the session id + const failable info = userInfo(content(sid), aname); + if (hasContent(info)) { + + // Try to authenticate the request + const value cinfo = content(info); + const failable authz = checkAuthnz(cadr(assoc("id", cinfo)), cadr(assoc("password", cinfo)), r); + if (!hasContent(authz)) { + + // Authentication failed, redirect to login page + r->ap_auth_type = const_cast(atype); + return httpd::reportStatus(login(dc.login, r)); + } + + // Successfully authenticated, store the user info in the request + r->ap_auth_type = const_cast(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("Missing AuthName")); + + // Extract user info from the session id + const failable info = userInfo(header, aname, r); + if (hasContent(info)) { + + // Try to authenticate the request + const value cinfo = content(info); + const failable authz = checkAuthnz(cadr(assoc("id", cinfo)), cadr(assoc("password", cinfo)), r); + if (!hasContent(authz)) { + + // Authentication failed, redirect to login page + r->ap_auth_type = const_cast(atype); + return httpd::reportStatus(login(dc.login, r)); + } + + // Successfully authenticated, store the user info in the request + r->ap_auth_type = const_cast(atype); + return httpd::reportStatus(authenticated(cinfo, r)); + } + } + + // Get the request args + const list > args = httpd::queryArgs(r); + + // Decline if the request is for another authentication provider + if (!isNil(assoc("openid_identifier", args))) + return DECLINED; + if (!isNil(assoc("mod_oauth1_step", args))) + return DECLINED; + if (!isNil(assoc("mod_oauth2_step", args))) + return DECLINED; + + // Redirect to the login page + r->ap_auth_type = const_cast(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(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(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(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, NULL, + // server config and merger + tuscany::httpd::makeServerConf, 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 < +AuthType Open +AuthName "$host" +AuthOpenAuth On +AuthOpenAuthLoginPage /login +AuthUserFile "$root/conf/httpd.passwd" +Require valid-user + + +# Use HTTPD form-based authentication + +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 + + +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/openauth.hpp b/sca-cpp/trunk/modules/http/openauth.hpp new file mode 100644 index 0000000000..53250b4732 --- /dev/null +++ b/sca-cpp/trunk/modules/http/openauth.hpp @@ -0,0 +1,98 @@ +/* + * 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$ */ + +#ifndef tuscany_openauth_hpp +#define tuscany_openauth_hpp + +/** + * Tuscany Open auth support utility functions. + */ + +#include "string.hpp" +#include "stream.hpp" +#include "list.hpp" +#include "tree.hpp" +#include "value.hpp" +#include "monad.hpp" +#include "../json/json.hpp" +#include "../http/httpd.hpp" +#include "../http/http.hpp" + +namespace tuscany { +namespace openauth { + +/** + * Return the session id from a request. + */ +const char* cookieName(const char* cs) { + if (*cs != ' ') + return cs; + return cookieName(cs + 1); +} +const maybe sessionID(const list c) { + if (isNil(c)) + return maybe(); + const string cn = cookieName(c_str(car(c))); + const int i = find(cn, "="); + if (i < length(cn)) { + const list kv = mklist(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 sessionID(const request_rec* r) { + const char* c = apr_table_get(r->headers_in, "Cookie"); + debug(c, "openauth::sessionid::cookies"); + if (c == NULL) + return maybe(); + return sessionID(tokenize(";", c)); +} + +/** + * Convert a session id to a cookie string. + */ +const string cookie(const string& sid) { + const time_t t = time(NULL) + 86400; + char exp[32]; + strftime(exp, 32, "%a, %d-%b-%Y %H:%M:%S GMT", gmtime(&t)); + const string c = string("TuscanyOpenAuth=") + sid + string(";path=/;expires=" + string(exp)) + ";secure=TRUE"; + debug(c, "openauth::cookie"); + return c; +} + +/** + * Redirect to the configured login page. + */ +const failable login(const string& page, request_rec* r) { + const list > largs = mklist >(mklist("openauth_referrer", httpd::escape(httpd::url(r->uri, r)))); + const string loc = httpd::url(page, r) + string("?") + httpd::queryString(largs); + debug(loc, "openauth::login::uri"); + return httpd::externalRedirect(loc, r); +} + +} +} + +#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/ -Order deny,allow -Allow from all +Require all granted ProxySet lbmethod=byrequests 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/ -Order deny,allow -Allow from all +Require all granted ProxySet lbmethod=byrequests @@ -43,8 +42,6 @@ ProxySet lbmethod=byrequests SetHandler balancer-manager HostnameLookups on -Deny from all -Allow from all Require user admin -- cgit v1.2.3