aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3184.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3184.patch')
-rw-r--r--meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3184.patch2094
1 files changed, 0 insertions, 2094 deletions
diff --git a/meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3184.patch b/meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3184.patch
deleted file mode 100644
index 0663bd2719..0000000000
--- a/meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3184.patch
+++ /dev/null
@@ -1,2094 +0,0 @@
-Fix CVE-2015-3184
-
-Patch is from:
-http://subversion.apache.org/security/CVE-2015-3184-advisory.txt
-
-Upstream-Status: Backport
-
-Signed-off-by: Wenzong Fan <wenzong.fan@windriver.com>
-
-Index: Makefile.in
-===================================================================
---- a/Makefile.in (revision 1691883)
-+++ b/Makefile.in (working copy)
-@@ -357,6 +357,7 @@ TEST_SHLIB_VAR_SWIG_RB=\
- fi;
-
- APXS = @APXS@
-+HTTPD_VERSION = @HTTPD_VERSION@
-
- PYTHON = @PYTHON@
- PERL = @PERL@
-@@ -509,6 +510,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $(TEST_DEPS
- if test "$(HTTP_LIBRARY)" != ""; then \
- flags="--http-library $(HTTP_LIBRARY) $$flags"; \
- fi; \
-+ if test "$(HTTPD_VERSION)" != ""; then \
-+ flags="--httpd-version $(HTTPD_VERSION) $$flags"; \
-+ fi; \
- if test "$(SERVER_MINOR_VERSION)" != ""; then \
- flags="--server-minor-version $(SERVER_MINOR_VERSION) $$flags"; \
- fi; \
-Index: build/ac-macros/apache.m4
-===================================================================
---- a/build/ac-macros/apache.m4 (revision 1691883)
-+++ b/build/ac-macros/apache.m4 (working copy)
-@@ -160,6 +160,20 @@ if test -n "$APXS" && test "$APXS" != "no"; then
- BUILD_APACHE_RULE=apache-mod
- INSTALL_APACHE_RULE=install-mods-shared
- INSTALL_APACHE_MODS=true
-+ HTTPD="`$APXS -q sbindir`/`$APXS -q PROGNAME`"
-+ if ! test -e $HTTPD ; then
-+ HTTPD="`$APXS -q bindir`/`$APXS -q PROGNAME`"
-+ fi
-+ HTTPD_VERSION=["`$HTTPD -v | $SED -e 's@^.*/\([0-9.]*\)\(.*$\)@\1@ ; 1q'`"]
-+ AC_ARG_ENABLE(broken-httpd-auth,
-+ AS_HELP_STRING([--enable-broken-httpd-auth],
-+ [Allow building against httpd 2.4 with broken auth]),
-+ [broken_httpd_auth=$enableval],[broken_httpd_auth=no])
-+ if test "$enable_broken_httpd_auth" = "yes"; then
-+ AC_MSG_NOTICE([Building with broken httpd auth])
-+ AC_DEFINE(SVN_ALLOW_BROKEN_HTTPD_AUTH, 1,
-+ [Defined to allow building against httpd 2.4 with broken auth])
-+ fi
-
- case $host in
- *-*-cygwin*)
-@@ -178,6 +192,7 @@ AC_SUBST(APACHE_LDFLAGS)
- AC_SUBST(APACHE_INCLUDES)
- AC_SUBST(APACHE_LIBEXECDIR)
- AC_SUBST(INSTALL_APACHE_MODS)
-+AC_SUBST(HTTPD_VERSION)
-
- # there aren't any flags that interest us ...
- #if test -n "$APXS" && test "$APXS" != "no"; then
-Index: build/run_tests.py
-===================================================================
---- a/build/run_tests.py (revision 1691883)
-+++ b/build/run_tests.py (working copy)
-@@ -29,6 +29,7 @@
- [--fs-type=<fs-type>] [--fsfs-packing] [--fsfs-sharding=<n>]
- [--list] [--milestone-filter=<regex>] [--mode-filter=<type>]
- [--server-minor-version=<version>] [--http-proxy=<host>:<port>]
-+ [--httpd-version=<version>]
- [--config-file=<file>] [--ssl-cert=<file>]
- <abs_srcdir> <abs_builddir>
- <prog ...>
-@@ -125,7 +126,7 @@ class TestHarness:
- fsfs_sharding=None, fsfs_packing=None,
- list_tests=None, svn_bin=None, mode_filter=None,
- milestone_filter=None, set_log_level=None, ssl_cert=None,
-- http_proxy=None):
-+ http_proxy=None, httpd_version=None):
- '''Construct a TestHarness instance.
-
- ABS_SRCDIR and ABS_BUILDDIR are the source and build directories.
-@@ -178,6 +179,7 @@ class TestHarness:
- self.log = None
- self.ssl_cert = ssl_cert
- self.http_proxy = http_proxy
-+ self.httpd_version = httpd_version
- if not sys.stdout.isatty() or sys.platform == 'win32':
- TextColors.disable()
-
-@@ -481,6 +483,8 @@ class TestHarness:
- svntest.main.options.ssl_cert = self.ssl_cert
- if self.http_proxy is not None:
- svntest.main.options.http_proxy = self.http_proxy
-+ if self.httpd_version is not None:
-+ svntest.main.options.httpd_version = self.httpd_version
-
- svntest.main.options.srcdir = self.srcdir
-
-@@ -645,7 +649,7 @@ def main():
- 'enable-sasl', 'parallel', 'config-file=',
- 'log-to-stdout', 'list', 'milestone-filter=',
- 'mode-filter=', 'set-log-level=', 'ssl-cert=',
-- 'http-proxy='])
-+ 'http-proxy=', 'httpd-version='])
- except getopt.GetoptError:
- args = []
-
-@@ -656,9 +660,9 @@ def main():
- base_url, fs_type, verbose, cleanup, enable_sasl, http_library, \
- server_minor_version, fsfs_sharding, fsfs_packing, parallel, \
- config_file, log_to_stdout, list_tests, mode_filter, milestone_filter, \
-- set_log_level, ssl_cert, http_proxy = \
-+ set_log_level, ssl_cert, http_proxy, httpd_version = \
- None, None, None, None, None, None, None, None, None, None, None, \
-- None, None, None, None, None, None, None
-+ None, None, None, None, None, None, None, None
- for opt, val in opts:
- if opt in ['-u', '--url']:
- base_url = val
-@@ -696,6 +700,8 @@ def main():
- ssl_cert = val
- elif opt in ['--http-proxy']:
- http_proxy = val
-+ elif opt in ['--httpd-version']:
-+ httpd_version = val
- else:
- raise getopt.GetoptError
-
-@@ -712,7 +718,7 @@ def main():
- fsfs_sharding, fsfs_packing, list_tests,
- mode_filter=mode_filter, milestone_filter=milestone_filter,
- set_log_level=set_log_level, ssl_cert=ssl_cert,
-- http_proxy=http_proxy)
-+ http_proxy=http_proxy, httpd_version=httpd_version)
-
- failed = th.run(args[2:])
- if failed:
-Index: subversion/mod_authz_svn/mod_authz_svn.c
-===================================================================
---- a/subversion/mod_authz_svn/mod_authz_svn.c (revision 1691883)
-+++ b/subversion/mod_authz_svn/mod_authz_svn.c (working copy)
-@@ -48,6 +48,23 @@
- #include "svn_dirent_uri.h"
- #include "private/svn_fspath.h"
-
-+/* The apache headers define these and they conflict with our definitions. */
-+#ifdef PACKAGE_BUGREPORT
-+#undef PACKAGE_BUGREPORT
-+#endif
-+#ifdef PACKAGE_NAME
-+#undef PACKAGE_NAME
-+#endif
-+#ifdef PACKAGE_STRING
-+#undef PACKAGE_STRING
-+#endif
-+#ifdef PACKAGE_TARNAME
-+#undef PACKAGE_TARNAME
-+#endif
-+#ifdef PACKAGE_VERSION
-+#undef PACKAGE_VERSION
-+#endif
-+#include "svn_private_config.h"
-
- #ifdef APLOG_USE_MODULE
- APLOG_USE_MODULE(authz_svn);
-@@ -67,6 +84,30 @@ typedef struct authz_svn_config_rec {
- const char *force_username_case;
- } authz_svn_config_rec;
-
-+#if AP_MODULE_MAGIC_AT_LEAST(20060110,0) /* version where
-+ ap_some_auth_required breaks */
-+# if AP_MODULE_MAGIC_AT_LEAST(20120211,47) /* first version with
-+ force_authn hook and
-+ ap_some_authn_required() which
-+ allows us to work without
-+ ap_some_auth_required() */
-+# define USE_FORCE_AUTHN 1
-+# define IN_SOME_AUTHN_NOTE "authz_svn-in-some-authn"
-+# define FORCE_AUTHN_NOTE "authz_svn-force-authn"
-+# else
-+ /* ap_some_auth_required() is busted and no viable alternative exists */
-+# ifndef SVN_ALLOW_BROKEN_HTTPD_AUTH
-+# error This version of httpd has a security hole with mod_authz_svn
-+# else
-+ /* user wants to build anyway */
-+# define USE_FORCE_AUTHN 0
-+# endif
-+# endif
-+#else
-+ /* old enough that ap_some_auth_required() still works */
-+# define USE_FORCE_AUTHN 0
-+#endif
-+
- /*
- * Configuration
- */
-@@ -819,9 +860,51 @@ access_checker(request_rec *r)
- &authz_svn_module);
- const char *repos_path = NULL;
- const char *dest_repos_path = NULL;
-- int status;
-+ int status, authn_required;
-
-+#if USE_FORCE_AUTHN
-+ /* Use the force_authn() hook available in 2.4.x to work securely
-+ * given that ap_some_auth_required() is no longer functional for our
-+ * purposes in 2.4.x.
-+ */
-+ int authn_configured;
-+
- /* We are not configured to run */
-+ if (!conf->anonymous || apr_table_get(r->notes, IN_SOME_AUTHN_NOTE)
-+ || (! (conf->access_file || conf->repo_relative_access_file)))
-+ return DECLINED;
-+
-+ /* Authentication is configured */
-+ authn_configured = ap_auth_type(r) != NULL;
-+ if (authn_configured)
-+ {
-+ /* If the user is trying to authenticate, let him. It doesn't
-+ * make much sense to grant anonymous access but deny authenticated
-+ * users access, even though you can do that with '$anon' in the
-+ * access file.
-+ */
-+ if (apr_table_get(r->headers_in,
-+ (PROXYREQ_PROXY == r->proxyreq)
-+ ? "Proxy-Authorization" : "Authorization"))
-+ {
-+ /* Set the note to force authn regardless of what access_checker_ex
-+ hook requires */
-+ apr_table_setn(r->notes, FORCE_AUTHN_NOTE, (const char*)1);
-+
-+ /* provide the proper return so the access_checker hook doesn't
-+ * prevent the code from continuing on to the other auth hooks */
-+ if (ap_satisfies(r) != SATISFY_ANY)
-+ return OK;
-+ else
-+ return HTTP_FORBIDDEN;
-+ }
-+ }
-+
-+#else
-+ /* Support for older versions of httpd that have a working
-+ * ap_some_auth_required() */
-+
-+ /* We are not configured to run */
- if (!conf->anonymous
- || (! (conf->access_file || conf->repo_relative_access_file)))
- return DECLINED;
-@@ -834,9 +917,10 @@ access_checker(request_rec *r)
- if (ap_satisfies(r) != SATISFY_ANY)
- return DECLINED;
-
-- /* If the user is trying to authenticate, let him. If anonymous
-- * access is allowed, so is authenticated access, by definition
-- * of the meaning of '*' in the access file.
-+ /* If the user is trying to authenticate, let him. It doesn't
-+ * make much sense to grant anonymous access but deny authenticated
-+ * users access, even though you can do that with '$anon' in the
-+ * access file.
- */
- if (apr_table_get(r->headers_in,
- (PROXYREQ_PROXY == r->proxyreq)
-@@ -848,6 +932,7 @@ access_checker(request_rec *r)
- return HTTP_FORBIDDEN;
- }
- }
-+#endif
-
- /* If anon access is allowed, return OK */
- status = req_check_access(r, conf, &repos_path, &dest_repos_path);
-@@ -856,7 +941,26 @@ access_checker(request_rec *r)
- if (!conf->authoritative)
- return DECLINED;
-
-+#if USE_FORCE_AUTHN
-+ if (authn_configured) {
-+ /* We have to check to see if authn is required because if so we must
-+ * return UNAUTHORIZED (401) rather than FORBIDDEN (403) since returning
-+ * the 403 leaks information about what paths may exist to
-+ * unauthenticated users. We must set a note here in order
-+ * to use ap_some_authn_rquired() without triggering an infinite
-+ * loop since the call will trigger this function to be called again. */
-+ apr_table_setn(r->notes, IN_SOME_AUTHN_NOTE, (const char*)1);
-+ authn_required = ap_some_authn_required(r);
-+ apr_table_unset(r->notes, IN_SOME_AUTHN_NOTE);
-+ if (authn_required)
-+ {
-+ ap_note_auth_failure(r);
-+ return HTTP_UNAUTHORIZED;
-+ }
-+ }
-+#else
- if (!ap_some_auth_required(r))
-+#endif
- log_access_verdict(APLOG_MARK, r, 0, repos_path, dest_repos_path);
-
- return HTTP_FORBIDDEN;
-@@ -937,6 +1041,17 @@ auth_checker(request_rec *r)
- return OK;
- }
-
-+#if USE_FORCE_AUTHN
-+static int
-+force_authn(request_rec *r)
-+{
-+ if (apr_table_get(r->notes, FORCE_AUTHN_NOTE))
-+ return OK;
-+
-+ return DECLINED;
-+}
-+#endif
-+
- /*
- * Module flesh
- */
-@@ -953,6 +1068,9 @@ register_hooks(apr_pool_t *p)
- * give SSLOptions +FakeBasicAuth a chance to work. */
- ap_hook_check_user_id(check_user_id, mod_ssl, NULL, APR_HOOK_FIRST);
- ap_hook_auth_checker(auth_checker, NULL, NULL, APR_HOOK_FIRST);
-+#if USE_FORCE_AUTHN
-+ ap_hook_force_authn(force_authn, NULL, NULL, APR_HOOK_FIRST);
-+#endif
- ap_register_provider(p,
- AUTHZ_SVN__SUBREQ_BYPASS_PROV_GRP,
- AUTHZ_SVN__SUBREQ_BYPASS_PROV_NAME,
-Index: subversion/tests/cmdline/README
-===================================================================
---- a/subversion/tests/cmdline/README (revision 1691883)
-+++ b/subversion/tests/cmdline/README (working copy)
-@@ -83,6 +83,133 @@ paths adjusted appropriately:
- Require valid-user
- </Location>
-
-+ <Location /authz-test-work/anon>
-+ DAV svn
-+ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp
-+ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz
-+ SVNListParentPath On
-+ # This may seem unnecessary but granting access to everyone here is necessary
-+ # to exercise a bug with httpd 2.3.x+. The "Require all granted" syntax is
-+ # new to 2.3.x+ which we can detect with the mod_authz_core.c module
-+ # signature. Use the "Allow from all" syntax with older versions for symmetry.
-+ <IfModule mod_authz_core.c>
-+ Require all granted
-+ </IfModule>
-+ <IfModule !mod_authz_core.c>
-+ Allow from all
-+ </IfMOdule>
-+ </Location>
-+ <Location /authz-test-work/mixed>
-+ DAV svn
-+ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp
-+ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile /usr/local/apache2/conf/users
-+ Require valid-user
-+ Satisfy Any
-+ </Location>
-+ <Location /authz-test-work/mixed-noauthwhenanon>
-+ DAV svn
-+ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp
-+ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile /usr/local/apache2/conf/users
-+ Require valid-user
-+ AuthzSVNNoAuthWhenAnonymousAllowed On
-+ </Location>
-+ <Location /authz-test-work/authn>
-+ DAV svn
-+ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp
-+ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile /usr/local/apache2/conf/users
-+ Require valid-user
-+ </Location>
-+ <Location /authz-test-work/authn-anonoff>
-+ DAV svn
-+ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp
-+ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile /usr/local/apache2/conf/users
-+ Require valid-user
-+ AuthzSVNAnonymous Off
-+ </Location>
-+ <Location /authz-test-work/authn-lcuser>
-+ DAV svn
-+ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp
-+ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile /usr/local/apache2/conf/users
-+ Require valid-user
-+ AuthzForceUsernameCase Lower
-+ </Location>
-+ <Location /authz-test-work/authn-lcuser>
-+ DAV svn
-+ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp
-+ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile /usr/local/apache2/conf/users
-+ Require valid-user
-+ AuthzForceUsernameCase Lower
-+ </Location>
-+ <Location /authz-test-work/authn-group>
-+ DAV svn
-+ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp
-+ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile /usr/local/apache2/conf/users
-+ AuthGroupFile /usr/local/apache2/conf/groups
-+ Require group random
-+ AuthzSVNAuthoritative Off
-+ </Location>
-+ <IfModule mod_authz_core.c>
-+ <Location /authz-test-work/sallrany>
-+ DAV svn
-+ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp
-+ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile /usr/local/apache2/conf/users
-+ AuthzSendForbiddenOnFailure On
-+ Satisfy All
-+ <RequireAny>
-+ Require valid-user
-+ Require expr req('ALLOW') == '1'
-+ </RequireAny>
-+ </Location>
-+ <Location /authz-test-work/sallrall>
-+ DAV svn
-+ SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp
-+ AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile /usr/local/apache2/conf/users
-+ AuthzSendForbiddenOnFailure On
-+ Satisfy All
-+ <RequireAll>
-+ Require valid-user
-+ Require expr req('ALLOW') == '1'
-+ </RequireAll>
-+ </Location>
-+ </IfModule>
-+
-+
- RedirectMatch permanent ^/svn-test-work/repositories/REDIRECT-PERM-(.*)$ /svn-test-work/repositories/$1
- RedirectMatch ^/svn-test-work/repositories/REDIRECT-TEMP-(.*)$ /svn-test-work/repositories/$1
-
-@@ -101,8 +228,17 @@ just drop the following 2-line snippet into the
- ----------------------------
- jrandom:xCGl35kV9oWCY
- jconstant:xCGl35kV9oWCY
-+JRANDOM:xCGl35kV9oWCY
-+JCONSTANT:xCGl35kV9oWCY
- ----------------------------
-
-+and these lines into the
-+/usr/local/apache/conf/groups file:
-+----------------------------
-+random: jrandom
-+constant: jconstant
-+----------------------------
-+
- Now, (re)start Apache and run the tests over mod_dav_svn.
-
- You can run a test script over DAV:
-@@ -138,6 +274,8 @@ Note [1]: It would be quite too much to expect tho
- ----------------------------
- jrandom:$apr1$3p1.....$FQW6RceW5QhJ2blWDQgKn0
- jconstant:$apr1$jp1.....$Usrqji1c9H6AbOxOGAzzb0
-+ JRANDOM:$apr1$3p1.....$FQW6RceW5QhJ2blWDQgKn0
-+ JCONSTANT:$apr1$jp1.....$Usrqji1c9H6AbOxOGAzzb0
- ----------------------------
-
-
-Index: subversion/tests/cmdline/davautocheck.sh
-===================================================================
---- a/subversion/tests/cmdline/davautocheck.sh (revision 1691883)
-+++ b/subversion/tests/cmdline/davautocheck.sh (working copy)
-@@ -289,8 +289,6 @@ LOAD_MOD_AUTHN_CORE="$(get_loadmodule_config mod_a
- || fail "Authn_Core module not found."
- LOAD_MOD_AUTHZ_CORE="$(get_loadmodule_config mod_authz_core)" \
- || fail "Authz_Core module not found."
--LOAD_MOD_AUTHZ_HOST="$(get_loadmodule_config mod_authz_host)" \
-- || fail "Authz_Host module not found."
- LOAD_MOD_UNIXD=$(get_loadmodule_config mod_unixd) \
- || fail "UnixD module not found"
- }
-@@ -298,6 +296,10 @@ LOAD_MOD_AUTHN_FILE="$(get_loadmodule_config mod_a
- || fail "Authn_File module not found."
- LOAD_MOD_AUTHZ_USER="$(get_loadmodule_config mod_authz_user)" \
- || fail "Authz_User module not found."
-+LOAD_MOD_AUTHZ_GROUPFILE="$(get_loadmodule_config mod_authz_groupfile)" \
-+ || fail "Authz_GroupFile module not found."
-+LOAD_MOD_AUTHZ_HOST="$(get_loadmodule_config mod_authz_host)" \
-+ || fail "Authz_Host module not found."
- }
- if [ ${APACHE_MPM:+set} ]; then
- LOAD_MOD_MPM=$(get_loadmodule_config mod_mpm_$APACHE_MPM) \
-@@ -328,6 +330,7 @@ HTTPD_ERROR_LOG="$HTTPD_ROOT/error_log"
- HTTPD_MIME_TYPES="$HTTPD_ROOT/mime.types"
- BASE_URL="http://localhost:$HTTPD_PORT"
- HTTPD_USERS="$HTTPD_ROOT/users"
-+HTTPD_GROUPS="$HTTPD_ROOT/groups"
-
- mkdir "$HTTPD_ROOT" \
- || fail "couldn't create temporary directory '$HTTPD_ROOT'"
-@@ -388,6 +391,14 @@ fi
- say "Adding users for lock authentication"
- $HTPASSWD -bc $HTTPD_USERS jrandom rayjandom
- $HTPASSWD -b $HTTPD_USERS jconstant rayjandom
-+$HTPASSWD -b $HTTPD_USERS JRANDOM rayjandom
-+$HTPASSWD -b $HTTPD_USERS JCONSTANT rayjandom
-+
-+say "Adding groups for mod_authz_svn tests"
-+cat > "$HTTPD_GROUPS" <<__EOF__
-+random: jrandom
-+constant: jconstant
-+__EOF__
-
- touch $HTTPD_MIME_TYPES
-
-@@ -405,7 +416,9 @@ $LOAD_MOD_AUTHN_CORE
- $LOAD_MOD_AUTHN_FILE
- $LOAD_MOD_AUTHZ_CORE
- $LOAD_MOD_AUTHZ_USER
-+$LOAD_MOD_AUTHZ_GROUPFILE
- $LOAD_MOD_AUTHZ_HOST
-+$LOAD_MOD_ACCESS_COMPAT
- LoadModule authz_svn_module "$MOD_AUTHZ_SVN"
-
- __EOF__
-@@ -497,6 +510,161 @@ CustomLog "$HTTPD_ROOT/ops" "%t %u %{SVN
- SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL}
- ${SVN_PATH_AUTHZ_LINE}
- </Location>
-+<Location /authz-test-work/anon>
-+ DAV svn
-+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp"
-+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz"
-+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL}
-+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING}
-+ SVNListParentPath On
-+ # This may seem unnecessary but granting access to everyone here is necessary
-+ # to exercise a bug with httpd 2.3.x+. The "Require all granted" syntax is
-+ # new to 2.3.x+ which we can detect with the mod_authz_core.c module
-+ # signature. Use the "Allow from all" syntax with older versions for symmetry.
-+ <IfModule mod_authz_core.c>
-+ Require all granted
-+ </IfModule>
-+ <IfModule !mod_authz_core.c>
-+ Allow from all
-+ </IfMOdule>
-+ ${SVN_PATH_AUTHZ_LINE}
-+</Location>
-+<Location /authz-test-work/mixed>
-+ DAV svn
-+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp"
-+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz"
-+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL}
-+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING}
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile $HTTPD_USERS
-+ Require valid-user
-+ Satisfy Any
-+ ${SVN_PATH_AUTHZ_LINE}
-+</Location>
-+<Location /authz-test-work/mixed-noauthwhenanon>
-+ DAV svn
-+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp"
-+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz"
-+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL}
-+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING}
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile $HTTPD_USERS
-+ Require valid-user
-+ AuthzSVNNoAuthWhenAnonymousAllowed On
-+ SVNPathAuthz On
-+</Location>
-+<Location /authz-test-work/authn>
-+ DAV svn
-+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp"
-+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz"
-+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL}
-+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING}
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile $HTTPD_USERS
-+ Require valid-user
-+ ${SVN_PATH_AUTHZ_LINE}
-+</Location>
-+<Location /authz-test-work/authn-anonoff>
-+ DAV svn
-+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp"
-+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz"
-+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL}
-+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING}
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile $HTTPD_USERS
-+ Require valid-user
-+ AuthzSVNAnonymous Off
-+ SVNPathAuthz On
-+</Location>
-+<Location /authz-test-work/authn-lcuser>
-+ DAV svn
-+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp"
-+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz"
-+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL}
-+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING}
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile $HTTPD_USERS
-+ Require valid-user
-+ AuthzForceUsernameCase Lower
-+ ${SVN_PATH_AUTHZ_LINE}
-+</Location>
-+<Location /authz-test-work/authn-lcuser>
-+ DAV svn
-+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp"
-+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz"
-+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL}
-+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING}
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile $HTTPD_USERS
-+ Require valid-user
-+ AuthzForceUsernameCase Lower
-+ ${SVN_PATH_AUTHZ_LINE}
-+</Location>
-+<Location /authz-test-work/authn-group>
-+ DAV svn
-+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp"
-+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz"
-+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL}
-+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING}
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile $HTTPD_USERS
-+ AuthGroupFile $HTTPD_GROUPS
-+ Require group random
-+ AuthzSVNAuthoritative Off
-+ SVNPathAuthz On
-+</Location>
-+<IfModule mod_authz_core.c>
-+ <Location /authz-test-work/sallrany>
-+ DAV svn
-+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp"
-+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz"
-+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL}
-+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING}
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile $HTTPD_USERS
-+ AuthzSendForbiddenOnFailure On
-+ Satisfy All
-+ <RequireAny>
-+ Require valid-user
-+ Require expr req('ALLOW') == '1'
-+ </RequireAny>
-+ ${SVN_PATH_AUTHZ_LINE}
-+ </Location>
-+ <Location /authz-test-work/sallrall>
-+ DAV svn
-+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp"
-+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz"
-+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL}
-+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING}
-+ SVNListParentPath On
-+ AuthType Basic
-+ AuthName "Subversion Repository"
-+ AuthUserFile $HTTPD_USERS
-+ AuthzSendForbiddenOnFailure On
-+ Satisfy All
-+ <RequireAll>
-+ Require valid-user
-+ Require expr req('ALLOW') == '1'
-+ </RequireAll>
-+ ${SVN_PATH_AUTHZ_LINE}
-+ </Location>
-+</IfModule>
- RedirectMatch permanent ^/svn-test-work/repositories/REDIRECT-PERM-(.*)\$ /svn-test-work/repositories/\$1
- RedirectMatch ^/svn-test-work/repositories/REDIRECT-TEMP-(.*)\$ /svn-test-work/repositories/\$1
- __EOF__
-Index: subversion/tests/cmdline/mod_authz_svn_tests.py
-===================================================================
---- a/subversion/tests/cmdline/mod_authz_svn_tests.py (nonexistent)
-+++ b/subversion/tests/cmdline/mod_authz_svn_tests.py (working copy)
-@@ -0,0 +1,1073 @@
-+#!/usr/bin/env python
-+#
-+# mod_authz_svn_tests.py: testing mod_authz_svn
-+#
-+# Subversion is a tool for revision control.
-+# See http://subversion.apache.org for more information.
-+#
-+# ====================================================================
-+# 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.
-+######################################################################
-+
-+# General modules
-+import os, re, logging
-+
-+logger = logging.getLogger()
-+
-+# Our testing module
-+import svntest
-+
-+# (abbreviation)
-+Skip = svntest.testcase.Skip_deco
-+SkipUnless = svntest.testcase.SkipUnless_deco
-+XFail = svntest.testcase.XFail_deco
-+Issues = svntest.testcase.Issues_deco
-+Issue = svntest.testcase.Issue_deco
-+Wimp = svntest.testcase.Wimp_deco
-+
-+ls_of_D_no_H = '''<html><head><title>repos - Revision 1: /A/D</title></head>
-+<body>
-+ <h2>repos - Revision 1: /A/D</h2>
-+ <ul>
-+ <li><a href="../">..</a></li>
-+ <li><a href="G/">G/</a></li>
-+ <li><a href="gamma">gamma</a></li>
-+ </ul>
-+</body></html>'''
-+
-+ls_of_D_H = '''<html><head><title>repos - Revision 1: /A/D</title></head>
-+<body>
-+ <h2>repos - Revision 1: /A/D</h2>
-+ <ul>
-+ <li><a href="../">..</a></li>
-+ <li><a href="G/">G/</a></li>
-+ <li><a href="H/">H/</a></li>
-+ <li><a href="gamma">gamma</a></li>
-+ </ul>
-+</body></html>'''
-+
-+ls_of_H = '''<html><head><title>repos - Revision 1: /A/D/H</title></head>
-+<body>
-+ <h2>repos - Revision 1: /A/D/H</h2>
-+ <ul>
-+ <li><a href="../">..</a></li>
-+ <li><a href="chi">chi</a></li>
-+ <li><a href="omega">omega</a></li>
-+ <li><a href="psi">psi</a></li>
-+ </ul>
-+</body></html>'''
-+
-+user1 = svntest.main.wc_author
-+user1_upper = user1.upper()
-+user1_pass = svntest.main.wc_passwd
-+user1_badpass = 'XXX'
-+assert user1_pass != user1_badpass, "Passwords can't match"
-+user2 = svntest.main.wc_author2
-+user2_upper = user2.upper()
-+user2_pass = svntest.main.wc_passwd
-+user2_badpass = 'XXX'
-+assert user2_pass != user2_badpass, "Passwords can't match"
-+
-+def write_authz_file(sbox):
-+ svntest.main.write_authz_file(sbox, {
-+ '/': '$anonymous = r\n' +
-+ 'jrandom = rw\n' +
-+ 'jconstant = rw',
-+ '/A/D/H': '$anonymous =\n' +
-+ '$authenticated =\n' +
-+ 'jrandom = rw'
-+ })
-+
-+def write_authz_file_groups(sbox):
-+ authz_name = sbox.authz_name()
-+ svntest.main.write_authz_file(sbox,{
-+ '/': '* =',
-+ })
-+
-+def verify_get(test_area_url, path, user, pw,
-+ expected_status, expected_body, headers):
-+ import httplib
-+ from urlparse import urlparse
-+ import base64
-+
-+ req_url = test_area_url + path
-+
-+ loc = urlparse(req_url)
-+
-+ if loc.scheme == 'http':
-+ h = httplib.HTTPConnection(loc.hostname, loc.port)
-+ else:
-+ h = httplib.HTTPSConnection(loc.hostname, loc.port)
-+
-+ if headers is None:
-+ headers = {}
-+
-+ if user and pw:
-+ auth_info = user + ':' + pw
-+ headers['Authorization'] = 'Basic ' + base64.b64encode(auth_info)
-+ else:
-+ auth_info = "anonymous"
-+
-+ h.request('GET', req_url, None, headers)
-+
-+ r = h.getresponse()
-+
-+ actual_status = r.status
-+ if expected_status and expected_status != actual_status:
-+
-+ logger.warn("Expected status '" + str(expected_status) +
-+ "' but got '" + str(actual_status) +
-+ "' on url '" + req_url + "' (" +
-+ auth_info + ").")
-+ raise svntest.Failure
-+
-+ if expected_body:
-+ actual_body = r.read()
-+ if expected_body != actual_body:
-+ logger.warn("Expected body:")
-+ logger.warn(expected_body)
-+ logger.warn("But got:")
-+ logger.warn(actual_body)
-+ logger.warn("on url '" + req_url + "' (" + auth_info + ").")
-+ raise svntest.Failure
-+
-+def verify_gets(test_area_url, tests):
-+ for test in tests:
-+ verify_get(test_area_url, test['path'], test.get('user'), test.get('pw'),
-+ test['status'], test.get('body'), test.get('headers'))
-+
-+
-+######################################################################
-+# Tests
-+#
-+# Each test must return on success or raise on failure.
-+
-+
-+#----------------------------------------------------------------------
-+
-+
-+@SkipUnless(svntest.main.is_ra_type_dav)
-+def anon(sbox):
-+ "test anonymous access"
-+ sbox.build(read_only = True, create_wc = False)
-+
-+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos',
-+ '/authz-test-work/anon')
-+
-+ write_authz_file(sbox)
-+
-+ anon_tests = (
-+ { 'path': '', 'status': 301 },
-+ { 'path': '/', 'status': 200 },
-+ { 'path': '/repos', 'status': 301 },
-+ { 'path': '/repos/', 'status': 200 },
-+ { 'path': '/repos/A', 'status': 301 },
-+ { 'path': '/repos/A/', 'status': 200 },
-+ { 'path': '/repos/A/D', 'status': 301 },
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H },
-+ { 'path': '/repos/A/D/gamma', 'status': 200 },
-+ { 'path': '/repos/A/D/H', 'status': 403 },
-+ { 'path': '/repos/A/D/H/', 'status': 403 },
-+ { 'path': '/repos/A/D/H/chi', 'status': 403 },
-+ # auth isn't configured so nothing should change when passing
-+ # authn details
-+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '', 'status': 301, 'user': user2, 'pw': user1_pass},
-+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user1_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user1_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user1_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user1_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user1_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ 'user': user2, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ )
-+
-+ verify_gets(test_area_url, anon_tests)
-+
-+
-+@SkipUnless(svntest.main.is_ra_type_dav)
-+def mixed(sbox):
-+ "test mixed anonymous and authenticated access"
-+ sbox.build(read_only = True, create_wc = False)
-+
-+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos',
-+ '/authz-test-work/mixed')
-+
-+ write_authz_file(sbox)
-+
-+ mixed_tests = (
-+ { 'path': '', 'status': 301, },
-+ { 'path': '/', 'status': 200, },
-+ { 'path': '/repos', 'status': 301, },
-+ { 'path': '/repos/', 'status': 200, },
-+ { 'path': '/repos/A', 'status': 301, },
-+ { 'path': '/repos/A/', 'status': 200, },
-+ { 'path': '/repos/A/D', 'status': 301, },
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ },
-+ { 'path': '/repos/A/D/gamma', 'status': 200, },
-+ { 'path': '/repos/A/D/H', 'status': 401, },
-+ { 'path': '/repos/A/D/H/', 'status': 401, },
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, },
-+ # auth is configured and user1 is allowed access to H
-+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H,
-+ 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ # try with the wrong password for user1
-+ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ # auth is configured and user2 is not allowed access to H
-+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ # try with the wrong password for user2
-+ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ )
-+
-+ verify_gets(test_area_url, mixed_tests)
-+
-+@SkipUnless(svntest.main.is_ra_type_dav)
-+@XFail(svntest.main.is_httpd_authz_provider_enabled)
-+# uses the AuthzSVNNoAuthWhenAnonymousAllowed On directive
-+# this is broken with httpd 2.3.x+ since it requires the auth system to accept
-+# r->user == NULL and there is a test for this in server/request.c now. It
-+# was intended as a workaround for the lack of Satisfy Any in 2.3.x+ which
-+# was resolved by httpd with mod_access_compat in 2.3.x+.
-+def mixed_noauthwhenanon(sbox):
-+ "test mixed with noauthwhenanon directive"
-+ sbox.build(read_only = True, create_wc = False)
-+
-+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos',
-+ '/authz-test-work/mixed-noauthwhenanon')
-+
-+ write_authz_file(sbox)
-+
-+ noauthwhenanon_tests = (
-+ { 'path': '', 'status': 301, },
-+ { 'path': '/', 'status': 200, },
-+ { 'path': '/repos', 'status': 301, },
-+ { 'path': '/repos/', 'status': 200, },
-+ { 'path': '/repos/A', 'status': 301, },
-+ { 'path': '/repos/A/', 'status': 200, },
-+ { 'path': '/repos/A/D', 'status': 301, },
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ },
-+ { 'path': '/repos/A/D/gamma', 'status': 200, },
-+ { 'path': '/repos/A/D/H', 'status': 401, },
-+ { 'path': '/repos/A/D/H/', 'status': 401, },
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, },
-+ # auth is configured and user1 is allowed access to H
-+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H,
-+ 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ # try with the wrong password for user1
-+ # note that unlike doing this with Satisfy Any this case
-+ # actually provides anon access when provided with an invalid
-+ # password
-+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ # auth is configured and user2 is not allowed access to H
-+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ # try with the wrong password for user2
-+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ )
-+
-+ verify_gets(test_area_url, noauthwhenanon_tests)
-+
-+
-+@SkipUnless(svntest.main.is_ra_type_dav)
-+def authn(sbox):
-+ "test authenticated only access"
-+ sbox.build(read_only = True, create_wc = False)
-+
-+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos',
-+ '/authz-test-work/authn')
-+
-+ write_authz_file(sbox)
-+
-+ authn_tests = (
-+ { 'path': '', 'status': 401, },
-+ { 'path': '/', 'status': 401, },
-+ { 'path': '/repos', 'status': 401, },
-+ { 'path': '/repos/', 'status': 401, },
-+ { 'path': '/repos/A', 'status': 401, },
-+ { 'path': '/repos/A/', 'status': 401, },
-+ { 'path': '/repos/A/D', 'status': 401, },
-+ { 'path': '/repos/A/D/', 'status': 401, },
-+ { 'path': '/repos/A/D/gamma', 'status': 401, },
-+ { 'path': '/repos/A/D/H', 'status': 401, },
-+ { 'path': '/repos/A/D/H/', 'status': 401, },
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, },
-+ # auth is configured and user1 is allowed access to H
-+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H,
-+ 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ # try with upper case username for user1
-+ { 'path': '', 'status': 301, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/', 'status': 200, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ # try with the wrong password for user1
-+ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ # auth is configured and user2 is not allowed access to H
-+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ # try with upper case username for user2
-+ { 'path': '', 'status': 301, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/', 'status': 200, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ # try with the wrong password for user2
-+ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ )
-+
-+ verify_gets(test_area_url, authn_tests)
-+
-+@SkipUnless(svntest.main.is_ra_type_dav)
-+def authn_anonoff(sbox):
-+ "test authenticated only access with anonoff"
-+ sbox.build(read_only = True, create_wc = False)
-+
-+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos',
-+ '/authz-test-work/authn-anonoff')
-+
-+ write_authz_file(sbox)
-+
-+ anonoff_tests = (
-+ { 'path': '', 'status': 401, },
-+ { 'path': '/', 'status': 401, },
-+ { 'path': '/repos', 'status': 401, },
-+ { 'path': '/repos/', 'status': 401, },
-+ { 'path': '/repos/A', 'status': 401, },
-+ { 'path': '/repos/A/', 'status': 401, },
-+ { 'path': '/repos/A/D', 'status': 401, },
-+ { 'path': '/repos/A/D/', 'status': 401, },
-+ { 'path': '/repos/A/D/gamma', 'status': 401, },
-+ { 'path': '/repos/A/D/H', 'status': 401, },
-+ { 'path': '/repos/A/D/H/', 'status': 401, },
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, },
-+ # auth is configured and user1 is allowed access to H
-+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H,
-+ 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ # try with upper case username for user1
-+ { 'path': '', 'status': 301, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/', 'status': 200, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1_upper, 'pw': user1_pass},
-+ # try with the wrong password for user1
-+ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ # auth is configured and user2 is not allowed access to H
-+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ # try with upper case username for user2
-+ { 'path': '', 'status': 301, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/', 'status': 200, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ # try with the wrong password for user2
-+ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ )
-+
-+ verify_gets(test_area_url, anonoff_tests)
-+
-+@SkipUnless(svntest.main.is_ra_type_dav)
-+def authn_lcuser(sbox):
-+ "test authenticated only access with lcuser"
-+ sbox.build(read_only = True, create_wc = False)
-+
-+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos',
-+ '/authz-test-work/authn-lcuser')
-+
-+ write_authz_file(sbox)
-+
-+ lcuser_tests = (
-+ # try with upper case username for user1 (works due to lcuser option)
-+ { 'path': '', 'status': 301, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/', 'status': 200, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H,
-+ 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1_upper, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1_upper, 'pw': user1_pass},
-+ # try with upper case username for user2 (works due to lcuser option)
-+ { 'path': '', 'status': 301, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/', 'status': 200, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2_upper, 'pw': user2_pass},
-+ )
-+
-+ verify_gets(test_area_url, lcuser_tests)
-+
-+# authenticated access only by group - a excuse to use AuthzSVNAuthoritative Off
-+# this is terribly messed up, Require group runs after mod_authz_svn.
-+# so if mod_authz_svn grants the access then it doesn't matter what the group
-+# requirement says. If we reject the access then you can use the AuthzSVNAuthoritative Off
-+# directive to fall through to the group check. Overall the behavior of setups like this
-+# is almost guaranteed to not be what users expect.
-+@SkipUnless(svntest.main.is_ra_type_dav)
-+def authn_group(sbox):
-+ "test authenticated only access via groups"
-+ sbox.build(read_only = True, create_wc = False)
-+
-+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos',
-+ '/authz-test-work/authn-group')
-+
-+ # Can't use write_authz_file() as most tests because we want to deny all
-+ # access with mod_authz_svn so the tests fall through to the group handling
-+ authz_name = sbox.authz_name()
-+ svntest.main.write_authz_file(sbox, {
-+ '/': '* =',
-+ })
-+
-+ group_tests = (
-+ { 'path': '', 'status': 401, },
-+ { 'path': '/', 'status': 401, },
-+ { 'path': '/repos', 'status': 401, },
-+ { 'path': '/repos/', 'status': 401, },
-+ { 'path': '/repos/A', 'status': 401, },
-+ { 'path': '/repos/A/', 'status': 401, },
-+ { 'path': '/repos/A/D', 'status': 401, },
-+ { 'path': '/repos/A/D/', 'status': 401, },
-+ { 'path': '/repos/A/D/gamma', 'status': 401, },
-+ { 'path': '/repos/A/D/H', 'status': 401, },
-+ { 'path': '/repos/A/D/H/', 'status': 401, },
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, },
-+ # auth is configured and user1 is allowed access repo including H
-+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H,
-+ 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ )
-+
-+ verify_gets(test_area_url, group_tests)
-+
-+# This test exists to validate our behavior when used with the new authz
-+# provider system introduced in httpd 2.3.x. The Satisfy directive
-+# determines how older authz hooks are combined and the RequireA(ll|ny)
-+# blocks handles how new authz providers are combined. The overall results of
-+# all the authz providers (combined per the Require* blocks) are then
-+# combined with the other authz hooks via the Satisfy directive.
-+# Meaning this test requires that mod_authz_svn says yes and there is
-+# either a valid user or the ALLOW header is 1. The header may seem
-+# like a silly test but it's easier to excercise than say a host directive
-+# in a repeatable test.
-+@SkipUnless(svntest.main.is_httpd_authz_provider_enabled)
-+def authn_sallrany(sbox):
-+ "test satisfy all require any config"
-+ sbox.build(read_only = True, create_wc = False)
-+
-+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos',
-+ '/authz-test-work/sallrany')
-+
-+ write_authz_file(sbox)
-+
-+ allow_header = { 'ALLOW': '1' }
-+
-+ sallrany_tests = (
-+ #anon access isn't allowed without ALLOW header
-+ { 'path': '', 'status': 401, },
-+ { 'path': '/', 'status': 401, },
-+ { 'path': '/repos', 'status': 401, },
-+ { 'path': '/repos/', 'status': 401, },
-+ { 'path': '/repos/A', 'status': 401, },
-+ { 'path': '/repos/A/', 'status': 401, },
-+ { 'path': '/repos/A/D', 'status': 401, },
-+ { 'path': '/repos/A/D/', 'status': 401, },
-+ { 'path': '/repos/A/D/gamma', 'status': 401, },
-+ { 'path': '/repos/A/D/H', 'status': 401, },
-+ { 'path': '/repos/A/D/H/', 'status': 401, },
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, },
-+ # auth is configured and user1 is allowed access repo including H
-+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H,
-+ 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass},
-+ # try with the wrong password for user1
-+ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass},
-+ # auth is configured and user2 is not allowed access to H
-+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ # try with the wrong password for user2
-+ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass},
-+ # anon is allowed with the ALLOW header
-+ { 'path': '', 'status': 301, 'headers': allow_header },
-+ { 'path': '/', 'status': 200, 'headers': allow_header },
-+ { 'path': '/repos', 'status': 301, 'headers': allow_header },
-+ { 'path': '/repos/', 'status': 200, 'headers': allow_header },
-+ { 'path': '/repos/A', 'status': 301, 'headers': allow_header },
-+ { 'path': '/repos/A/', 'status': 200, 'headers': allow_header },
-+ { 'path': '/repos/A/D', 'status': 301, 'headers': allow_header },
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, 'headers': allow_header },
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'headers': allow_header },
-+ # these 3 tests return 403 instead of 401 becasue the config allows
-+ # the anon user with the ALLOW header without any auth and the old hook
-+ # system has no way of knowing it should return 401 since authentication is
-+ # configured and can change the behavior. It could decide to return 401 just on
-+ # the basis of authentication being configured but then that leaks info in other
-+ # cases so it's better for this case to be "broken".
-+ { 'path': '/repos/A/D/H', 'status': 403, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'headers': allow_header },
-+ # auth is configured and user1 is allowed access repo including H
-+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H,
-+ 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ # try with the wrong password for user1
-+ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ # auth is configured and user2 is not allowed access to H
-+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ # try with the wrong password for user2
-+ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+
-+ )
-+
-+ verify_gets(test_area_url, sallrany_tests)
-+
-+# See comments on authn_sallrany test for some background on the interaction
-+# of Satisfy Any and the newer Require blocks.
-+@SkipUnless(svntest.main.is_httpd_authz_provider_enabled)
-+def authn_sallrall(sbox):
-+ "test satisfy all require all config"
-+ sbox.build(read_only = True, create_wc = False)
-+
-+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos',
-+ '/authz-test-work/sallrall')
-+
-+ write_authz_file(sbox)
-+
-+ allow_header = { 'ALLOW': '1' }
-+
-+ sallrall_tests = (
-+ #anon access isn't allowed without ALLOW header
-+ { 'path': '', 'status': 403, },
-+ { 'path': '/', 'status': 403, },
-+ { 'path': '/repos', 'status': 403, },
-+ { 'path': '/repos/', 'status': 403, },
-+ { 'path': '/repos/A', 'status': 403, },
-+ { 'path': '/repos/A/', 'status': 403, },
-+ { 'path': '/repos/A/D', 'status': 403, },
-+ { 'path': '/repos/A/D/', 'status': 403, },
-+ { 'path': '/repos/A/D/gamma', 'status': 403, },
-+ { 'path': '/repos/A/D/H', 'status': 403, },
-+ { 'path': '/repos/A/D/H/', 'status': 403, },
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, },
-+ # auth is configured but no access is allowed without the ALLOW header
-+ { 'path': '', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_pass},
-+ # try with the wrong password for user1
-+ { 'path': '', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_badpass},
-+ # auth is configured but no access is allowed without the ALLOW header
-+ { 'path': '', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass},
-+ # try with the wrong password for user2
-+ { 'path': '', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_badpass},
-+ # anon is not allowed even with ALLOW header
-+ { 'path': '', 'status': 401, 'headers': allow_header },
-+ { 'path': '/', 'status': 401, 'headers': allow_header },
-+ { 'path': '/repos', 'status': 401, 'headers': allow_header },
-+ { 'path': '/repos/', 'status': 401, 'headers': allow_header },
-+ { 'path': '/repos/A', 'status': 401, 'headers': allow_header },
-+ { 'path': '/repos/A/', 'status': 401, 'headers': allow_header },
-+ { 'path': '/repos/A/D', 'status': 401, 'headers': allow_header },
-+ { 'path': '/repos/A/D/', 'status': 401, 'headers': allow_header },
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H', 'status': 401, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'headers': allow_header },
-+ # auth is configured and user1 is allowed access repo including H
-+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H,
-+ 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header },
-+ # try with the wrong password for user1
-+ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header },
-+ # auth is configured and user2 is not allowed access to H
-+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H,
-+ 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header },
-+ # try with the wrong password for user2
-+ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header },
-+
-+ )
-+
-+ verify_gets(test_area_url, sallrall_tests)
-+
-+
-+########################################################################
-+# Run the tests
-+
-+
-+# list all tests here, starting with None:
-+test_list = [ None,
-+ anon,
-+ mixed,
-+ mixed_noauthwhenanon,
-+ authn,
-+ authn_anonoff,
-+ authn_lcuser,
-+ authn_group,
-+ authn_sallrany,
-+ authn_sallrall,
-+ ]
-+serial_only = True
-+
-+if __name__ == '__main__':
-+ svntest.main.run_tests(test_list)
-+ # NOTREACHED
-+
-+
-+### End of file.
-
-Property changes on: subversion/tests/cmdline/mod_authz_svn_tests.py
-___________________________________________________________________
-Added: svn:eol-style
-## -0,0 +1 ##
-+native
-\ No newline at end of property
-Index: subversion/tests/cmdline/svntest/main.py
-===================================================================
---- a/subversion/tests/cmdline/svntest/main.py (revision 1691883)
-+++ b/subversion/tests/cmdline/svntest/main.py (working copy)
-@@ -1378,6 +1378,30 @@ def is_plaintext_password_storage_disabled():
- return False
- return True
-
-+
-+# https://issues.apache.org/bugzilla/show_bug.cgi?id=56480
-+# https://issues.apache.org/bugzilla/show_bug.cgi?id=55397
-+__mod_dav_url_quoting_broken_versions = frozenset([
-+ '2.2.27',
-+ '2.2.26',
-+ '2.2.25',
-+ '2.4.9',
-+ '2.4.8',
-+ '2.4.7',
-+ '2.4.6',
-+ '2.4.5',
-+])
-+def is_mod_dav_url_quoting_broken():
-+ if is_ra_type_dav():
-+ return (options.httpd_version in __mod_dav_url_quoting_broken_versions)
-+ return None
-+
-+def is_httpd_authz_provider_enabled():
-+ if is_ra_type_dav():
-+ v = options.httpd_version.split('.')
-+ return (v[0] == '2' and int(v[1]) >= 3) or int(v[0]) > 2
-+ return None
-+
- ######################################################################
-
-
-@@ -1435,6 +1459,8 @@ class TestSpawningThread(threading.Thread):
- args.append('--ssl-cert=' + options.ssl_cert)
- if options.http_proxy:
- args.append('--http-proxy=' + options.http_proxy)
-+ if options.httpd_version:
-+ args.append('--httpd-version=' + options.httpd_version)
-
- result, stdout_lines, stderr_lines = spawn_process(command, 0, False, None,
- *args)
-@@ -1600,6 +1626,12 @@ class TestRunner:
- sandbox.cleanup_test_paths()
- return exit_code
-
-+def is_httpd_authz_provider_enabled():
-+ if is_ra_type_dav():
-+ v = options.httpd_version.split('.')
-+ return (v[0] == '2' and int(v[1]) >= 3) or int(v[0]) > 2
-+ return None
-+
- ######################################################################
- # Main testing functions
-
-@@ -1780,6 +1812,8 @@ def _create_parser():
- help='Path to SSL server certificate.')
- parser.add_option('--http-proxy', action='store',
- help='Use the HTTP Proxy at hostname:port.')
-+ parser.add_option('--httpd-version', action='store',
-+ help='Assume HTTPD is this version.')
- parser.add_option('--tools-bin', action='store', dest='tools_bin',
- help='Use the svn tools installed in this path')
-
-Index: win-tests.py
-===================================================================
---- a/win-tests.py (revision 1691883)
-+++ b/win-tests.py (working copy)
-@@ -481,6 +481,7 @@ class Httpd:
- self.httpd_config = os.path.join(self.root, 'httpd.conf')
- self.httpd_users = os.path.join(self.root, 'users')
- self.httpd_mime_types = os.path.join(self.root, 'mime.types')
-+ self.httpd_groups = os.path.join(self.root, 'groups')
- self.abs_builddir = abs_builddir
- self.abs_objdir = abs_objdir
- self.service_name = 'svn-test-httpd-' + str(httpd_port)
-@@ -494,6 +495,7 @@ class Httpd:
- create_target_dir(self.root_dir)
-
- self._create_users_file()
-+ self._create_groups_file()
- self._create_mime_types_file()
- self._create_dontdothat_file()
-
-@@ -540,6 +542,8 @@ class Httpd:
- if self.httpd_ver >= 2.2:
- fp.write(self._sys_module('auth_basic_module', 'mod_auth_basic.so'))
- fp.write(self._sys_module('authn_file_module', 'mod_authn_file.so'))
-+ fp.write(self._sys_module('authz_groupfile_module', 'mod_authz_groupfile.so'))
-+ fp.write(self._sys_module('authz_host_module', 'mod_authz_host.so'))
- else:
- fp.write(self._sys_module('auth_module', 'mod_auth.so'))
- fp.write(self._sys_module('alias_module', 'mod_alias.so'))
-@@ -562,6 +566,7 @@ class Httpd:
- # Define two locations for repositories
- fp.write(self._svn_repo('repositories'))
- fp.write(self._svn_repo('local_tmp'))
-+ fp.write(self._svn_authz_repo())
-
- # And two redirects for the redirect tests
- fp.write('RedirectMatch permanent ^/svn-test-work/repositories/'
-@@ -592,7 +597,18 @@ class Httpd:
- 'jrandom', 'rayjandom'])
- os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users,
- 'jconstant', 'rayjandom'])
-+ os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users,
-+ 'JRANDOM', 'rayjandom'])
-+ os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users,
-+ 'JCONSTANT', 'rayjandom'])
-
-+ def _create_groups_file(self):
-+ "Create groups for mod_authz_svn tests"
-+ fp = open(self.httpd_groups, 'w')
-+ fp.write('random: jrandom\n')
-+ fp.write('constant: jconstant\n')
-+ fp.close()
-+
- def _create_mime_types_file(self):
- "Create empty mime.types file"
- fp = open(self.httpd_mime_types, 'w')
-@@ -652,6 +668,153 @@ class Httpd:
- ' DontDoThatConfigFile ' + self._quote(self.dontdothat_file) + '\n' \
- '</Location>\n'
-
-+ def _svn_authz_repo(self):
-+ local_tmp = os.path.join(self.abs_builddir,
-+ CMDLINE_TEST_SCRIPT_NATIVE_PATH,
-+ 'svn-test-work', 'local_tmp')
-+ return \
-+ '<Location /authz-test-work/anon>' + '\n' \
-+ ' DAV svn' + '\n' \
-+ ' SVNParentPath ' + local_tmp + '\n' \
-+ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
-+ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
-+ ' SVNListParentPath On' + '\n' \
-+ ' <IfModule mod_authz_core.c>' + '\n' \
-+ ' Require all granted' + '\n' \
-+ ' </IfModule>' + '\n' \
-+ ' <IfModule !mod_authz_core.c>' + '\n' \
-+ ' Allow from all' + '\n' \
-+ ' </IfModule>' + '\n' \
-+ ' SVNPathAuthz ' + self.path_authz_option + '\n' \
-+ '</Location>' + '\n' \
-+ '<Location /authz-test-work/mixed>' + '\n' \
-+ ' DAV svn' + '\n' \
-+ ' SVNParentPath ' + local_tmp + '\n' \
-+ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
-+ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
-+ ' SVNListParentPath On' + '\n' \
-+ ' AuthType Basic' + '\n' \
-+ ' AuthName "Subversion Repository"' + '\n' \
-+ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \
-+ ' Require valid-user' + '\n' \
-+ ' Satisfy Any' + '\n' \
-+ ' SVNPathAuthz ' + self.path_authz_option + '\n' \
-+ '</Location>' + '\n' \
-+ '<Location /authz-test-work/mixed-noauthwhenanon>' + '\n' \
-+ ' DAV svn' + '\n' \
-+ ' SVNParentPath ' + local_tmp + '\n' \
-+ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
-+ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
-+ ' SVNListParentPath On' + '\n' \
-+ ' AuthType Basic' + '\n' \
-+ ' AuthName "Subversion Repository"' + '\n' \
-+ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \
-+ ' Require valid-user' + '\n' \
-+ ' AuthzSVNNoAuthWhenAnonymousAllowed On' + '\n' \
-+ ' SVNPathAuthz On' + '\n' \
-+ '</Location>' + '\n' \
-+ '<Location /authz-test-work/authn>' + '\n' \
-+ ' DAV svn' + '\n' \
-+ ' SVNParentPath ' + local_tmp + '\n' \
-+ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
-+ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
-+ ' SVNListParentPath On' + '\n' \
-+ ' AuthType Basic' + '\n' \
-+ ' AuthName "Subversion Repository"' + '\n' \
-+ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \
-+ ' Require valid-user' + '\n' \
-+ ' SVNPathAuthz ' + self.path_authz_option + '\n' \
-+ '</Location>' + '\n' \
-+ '<Location /authz-test-work/authn-anonoff>' + '\n' \
-+ ' DAV svn' + '\n' \
-+ ' SVNParentPath ' + local_tmp + '\n' \
-+ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
-+ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
-+ ' SVNListParentPath On' + '\n' \
-+ ' AuthType Basic' + '\n' \
-+ ' AuthName "Subversion Repository"' + '\n' \
-+ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \
-+ ' Require valid-user' + '\n' \
-+ ' AuthzSVNAnonymous Off' + '\n' \
-+ ' SVNPathAuthz On' + '\n' \
-+ '</Location>' + '\n' \
-+ '<Location /authz-test-work/authn-lcuser>' + '\n' \
-+ ' DAV svn' + '\n' \
-+ ' SVNParentPath ' + local_tmp + '\n' \
-+ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
-+ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
-+ ' SVNListParentPath On' + '\n' \
-+ ' AuthType Basic' + '\n' \
-+ ' AuthName "Subversion Repository"' + '\n' \
-+ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \
-+ ' Require valid-user' + '\n' \
-+ ' AuthzForceUsernameCase Lower' + '\n' \
-+ ' SVNPathAuthz ' + self.path_authz_option + '\n' \
-+ '</Location>' + '\n' \
-+ '<Location /authz-test-work/authn-lcuser>' + '\n' \
-+ ' DAV svn' + '\n' \
-+ ' SVNParentPath ' + local_tmp + '\n' \
-+ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
-+ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
-+ ' SVNListParentPath On' + '\n' \
-+ ' AuthType Basic' + '\n' \
-+ ' AuthName "Subversion Repository"' + '\n' \
-+ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \
-+ ' Require valid-user' + '\n' \
-+ ' AuthzForceUsernameCase Lower' + '\n' \
-+ ' SVNPathAuthz ' + self.path_authz_option + '\n' \
-+ '</Location>' + '\n' \
-+ '<Location /authz-test-work/authn-group>' + '\n' \
-+ ' DAV svn' + '\n' \
-+ ' SVNParentPath ' + local_tmp + '\n' \
-+ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
-+ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
-+ ' SVNListParentPath On' + '\n' \
-+ ' AuthType Basic' + '\n' \
-+ ' AuthName "Subversion Repository"' + '\n' \
-+ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \
-+ ' AuthGroupFile ' + self._quote(self.httpd_groups) + '\n' \
-+ ' Require group random' + '\n' \
-+ ' AuthzSVNAuthoritative Off' + '\n' \
-+ ' SVNPathAuthz On' + '\n' \
-+ '</Location>' + '\n' \
-+ '<IfModule mod_authz_core.c>' + '\n' \
-+ '<Location /authz-test-work/sallrany>' + '\n' \
-+ ' DAV svn' + '\n' \
-+ ' SVNParentPath ' + local_tmp + '\n' \
-+ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
-+ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
-+ ' SVNListParentPath On' + '\n' \
-+ ' AuthType Basic' + '\n' \
-+ ' AuthName "Subversion Repository"' + '\n' \
-+ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \
-+ ' AuthzSendForbiddenOnFailure On' + '\n' \
-+ ' Satisfy All' + '\n' \
-+ ' <RequireAny>' + '\n' \
-+ ' Require valid-user' + '\n' \
-+ ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \
-+ ' </RequireAny>' + '\n' \
-+ ' SVNPathAuthz ' + self.path_authz_option + '\n' \
-+ '</Location>' + '\n' \
-+ '<Location /authz-test-work/sallrall>'+ '\n' \
-+ ' DAV svn' + '\n' \
-+ ' SVNParentPath ' + local_tmp + '\n' \
-+ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
-+ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
-+ ' SVNListParentPath On' + '\n' \
-+ ' AuthType Basic' + '\n' \
-+ ' AuthName "Subversion Repository"' + '\n' \
-+ ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \
-+ ' AuthzSendForbiddenOnFailure On' + '\n' \
-+ ' Satisfy All' + '\n' \
-+ ' <RequireAll>' + '\n' \
-+ ' Require valid-user' + '\n' \
-+ ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \
-+ ' </RequireAll>' + '\n' \
-+ ' SVNPathAuthz ' + self.path_authz_option + '\n' \
-+ '</Location>' + '\n' \
-+ '</IfModule>' + '\n' \
-+
- def start(self):
- if self.service:
- self._start_service()
-@@ -786,6 +949,10 @@ if not test_javahl:
- log_file = os.path.join(abs_builddir, log)
- fail_log_file = os.path.join(abs_builddir, faillog)
-
-+ if run_httpd:
-+ httpd_version = "%.1f" % daemon.httpd_ver
-+ else:
-+ httpd_version = None
- th = run_tests.TestHarness(abs_srcdir, abs_builddir,
- log_file,
- fail_log_file,
-@@ -795,6 +962,7 @@ if not test_javahl:
- fsfs_sharding, fsfs_packing,
- list_tests, svn_bin, mode_filter,
- milestone_filter,
-+ httpd_version=httpd_version,
- set_log_level=log_level, ssl_cert=ssl_cert)
- old_cwd = os.getcwd()
- try: