summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sca-cpp/trunk/.gitignore1
-rwxr-xr-xsca-cpp/trunk/components/cache/memcached-ssl-test2
-rw-r--r--sca-cpp/trunk/hosting/server/Makefile.am36
-rw-r--r--sca-cpp/trunk/hosting/server/authn.py40
-rw-r--r--sca-cpp/trunk/hosting/server/data/accounts/admin/user.account1
-rw-r--r--sca-cpp/trunk/hosting/server/data/accounts/jane/user.account1
-rw-r--r--sca-cpp/trunk/hosting/server/data/accounts/jane@localhost/user.account1
-rw-r--r--sca-cpp/trunk/hosting/server/data/accounts/jane@sca-store.com/user.account1
-rw-r--r--sca-cpp/trunk/hosting/server/data/accounts/john/user.account1
-rw-r--r--sca-cpp/trunk/hosting/server/data/accounts/john@localhost/user.account1
-rw-r--r--sca-cpp/trunk/hosting/server/data/accounts/john@sca-store.com/user.account1
-rwxr-xr-xsca-cpp/trunk/hosting/server/delete-auth61
-rwxr-xr-xsca-cpp/trunk/hosting/server/get-auth62
-rwxr-xr-xsca-cpp/trunk/hosting/server/put-auth80
-rw-r--r--sca-cpp/trunk/hosting/server/server.composite51
-rwxr-xr-xsca-cpp/trunk/hosting/server/ssl-start113
-rw-r--r--sca-cpp/trunk/hosting/server/user.py6
-rwxr-xr-xsca-cpp/trunk/modules/http/basic-auth-conf15
-rwxr-xr-xsca-cpp/trunk/modules/http/cert-auth-conf10
-rwxr-xr-xsca-cpp/trunk/modules/http/form-auth-conf14
-rwxr-xr-xsca-cpp/trunk/modules/http/httpd-ssl-conf26
-rwxr-xr-xsca-cpp/trunk/modules/http/httpd-tunnel-ssl-conf38
-rw-r--r--sca-cpp/trunk/modules/http/mod-openauth.cpp189
-rwxr-xr-xsca-cpp/trunk/modules/http/mod-security-conf28
-rwxr-xr-xsca-cpp/trunk/modules/http/open-auth-conf22
-rw-r--r--sca-cpp/trunk/modules/http/openauth.hpp10
-rwxr-xr-xsca-cpp/trunk/modules/http/passwd-auth-conf2
-rw-r--r--sca-cpp/trunk/modules/oauth/Makefile.am2
-rw-r--r--sca-cpp/trunk/modules/oauth/mod-oauth1.cpp139
-rw-r--r--sca-cpp/trunk/modules/oauth/mod-oauth2.cpp141
-rwxr-xr-xsca-cpp/trunk/modules/oauth/oauth-conf20
-rwxr-xr-xsca-cpp/trunk/modules/oauth/oauth12-conf115
-rwxr-xr-xsca-cpp/trunk/modules/oauth/start-mixed-test13
-rwxr-xr-xsca-cpp/trunk/modules/oauth/start-test6
-rwxr-xr-xsca-cpp/trunk/modules/openid/openid-conf9
-rwxr-xr-xsca-cpp/trunk/modules/openid/start-test6
-rw-r--r--sca-cpp/trunk/modules/server/mod-eval.hpp258
-rwxr-xr-xsca-cpp/trunk/samples/store-cluster/tunnel-ssl-conf1
38 files changed, 1156 insertions, 367 deletions
diff --git a/sca-cpp/trunk/.gitignore b/sca-cpp/trunk/.gitignore
index 539b8309ac..cb61e71d6c 100644
--- a/sca-cpp/trunk/.gitignore
+++ b/sca-cpp/trunk/.gitignore
@@ -148,6 +148,7 @@ hosting/server/nuvem
hosting/server/lib
hosting/server/data/apps/*/nuvem
hosting/server/data/apps/*/lib
+hosting/server/data/authn
chat-send
opencl-shell
opencl-test
diff --git a/sca-cpp/trunk/components/cache/memcached-ssl-test b/sca-cpp/trunk/components/cache/memcached-ssl-test
index 8ef37a0b98..a9d42ffd83 100755
--- a/sca-cpp/trunk/components/cache/memcached-ssl-test
+++ b/sca-cpp/trunk/components/cache/memcached-ssl-test
@@ -29,6 +29,7 @@ rm -rf tmp
../../modules/http/httpd-conf tmp/tunnel localhost 8089 htdocs
../../modules/http/httpd-event-conf tmp/tunnel
+../../modules/http/httpd-tunnel-ssl-conf tmp/tunnel
tar -C tmp/ssl -c `../../modules/http/ssl-cert-find tmp/ssl` | tar -C tmp/tunnel -x
../../modules/http/tunnel-ssl-conf tmp/tunnel 11211 localhost 8453 11411
../../modules/http/tunnel-ssl-conf tmp/tunnel 11212 localhost 8453 11412
@@ -39,6 +40,7 @@ tar -C tmp/ssl -c `../../modules/http/ssl-cert-find tmp/ssl` | tar -C tmp/tunnel
../../modules/http/httpd-event-conf tmp/server
tar -C tmp/ssl -c `../../modules/http/ssl-cert-find tmp/ssl` | tar -C tmp/server -x
../../modules/http/httpd-ssl-conf tmp/server 8453
+../../modules/http/httpd-tunnel-ssl-conf tmp/server
../../modules/http/cert-auth-conf tmp/server
../../modules/http/httpd-start tmp/server
sleep 1
diff --git a/sca-cpp/trunk/hosting/server/Makefile.am b/sca-cpp/trunk/hosting/server/Makefile.am
index d140895dcd..d6e15f819b 100644
--- a/sca-cpp/trunk/hosting/server/Makefile.am
+++ b/sca-cpp/trunk/hosting/server/Makefile.am
@@ -18,16 +18,18 @@
if WANT_PYTHON
moddir = $(prefix)/hosting/server
-dist_mod_SCRIPTS = start stop ssl-start mkapplinks config-backup data-backup
+dist_mod_SCRIPTS = start stop ssl-start mkapplinks config-backup data-backup put-auth get-auth delete-auth
-not_minified = htdocs/public/iframe.html htdocs/create/index.html htdocs/page/index.html htdocs/login/index.html htdocs/public/notfound/index.html htdocs/public/oops/index.html htdocs/proxy/public/oops/index.html htdocs/graph/index.html htdocs/public/notauth/index.html htdocs/account/index.html htdocs/home/index.html htdocs/index.html htdocs/public/notyet/index.html htdocs/clone/index.html htdocs/delete/index.html htdocs/stats/index.html htdocs/app/index.html htdocs/store/index.html htdocs/config.js htdocs/public/config.js
+not_minified = htdocs/public/iframe.html htdocs/create/index.html htdocs/page/index.html htdocs/login/index.html htdocs/public/notfound/index.html htdocs/public/oops/index.html htdocs/proxy/public/oops/index.html htdocs/graph/index.html htdocs/public/notauth/index.html htdocs/account/index.html htdocs/home/index.html htdocs/index.html htdocs/public/notyet/index.html htdocs/clone/index.html htdocs/delete/index.html htdocs/stats/index.html htdocs/app/index.html htdocs/store/index.html htdocs/config.js htdocs/public/config.js htdocs/cache-template.cmf htdocs/app/cache-template.cmf htdocs/cache-template.cmf htdocs/app/cache-template.cmf
minified = htdocs/public/iframe-min.html htdocs/create/index-min.html htdocs/page/index-min.html htdocs/login/index-min.html htdocs/public/notfound/index-min.html htdocs/public/oops/index-min.html htdocs/proxy/public/oops/index-min.html htdocs/graph/index-min.html htdocs/public/notauth/index-min.html htdocs/account/index-min.html htdocs/home/index-min.html htdocs/index-min.html htdocs/public/notyet/index-min.html htdocs/clone/index-min.html htdocs/delete/index-min.html htdocs/stats/index-min.html htdocs/app/index-min.html htdocs/store/index-min.html htdocs/config-min.js htdocs/public/config-min.js
-resources = server.composite *.py htdocs/*.cmf htdocs/*.ico htdocs/home/*.png htdocs/app/*.cmf htdocs/home/*.b64 htdocs/*.txt htdocs/public/*.png htdocs/public/*.b64 data/palettes/*/palette.composite data/accounts/*/*.account data/apps/*/app.composite data/apps/*/app.stats data/apps/*/htdocs/app.html data/dashboards/*/user.apps data/store/*/store.apps ${not_minified} ${minified}
+js_minified = ../../modules/js/htdocs/all-min.js ../../modules/js/htdocs/ui-min.css
+
+resources = server.composite *.py data/palettes/*/palette.composite data/accounts/*/*.account data/apps/*/app.composite data/apps/*/app.stats data/apps/*/htdocs/app.html data/dashboards/*/user.apps data/store/*/store.apps htdocs/cache-manifest.cmf htdocs/app/cache-manifest.cmf htdocs/*.ico htdocs/home/*.png htdocs/home/*.b64 htdocs/*.txt htdocs/public/*.png htdocs/public/*.b64 ${minified}
nobase_dist_mod_DATA = ${resources}
-EXTRA_DIST = ${resources}
+EXTRA_DIST = ${resources} ${not_minified}
SUFFIXES = -min.html -min.js
.html-min.html:
@@ -36,9 +38,29 @@ SUFFIXES = -min.html -min.js
.js-min.js:
../../modules/http/minify-js $< $@
-CLEANFILES = ${minified}
+htdocs/cache-manifest.cmf: htdocs/cache-template.cmf ${minified} ${js_minified}
+ ../../modules/http/cache-manifest htdocs $^
+
+htdocs/app/cache-manifest.cmf: htdocs/app/cache-template.cmf ${minified} ${js_minified}
+ ../../modules/http/cache-manifest htdocs/app $^
+
+nuvem:
+ ln -s "../../../nuvem/nuvem-parallel/nuvem" "nuvem"
+
+lib:
+ ln -s "../../components" "lib"
+
+install-data-hook:
+ cd $(moddir); rm -f nuvem; ln -s "../../../nuvem/nuvem-parallel/nuvem" "nuvem"
+ cd $(moddir); rm -f lib; ln -s "../../components" "lib"
+
+CLEANFILES = ${minified} nuvem lib htdocs/cache-manifest.cmf htdocs/app/cache-manifest.cmf
+
+client_test_SOURCES = client-test.cpp
+client_test_LDFLAGS = -lxml2 -lcurl -lmozjs
-dist_noinst_SCRIPTS = server-test test.py
-TESTS = server-test
+dist_noinst_SCRIPTS = logic-test server-test test.py
+noinst_PROGRAMS = client-test
+TESTS = logic-test
endif
diff --git a/sca-cpp/trunk/hosting/server/authn.py b/sca-cpp/trunk/hosting/server/authn.py
new file mode 100644
index 0000000000..4d4f34b9fb
--- /dev/null
+++ b/sca-cpp/trunk/hosting/server/authn.py
@@ -0,0 +1,40 @@
+# 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.
+
+# User authenticator implementation
+from time import strftime
+from util import *
+
+# Convert a particular user id to an authentication id
+def authnid(id):
+ return append(append(('authn',), id), ('user.authn',))
+
+# Get a user's authentication
+def get(id, cache):
+ authn = cache.get(authnid(id))
+ if isNil(authn) or authn is None:
+ return None
+ return authn
+
+# Update a user's authentication
+def put(id, authn, cache):
+ return cache.put(authnid(id), authn)
+
+# Delete a user's authentication
+def delete(id, cache):
+ return cache.delete(authnid(id))
+
diff --git a/sca-cpp/trunk/hosting/server/data/accounts/admin/user.account b/sca-cpp/trunk/hosting/server/data/accounts/admin/user.account
new file mode 100644
index 0000000000..4f4a754a92
--- /dev/null
+++ b/sca-cpp/trunk/hosting/server/data/accounts/admin/user.account
@@ -0,0 +1 @@
+((entry (title "Admin") (id "admin")))
diff --git a/sca-cpp/trunk/hosting/server/data/accounts/jane/user.account b/sca-cpp/trunk/hosting/server/data/accounts/jane/user.account
new file mode 100644
index 0000000000..a3cf7e2c3d
--- /dev/null
+++ b/sca-cpp/trunk/hosting/server/data/accounts/jane/user.account
@@ -0,0 +1 @@
+((entry (title "Jane Doe") (id "jane") (content (account (description "This is Jane") (keys (key (((@name "key1") (@value "value1")) ((@name "key2") (@value "value2")) ((@name "key3") (@value "value3")) ((@name "") (@value "")) ((@name "") (@value "")))))))))
diff --git a/sca-cpp/trunk/hosting/server/data/accounts/jane@localhost/user.account b/sca-cpp/trunk/hosting/server/data/accounts/jane@localhost/user.account
deleted file mode 100644
index 5fca389f04..0000000000
--- a/sca-cpp/trunk/hosting/server/data/accounts/jane@localhost/user.account
+++ /dev/null
@@ -1 +0,0 @@
-((entry (title "Jane Doe") (id "jane@localhost")))
diff --git a/sca-cpp/trunk/hosting/server/data/accounts/jane@sca-store.com/user.account b/sca-cpp/trunk/hosting/server/data/accounts/jane@sca-store.com/user.account
deleted file mode 100644
index e0d25671b6..0000000000
--- a/sca-cpp/trunk/hosting/server/data/accounts/jane@sca-store.com/user.account
+++ /dev/null
@@ -1 +0,0 @@
-((entry (title "Jane Doe") (id "jane@sca-store.com") (content (account (description "This is Jane") (keys (key (((@name "key1") (@value "value1")) ((@name "key2") (@value "value2")) ((@name "key3") (@value "value3")) ((@name "") (@value "")) ((@name "") (@value ""))))))))) \ No newline at end of file
diff --git a/sca-cpp/trunk/hosting/server/data/accounts/john/user.account b/sca-cpp/trunk/hosting/server/data/accounts/john/user.account
new file mode 100644
index 0000000000..9989daa228
--- /dev/null
+++ b/sca-cpp/trunk/hosting/server/data/accounts/john/user.account
@@ -0,0 +1 @@
+((entry (title "John Doe") (id "john") (content (account (description "This is John") (keys (key (((@name "key1") (@value "value1")) ((@name "key2") (@value "value2")) ((@name "key3") (@value "value3")) ((@name "key4") (@value "value4")) ((@name "key5") (@value "value5")))))))))
diff --git a/sca-cpp/trunk/hosting/server/data/accounts/john@localhost/user.account b/sca-cpp/trunk/hosting/server/data/accounts/john@localhost/user.account
deleted file mode 100644
index 35d6f30f0b..0000000000
--- a/sca-cpp/trunk/hosting/server/data/accounts/john@localhost/user.account
+++ /dev/null
@@ -1 +0,0 @@
-((entry (title "John Doe") (id "john@localhost")))
diff --git a/sca-cpp/trunk/hosting/server/data/accounts/john@sca-store.com/user.account b/sca-cpp/trunk/hosting/server/data/accounts/john@sca-store.com/user.account
deleted file mode 100644
index 273335e1c7..0000000000
--- a/sca-cpp/trunk/hosting/server/data/accounts/john@sca-store.com/user.account
+++ /dev/null
@@ -1 +0,0 @@
-((entry (title "John Doe") (id "john@sca-store.com") (content (account (description "This is John") (keys (key (((@name "key1") (@value "value1")) ((@name "key2") (@value "value2")) ((@name "key3") (@value "value3")) ((@name "key4") (@value "value4")) ((@name "key5") (@value "value5"))))))))) \ No newline at end of file
diff --git a/sca-cpp/trunk/hosting/server/delete-auth b/sca-cpp/trunk/hosting/server/delete-auth
new file mode 100755
index 0000000000..407d730c80
--- /dev/null
+++ b/sca-cpp/trunk/hosting/server/delete-auth
@@ -0,0 +1,61 @@
+#!/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.
+
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+mkdir -p $1
+root=`echo "import os; print os.path.realpath('$1')" | python`
+admin=$2
+apass=$3
+user=$4
+
+httpd_prefix=`cat $here/../../modules/http/httpd.prefix`
+
+conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
+sslconf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-ssl-conf"`
+if [ "$sslconf" = "" ]; then
+ scheme="http"
+ addr=`echo $conf | awk '{ print $7 }'`
+ host=`$here/../../modules/http/httpd-addr ip $addr`
+ if [ "$host" = "" ]; then
+ host="localhost"
+ fi
+ port=`$here/../../modules/http/httpd-addr port $addr`
+else
+ scheme="https"
+ ssladdr=`echo $sslconf | awk '{ print $6 }'`
+ host=`$here/../../modules/http/httpd-addr ip $ssladdr`
+ if [ "$host" = "" ]; then
+ host="localhost"
+ fi
+ port=`$here/../../modules/http/httpd-addr port $ssladdr`
+fi
+
+# Compute user id
+slash=`echo $user | grep "/"`
+if [ "$slash" = "" ]; then
+ id="\"$user\""
+ upath=$user
+else
+ id=`echo $user | awk -F "/" '{ printf "\"%s\" \"%s\"", $2, $3 }'`
+ upath=`echo $user | awk -F "/" '{ printf "%s/%s", $2, $3 }'`
+fi
+
+# Delete user auth
+curl -k -L -u $admin:$apass -X DELETE -H "X-Forwarded-Server: $host" $scheme://$host:$port/c/Authenticator/$upath
+
diff --git a/sca-cpp/trunk/hosting/server/get-auth b/sca-cpp/trunk/hosting/server/get-auth
new file mode 100755
index 0000000000..2be546f91f
--- /dev/null
+++ b/sca-cpp/trunk/hosting/server/get-auth
@@ -0,0 +1,62 @@
+#!/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.
+
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+mkdir -p $1
+root=`echo "import os; print os.path.realpath('$1')" | python`
+admin=$2
+apass=$3
+user=$4
+
+httpd_prefix=`cat $here/../../modules/http/httpd.prefix`
+
+conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
+
+sslconf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-ssl-conf"`
+if [ "$sslconf" = "" ]; then
+ scheme="http"
+ addr=`echo $conf | awk '{ print $7 }'`
+ host=`$here/../../modules/http/httpd-addr ip $addr`
+ if [ "$host" = "" ]; then
+ host="localhost"
+ fi
+ port=`$here/../../modules/http/httpd-addr port $addr`
+else
+ scheme="https"
+ ssladdr=`echo $sslconf | awk '{ print $6 }'`
+ host=`$here/../../modules/http/httpd-addr ip $ssladdr`
+ if [ "$host" = "" ]; then
+ host="localhost"
+ fi
+ port=`$here/../../modules/http/httpd-addr port $ssladdr`
+fi
+
+# Compute user id
+slash=`echo $user | grep "/"`
+if [ "$slash" = "" ]; then
+ id="\"$user\""
+ upath=$user
+else
+ id=`echo $user | awk -F "/" '{ printf "\"%s\" \"%s\"", $2, $3 }'`
+ upath=`echo $user | awk -F "/" '{ printf "%s/%s", $2, $3 }'`
+fi
+
+# Get user auth
+curl -k -L -u $admin:$apass -H "X-Forwarded-Server: $host" $scheme://$host:$port/c/Authenticator/$upath
+
diff --git a/sca-cpp/trunk/hosting/server/put-auth b/sca-cpp/trunk/hosting/server/put-auth
new file mode 100755
index 0000000000..351c9b7d7a
--- /dev/null
+++ b/sca-cpp/trunk/hosting/server/put-auth
@@ -0,0 +1,80 @@
+#!/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.
+
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+mkdir -p $1
+root=`echo "import os; print os.path.realpath('$1')" | python`
+admin=$2
+apass=$3
+user=$4
+upass=$5
+
+httpd_prefix=`cat $here/../../modules/http/httpd.prefix`
+
+conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
+sslconf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-ssl-conf"`
+if [ "$sslconf" = "" ]; then
+ scheme="http"
+ addr=`echo $conf | awk '{ print $7 }'`
+ host=`$here/../../modules/http/httpd-addr ip $addr`
+ if [ "$host" = "" ]; then
+ host="localhost"
+ fi
+ port=`$here/../../modules/http/httpd-addr port $addr`
+else
+ scheme="https"
+ ssladdr=`echo $sslconf | awk '{ print $6 }'`
+ host=`$here/../../modules/http/httpd-addr ip $ssladdr`
+ if [ "$host" = "" ]; then
+ host="localhost"
+ fi
+ port=`$here/../../modules/http/httpd-addr port $ssladdr`
+fi
+
+# Get password hash
+rm -f $root/conf/auth.passwd
+touch $root/conf/auth.passwd
+$httpd_prefix/bin/htpasswd -b $root/conf/auth.passwd "$user" "$upass" 2>/dev/null
+hash=`cat $root/conf/auth.passwd | awk -F ":" '{ print $2 }'`
+rm -f $root/conf/auth.passwd
+
+# Compute user id
+slash=`echo $user | grep "/"`
+if [ "$slash" = "" ]; then
+ id="\"$user\""
+ upath=$user
+else
+ id=`echo $user | awk -F "/" '{ printf "\"%s\" \"%s\"", $2, $3 }'`
+ upath=`echo $user | awk -F "/" '{ printf "%s/%s", $2, $3 }'`
+fi
+
+# Put user auth
+cat >$root/conf/auth.entry <<EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom">
+ <title type="text">$user</title>
+ <id>$user</id>
+ <content type="application/xml">
+ <hash>$hash</hash>
+ </content>
+</entry>
+EOF
+curl -k -L -u $admin:$apass -X PUT -H "X-Forwarded-Server: $host" --data-binary @$root/conf/auth.entry $scheme://$host:$port/c/Authenticator/$upath
+rm $root/conf/auth.entry
+
diff --git a/sca-cpp/trunk/hosting/server/server.composite b/sca-cpp/trunk/hosting/server/server.composite
index 0806a2fa4b..7e4d7196d0 100644
--- a/sca-cpp/trunk/hosting/server/server.composite
+++ b/sca-cpp/trunk/hosting/server/server.composite
@@ -31,12 +31,9 @@
<property name="lastname">?</property>
<property name="realm">?</property>
<property name="host">?</property>
- <service name="User">
- <binding.http uri="user"/>
- </service>
</component>
- <component name="EditWidget">
+ <component name="Editor">
<implementation.widget location="/index.html"/>
<reference name="user" target="User"/>
<reference name="accounts" target="Accounts"/>
@@ -49,7 +46,7 @@
<reference name="log" target="Log"/>
</component>
- <component name="AppWidget">
+ <component name="App">
<implementation.widget location="/app/index.html"/>
<reference name="user" target="User"/>
<reference name="pages" target="Pages"/>
@@ -59,18 +56,17 @@
<component name="Accounts">
<implementation.python script="accounts.py"/>
- <service name="Accounts">
- <binding.http uri="accounts"/>
- </service>
<reference name="user" target="User"/>
<reference name="cache" target="Cache"/>
</component>
+ <component name="Authenticator">
+ <implementation.python script="authn.py"/>
+ <reference name="cache" target="Cache"/>
+ </component>
+
<component name="Dashboards">
<implementation.python script="dashboards.py"/>
- <service name="Dashboards">
- <binding.http uri="dashboards"/>
- </service>
<reference name="user" target="User"/>
<reference name="cache" target="Cache"/>
<reference name="apps" target="Apps"/>
@@ -78,9 +74,6 @@
<component name="AppStore">
<implementation.python script="store.py"/>
- <service name="AppStore">
- <binding.http uri="appstore"/>
- </service>
<reference name="user" target="User"/>
<reference name="cache" target="Cache"/>
<reference name="apps" target="Apps"/>
@@ -88,9 +81,6 @@
<component name="Apps">
<implementation.python script="apps.py"/>
- <service name="Apps">
- <binding.http uri="apps"/>
- </service>
<reference name="user" target="User"/>
<reference name="cache" target="Cache"/>
<reference name="dashboard" target="Dashboards"/>
@@ -101,9 +91,6 @@
<component name="Composites">
<implementation.python script="composites.py"/>
- <service name="Composites">
- <binding.http uri="composites"/>
- </service>
<reference name="user" target="User"/>
<reference name="cache" target="Doccache"/>
<reference name="apps" target="Apps"/>
@@ -111,9 +98,6 @@
<component name="Pages">
<implementation.python script="pages.py"/>
- <service name="Pages">
- <binding.http uri="pages"/>
- </service>
<reference name="user" target="User"/>
<reference name="cache" target="Doccache"/>
<reference name="apps" target="Apps"/>
@@ -121,17 +105,11 @@
<component name="Palettes">
<implementation.python script="palettes.py"/>
- <service name="Palettes">
- <binding.http uri="palettes"/>
- </service>
<reference name="cache" target="Doccache"/>
</component>
<component name="Cache">
<implementation.cpp path="../../components/cache" library="libdatacache"/>
- <service name="Cache">
- <binding.http uri="cache"/>
- </service>
<reference name="l1reader" target="Memcache"/>
<reference name="l1writer" target="Memcache"/>
<reference name="l2reader" target="Database"/>
@@ -140,9 +118,6 @@
<component name="Doccache">
<implementation.cpp path="../../components/cache" library="libdatacache"/>
- <service name="Doccache">
- <binding.http uri="doccache"/>
- </service>
<reference name="l1reader" target="Memcache"/>
<reference name="l1writer" target="Memcache"/>
<reference name="l2reader" target="Documents"/>
@@ -151,9 +126,6 @@
<component name="Memcache">
<implementation.cpp path="../../components/cache" library="libmemcache"/>
- <service name="Memcache">
- <binding.http uri="memcache"/>
- </service>
<property name="server">localhost:11211</property>
<property name="server">localhost:11212</property>
</component>
@@ -162,25 +134,16 @@
<implementation.cpp path="../../components/filedb" library="libfiledb"/>
<property name="dbname">data</property>
<property name="format">scheme</property>
- <service name="Database">
- <binding.http uri="database"/>
- </service>
</component>
<component name="Documents">
<implementation.cpp path="../../components/filedb" library="libfiledb"/>
<property name="dbname">data</property>
<property name="format">xml</property>
- <service name="Documents">
- <binding.http uri="documents"/>
- </service>
</component>
<component name="Log">
<implementation.python script="log.py"/>
- <service name="Log">
- <binding.http uri="log"/>
- </service>
</component>
</composite>
diff --git a/sca-cpp/trunk/hosting/server/ssl-start b/sca-cpp/trunk/hosting/server/ssl-start
index b80b2adf40..d699089847 100755
--- a/sca-cpp/trunk/hosting/server/ssl-start
+++ b/sca-cpp/trunk/hosting/server/ssl-start
@@ -22,7 +22,6 @@
# 127.0.0.1 www.example.com
here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
-jsprefix=`echo "import os; print os.path.realpath('$here/../../modules/js')" | python`
host=`hostname`
# Create SSL certificates
@@ -41,39 +40,33 @@ fi
../../components/cache/memcached-start tmp 11211
../../components/cache/memcached-start tmp 11212
+# Clear document cache
+rm -rf tmp/cache
+
# Configure server
../../modules/http/httpd-conf tmp www.example.com 8090 htdocs
+../../modules/http/alt-host-conf tmp ww1.example.com
+../../modules/http/alt-host-conf tmp ww2.example.com
../../modules/http/httpd-event-conf tmp
+#../../modules/http/cache-conf tmp
../../modules/http/httpd-ssl-conf tmp 8453
+#../../modules/http/cache-ssl-conf tmp
# Configure HTTP basic auth
-../../modules/http/basic-auth-conf tmp
+../../modules/http/basic-auth-conf tmp component
# Configure OAuth authentication
# Configure your OAuth app keys here
-../../modules/oauth/oauth-conf tmp
+../../modules/oauth/oauth-conf tmp component
../../modules/oauth/oauth-memcached-conf tmp localhost 11212
../../modules/oauth/oauth2-appkey-conf tmp facebook.com 12345 67890
../../modules/oauth/oauth2-appkey-conf tmp google.com 12345 67890
-# Configure password authentication
-../../modules/http/open-auth-conf tmp
-../../modules/http/passwd-auth-conf tmp john john
-../../modules/http/passwd-auth-conf tmp jane jane
-../../modules/http/passwd-auth-conf tmp admin admin
-
-# Configure OpenID step2 authentication
-../../modules/openid/openid-conf tmp
-../../modules/openid/openid-step2-conf tmp
-../../modules/openid/openid-memcached-conf tmp localhost 11212
+# Configure form-based authentication
+../../modules/http/open-auth-conf tmp component 80b67f38-b79e-4a72-bb5c-22c69fb00820
-# Configure authorized users
-../../modules/http/group-auth-conf tmp john
-../../modules/http/group-auth-conf tmp jane
-../../modules/http/group-auth-conf tmp admin
-# Configure the email addresses associated with your OpenID and OAuth ids here
-../../modules/http/group-auth-conf tmp john@example.com
-../../modules/http/group-auth-conf tmp jane@example.com
+# Configure authorized admins
+../../modules/http/passwd-auth-conf tmp admin admin
# Configure mod-security
#../../modules/http/mod-security-conf tmp
@@ -103,26 +96,6 @@ SecAuditLog "|$here/../../components/log/scribe-cat $host secaudit"
EOF
-else
- cat >tmp/conf/log.conf <<EOF
-# Generated by: ssl=start $*
-ErrorLog $here/tmp/logs/error_log
-CustomLog $here/tmp/logs/access_log combined
-
-EOF
-
- cat >tmp/conf/log-ssl.conf <<EOF
-# Generated by: ssl-start $*
-CustomLog $here/tmp/logs/ssl_access_log sslcombined
-
-EOF
-
- cat >tmp/conf/mod-security-log.conf <<EOF
-# Generated by: ssl-start $*
-SecAuditLog $here/tmp/logs/secaudit_log
-
-EOF
-
fi
#../../modules/http/httpd-loglevel-conf tmp debug
@@ -143,10 +116,11 @@ cat >>tmp/conf/svhost-ssl.conf <<EOF
ErrorDocument 404 /public/notfound/
ErrorDocument 401 /public/notauth/
ErrorDocument 403 /public/notauth/
+ErrorDocument 400 /public/oops/
+ErrorDocument 405 /public/oops/
ErrorDocument 500 /public/oops/
ErrorDocument 502 /public/oops/
ErrorDocument 503 /public/oops/
-ErrorDocument 405 /public/oops/
EOF
@@ -160,6 +134,12 @@ SCAComposite server.composite
# Configure SCA Composite for mass dynamic virtual Hosting
SCAVirtualContributor Composites
+# Configure SCA Authenticator component
+SCAAuthenticator Authenticator
+
+# Configure SCA wiring timeout
+SCAWiringTimeout 10
+
EOF
# Configure resource aliases
@@ -172,14 +152,6 @@ Alias /proxy/public/config-min.js $here/public/config-min.js
EOF
-# Create app implementation resource links
-if [ ! -e "nuvem" ]; then
- ln -s "../../../nuvem/nuvem-parallel/nuvem" "nuvem"
-fi
-if [ ! -e "lib" ]; then
- ln -s "../../components" "lib"
-fi
-
# Configure app resource aliases
cat >>tmp/conf/svhost-ssl.conf <<EOF
# Generated by: ssl-start $*
@@ -188,6 +160,49 @@ AliasMatch /v/([^/]+)(.*)$ $here/htdocs/app\$2
EOF
+# Configure admin access to server status and info
+cat >tmp/conf/adminauth.conf <<EOF
+# Generated by: ssl-start $*
+# Allow the server admin to view the server status and info
+<Location /server-status>
+AuthType None
+Require all granted
+</Location>
+
+<Location /server-info>
+AuthType None
+Require all granted
+</Location>
+
+EOF
+
+# Configure admin access to components
+cat >>tmp/conf/locauth-ssl.conf <<EOF
+# Generated by: ssl-start $*
+# Allow the server admin to access all components
+<Location /c>
+Require user admin
+</Location>
+<Location /r>
+Require user admin
+</Location>
+<Location /r/Editor>
+Require valid-user
+</Location>
+<Location /r/App>
+Require valid-user
+</Location>
+EOF
+
# Start server
../../modules/http/httpd-start tmp
+sleep 2
+
+# Configure authorized users
+./put-auth tmp admin admin admin admin
+./put-auth tmp admin admin john john
+./put-auth tmp admin admin jane jane
+# Configure the email addresses associated with your OAuth ids here
+./put-auth tmp admin admin /oauth1/john@example.com password
+./put-auth tmp admin admin /oauth2/jane@example.com password
diff --git a/sca-cpp/trunk/hosting/server/user.py b/sca-cpp/trunk/hosting/server/user.py
index 9be48b33da..8038e43563 100644
--- a/sca-cpp/trunk/hosting/server/user.py
+++ b/sca-cpp/trunk/hosting/server/user.py
@@ -21,9 +21,7 @@
def get(i, user, email, nick, full, first, last, realm, host):
if email.eval() != '?':
return email.eval()
- if nick.eval() != '?':
- return nick.eval() + '@' + realm.eval()
if user.eval() != '?':
- return user.eval() + '@' + realm.eval()
- return 'anonymous@' + host.eval();
+ return user.eval()
+ return 'anonymous'
diff --git a/sca-cpp/trunk/modules/http/basic-auth-conf b/sca-cpp/trunk/modules/http/basic-auth-conf
index 39dde90b50..8710d1fdf7 100755
--- a/sca-cpp/trunk/modules/http/basic-auth-conf
+++ b/sca-cpp/trunk/modules/http/basic-auth-conf
@@ -25,9 +25,16 @@ root=`echo "import os; print os.path.realpath('$1')" | python`
conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
host=`echo $conf | awk '{ print $6 }'`
-loc=$2
-if [ "$loc" = "" ]; then
+if [ "$2" = "" ]; then
+ providers="file"
+else
+ providers="$2 file"
+fi
+
+if [ "$3" = "" ]; then
loc="/"
+else
+ loc="$3"
fi
sslconf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-ssl-conf"`
@@ -52,7 +59,9 @@ cat >>$root/conf/locauth$sslsuffix.conf <<EOF
<Location $loc>
AuthType Basic
AuthName "$host"
-AuthBasicProvider file
+AuthBasicProvider socache $providers
+AuthnCacheProvideFor $providers
+AuthnCacheContext /
Require valid-user
</Location>
diff --git a/sca-cpp/trunk/modules/http/cert-auth-conf b/sca-cpp/trunk/modules/http/cert-auth-conf
index 514e46324f..a30fdfff8c 100755
--- a/sca-cpp/trunk/modules/http/cert-auth-conf
+++ b/sca-cpp/trunk/modules/http/cert-auth-conf
@@ -32,6 +32,12 @@ else
sslsuffix="-ssl"
fi
+if [ "$2" = "" ]; then
+ providers="file"
+else
+ providers="$2 file"
+fi
+
# Disallow public access to server resources
cat >$root/conf/noauth$sslsuffix.conf <<EOF
# Generated by: cert-auth-conf $*
@@ -49,7 +55,9 @@ SSLVerifyDepth 1
<Location />
AuthType Basic
AuthName "$host"
-AuthBasicProvider file
+AuthBasicProvider socache $providers
+AuthnCacheProvideFor $providers
+AuthnCacheContext /
Require valid-user
</Location>
diff --git a/sca-cpp/trunk/modules/http/form-auth-conf b/sca-cpp/trunk/modules/http/form-auth-conf
index 08b97b9df8..fbe943f3d9 100755
--- a/sca-cpp/trunk/modules/http/form-auth-conf
+++ b/sca-cpp/trunk/modules/http/form-auth-conf
@@ -26,9 +26,15 @@ conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
host=`echo $conf | awk '{ print $6 }'`
if [ "$2" = "" ]; then
+ providers="file"
+else
+ providers="$2 file"
+fi
+
+if [ "$3" = "" ]; then
pw=`cat $root/cert/ca.key | head -2 | tail -1`
else
- pw="$2"
+ pw="$3"
fi
sslconf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-ssl-conf"`
@@ -53,8 +59,10 @@ cat >>$root/conf/locauth$sslsuffix.conf <<EOF
<Location />
AuthType Form
AuthName "$host"
-AuthFormProvider file
-AuthFormLoginRequiredLocation /login
+AuthFormProvider socache $providers
+AuthnCacheProvideFor $providers
+AuthnCacheContext /
+AuthFormLoginRequiredLocation /login/
AuthFormLogoutLocation /
Session On
SessionCookieName TuscanyFormAuth domain=.$host; path=/
diff --git a/sca-cpp/trunk/modules/http/httpd-ssl-conf b/sca-cpp/trunk/modules/http/httpd-ssl-conf
index 3cb90d61e0..f99a10071c 100755
--- a/sca-cpp/trunk/modules/http/httpd-ssl-conf
+++ b/sca-cpp/trunk/modules/http/httpd-ssl-conf
@@ -43,6 +43,15 @@ htdocs=`echo $conf | awk '{ print $8 }'`
mkdir -p $htdocs
htdocs=`echo "import os; print os.path.realpath('$htdocs')" | python`
+uname=`uname -s`
+if [ $uname = "Darwin" ]; then
+ libsuffix=".dylib"
+else
+ libsuffix=".so"
+fi
+
+modules_prefix=`cat $here/httpd-modules.prefix`
+
# Extract organization name from our CA certificate
org=`openssl x509 -noout -subject -nameopt multiline -in $root/cert/ca.crt | grep organizationName | awk -F "= " '{ print $2 }'`
@@ -69,7 +78,7 @@ ServerName https://$host$sslpportsuffix
<Location />
RewriteEngine on
-RewriteCond %{HTTP_HOST} !^$host [NC]
+Include conf/hostcond.conf
RewriteCond %{HTTP:X-Forwarded-Server} ^$ [NC]
RewriteCond %{REQUEST_URI} !^/server-status [NC]
RewriteCond %{REQUEST_URI} !^/balancer-manager [NC]
@@ -176,7 +185,7 @@ Include conf/log-ssl.conf
# Enable HTTPS reverse proxy
ProxyRequests Off
-ProxyPreserveHost Off
+ProxyPreserveHost On
ProxyStatus On
SSLProxyEngine on
SSLProxyCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
@@ -222,11 +231,6 @@ CustomLog $root/logs/ssl_access_log sslcombined
EOF
# Configure virtual hosts
-proxycert="server"
-if [ "$proxyconf" != "" ]; then
- proxycert="proxy"
-fi
-
cat >$root/conf/svhost-ssl.conf <<EOF
# Generated by: httpd-ssl-conf $*
# Static virtual host configuration
@@ -238,10 +242,6 @@ SSLCertificateChainFile "$root/cert/ca.crt"
SSLCertificateFile "$root/cert/server.crt"
SSLCertificateKeyFile "$root/cert/server.key"
-# Declare proxy SSL client certificates
-SSLProxyCACertificateFile "$root/cert/ca.crt"
-SSLProxyMachineCertificateFile "$root/cert/$proxycert.pem"
-
EOF
cat >$root/conf/dvhost-ssl.conf <<EOF
@@ -255,9 +255,5 @@ SSLCertificateChainFile "$root/cert/ca.crt"
SSLCertificateFile "$root/cert/vhost.crt"
SSLCertificateKeyFile "$root/cert/vhost.key"
-# Declare proxy SSL client certificates
-SSLProxyCACertificateFile "$root/cert/ca.crt"
-SSLProxyMachineCertificateFile "$root/cert/$proxycert.pem"
-
EOF
diff --git a/sca-cpp/trunk/modules/http/httpd-tunnel-ssl-conf b/sca-cpp/trunk/modules/http/httpd-tunnel-ssl-conf
new file mode 100755
index 0000000000..0028576364
--- /dev/null
+++ b/sca-cpp/trunk/modules/http/httpd-tunnel-ssl-conf
@@ -0,0 +1,38 @@
+#!/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 Tunnel configuration
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+mkdir -p $1
+root=`echo "import os; print os.path.realpath('$1')" | python`
+
+uname=`uname -s`
+if [ $uname = "Darwin" ]; then
+ libsuffix=".dylib"
+else
+ libsuffix=".so"
+fi
+
+# Generate required modules list
+cat >>$root/conf/modules.conf <<EOF
+# Generated by: httpd-tunnel-ssl-conf $*
+LoadModule mod_tuscany_ssltunnel $here/libmod_tuscany_ssltunnel$libsuffix
+
+EOF
+
diff --git a/sca-cpp/trunk/modules/http/mod-openauth.cpp b/sca-cpp/trunk/modules/http/mod-openauth.cpp
index b1aabd73fe..2e308ecedb 100644
--- a/sca-cpp/trunk/modules/http/mod-openauth.cpp
+++ b/sca-cpp/trunk/modules/http/mod-openauth.cpp
@@ -44,6 +44,7 @@
#include "http.hpp"
#include "openauth.hpp"
+
extern "C" {
extern module AP_MODULE_DECLARE_DATA mod_tuscany_openauth;
}
@@ -64,6 +65,20 @@ public:
};
/**
+ * Authentication provider configuration.
+ */
+class AuthnProviderConf {
+public:
+ AuthnProviderConf() : name(), provider(NULL) {
+ }
+ AuthnProviderConf(const string name, const authn_provider* provider) : name(name), provider(provider) {
+ }
+
+ string name;
+ const authn_provider* provider;
+};
+
+/**
* Directory configuration.
*/
class DirConf {
@@ -75,6 +90,7 @@ public:
const char* dir;
bool enabled;
string login;
+ list<AuthnProviderConf> apcs;
};
#ifdef WANT_MAINTAINER_LOG
@@ -101,10 +117,39 @@ const bool debugSession(request_rec* r, session_rec* z) {
#endif
/**
+ * Run the authnz hooks to authenticate a request.
+ */
+const failable<int> checkAuthnzProviders(const string& user, const string& pw, request_rec* r, const list<AuthnProviderConf>& apcs) {
+ if (isNil(apcs))
+ return mkfailure<int>("Authentication failure for: " + user);
+ const AuthnProviderConf apc = car<AuthnProviderConf>(apcs);
+ if (apc.provider == NULL || !apc.provider->check_password)
+ return checkAuthnzProviders(user, pw, r, cdr(apcs));
+
+ apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, c_str(apc.name));
+ const authn_status auth_result = apc.provider->check_password(r, c_str(user), c_str(pw));
+ apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE);
+ if (auth_result != AUTH_GRANTED)
+ return checkAuthnzProviders(user, pw, r, cdr(apcs));
+ return OK;
+}
+
+const failable<int> checkAuthnz(const string& user, const string& pw, request_rec* r, const DirConf& dc) {
+ if (substr(user, 0, 1) == "/" && pw == "password")
+ return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED);
+
+ if (isNil(dc.apcs)) {
+ const authn_provider* provider = (const authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION);
+ return checkAuthnzProviders(user, pw, r, mklist<AuthnProviderConf>(AuthnProviderConf(AUTHN_DEFAULT_PROVIDER, provider)));
+ }
+ return checkAuthnzProviders(user, pw, r, dc.apcs);
+}
+
+/**
* Return the user info from a form auth encrypted session cookie.
*/
static int (*ap_session_load_fn) (request_rec * r, session_rec ** z) = NULL;
-static void (*ap_session_get_fn) (request_rec * r, session_rec * z, const char *key, const char **value) = NULL;
+static int (*ap_session_get_fn) (request_rec * r, session_rec * z, const char *key, const char **value) = NULL;
const failable<value> userInfoFromSession(const string& realm, request_rec* r) {
debug("modopenauth::userInfoFromSession");
@@ -186,36 +231,23 @@ const failable<int> authenticated(const list<list<value> >& info, request_rec* r
}
/**
- * 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) {
+ gc_scoped_pool pool(r->pool);
+
// Decline if we're not enabled or AuthType is not set to Open
const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
if (!dc.enabled)
return DECLINED;
const char* atype = ap_auth_type(r);
- debug(atype, "modopenauth::checkAuthn::auth_type");
if (atype == NULL || strcasecmp(atype, "Open"))
return DECLINED;
-
- // Create a scoped memory pool
- gc_scoped_pool pool(r->pool);
debug_httpdRequest(r, "modopenauth::checkAuthn::input");
+ debug(atype, "modopenauth::checkAuthn::auth_type");
+
+ // Get the request args
+ const list<list<value> > args = httpd::queryArgs(r);
// Get session id from the request
const maybe<string> sid = sessionID(r, "TuscanyOpenAuth");
@@ -231,17 +263,17 @@ static int checkAuthn(request_rec *r) {
return httpd::reportStatus(mkfailure<int>("Missing AuthName"));
// Extract user info from the session id
- const failable<value> info = userInfoFromCookie(content(sid), aname, r);
- if (hasContent(info)) {
+ const failable<value> userinfo = userInfoFromCookie(content(sid), aname, r);
+ if (hasContent(userinfo)) {
// Try to authenticate the request
- const value uinfo = content(info);
- const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", uinfo)), cadr(assoc<value>("password", uinfo)), r);
+ const value uinfo = content(userinfo);
+ const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", uinfo)), cadr(assoc<value>("password", uinfo)), r, dc);
if (!hasContent(authz)) {
// Authentication failed, redirect to login page
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(login(dc.login, r));
+ return httpd::reportStatus(login(dc.login, value(), 1, r));
}
// Successfully authenticated, store the user info in the request
@@ -265,12 +297,12 @@ static int checkAuthn(request_rec *r) {
// Try to authenticate the request
const value uinfo = content(info);
- const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", uinfo)), cadr(assoc<value>("password", uinfo)), r);
+ const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", uinfo)), cadr(assoc<value>("password", uinfo)), r, dc);
if (!hasContent(authz)) {
// Authentication failed, redirect to login page
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(login(dc.login, r));
+ return httpd::reportStatus(login(dc.login, value(), 1, r));
}
// Successfully authenticated, store the user info in the request
@@ -279,9 +311,6 @@ static int checkAuthn(request_rec *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;
@@ -291,57 +320,59 @@ static int checkAuthn(request_rec *r) {
hasContent(sessionID(r, "TuscanyOAuth1")) ||
hasContent(sessionID(r, "TuscanyOAuth2")))
return DECLINED;
+
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(login(dc.login, r));
+ return httpd::reportStatus(login(dc.login, value(), value(), r));
}
/**
- * Fixup cache control.
+ * Save the auth session cookie in the response.
*/
-bool filterCacheControl(const string& tok) {
- return tok != "no-cache";
+static int sessionCookieSave(request_rec* r, session_rec* z) {
+ gc_scoped_pool pool(r->pool);
+
+ const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
+ if (!dc.enabled)
+ return DECLINED;
+
+ debug(c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))), "modopenauth::setcookie");
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))));
+ return OK;
}
-static apr_status_t outputFilter(ap_filter_t * f, apr_bucket_brigade * in) {
- request_rec *r = f->r->main;
- if (!r)
- r = f->r;
- for (; r != NULL; r = r->next) {
- if (r->status != HTTP_OK && r->status != HTTP_NOT_MODIFIED) {
-
- // Don't cache errors and redirects
- debug("no-cache", "modopenauth::outputFilter::nokCacheControl");
- apr_table_set(r->headers_out, "Cache-Control", "no-cache");
- continue;
- }
+/**
+ * Load the auth session cookie from the request. Similar
+ */
+static int sessionCookieLoad(request_rec* r, session_rec** z) {
+ gc_scoped_pool pool(r->pool);
- // Cache OK content
- const char* cc = apr_table_get(r->headers_out, "Cache-Control");
- if (cc == NULL) {
- debug("modopenauth::outputFilter::noCacheControl");
- continue;
- }
- debug(cc, "modopenauth::outputFilter::cacheControl");
- const string ncc = join(", ", filter<string>(filterCacheControl, tokenize(", ", cc)));
- if (length(ncc) == 0) {
- debug("modopenauth::outputFilter::noCacheControl");
- apr_table_unset(r->headers_out, "Cache-Control");
- continue;
- }
+ const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
+ if (!dc.enabled)
+ return DECLINED;
- debug(ncc, "modopenauth::outputFilter::okCacheControl");
- apr_table_set(r->headers_out, "Cache-Control", c_str(ncc));
+ // First look in the notes
+ const char* note = apr_pstrcat(r->pool, "mod_openauth", "TuscanyOpenAuth", NULL);
+ session_rec* zz = (session_rec*)(void*)apr_table_get(r->notes, note);
+ if (zz != NULL) {
+ *z = zz;
+ return OK;
}
- ap_remove_output_filter(f);
- return ap_pass_brigade(f->next, in);
-}
+ // Parse the cookie
+ const maybe<string> sid = openauth::sessionID(r, "TuscanyOpenAuth");
-/**
- * Insert our cache control output filter.
- */
-static void insertOutputFilter(request_rec * r) {
- ap_add_output_filter("mod_openauth", NULL, r, r->connection);
+ // Create a new session
+ zz = (session_rec*)apr_pcalloc(r->pool, sizeof(session_rec));
+ zz->pool = r->pool;
+ zz->entries = apr_table_make(r->pool, 10);
+ zz->encoded = hasContent(sid)? c_str(content(sid)) : NULL;
+ zz->uuid = (apr_uuid_t *) apr_pcalloc(r->pool, sizeof(apr_uuid_t));
+ *z = zz;
+
+ // Store it in the notes
+ apr_table_setn(r->notes, note, (char*)zz);
+
+ return OK;
}
/**
@@ -357,6 +388,7 @@ int postConfigMerge(ServerConf& mainsc, server_rec* s) {
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");
@@ -369,6 +401,7 @@ int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp,
*/
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;
@@ -395,11 +428,25 @@ const char* confLogin(cmd_parms *cmd, void *c, const char* arg) {
dc.login = arg;
return NULL;
}
+const char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) {
+ gc_scoped_pool pool(cmd->pool);
+ DirConf& dc = httpd::dirConf<DirConf>(c);
+
+ // Lookup and cache the Authn provider
+ const authn_provider* provider = (authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, arg, AUTHN_PROVIDER_VERSION);
+ if (provider == NULL)
+ return apr_psprintf(cmd->pool, "Unknown Authn provider: %s", arg);
+ if (!provider->check_password)
+ return apr_psprintf(cmd->pool, "The '%s' Authn provider doesn't support password authentication", arg);
+ dc.apcs = append<AuthnProviderConf>(dc.apcs, mklist<AuthnProviderConf>(AuthnProviderConf(arg, provider)));
+ return NULL;
+}
/**
* HTTP server module declaration.
*/
const command_rec commands[] = {
+ AP_INIT_ITERATE("AuthOpenAuthProvider", (const char*(*)())confAuthnProvider, NULL, OR_AUTHCFG, "Auth providers for a directory or location"),
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}
@@ -409,8 +456,8 @@ 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);
- ap_register_output_filter("mod_openauth", outputFilter, NULL, AP_FTYPE_CONTENT_SET);
- ap_hook_insert_filter(insertOutputFilter, NULL, NULL, APR_HOOK_LAST);
+ ap_hook_session_load(sessionCookieLoad, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_session_save(sessionCookieSave, NULL, NULL, APR_HOOK_MIDDLE);
}
}
diff --git a/sca-cpp/trunk/modules/http/mod-security-conf b/sca-cpp/trunk/modules/http/mod-security-conf
index 4d978a01cb..5d03fc5cfb 100755
--- a/sca-cpp/trunk/modules/http/mod-security-conf
+++ b/sca-cpp/trunk/modules/http/mod-security-conf
@@ -51,8 +51,8 @@ SecDefaultAction "phase:2,pass,nolog,auditlog"
#SecDebugLog $root/logs//modsec_debug_log
#SecDebugLogLevel 3
-# Allow mod-security to access request bodies
-SecRequestBodyAccess On
+# Process request bodies
+SecRequestBodyAccess Off
SecRule REQUEST_HEADERS:Content-Type "text/xml" "phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "application/xml" "phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRequestBodyLimit 13107200
@@ -90,8 +90,8 @@ SecRule RESPONSE_STATUS "@streq 408" "phase:5,t:none,nolog,pass, setvar:ip.slow_
SecRule IP:SLOW_DOS_COUNTER "@gt 5" "phase:1,t:none,log,drop, msg:'Client Connection Dropped due to high # of slow DoS alerts'"
SecWriteStateLimit 50
-# Allow mod-security to access response bodies
-SecResponseBodyAccess On
+# Process response bodies
+SecResponseBodyAccess Off
SecResponseBodyMimeType text/plain text/html text/xml application/xml
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
@@ -157,28 +157,28 @@ SecRule &TX:REAL_IP "@eq 0" "phase:1,id:'981218',t:none,pass,nolog,initcol:glob
# Include all base mod-security CRS rules
Include ${modsecurity_prefix}/base_rules/modsecurity_crs_20_protocol_violations.conf
-Include ${modsecurity_prefix}/base_rules/modsecurity_crs_41_xss_attacks.conf
-Include ${modsecurity_prefix}/base_rules/modsecurity_crs_50_outbound.conf
+#Include ${modsecurity_prefix}/base_rules/modsecurity_crs_41_xss_attacks.conf
+#Include ${modsecurity_prefix}/base_rules/modsecurity_crs_50_outbound.conf
Include ${modsecurity_prefix}/base_rules/modsecurity_crs_35_bad_robots.conf
Include ${modsecurity_prefix}/base_rules/modsecurity_crs_47_common_exceptions.conf
Include ${modsecurity_prefix}/base_rules/modsecurity_crs_60_correlation.conf
-Include ${modsecurity_prefix}/base_rules/modsecurity_crs_40_generic_attacks.conf
+#Include ${modsecurity_prefix}/base_rules/modsecurity_crs_40_generic_attacks.conf
Include ${modsecurity_prefix}/base_rules/modsecurity_crs_21_protocol_anomalies.conf
Include ${modsecurity_prefix}/base_rules/modsecurity_crs_30_http_policy.conf
Include ${modsecurity_prefix}/base_rules/modsecurity_crs_49_inbound_blocking.conf
Include ${modsecurity_prefix}/base_rules/modsecurity_crs_41_sql_injection_attacks.conf
-Include ${modsecurity_prefix}/base_rules/modsecurity_crs_45_trojans.conf
+#Include ${modsecurity_prefix}/base_rules/modsecurity_crs_45_trojans.conf
Include ${modsecurity_prefix}/base_rules/modsecurity_crs_59_outbound_blocking.conf
Include ${modsecurity_prefix}/base_rules/modsecurity_crs_23_request_limits.conf
Include ${modsecurity_prefix}/base_rules/modsecurity_crs_42_tight_security.conf
# Include some optional mod-security CRS rules
-Include ${modsecurity_prefix}/optional_rules/modsecurity_crs_10_ignore_static.conf
-Include ${modsecurity_prefix}/optional_rules/modsecurity_crs_13_xml_enabler.conf
-Include ${modsecurity_prefix}/optional_rules/modsecurity_crs_25_cc_known.conf
-Include ${modsecurity_prefix}/optional_rules/modsecurity_crs_42_comment_spam.conf
-Include ${modsecurity_prefix}/optional_rules/modsecurity_crs_47_skip_outbound_checks.conf
-Include ${modsecurity_prefix}/optional_rules/modsecurity_crs_55_application_defects.conf
+#Include ${modsecurity_prefix}/optional_rules/modsecurity_crs_10_ignore_static.conf
+#Include ${modsecurity_prefix}/optional_rules/modsecurity_crs_13_xml_enabler.conf
+#Include ${modsecurity_prefix}/optional_rules/modsecurity_crs_25_cc_known.conf
+#Include ${modsecurity_prefix}/optional_rules/modsecurity_crs_42_comment_spam.conf
+#Include ${modsecurity_prefix}/optional_rules/modsecurity_crs_47_skip_outbound_checks.conf
+#Include ${modsecurity_prefix}/optional_rules/modsecurity_crs_55_application_defects.conf
EOF
diff --git a/sca-cpp/trunk/modules/http/open-auth-conf b/sca-cpp/trunk/modules/http/open-auth-conf
index 5226622058..f4715b3a1c 100755
--- a/sca-cpp/trunk/modules/http/open-auth-conf
+++ b/sca-cpp/trunk/modules/http/open-auth-conf
@@ -40,14 +40,20 @@ else
fi
if [ "$2" = "" ]; then
+ providers="file"
+else
+ providers="$2 file"
+fi
+
+if [ "$3" = "" ]; then
pw=`cat $root/cert/ca.key | head -2 | tail -1`
else
- pw="$2"
+ pw="$3"
fi
# Configure HTTPD mod_tuscany_openauth module
cat >>$root/conf/modules.conf <<EOF
-# Generated by: openauth-conf $*
+# Generated by: open-auth-conf $*
# Load support for Open authentication
LoadModule mod_tuscany_openauth $here/libmod_tuscany_openauth$libsuffix
@@ -67,11 +73,13 @@ cat >>$root/conf/locauth$sslsuffix.conf <<EOF
<Location />
AuthType Open
AuthName "$host"
+AuthOpenAuthProvider socache $providers
+AuthnCacheProvideFor $providers
+AuthnCacheContext /
Session On
-SessionCookieName TuscanyOpenAuth domain=.$host; path=/
SessionCryptoPassphrase $pw
AuthOpenAuth On
-AuthOpenAuthLoginPage /login
+AuthOpenAuthLoginPage /login/
Require valid-user
</Location>
@@ -79,8 +87,10 @@ Require valid-user
<Location /login/dologin>
AuthType Form
AuthName "$host"
-AuthFormProvider file
-AuthFormLoginRequiredLocation /login
+AuthFormProvider socache $providers
+AuthnCacheProvideFor $providers
+AuthnCacheContext /
+AuthFormLoginRequiredLocation /login/?openauth_attempt=1
AuthFormLogoutLocation /
Require valid-user
SetHandler form-login-handler
diff --git a/sca-cpp/trunk/modules/http/openauth.hpp b/sca-cpp/trunk/modules/http/openauth.hpp
index 5d887885aa..3ffa88d362 100644
--- a/sca-cpp/trunk/modules/http/openauth.hpp
+++ b/sca-cpp/trunk/modules/http/openauth.hpp
@@ -77,7 +77,7 @@ const string cookie(const string& key, const string& sid, const string& domain)
const time_t t = time(NULL) + 86400;
char exp[32];
strftime(exp, 32, "%a, %d-%b-%Y %H:%M:%S GMT", gmtime(&t));
- const string c = key + string("=") + sid + "; expires=" + string(exp) + "; domain=." + domain + "; path=/";
+ const string c = key + string("=") + sid + "; expires=" + string(exp) + "; domain=." + httpd::realm(domain) + "; path=/";
debug(c, "openauth::cookie");
return c;
}
@@ -85,9 +85,11 @@ const string cookie(const string& key, const string& sid, const string& domain)
/**
* Redirect to the configured login page.
*/
-const failable<int> login(const string& page, 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("?") + http::queryString(largs);
+const failable<int> login(const string& page, const value& ref, const value& attempt, request_rec* r) {
+ const list<list<value> > rarg = ref == string("/")? list<list<value> >() : mklist<list<value> >(mklist<value>("openauth_referrer", httpd::escape(httpd::url(isNil(ref)? r->uri : ref, r))));
+ const list<list<value> > aarg = isNil(attempt)? list<list<value> >() : mklist<list<value> >(mklist<value>("openauth_attempt", attempt));
+ const list<list<value> > largs = append<list<value> >(rarg, aarg);
+ const string loc = isNil(largs)? httpd::url(page, r) : httpd::url(page, r) + string("?") + http::queryString(largs);
debug(loc, "openauth::login::uri");
return httpd::externalRedirect(loc, r);
}
diff --git a/sca-cpp/trunk/modules/http/passwd-auth-conf b/sca-cpp/trunk/modules/http/passwd-auth-conf
index 119b0fbb3b..718b96de0a 100755
--- a/sca-cpp/trunk/modules/http/passwd-auth-conf
+++ b/sca-cpp/trunk/modules/http/passwd-auth-conf
@@ -27,5 +27,5 @@ httpd_prefix=`cat $here/httpd.prefix`
# Create password file
touch $root/conf/httpd.passwd
-$httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd $user $pass 2>/dev/null
+$httpd_prefix/bin/htpasswd -b $root/conf/httpd.passwd "$user" "$pass" 2>/dev/null
diff --git a/sca-cpp/trunk/modules/oauth/Makefile.am b/sca-cpp/trunk/modules/oauth/Makefile.am
index a5a5916a84..9e8eb5a0dd 100644
--- a/sca-cpp/trunk/modules/oauth/Makefile.am
+++ b/sca-cpp/trunk/modules/oauth/Makefile.am
@@ -19,7 +19,7 @@ if WANT_OAUTH
INCLUDES = -I${HTTPD_INCLUDE} -I${LIBOAUTH_INCLUDE}
-dist_mod_SCRIPTS = oauth-conf oauth-memcached-conf oauth1-appkey-conf oauth2-appkey-conf
+dist_mod_SCRIPTS = oauth-conf oauth12-conf oauth-memcached-conf oauth1-appkey-conf oauth2-appkey-conf
moddir=$(prefix)/modules/oauth
mod_LTLIBRARIES = libmod_tuscany_oauth1.la libmod_tuscany_oauth2.la
diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp
index eb23443491..d2c7cf7ddd 100644
--- a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp
+++ b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp
@@ -71,6 +71,20 @@ public:
};
/**
+ * Authentication provider configuration.
+ */
+class AuthnProviderConf {
+public:
+ AuthnProviderConf() : name(), provider(NULL) {
+ }
+ AuthnProviderConf(const string name, const authn_provider* provider) : name(name), provider(provider) {
+ }
+
+ string name;
+ const authn_provider* provider;
+};
+
+/**
* Directory configuration.
*/
class DirConf {
@@ -83,9 +97,39 @@ public:
bool enabled;
string login;
list<list<value> > scopeattrs;
+ list<AuthnProviderConf> apcs;
};
/**
+ * Run the authnz hooks to authenticate a request.
+ */
+const failable<int> checkAuthnzProviders(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) {
+ if (isNil(apcs))
+ return mkfailure<int>("Authentication failure for: " + user, HTTP_UNAUTHORIZED);
+ const AuthnProviderConf apc = car<AuthnProviderConf>(apcs);
+ if (apc.provider == NULL || !apc.provider->check_password)
+ return checkAuthnzProviders(user, r, cdr(apcs));
+
+ apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, c_str(apc.name));
+ const authn_status auth_result = apc.provider->check_password(r, c_str(string("/oauth1/") + user), "password");
+ apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE);
+ if (auth_result != AUTH_GRANTED)
+ return checkAuthnzProviders(user, r, cdr(apcs));
+ return OK;
+}
+
+const failable<int> checkAuthnz(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) {
+ if (substr(user, 0, 1) == "/")
+ return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED);
+
+ if (isNil(apcs)) {
+ const authn_provider* provider = (const authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION);
+ return checkAuthnzProviders(user, r, mklist<AuthnProviderConf>(AuthnProviderConf(AUTHN_DEFAULT_PROVIDER, provider)));
+ }
+ return checkAuthnzProviders(user, r, apcs);
+}
+
+/**
* Return the user info for a session.
*/
const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) {
@@ -95,27 +139,31 @@ const failable<value> userInfo(const value& sid, const memcache::MemCached& mc)
/**
* Handle an authenticated request.
*/
-const failable<int> authenticated(const list<list<value> >& attrs, const list<list<value> >& info, request_rec* r) {
- debug(info, "modoauth1::authenticated::info");
+const failable<int> authenticated(const list<list<value> >& userinfo, const bool check, request_rec* r, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs) {
+ debug(userinfo, "modoauth2::authenticated::userinfo");
- if (isNil(attrs)) {
+ if (isNil(scopeattrs)) {
// Store user id in an environment variable
- const list<value> id = assoc<value>("id", info);
+ const list<value> id = assoc<value>("id", userinfo);
if (isNil(id) || isNil(cdr(id)))
return mkfailure<int>("Couldn't retrieve user id");
- apr_table_set(r->subprocess_env, "OAUTH1_ID", apr_pstrdup(r->pool, c_str(cadr(id))));
+ apr_table_set(r->subprocess_env, "OAUTH2_ID", apr_pstrdup(r->pool, c_str(cadr(id))));
// If the request user field has not been mapped to another attribute, map the
// OAuth id attribute to it
if (r->user == NULL || r->user[0] == '\0')
r->user = apr_pstrdup(r->pool, c_str(cadr(id)));
+
+ // Run the authnz hooks to check the authenticated user
+ if (check)
+ return checkAuthnz(r->user == NULL? "" : r->user, r, apcs);
return OK;
}
- // Store each configure OAuth scope attribute in an environment variable
- const list<value> a = car(attrs);
- const list<value> v = assoc<value>(cadr(a), info);
+ // Store each configured OAuth scope attribute in an environment variable
+ const list<value> a = car(scopeattrs);
+ const list<value> v = assoc<value>(cadr(a), userinfo);
if (!isNil(v) && !isNil(cdr(v))) {
// Map the REMOTE_USER attribute to the request user field
@@ -124,7 +172,7 @@ const failable<int> authenticated(const list<list<value> >& attrs, const list<li
else
apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, c_str(car(a))), apr_pstrdup(r->pool, c_str(cadr(v))));
}
- return authenticated(cdr(attrs), info, r);
+ return authenticated(userinfo, check, r, cdr(scopeattrs), apcs);
}
/**
@@ -297,7 +345,8 @@ const failable<list<value> > profileUserInfo(const value& cid, const string& inf
/**
* Handle an access_token request.
*/
-const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const memcache::MemCached& mc) {
+const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs, const memcache::MemCached& mc) {
+
// Extract access_token URI, client ID and verification code
const list<value> ref = assoc<value>("openauth_referrer", args);
if (isNil(ref) || isNil(cdr(ref)))
@@ -372,13 +421,18 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r,
debug(profres, "modoauth1::access_token::profres");
// Retrieve the user info from the profile
- const failable<list<value> > iv = profileUserInfo(cadr(cid), profres);
- if (!hasContent(iv))
- return mkfailure<int>(iv);
+ const failable<list<value> > userinfo = profileUserInfo(cadr(cid), profres);
+ if (!hasContent(userinfo))
+ return mkfailure<int>(userinfo);
+
+ // Validate the authenticated user
+ const failable<int> authrc = authenticated(content(userinfo), true, r, scopeattrs, apcs);
+ if (!hasContent(authrc))
+ return authrc;
// Store user info in memcached keyed by session ID
const value sid = string("OAuth1_") + mkrand();
- const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth1", sid), content(iv), mc);
+ const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth1", sid), content(userinfo), mc);
if (!hasContent(prc))
return mkfailure<int>(prc);
@@ -392,20 +446,19 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r,
* Check user authentication.
*/
static int checkAuthn(request_rec *r) {
+ gc_scoped_pool pool(r->pool);
+
// Decline if we're not enabled or AuthType is not set to Open
const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth1);
if (!dc.enabled)
return DECLINED;
const char* atype = ap_auth_type(r);
- debug(atype, "modopenauth::checkAuthn::auth_type");
if (atype == NULL || strcasecmp(atype, "Open"))
return DECLINED;
-
- // Create a scoped memory pool
- gc_scoped_pool pool(r->pool);
+ debug_httpdRequest(r, "modoauth1::checkAuthn::input");
+ debug(atype, "modopenauth::checkAuthn::auth_type");
// Get the server configuration
- debug_httpdRequest(r, "modoauth1::checkAuthn::input");
const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth1);
// Get session id from the request
@@ -415,24 +468,33 @@ static int checkAuthn(request_rec *r) {
if (substr(content(sid), 0, 7) != "OAuth1_")
return DECLINED;
- // If we're authenticated store the user info in the request
- const failable<value> info = userInfo(content(sid), sc.mc);
- if (hasContent(info)) {
- r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authenticated(dc.scopeattrs, content(info), r));
- }
+ // Extract the user info from the auth session
+ const failable<value> userinfo = userInfo(content(sid), sc.mc);
+ if (!hasContent(userinfo))
+ return httpd::reportStatus(mkfailure<int>(userinfo));
+ r->ap_auth_type = const_cast<char*>(atype);
+ return httpd::reportStatus(authenticated(content(userinfo), false, r, dc.scopeattrs, dc.apcs));
}
+ // Get the request args
+ const list<list<value> > args = httpd::queryArgs(r);
+
// Handle OAuth authorize request step
if (string(r->uri) == "/oauth1/authorize/") {
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authorize(httpd::queryArgs(r), r, sc.appkeys, sc.mc));
+ return httpd::reportStatus(authorize(args, r, sc.appkeys, sc.mc));
}
// Handle OAuth access_token request step
if (string(r->uri) == "/oauth1/access_token/") {
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(accessToken(httpd::queryArgs(r), r, sc.appkeys, sc.mc));
+ const failable<int> authrc = accessToken(args, r, sc.appkeys, dc.scopeattrs, dc.apcs, sc.mc);
+
+ // Redirect to the login page if user is not authorized
+ if (!hasContent(authrc) && rcode(authrc) == HTTP_UNAUTHORIZED)
+ return httpd::reportStatus(openauth::login(dc.login, string("/"), 1, r));
+
+ return httpd::reportStatus(authrc);
}
// Redirect to the login page, unless we have a session id or an authorization
@@ -443,10 +505,11 @@ static int checkAuthn(request_rec *r) {
hasContent(openauth::sessionID(r, "TuscanyOpenAuth")) ||
hasContent(openauth::sessionID(r, "TuscanyOAuth2")))
return DECLINED;
- if ((substr(string(r->uri), 0, 8) == "/oauth2/") || !isNil(assoc<value>("openid_identifier", httpd::queryArgs(r))))
+ if ((substr(string(r->uri), 0, 8) == "/oauth2/") || !isNil(assoc<value>("openid_identifier", args)))
return DECLINED;
+
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(openauth::login(dc.login, r));
+ return httpd::reportStatus(openauth::login(dc.login, value(), value(), r));
}
/**
@@ -471,6 +534,7 @@ int postConfigMerge(ServerConf& mainsc, server_rec* s) {
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_oauth1);
debug(httpd::serverName(s), "modoauth1::postConfig::serverName");
@@ -487,7 +551,7 @@ public:
}
const gc_ptr<http::CURLSession> operator()() const {
- return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, "");
+ return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, "", 0);
}
private:
@@ -501,6 +565,7 @@ private:
*/
void childInit(apr_pool_t* p, server_rec* s) {
gc_scoped_pool pool(p);
+
ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_oauth1);
if(psc == NULL) {
cfailure << "[Tuscany] Due to one or more errors mod_tuscany_oauth1 loading failed. Causing apache to stop loading." << endl;
@@ -572,11 +637,25 @@ const char* confScopeAttr(cmd_parms *cmd, void* c, const char* arg1, const char*
dc.scopeattrs = cons<list<value> >(mklist<value>(arg1, arg2), dc.scopeattrs);
return NULL;
}
+const char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) {
+ gc_scoped_pool pool(cmd->pool);
+ DirConf& dc = httpd::dirConf<DirConf>(c);
+
+ // Lookup and cache the Authn provider
+ const authn_provider* provider = (authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, arg, AUTHN_PROVIDER_VERSION);
+ if (provider == NULL)
+ return apr_psprintf(cmd->pool, "Unknown Authn provider: %s", arg);
+ if (!provider->check_password)
+ return apr_psprintf(cmd->pool, "The '%s' Authn provider doesn't support password authentication", arg);
+ dc.apcs = append<AuthnProviderConf>(dc.apcs, mklist<AuthnProviderConf>(AuthnProviderConf(arg, provider)));
+ return NULL;
+}
/**
* HTTP server module declaration.
*/
const command_rec commands[] = {
+ AP_INIT_ITERATE("AuthOAuthProvider", (const char*(*)())confAuthnProvider, NULL, OR_AUTHCFG, "Auth providers for a directory or location"),
AP_INIT_TAKE3("AddAuthOAuth1AppKey", (const char*(*)())confAppKey, NULL, RSRC_CONF, "OAuth 1.0 name app-id app-key"),
AP_INIT_ITERATE("AddAuthOAuthMemcached", (const char*(*)())confMemcached, NULL, RSRC_CONF, "Memcached server host:port"),
AP_INIT_FLAG("AuthOAuth", (const char*(*)())confEnabled, NULL, OR_AUTHCFG, "OAuth 1.0 authentication On | Off"),
diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp
index cbece191aa..e384a0e742 100644
--- a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp
+++ b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp
@@ -65,6 +65,20 @@ public:
};
/**
+ * Authentication provider configuration.
+ */
+class AuthnProviderConf {
+public:
+ AuthnProviderConf() : name(), provider(NULL) {
+ }
+ AuthnProviderConf(const string name, const authn_provider* provider) : name(name), provider(provider) {
+ }
+
+ string name;
+ const authn_provider* provider;
+};
+
+/**
* Directory configuration.
*/
class DirConf {
@@ -77,9 +91,39 @@ public:
bool enabled;
string login;
list<list<value> > scopeattrs;
+ list<AuthnProviderConf> apcs;
};
/**
+ * Run the authnz hooks to authenticate a request.
+ */
+const failable<int> checkAuthnzProviders(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) {
+ if (isNil(apcs))
+ return mkfailure<int>("Authentication failure for: " + user, HTTP_UNAUTHORIZED);
+ const AuthnProviderConf apc = car<AuthnProviderConf>(apcs);
+ if (apc.provider == NULL || !apc.provider->check_password)
+ return checkAuthnzProviders(user, r, cdr(apcs));
+
+ apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, c_str(apc.name));
+ const authn_status auth_result = apc.provider->check_password(r, c_str(string("/oauth2/") + user), "password");
+ apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE);
+ if (auth_result != AUTH_GRANTED)
+ return checkAuthnzProviders(user, r, cdr(apcs));
+ return OK;
+}
+
+const failable<int> checkAuthnz(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) {
+ if (substr(user, 0, 1) == "/")
+ return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED);
+
+ if (isNil(apcs)) {
+ const authn_provider* provider = (const authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION);
+ return checkAuthnzProviders(user, r, mklist<AuthnProviderConf>(AuthnProviderConf(AUTHN_DEFAULT_PROVIDER, provider)));
+ }
+ return checkAuthnzProviders(user, r, apcs);
+}
+
+/**
* Return the user info for a session.
*/
const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) {
@@ -89,13 +133,13 @@ const failable<value> userInfo(const value& sid, const memcache::MemCached& mc)
/**
* Handle an authenticated request.
*/
-const failable<int> authenticated(const list<list<value> >& attrs, const list<list<value> >& info, request_rec* r) {
- debug(info, "modoauth2::authenticated::info");
+const failable<int> authenticated(const list<list<value> >& userinfo, const bool check, request_rec* r, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs) {
+ debug(userinfo, "modoauth2::authenticated::userinfo");
- if (isNil(attrs)) {
+ if (isNil(scopeattrs)) {
// Store user id in an environment variable
- const list<value> id = assoc<value>("id", info);
+ const list<value> id = assoc<value>("id", userinfo);
if (isNil(id) || isNil(cdr(id)))
return mkfailure<int>("Couldn't retrieve user id");
apr_table_set(r->subprocess_env, "OAUTH2_ID", apr_pstrdup(r->pool, c_str(cadr(id))));
@@ -104,12 +148,16 @@ const failable<int> authenticated(const list<list<value> >& attrs, const list<li
// OAuth id attribute to it
if (r->user == NULL || r->user[0] == '\0')
r->user = apr_pstrdup(r->pool, c_str(cadr(id)));
+
+ // Run the authnz hooks to check the authenticated user
+ if (check)
+ return checkAuthnz(r->user == NULL? "" : r->user, r, apcs);
return OK;
}
- // Store each configure OAuth scope attribute in an environment variable
- const list<value> a = car(attrs);
- const list<value> v = assoc<value>(cadr(a), info);
+ // Store each configured OAuth scope attribute in an environment variable
+ const list<value> a = car(scopeattrs);
+ const list<value> v = assoc<value>(cadr(a), userinfo);
if (!isNil(v) && !isNil(cdr(v))) {
// Map the REMOTE_USER attribute to the request user field
@@ -118,7 +166,7 @@ const failable<int> authenticated(const list<list<value> >& attrs, const list<li
else
apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, c_str(car(a))), apr_pstrdup(r->pool, c_str(cadr(v))));
}
- return authenticated(cdr(attrs), info, r);
+ return authenticated(userinfo, check, r, cdr(scopeattrs), apcs);
}
/**
@@ -181,7 +229,8 @@ const failable<list<value> > profileUserInfo(const value& cid, const list<value>
/**
* Handle an access_token request.
*/
-const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const perthread_ptr<http::CURLSession>& cs, const memcache::MemCached& mc) {
+const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const perthread_ptr<http::CURLSession>& cs, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs, const memcache::MemCached& mc) {
+
// Extract access_token URI, client ID and authorization code parameters
const list<value> state = assoc<value>("state", args);
if (isNil(state) || isNil(cdr(state)))
@@ -245,17 +294,22 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r,
debug(content(profres), "modoauth2::access_token::info");
// Retrieve the user info from the profile
- const failable<list<value> > iv = profileUserInfo(cadr(cid), content(profres));
- if (!hasContent(iv))
- return mkfailure<int>(iv);
+ const failable<list<value> > userinfo = profileUserInfo(cadr(cid), content(profres));
+ if (!hasContent(userinfo))
+ return mkfailure<int>(userinfo);
- // Store user info in memcached keyed by session ID
+ // Validate the authenticated user
+ const failable<int> authrc = authenticated(content(userinfo), true, r, scopeattrs, apcs);
+ if (!hasContent(authrc))
+ return authrc;
+
+ // Store user info in memcached keyed by a session ID
const value sid = string("OAuth2_") + mkrand();
- const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth2", sid), content(iv), mc);
+ const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth2", sid), content(userinfo), mc);
if (!hasContent(prc))
return mkfailure<int>(prc);
- // Send session ID to the client in a cookie
+ // Send the session ID to the client in a cookie
debug(c_str(openauth::cookie("TuscanyOAuth2", sid, httpd::hostName(r))), "modoauth2::access_token::setcookie");
apr_table_set(r->err_headers_out, "Set-Cookie", c_str(openauth::cookie("TuscanyOAuth2", sid, httpd::hostName(r))));
return httpd::externalRedirect(httpd::url(httpd::unescape(cadr(ref)), r), r);
@@ -265,20 +319,19 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r,
* Check user authentication.
*/
static int checkAuthn(request_rec *r) {
+ gc_scoped_pool pool(r->pool);
+
// Decline if we're not enabled or AuthType is not set to Open
const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth2);
if (!dc.enabled)
return DECLINED;
const char* atype = ap_auth_type(r);
- debug(atype, "modopenauth::checkAuthn::auth_type");
if (atype == NULL || strcasecmp(atype, "Open"))
return DECLINED;
-
- // Create a scoped memory pool
- gc_scoped_pool pool(r->pool);
+ debug_httpdRequest(r, "modoauth2::checkAuthn::input");
+ debug(atype, "modopenauth::checkAuthn::auth_type");
// Get the server configuration
- debug_httpdRequest(r, "modoauth2::checkAuthn::input");
const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth2);
// Get session id from the request
@@ -288,24 +341,33 @@ static int checkAuthn(request_rec *r) {
if (substr(content(sid), 0, 7) != "OAuth2_")
return DECLINED;
- // If we're authenticated store the user info in the request
- const failable<value> info = userInfo(content(sid), sc.mc);
- if (hasContent(info)) {
- r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authenticated(dc.scopeattrs, content(info), r));
- }
+ // Extract the user info from the auth session
+ const failable<value> userinfo = userInfo(content(sid), sc.mc);
+ if (!hasContent(userinfo))
+ return httpd::reportStatus(mkfailure<int>(userinfo));
+ r->ap_auth_type = const_cast<char*>(atype);
+ return httpd::reportStatus(authenticated(content(userinfo), false, r, dc.scopeattrs, dc.apcs));
}
+ // Get the request args
+ const list<list<value> > args = httpd::queryArgs(r);
+
// Handle OAuth authorize request step
if (string(r->uri) == "/oauth2/authorize/") {
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authorize(httpd::queryArgs(r), r, sc.appkeys));
+ return httpd::reportStatus(authorize(args, r, sc.appkeys));
}
// Handle OAuth access_token request step
if (string(r->uri) == "/oauth2/access_token/") {
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(accessToken(httpd::queryArgs(r), r, sc.appkeys, sc.cs, sc.mc));
+ const failable<int> authrc = accessToken(args, r, sc.appkeys, sc.cs, dc.scopeattrs, dc.apcs, sc.mc);
+
+ // Redirect to the login page if user is not authorized
+ if (!hasContent(authrc) && rcode(authrc) == HTTP_UNAUTHORIZED)
+ return httpd::reportStatus(openauth::login(dc.login, string("/"), 1, r));
+
+ return httpd::reportStatus(authrc);
}
// Redirect to the login page, unless we have a session id or an authorization
@@ -316,10 +378,11 @@ static int checkAuthn(request_rec *r) {
hasContent(openauth::sessionID(r, "TuscanyOpenAuth")) ||
hasContent(openauth::sessionID(r, "TuscanyOAuth1")))
return DECLINED;
- if ((substr(string(r->uri), 0, 8) == "/oauth1/") || !isNil(assoc<value>("openid_identifier", httpd::queryArgs(r))))
+ if ((substr(string(r->uri), 0, 8) == "/oauth1/") || !isNil(assoc<value>("openid_identifier", args)))
return DECLINED;
+
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(openauth::login(dc.login, r));
+ return httpd::reportStatus(openauth::login(dc.login, value(), value(), r));
}
/**
@@ -344,6 +407,7 @@ int postConfigMerge(ServerConf& mainsc, server_rec* s) {
int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, server_rec* s) {
gc_scoped_pool pool(p);
+
ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_oauth2);
debug(httpd::serverName(s), "modoauth2::postConfig::serverName");
@@ -360,7 +424,7 @@ public:
}
const gc_ptr<http::CURLSession> operator()() const {
- return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, "");
+ return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, "", 0);
}
private:
@@ -374,6 +438,7 @@ private:
*/
void childInit(apr_pool_t* p, server_rec* s) {
gc_scoped_pool pool(p);
+
ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_oauth2);
if(psc == NULL) {
cfailure << "[Tuscany] Due to one or more errors mod_tuscany_oauth2 loading failed. Causing apache to stop loading." << endl;
@@ -445,11 +510,25 @@ const char* confScopeAttr(cmd_parms *cmd, void* c, const char* arg1, const char*
dc.scopeattrs = cons<list<value> >(mklist<value>(arg1, arg2), dc.scopeattrs);
return NULL;
}
+const char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) {
+ gc_scoped_pool pool(cmd->pool);
+ DirConf& dc = httpd::dirConf<DirConf>(c);
+
+ // Lookup and cache the Authn provider
+ const authn_provider* provider = (authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, arg, AUTHN_PROVIDER_VERSION);
+ if (provider == NULL)
+ return apr_psprintf(cmd->pool, "Unknown Authn provider: %s", arg);
+ if (!provider->check_password)
+ return apr_psprintf(cmd->pool, "The '%s' Authn provider doesn't support password authentication", arg);
+ dc.apcs = append<AuthnProviderConf>(dc.apcs, mklist<AuthnProviderConf>(AuthnProviderConf(arg, provider)));
+ return NULL;
+}
/**
* HTTP server module declaration.
*/
const command_rec commands[] = {
+ AP_INIT_ITERATE("AuthOAuthProvider", (const char*(*)())confAuthnProvider, NULL, OR_AUTHCFG, "Auth providers for a directory or location"),
AP_INIT_TAKE3("AddAuthOAuth2AppKey", (const char*(*)())confAppKey, NULL, RSRC_CONF, "OAuth 2.0 name app-id app-key"),
AP_INIT_ITERATE("AddAuthOAuthMemcached", (const char*(*)())confMemcached, NULL, RSRC_CONF, "Memcached server host:port"),
AP_INIT_FLAG("AuthOAuth", (const char*(*)())confEnabled, NULL, OR_AUTHCFG, "OAuth 2.0 authentication On | Off"),
diff --git a/sca-cpp/trunk/modules/oauth/oauth-conf b/sca-cpp/trunk/modules/oauth/oauth-conf
index 0b8f14b636..26e654036b 100755
--- a/sca-cpp/trunk/modules/oauth/oauth-conf
+++ b/sca-cpp/trunk/modules/oauth/oauth-conf
@@ -39,18 +39,23 @@ else
sslsuffix="-ssl"
fi
+if [ "$2" = "" ]; then
+ providers="file"
+else
+ providers="$2 file"
+fi
+
# Configure HTTPD mod_tuscany_oauth module
cat >>$root/conf/modules.conf <<EOF
# Generated by: oauth-conf $*
# Load support for OAuth authentication
-LoadModule mod_tuscany_oauth1 $here/libmod_tuscany_oauth1$libsuffix
LoadModule mod_tuscany_oauth2 $here/libmod_tuscany_oauth2$libsuffix
EOF
# Disallow public access to server resources
cat >$root/conf/noauth$sslsuffix.conf <<EOF
-# Generated by: oauth-auth-conf $*
+# Generated by: oauth-conf $*
# Disallow public access to server resources
EOF
@@ -62,9 +67,12 @@ cat >>$root/conf/locauth$sslsuffix.conf <<EOF
<Location />
AuthType Open
AuthName "$host"
+AuthOAuthProvider socache $providers
+AuthnCacheProvideFor $providers
+AuthnCacheContext /
Require valid-user
AuthOAuth On
-AuthOAuthLoginPage /login
+AuthOAuthLoginPage /login/
AddAuthOAuth2ScopeAttr REALM realm
AddAuthOAuth2ScopeAttr REMOTE_USER email
AddAuthOAuth2ScopeAttr EMAIL email
@@ -72,13 +80,7 @@ AddAuthOAuth2ScopeAttr NICKNAME name
AddAuthOAuth2ScopeAttr FULLNAME name
AddAuthOAuth2ScopeAttr FIRSTNAME first_name
AddAuthOAuth2ScopeAttr LASTNAME last_name
-AddAuthOAuth1ScopeAttr REALM realm
-AddAuthOAuth1ScopeAttr REMOTE_USER email
-AddAuthOAuth1ScopeAttr EMAIL email
-AddAuthOAuth1ScopeAttr NICKNAME screen_name
AddAuthOAuth2ScopeAttr FULLNAME name
-AddAuthOAuth1ScopeAttr FIRSTNAME first-name
-AddAuthOAuth1ScopeAttr LASTNAME last-name
</Location>
EOF
diff --git a/sca-cpp/trunk/modules/oauth/oauth12-conf b/sca-cpp/trunk/modules/oauth/oauth12-conf
new file mode 100755
index 0000000000..43c879faee
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/oauth12-conf
@@ -0,0 +1,115 @@
+#!/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 an OAuth server conf
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+mkdir -p $1
+root=`echo "import os; print os.path.realpath('$1')" | python`
+
+uname=`uname -s`
+if [ $uname = "Darwin" ]; then
+ libsuffix=".dylib"
+else
+ libsuffix=".so"
+fi
+
+conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
+host=`echo $conf | awk '{ print $6 }'`
+
+sslconf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-ssl-conf"`
+if [ "$sslconf" = "" ]; then
+ sslsuffix=""
+else
+ sslsuffix="-ssl"
+fi
+
+if [ "$2" = "" ]; then
+ providers="file"
+else
+ providers="$2 file"
+fi
+
+# Configure HTTPD mod_tuscany_oauth module
+cat >>$root/conf/modules.conf <<EOF
+# Generated by: oauth12-conf $*
+# Load support for OAuth authentication
+LoadModule mod_tuscany_oauth1 $here/libmod_tuscany_oauth1$libsuffix
+LoadModule mod_tuscany_oauth2 $here/libmod_tuscany_oauth2$libsuffix
+
+EOF
+
+# Disallow public access to server resources
+cat >$root/conf/noauth$sslsuffix.conf <<EOF
+# Generated by: oauth12-conf $*
+# Disallow public access to server resources
+
+EOF
+
+# Configure OAuth authentication
+cat >>$root/conf/locauth$sslsuffix.conf <<EOF
+# Generated by: oauth12-conf $*
+# Enable OAuth authentication
+<Location />
+AuthType Open
+AuthName "$host"
+AuthOAuthProvider socache $providers
+AuthnCacheProvideFor $providers
+AuthnCacheContext /
+Require valid-user
+AuthOAuth On
+AuthOAuthLoginPage /login/
+AddAuthOAuth2ScopeAttr REALM realm
+AddAuthOAuth2ScopeAttr REMOTE_USER email
+AddAuthOAuth2ScopeAttr EMAIL email
+AddAuthOAuth2ScopeAttr NICKNAME name
+AddAuthOAuth2ScopeAttr FULLNAME name
+AddAuthOAuth2ScopeAttr FIRSTNAME first_name
+AddAuthOAuth2ScopeAttr LASTNAME last_name
+AddAuthOAuth1ScopeAttr REALM realm
+AddAuthOAuth1ScopeAttr REMOTE_USER email
+AddAuthOAuth1ScopeAttr EMAIL email
+AddAuthOAuth1ScopeAttr NICKNAME screen_name
+AddAuthOAuth2ScopeAttr FULLNAME name
+AddAuthOAuth1ScopeAttr FIRSTNAME first-name
+AddAuthOAuth1ScopeAttr LASTNAME last-name
+</Location>
+
+EOF
+
+cat >>$root/conf/auth.conf <<EOF
+# Configure OAuth App keys
+Include $root/cert/oauth-keys.conf
+
+EOF
+
+mkdir -p $root/cert
+cat >$root/cert/oauth-keys.conf <<EOF
+# Generated by: oauth12-conf $*
+# OAuth App keys
+
+EOF
+
+if [ -d "$HOME/.oauth" ]; then
+ cat >>$root/conf/auth.conf <<EOF
+# Configure OAuth App keys
+Include $HOME/.oauth/*-key.conf
+
+EOF
+fi
+
diff --git a/sca-cpp/trunk/modules/oauth/start-mixed-test b/sca-cpp/trunk/modules/oauth/start-mixed-test
index e5a8837354..478f2cc777 100755
--- a/sca-cpp/trunk/modules/oauth/start-mixed-test
+++ b/sca-cpp/trunk/modules/oauth/start-mixed-test
@@ -38,7 +38,7 @@ rm -rf tmp
../openid/openid-memcached-conf tmp www.example.com 11212
../openid/openid-memcached-conf tmp www.example.com 11213
-./oauth-conf tmp
+./oauth12-conf tmp
./oauth-memcached-conf tmp www.example.com 11212
./oauth-memcached-conf tmp www.example.com 11213
@@ -48,13 +48,16 @@ rm -rf tmp
./oauth2-appkey-conf tmp facebook.com app1234 secret6789
./oauth2-appkey-conf tmp github.com app5678 secret8901
-../http/open-auth-conf tmp
-../http/passwd-auth-conf tmp foo foo
+../../modules/http/open-auth-conf tmp
-# For this test to work you need to add your form, oauth and open id ids
-# to the authorized user group
+# For this test to work you need to add your oauth and openid user ids to
+# the password file with a dummy 'password' password, and to the group
+# of authorized users
+../../modules/http/passwd-auth-conf tmp foo foo
../../modules/http/group-auth-conf tmp foo
+../../modules/http/passwd-auth-conf tmp /openid/123456 password
../../modules/http/group-auth-conf tmp 123456
+../../modules/http/passwd-auth-conf tmp /oauth2/jane@example.com password
../../modules/http/group-auth-conf tmp jane@example.com
../../modules/server/server-conf tmp
diff --git a/sca-cpp/trunk/modules/oauth/start-test b/sca-cpp/trunk/modules/oauth/start-test
index 8fc41cdb9a..cadbed2bac 100755
--- a/sca-cpp/trunk/modules/oauth/start-test
+++ b/sca-cpp/trunk/modules/oauth/start-test
@@ -33,7 +33,7 @@ rm -rf tmp
../../modules/http/httpd-conf tmp www.example.com 8090 htdocs
../../modules/http/httpd-ssl-conf tmp 8453
-./oauth-conf tmp
+./oauth12-conf tmp
./oauth-memcached-conf tmp www.example.com 11212
./oauth-memcached-conf tmp www.example.com 11213
@@ -44,7 +44,9 @@ rm -rf tmp
./oauth2-appkey-conf tmp github.com app5678 secret8901
# For this test to work you need to add your oauth user id to the
-# authorized user group
+# password file with a dummy 'password' password, and to the group
+# of authorized users
+../../modules/http/passwd-auth-conf tmp /oauth2/jane@example.com password
../../modules/http/group-auth-conf tmp jane@example.com
../../modules/server/server-conf tmp
diff --git a/sca-cpp/trunk/modules/openid/openid-conf b/sca-cpp/trunk/modules/openid/openid-conf
index d07e4b7cad..7f986fc8d7 100755
--- a/sca-cpp/trunk/modules/openid/openid-conf
+++ b/sca-cpp/trunk/modules/openid/openid-conf
@@ -33,6 +33,12 @@ else
sslsuffix="-ssl"
fi
+if [ "$2" = "" ]; then
+ providers="file"
+else
+ providers="$2"
+fi
+
# Configure HTTPD mod_auth_openid module
cat >>$root/conf/modules.conf <<EOF
# Generated by: openid-conf $*
@@ -55,6 +61,9 @@ cat >>$root/conf/locauth$sslsuffix.conf <<EOF
<Location />
AuthType Open
AuthName "$host"
+#AuthOpenIDProvider socache $providers
+#AuthnCacheProvideFor $providers
+#AuthnCacheContext /
Require valid-user
AuthOpenIDEnabled On
AuthOpenIDCookiePath /
diff --git a/sca-cpp/trunk/modules/openid/start-test b/sca-cpp/trunk/modules/openid/start-test
index f0d27d16be..56ebbc3736 100755
--- a/sca-cpp/trunk/modules/openid/start-test
+++ b/sca-cpp/trunk/modules/openid/start-test
@@ -32,8 +32,10 @@ rm -rf tmp
./openid-memcached-conf tmp localhost 11213
./openid-step2-conf tmp
-# For this test to work you need to add your openid (or email address if
-# available from your openid attributes to the the authorized user group
+# For this test to work you need to add your openid user id to the
+# password file with a dummy 'password' password, and to the group
+# of authorized users
+../../modules/http/passwd-auth-conf tmp /openid/jane@example.com password
../../modules/http/group-auth-conf tmp jane@example.com
../../modules/server/server-conf tmp
diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp
index ac5bf55698..ee99baa039 100644
--- a/sca-cpp/trunk/modules/server/mod-eval.hpp
+++ b/sca-cpp/trunk/modules/server/mod-eval.hpp
@@ -43,6 +43,10 @@
#include "../http/http.hpp"
#include "../http/httpd.hpp"
+#include "apr_md5.h"
+#include "ap_provider.h"
+#include "mod_auth.h"
+
extern "C" {
extern module AP_MODULE_DECLARE_DATA mod_tuscany_eval;
}
@@ -75,8 +79,10 @@ public:
string domain;
string contribPath;
string composName;
- string providerName;
- value provider;
+ string contributorName;
+ value contributor;
+ string authenticatorName;
+ value authenticator;
};
/**
@@ -115,7 +121,7 @@ public:
ServerConf() {
}
- ServerConf(apr_pool_t* p, const server_rec* s) : p(p), server(s) {
+ ServerConf(apr_pool_t* p, const server_rec* s) : p(p), server(s), timeout(0) {
}
const gc_pool p;
@@ -123,6 +129,7 @@ public:
lambda<value(const list<value>&)> lifecycle;
ContribConf contribc;
SSLConf sslc;
+ int timeout;
VhostConf vhostc;
Composite compos;
};
@@ -145,7 +152,12 @@ public:
};
/**
- * Convert a result represented as a content + failure pair to a
+ * Authentication cache store function.
+ */
+static APR_OPTIONAL_FN_TYPE(ap_authn_cache_store) *authnCacheStore = NULL;
+
+/**
+ * Convert a result represented as a (content reason? code?) tuple to a
* failable monad.
*/
const failable<value> failableResult(const list<value>& v) {
@@ -177,9 +189,9 @@ public:
/**
* Make an HTTP proxy lambda to an absolute URI
*/
-const value mkhttpProxy(const string& uri, const gc_pool& p) {
+const value mkhttpProxy(const string& uri, const int timeout, const gc_pool& p) {
debug(uri, "modeval::mkhttpProxy::uri");
- return lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", p));
+ return lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", timeout, p));
}
/**
@@ -187,7 +199,7 @@ const value mkhttpProxy(const string& uri, const gc_pool& p) {
*/
class implProxy {
public:
- implProxy(const value& name, const list<value>& impls, const SSLConf& sslc) : name(name), impls(impls), sslc(sslc) {
+ implProxy(const value& name, const list<value>& impls, const SSLConf& sslc, const int timeout) : name(name), impls(impls), sslc(sslc), timeout(timeout) {
}
const value callImpl(const value& cname, const list<value>& aparams) const {
@@ -229,7 +241,7 @@ public:
ostringstream appuri;
appuri << httpd::scheme(currentRequest) << "://" << substr(uri, 6) << "." << http::topDomain(httpd::hostName(currentRequest)) << ":" << httpd::port(currentRequest) << "/";
debug(str(appuri), "modeval::implProxy::httpproxy::appuri");
- const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(str(appuri), sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), p));
+ const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(str(appuri), sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), timeout, p));
return px(aparams);
}
@@ -237,13 +249,13 @@ public:
// only if the target is in the same top level domain
if (http::topDomain(http::hostName(uri, p)) == http::topDomain(httpd::hostName(currentRequest))) {
debug(uri, "modeval::implProxy::httpproxy::samedomain");
- const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), p));
+ const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), timeout, p));
return px(aparams);
}
// No SSL certificate or cookie on a cross domain call
debug(uri, "modeval::implProxy::httpproxy::crossdomain");
- const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", p));
+ const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", timeout, p));
return px(aparams);
}
@@ -259,11 +271,12 @@ private:
const value name;
const list<value>& impls;
const SSLConf& sslc;
+ const int timeout;
};
-const value mkimplProxy(const value& name, const list<value>& impls, const SSLConf& sslc) {
+const value mkimplProxy(const value& name, const list<value>& impls, const SSLConf& sslc, const int timeout) {
debug(name, "modeval::implProxy::impl");
- return lambda<value(const list<value>&)>(implProxy(name, impls, sslc));
+ return lambda<value(const list<value>&)>(implProxy(name, impls, sslc, timeout));
}
/**
@@ -303,7 +316,7 @@ const value mkunwiredProxy(const string& ref) {
/**
* Convert a list of component references to a list of proxy lambdas.
*/
-const value mkrefProxy(const value& ref, const list<value>& impls, const SSLConf& sslc, const gc_pool& p) {
+const value mkrefProxy(const value& ref, const list<value>& impls, const SSLConf& sslc, const int timeout, const gc_pool& p) {
const value target = scdl::target(ref);
const bool wbyimpl = scdl::wiredByImpl(ref);
debug(ref, "modeval::mkrefProxy::ref");
@@ -312,18 +325,18 @@ const value mkrefProxy(const value& ref, const list<value>& impls, const SSLConf
// Use an HTTP proxy or an internal proxy to the component implementation
if (wbyimpl)
- return mkimplProxy(value(), impls, sslc);
+ return mkimplProxy(value(), impls, sslc, timeout);
if (isNil(target))
return mkunwiredProxy(scdl::name(ref));
if (http::isAbsolute(target))
- return mkhttpProxy(target, p);
- return mkimplProxy(car(pathValues(target)), impls, sslc);
+ return mkhttpProxy(target, timeout, p);
+ return mkimplProxy(car(pathValues(target)), impls, sslc, timeout);
}
-const list<value> refProxies(const list<value>& refs, const list<value>& impls, const SSLConf& sslc, const gc_pool& p) {
+const list<value> refProxies(const list<value>& refs, const list<value>& impls, const SSLConf& sslc, const int timeout, const gc_pool& p) {
if (isNil(refs))
return refs;
- return cons(mkrefProxy(car(refs), impls, sslc, p), refProxies(cdr(refs), impls, sslc, p));
+ return cons(mkrefProxy(car(refs), impls, sslc, timeout, p), refProxies(cdr(refs), impls, sslc, timeout, p));
}
/**
@@ -422,15 +435,29 @@ struct realmPropProxy {
const char* env = apr_table_get(currentRequest->subprocess_env, "REALM");
if (env == NULL)
return v;
- const char* realm = strncmp(env, "www.", 4) == 0? env + 4 : env;
- if (*realm == '\0')
+ const string realm = httpd::realm(string(env));
+ if (length(realm) == 0)
return v;
- const value r = string(realm);
+ const value r = realm;
debug(r, "modeval::realmPropProxy::value");
return r;
}
};
+struct timeoutPropProxy {
+ const value v;
+ timeoutPropProxy(const value& v) : v(atoi(c_str((string)v))) {
+ }
+ const value operator()(unused const list<value>& params) const {
+ if (currentRequest == NULL)
+ return v;
+ const ServerConf& sc = httpd::serverConf<ServerConf>(currentRequest, &mod_tuscany_eval);
+ const value r = sc.timeout;
+ debug(r, "modeval::timeoutPropProxy::value");
+ return r;
+ }
+};
+
struct userPropProxy {
const value v;
userPropProxy(const value& v) : v(v) {
@@ -461,6 +488,8 @@ const value mkpropProxy(const value& prop) {
return lambda<value(const list<value>&)>(userPropProxy(v));
if (n == "realm")
return lambda<value(const list<value>&)>(realmPropProxy(v));
+ if (n == "timeout")
+ return lambda<value(const list<value>&)>(timeoutPropProxy(v));
if (n == "email")
return lambda<value(const list<value>&)>(envPropProxy("EMAIL", v));
if (n == "nickname")
@@ -499,7 +528,7 @@ struct implementationFailure {
}
};
-const value evalComponent(const string& contribPath, const value& comp, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const gc_pool& p) {
+const value evalComponent(const string& contribPath, const value& comp, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const int timeout, const gc_pool& p) {
extern const failable<lambda<value(const list<value>&)> > evalImplementation(const string& cpath, const value& impl, const list<value>& px, const lambda<value(const list<value>&)>& lifecycle);
const value impl = scdl::implementation(comp);
@@ -507,7 +536,7 @@ const value evalComponent(const string& contribPath, const value& comp, const li
debug(impl, "modeval::evalComponent::impl");
// Convert component references to configured proxy lambdas
- const list<value> rpx(refProxies(scdl::references(comp), impls, sslc, p));
+ const list<value> rpx(refProxies(scdl::references(comp), impls, sslc, timeout, p));
// Convert component properties to configured proxy lambdas
const list<value> ppx(propProxies(scdl::properties(comp)));
@@ -522,12 +551,12 @@ const value evalComponent(const string& contribPath, const value& comp, const li
/**
* Return a list of component-name + configured-implementation pairs.
*/
-const list<value> componentToImplementationAssoc(const list<value>& c, const string& contribPath, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const gc_pool& p) {
+const list<value> componentToImplementationAssoc(const list<value>& c, const string& contribPath, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const int timeout, const gc_pool& p) {
if (isNil(c))
return c;
return cons<value>(mklist<value>(scdl::name(car(c)),
- evalComponent(contribPath, car(c), impls, lifecycle, sslc, p)),
- componentToImplementationAssoc(cdr(c), contribPath, impls, lifecycle, sslc, p));
+ evalComponent(contribPath, car(c), impls, lifecycle, sslc, timeout, p)),
+ componentToImplementationAssoc(cdr(c), contribPath, impls, lifecycle, sslc, timeout, p));
}
/**
@@ -541,16 +570,17 @@ const failable<list<value> > readComponents(const string& path) {
}
/**
- * Get the components returned by a provider.
+ * Get the components returned by a contributor.
*/
-const failable<list<value> > getComponents(const lambda<value(const list<value>&)>& provider, const string& name) {
- const failable<value> val = failableResult(provider(cons<value>("get", mklist<value>(mklist<value>(name)))));
+const failable<list<value> > getComponents(const lambda<value(const list<value>&)>& contributor, const string& name) {
+ const failable<value> val = failableResult(contributor(cons<value>("get", mklist<value>(mklist<value>(name)))));
if (!hasContent(val))
return mkfailure<list<value> >(val);
- const list<value> c = assoc<value>(value("content"), (list<list<value> >)cdr<value>(content(val)));
+ const list<value> c = assoc<value>(value("composite"), assoc<value>(value("content"), (list<list<value> >)cdr<value>(car<value>(content(val)))));
+ debug(c, "modeval::getComponents::comp");
if (isNil(c))
return mkfailure<list<value> >(string("Could not get composite: ") + name);
- const failable<list<string> > x = writeXML(car<value>(valuesToElements(mklist<value>(mklist<value>(cadr(c))))));
+ const failable<list<string> > x = writeXML(car<value>(valuesToElements(mklist<value>(mklist<value>(c)))));
if (!hasContent(x))
return mkfailure<list<value> >(x);
return scdl::components(readXML(content(x)));
@@ -631,16 +661,16 @@ const list<value> uriToComponentAssoc(const list<value>& c) {
/**
* Configure the components declared in the deployed composite.
*/
-const failable<Composite> confComponents(const string& contribPath, const string& composName, const value& provider, const string& vhost, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const gc_pool& p) {
+const failable<Composite> confComponents(const string& contribPath, const string& composName, const value& contributor, const string& vhost, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const int timeout, const gc_pool& p) {
debug(contribPath, "modeval::confComponents::contribPath");
debug(composName, "modeval::confComponents::composName");
- debug(provider, "modeval::confComponents::provider");
+ debug(contributor, "modeval::confComponents::contributor");
debug(vhost, "modeval::confComponents::vhost");
debug(impls, "modeval::confComponents::impls");
- const failable<list<value> > fcomps = isNil(provider)?
+ const failable<list<value> > fcomps = isNil(contributor)?
readComponents(scdl::resourcePath(length(vhost) != 0? contribPath + vhost + "/" : contribPath, composName)) :
- getComponents(provider, vhost);
+ getComponents(contributor, vhost);
if (!hasContent(fcomps))
return mkfailure<Composite>(fcomps);
@@ -654,8 +684,8 @@ const failable<Composite> confComponents(const string& contribPath, const string
debug(flatten(svcs), "modeval::confComponents::svcs");
const list<value> cimpls = mkbtree(sort(componentToImplementationAssoc(comps,
- isNil(provider)? length(vhost) != 0? contribPath + vhost + "/" : contribPath : contribPath,
- impls, lifecycle, sslc, p)));
+ isNil(contributor)? length(vhost) != 0? contribPath + vhost + "/" : contribPath : contribPath,
+ impls, lifecycle, sslc, timeout, p)));
debug(flatten(cimpls), "modeval::confComponents::impls");
return Composite(refs, svcs, cimpls);
@@ -720,6 +750,10 @@ const failable<int> get(const list<value>& rpath, request_rec* r, const lambda<v
const value c = content(val);
debug(c, "modeval::get::content");
+ // Return a nil value as a not found status
+ if (!isList(c) && isNil(c))
+ return HTTP_NOT_FOUND;
+
// Check if the client requested a specific format
const list<value> fmt = assoc<value>("format", args);
@@ -735,6 +769,7 @@ const failable<int> get(const list<value>& rpath, request_rec* r, const lambda<v
debug(lc, "modeval::get::symbol");
return httpd::writeResult(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8", r);
}
+
const list<value> lc = mklist<value>(mklist<value>("value", c));
debug(lc, "modeval::get::value");
return httpd::writeResult(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8", r);
@@ -1041,9 +1076,9 @@ const int translateRequest(request_rec* r, const list<value>& rpath, const list<
// Attempt to map a request targeting the main host to an actual file
if (isNil(vpath)) {
- const failable<request_rec*, int> fnr = httpd::internalSubRequest(r->uri, r);
+ const failable<request_rec*> fnr = httpd::internalSubRequest(r->uri, r);
if (!hasContent(fnr))
- return HTTP_INTERNAL_SERVER_ERROR;
+ return rcode(fnr);
request_rec* nr = content(fnr);
nr->uri = r->filename;
const int tr = ap_core_translate(nr);
@@ -1082,7 +1117,6 @@ int translate(request_rec *r) {
if(r->method_number != M_GET && r->method_number != M_POST && r->method_number != M_PUT && r->method_number != M_DELETE)
return DECLINED;
- // Create a scoped memory pool
gc_scoped_pool pool(r->pool);
debug_httpdRequest(r, "modeval::translate::input");
@@ -1103,9 +1137,9 @@ int translate(request_rec *r) {
// If the request is targeting a virtual host, configure the components
// in that virtual host
- if (length(sc.vhostc.domain) != 0 && (length(sc.vhostc.contribPath) != 0 || !isNil(sc.vhostc.provider)) && httpd::isVhostRequest(sc.server, sc.vhostc.domain, r)) {
+ if (length(sc.vhostc.domain) != 0 && (length(sc.vhostc.contribPath) != 0 || !isNil(sc.vhostc.contributor)) && httpd::isVhostRequest(sc.server, sc.vhostc.domain, r)) {
const string vname = http::subDomain(httpd::hostName(r));
- const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.provider, vname, reqc.impls, sc.lifecycle, sc.sslc, sc.p);
+ const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.contributor, vname, reqc.impls, sc.lifecycle, sc.sslc, sc.timeout, sc.p);
if (!hasContent(fvcompos))
return DECLINED;
const Composite vcompos = content(fvcompos);
@@ -1124,9 +1158,9 @@ int translate(request_rec *r) {
return rc;
// Attempt to map the first segment of the request path to a virtual host
- if (length(prefix) != 0 && (length(sc.vhostc.contribPath) != 0 || !isNil(sc.vhostc.provider))) {
+ if (length(prefix) != 0 && (length(sc.vhostc.contribPath) != 0 || !isNil(sc.vhostc.contributor))) {
const string vname = prefix;
- const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.provider, vname, reqc.impls, sc.lifecycle, sc.sslc, sc.p);
+ const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.contributor, vname, reqc.impls, sc.lifecycle, sc.sslc, sc.timeout, sc.p);
if (!hasContent(fvcompos))
return DECLINED;
const Composite vcompos = content(fvcompos);
@@ -1150,9 +1184,9 @@ const int handleRequest(const list<value>& rpath, request_rec *r, const list<val
mkfailure<int>(string("Couldn't find component implementation: ") + cadr(rpath));
return HTTP_NOT_FOUND;
}
+ const lambda<value(const list<value>&)> l(cadr<value>(impl));
// Handle HTTP method
- const lambda<value(const list<value>&)> l(cadr<value>(impl));
if (r->header_only)
return OK;
if(r->method_number == M_GET)
@@ -1182,7 +1216,7 @@ int handler(request_rec *r) {
if(strcmp(r->handler, "mod_tuscany_eval"))
return DECLINED;
- // Create a scoped memory pool and a scope for the current request
+ // Create a scope for the current request
gc_scoped_pool pool(r->pool);
ScopedRequest sr(r);
@@ -1228,6 +1262,61 @@ int handler(request_rec *r) {
}
/**
+ * Call an authenticator component to check a user's password.
+ */
+authn_status checkPassword(request_rec* r, const char* u, const char* p) {
+ gc_scoped_pool pool(r->pool);
+
+ // Prevent FakeBasicAuth spoofing
+ const string user = u;
+ const string password = p;
+ debug(user, "modeval::checkPassword::user");
+ if (substr(user, 0, 1) != "/" && find(user, "/") != length(user) && password == "password") {
+ mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED);
+ return AUTH_DENIED;
+ }
+
+ // Get the server configuration
+ const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_eval);
+ if (isNil(sc.vhostc.authenticator)) {
+ mkfailure<int>("SCA authenticator not configured");
+ return AUTH_GENERAL_ERROR;
+ }
+
+ // Retrieve the user's password hash
+ const list<value> uid = pathValues(user);
+ const failable<value> val = failableResult(sc.vhostc.authenticator(cons<value>("get", mklist<value>(uid))));
+ if (!hasContent(val)) {
+ mkfailure<int>(string("SCA authentication check user failed, user not found: ") + user);
+ return AUTH_USER_NOT_FOUND;
+ }
+ const value hval = content(val);
+ const list<value> hcontent = isList(hval) && !isNil(hval) && isList(car<value>(hval)) && !isNil(car<value>(hval))? assoc<value>(value("content"), cdr<value>(car<value>(hval))) : list<value>();
+ const list<value> hassoc = isNil(hcontent)? list<value>() : assoc<value>(value("hash"), cdr<value>(hcontent));
+ if (isNil(hassoc)) {
+ mkfailure<int>(string("SCA authentication check user failed, hash not found: ") + user);
+ return AUTH_USER_NOT_FOUND;
+ }
+ const string hash = cadr<value>(hassoc);
+ if (length(hash) == 0) {
+ mkfailure<int>(string("SCA authentication check user failed: ") + user);
+ return AUTH_USER_NOT_FOUND;
+ }
+
+ // Cache the hash in the auth cache provider, if available
+ if (authnCacheStore != NULL)
+ authnCacheStore(r, "component", u, NULL, c_str(hash));
+
+ // Validate the presented password against the hash
+ const apr_status_t rv = apr_password_validate(p, c_str(hash));
+ if (rv != APR_SUCCESS) {
+ mkfailure<int>(string("SCA authentication user password check failed: ") + user);
+ return AUTH_DENIED;
+ }
+ return AUTH_GRANTED;
+}
+
+/**
* Cleanup callback, called when the server is stopped or restarted.
*/
apr_status_t serverCleanup(void* v) {
@@ -1262,6 +1351,7 @@ const int postConfigMerge(const ServerConf& mainsc, server_rec* s) {
if (sc.sslc.ca == "") sc.sslc.ca = mainsc.sslc.ca;
if (sc.sslc.cert == "") sc.sslc.cert = mainsc.sslc.cert;
if (sc.sslc.key == "") sc.sslc.key = mainsc.sslc.key;
+ sc.timeout = mainsc.timeout;
sc.compos = mainsc.compos;
return postConfigMerge(mainsc, s->next);
}
@@ -1311,7 +1401,7 @@ int postConfig(apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp,
}
// Configure the deployed components
- const failable<Composite> compos = confComponents(sc.contribc.contribPath, sc.contribc.composName, value(), "", sc.compos.impls, sc.lifecycle, sc.sslc, sc.p);
+ const failable<Composite> compos = confComponents(sc.contribc.contribPath, sc.contribc.composName, value(), "", sc.compos.impls, sc.lifecycle, sc.sslc, sc.timeout, sc.p);
if (!hasContent(compos)) {
cfailure << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl;
return -1;
@@ -1326,28 +1416,49 @@ int postConfig(apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp,
}
/**
+ * Exit after a failure.
+ */
+void failureExitChild() {
+ cfailure << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl;
+ exit(APEXIT_CHILDFATAL);
+}
+
+/**
* Child process initialization.
*/
void childInit(apr_pool_t* p, server_rec* s) {
gc_scoped_pool pool(p);
+
ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_eval);
- if(psc == NULL) {
- cfailure << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl;
- exit(APEXIT_CHILDFATAL);
- }
+ if(psc == NULL)
+ failureExitChild();
ServerConf& sc = *psc;
// Start the components in the child process
const failable<list<value> > fsimpls = startComponents(sc.compos.impls);
- if (!hasContent(fsimpls)) {
- cfailure << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl;
- exit(APEXIT_CHILDFATAL);
- }
+ if (!hasContent(fsimpls))
+ failureExitChild();
sc.compos.impls = content(fsimpls);
- // Create a proxy for the vhost provider if needed
- if (length(sc.vhostc.providerName) != 0)
- sc.vhostc.provider = mkimplProxy(sc.vhostc.providerName, sc.compos.impls, sc.sslc);
+ // Get the vhost contributor component implementation lambda
+ if (length(sc.vhostc.contributorName) != 0) {
+ const list<value> impl(assoctree<value>(sc.vhostc.contributorName, sc.compos.impls));
+ if (isNil(impl)) {
+ mkfailure<int>(string("Couldn't find contributor component implementation: ") + sc.vhostc.contributorName);
+ failureExitChild();
+ }
+ sc.vhostc.contributor = cadr<value>(impl);
+ }
+
+ // Get the vhost authenticator component implementation lambda
+ if (length(sc.vhostc.authenticatorName) != 0) {
+ const list<value> impl(assoctree<value>(sc.vhostc.authenticatorName, sc.compos.impls));
+ if (isNil(impl)) {
+ mkfailure<int>(string("Couldn't find authenticator component implementation: ") + sc.vhostc.authenticatorName);
+ failureExitChild();
+ }
+ sc.vhostc.authenticator = cadr<value>(impl);
+ }
// Merge the updated configuration into the virtual hosts
postConfigMerge(sc, s->next);
@@ -1383,10 +1494,10 @@ const char* confVirtualContribution(cmd_parms *cmd, unused void *c, const char *
sc.vhostc.contribPath = arg;
return NULL;
}
-const char* confVirtualprovider(cmd_parms *cmd, unused void *c, const char *arg) {
+const char* confVirtualContributor(cmd_parms *cmd, unused void *c, const char *arg) {
gc_scoped_pool pool(cmd->pool);
ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval);
- sc.vhostc.providerName = arg;
+ sc.vhostc.contributorName = arg;
return NULL;
}
const char* confVirtualComposite(cmd_parms *cmd, unused void *c, const char *arg) {
@@ -1395,6 +1506,12 @@ const char* confVirtualComposite(cmd_parms *cmd, unused void *c, const char *arg
sc.vhostc.composName = arg;
return NULL;
}
+const char* confAuthenticator(cmd_parms *cmd, unused void *c, const char *arg) {
+ gc_scoped_pool pool(cmd->pool);
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval);
+ sc.vhostc.authenticatorName = arg;
+ return NULL;
+}
const char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) {
gc_scoped_pool pool(cmd->pool);
ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval);
@@ -1413,6 +1530,12 @@ const char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) {
sc.sslc.key = arg;
return NULL;
}
+const char* confTimeout(cmd_parms *cmd, unused void *c, const char *arg) {
+ gc_scoped_pool pool(cmd->pool);
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval);
+ sc.timeout = atoi(arg);
+ return NULL;
+}
const char* confEnv(unused cmd_parms *cmd, unused void *c, const char *name, const char *value) {
gc_scoped_pool pool(cmd->pool);
setenv(name, value != NULL? value : "", 1);
@@ -1427,20 +1550,33 @@ const command_rec commands[] = {
AP_INIT_TAKE1("SCAComposite", (const char*(*)())confComposite, NULL, RSRC_CONF, "SCA composite location"),
AP_INIT_TAKE1("SCAVirtualDomain", (const char*(*)())confVirtualDomain, NULL, RSRC_CONF, "SCA virtual host domain"),
AP_INIT_TAKE1("SCAVirtualContribution", (const char*(*)())confVirtualContribution, NULL, RSRC_CONF, "SCA virtual host contribution path"),
- AP_INIT_TAKE1("SCAVirtualContributor", (const char*(*)())confVirtualprovider, NULL, RSRC_CONF, "SCA virtual host provider component"),
+ AP_INIT_TAKE1("SCAVirtualContributor", (const char*(*)())confVirtualContributor, NULL, RSRC_CONF, "SCA virtual host contributor component"),
AP_INIT_TAKE1("SCAVirtualComposite", (const char*(*)())confVirtualComposite, NULL, RSRC_CONF, "SCA virtual composite location"),
+ AP_INIT_TAKE1("SCAAuthenticator", (const char*(*)())confAuthenticator, NULL, RSRC_CONF, "SCA authenticator component"),
AP_INIT_TAKE12("SCASetEnv", (const char*(*)())confEnv, NULL, OR_FILEINFO, "Environment variable name and optional value"),
AP_INIT_TAKE1("SCAWiringSSLCACertificateFile", (const char*(*)())confCAFile, NULL, RSRC_CONF, "SCA wiring SSL CA certificate file"),
AP_INIT_TAKE1("SCAWiringSSLCertificateFile", (const char*(*)())confCertFile, NULL, RSRC_CONF, "SCA wiring SSL certificate file"),
AP_INIT_TAKE1("SCAWiringSSLCertificateKeyFile", (const char*(*)())confCertKeyFile, NULL, RSRC_CONF, "SCA wiring SSL certificate key file"),
+ AP_INIT_TAKE1("SCAWiringTimeout", (const char*(*)())confTimeout, NULL, RSRC_CONF, "SCA wiring timeout"),
{NULL, NULL, NULL, 0, NO_ARGS, NULL}
};
+const authn_provider AuthnProvider = {
+ &checkPassword,
+ NULL
+};
+
+void retrieveAuthnCacheStore() {
+ authnCacheStore = APR_RETRIEVE_OPTIONAL_FN(ap_authn_cache_store);
+}
+
void registerHooks(unused apr_pool_t *p) {
ap_hook_post_config(postConfig, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_child_init(childInit, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_handler(handler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "component", AUTHN_PROVIDER_VERSION, &AuthnProvider, AP_AUTH_INTERNAL_PER_CONF);
+ ap_hook_optional_fn_retrieve(retrieveAuthnCacheStore, NULL, NULL, APR_HOOK_MIDDLE);
}
}
diff --git a/sca-cpp/trunk/samples/store-cluster/tunnel-ssl-conf b/sca-cpp/trunk/samples/store-cluster/tunnel-ssl-conf
index 7a9a8ad305..f798fdab0b 100755
--- a/sca-cpp/trunk/samples/store-cluster/tunnel-ssl-conf
+++ b/sca-cpp/trunk/samples/store-cluster/tunnel-ssl-conf
@@ -28,5 +28,6 @@ set -x
../../modules/http/httpd-event-conf $root
tar -C tmp/ssl -c `../../modules/http/ssl-cert-find tmp/ssl` | tar -C $root -x
../../modules/http/httpd-ssl-conf $root $sslport
+../../modules/http/httpd-tunnel-ssl-conf $root
../../modules/http/cert-auth-conf $root