diff --git a/SOURCES/subversion-1.7.14-CVE-2015-0248.patch b/SOURCES/subversion-1.7.14-CVE-2015-0248.patch
new file mode 100644
index 0000000..cb84022
--- /dev/null
+++ b/SOURCES/subversion-1.7.14-CVE-2015-0248.patch
@@ -0,0 +1,112 @@
+# ./pullrev.sh 1667246
+
+https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2015-0248
+
+http://svn.apache.org/viewvc?view=revision&revision=1667246
+
+--- subversion-1.7.14/subversion/mod_dav_svn/reports/get-location-segments.c
++++ subversion-1.7.14/subversion/mod_dav_svn/reports/get-location-segments.c
+@@ -181,17 +181,36 @@
+                                   "Not all parameters passed.",
+                                   SVN_DAV_ERROR_NAMESPACE,
+                                   SVN_DAV_ERROR_TAG);
+-  if (SVN_IS_VALID_REVNUM(start_rev)
+-      && SVN_IS_VALID_REVNUM(end_rev)
+-      && (end_rev > start_rev))
++
++  /* No START_REV or PEG_REVISION?  We'll use HEAD. */
++  if (!SVN_IS_VALID_REVNUM(start_rev) || !SVN_IS_VALID_REVNUM(peg_revision))
++    {
++      svn_revnum_t youngest;
++
++      serr = svn_fs_youngest_rev(&youngest, resource->info->repos->fs,
++                                 resource->pool);
++      if (serr != NULL)
++        return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
++                                    "Could not determine youngest revision",
++                                    resource->pool);
++
++      if (!SVN_IS_VALID_REVNUM(start_rev))
++        start_rev = youngest;
++      if (!SVN_IS_VALID_REVNUM(peg_revision))
++        peg_revision = youngest;
++    }
++
++  /* No END_REV?  We'll use 0. */
++  if (!SVN_IS_VALID_REVNUM(end_rev))
++    end_rev = 0;
++
++  if (end_rev > start_rev)
+     return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
+                                   "End revision must not be younger than "
+                                   "start revision",
+                                   SVN_DAV_ERROR_NAMESPACE,
+                                   SVN_DAV_ERROR_TAG);
+-  if (SVN_IS_VALID_REVNUM(peg_revision)
+-      && SVN_IS_VALID_REVNUM(start_rev)
+-      && (start_rev > peg_revision))
++  if (start_rev > peg_revision)
+     return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
+                                   "Start revision must not be younger than "
+                                   "peg revision",
+--- subversion-1.7.14/subversion/svnserve/serve.c
++++ subversion-1.7.14/subversion/svnserve/serve.c
+@@ -2266,10 +2266,31 @@
+ 
+   abs_path = svn_fspath__join(b->fs_path->data, relative_path, pool);
+ 
+-  if (SVN_IS_VALID_REVNUM(start_rev)
+-      && SVN_IS_VALID_REVNUM(end_rev)
+-      && (end_rev > start_rev))
++  SVN_ERR(trivial_auth_request(conn, pool, b));
++  SVN_ERR(log_command(baton, conn, pool, "%s",
++                      svn_log__get_location_segments(abs_path, peg_revision,
++                                                     start_rev, end_rev,
++                                                     pool)));
++
++  /* No START_REV or PEG_REVISION?  We'll use HEAD. */
++  if (!SVN_IS_VALID_REVNUM(start_rev) || !SVN_IS_VALID_REVNUM(peg_revision))
+     {
++      svn_revnum_t youngest;
++
++      SVN_CMD_ERR(svn_fs_youngest_rev(&youngest, b->fs, pool));
++
++      if (!SVN_IS_VALID_REVNUM(start_rev))
++        start_rev = youngest;
++      if (!SVN_IS_VALID_REVNUM(peg_revision))
++        peg_revision = youngest;
++    }
++
++  /* No END_REV?  We'll use 0. */
++  if (!SVN_IS_VALID_REVNUM(end_rev))
++    end_rev = 0;
++
++  if (end_rev > start_rev)
++    {
+       err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                               "Get-location-segments end revision must not be "
+                               "younger than start revision");
+@@ -2276,9 +2297,7 @@
+       return log_fail_and_flush(err, b, conn, pool);
+     }
+ 
+-  if (SVN_IS_VALID_REVNUM(peg_revision)
+-      && SVN_IS_VALID_REVNUM(start_rev)
+-      && (start_rev > peg_revision))
++  if (start_rev > peg_revision)
+     {
+       err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                               "Get-location-segments start revision must not "
+@@ -2286,12 +2305,6 @@
+       return log_fail_and_flush(err, b, conn, pool);
+     }
+ 
+-  SVN_ERR(trivial_auth_request(conn, pool, b));
+-  SVN_ERR(log_command(baton, conn, pool, "%s",
+-                      svn_log__get_location_segments(abs_path, peg_revision,
+-                                                     start_rev, end_rev,
+-                                                     pool)));
+-
+   /* All the parameters are fine - let's perform the query against the
+    * repository. */
+ 
diff --git a/SOURCES/subversion-1.7.14-CVE-2015-0251.patch b/SOURCES/subversion-1.7.14-CVE-2015-0251.patch
new file mode 100644
index 0000000..1908318
--- /dev/null
+++ b/SOURCES/subversion-1.7.14-CVE-2015-0251.patch
@@ -0,0 +1,66 @@
+# ./pullrev.sh 1667248
+
+https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2015-0251
+
+http://svn.apache.org/viewvc?view=revision&revision=1667248
+
+--- subversion-1.7.14/subversion/mod_dav_svn/deadprops.c
++++ subversion-1.7.14/subversion/mod_dav_svn/deadprops.c
+@@ -160,6 +160,23 @@
+ }
+ 
+ 
++static svn_error_t *
++change_txn_prop(svn_fs_txn_t *txn,
++                const char *propname,
++                const svn_string_t *value,
++                apr_pool_t *scratch_pool)
++{
++  if (strcmp(propname, SVN_PROP_REVISION_AUTHOR) == 0)
++    return svn_error_create(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
++                            "Attempted to modify 'svn:author' property "
++                            "on a transaction");
++
++  SVN_ERR(svn_repos_fs_change_txn_prop(txn, propname, value, scratch_pool));
++
++  return SVN_NO_ERROR;
++}
++
++
+ static dav_error *
+ save_value(dav_db *db, const dav_prop_name *name,
+            const svn_string_t *const *old_value_p,
+@@ -210,9 +227,8 @@
+     {
+       if (db->resource->working)
+         {
+-          serr = svn_repos_fs_change_txn_prop(resource->info->root.txn,
+-                                              propname, value,
+-                                              subpool);
++          serr = change_txn_prop(resource->info->root.txn, propname,
++                                 value, subpool);
+         }
+       else
+         {
+@@ -251,8 +267,8 @@
+     }
+   else if (resource->info->restype == DAV_SVN_RESTYPE_TXN_COLLECTION)
+     {
+-      serr = svn_repos_fs_change_txn_prop(resource->info->root.txn,
+-                                          propname, value, subpool);
++      serr = change_txn_prop(resource->info->root.txn, propname,
++                             value, subpool);
+     }
+   else
+     {
+@@ -561,8 +577,8 @@
+   /* Working Baseline or Working (Version) Resource */
+   if (db->resource->baselined)
+     if (db->resource->working)
+-      serr = svn_repos_fs_change_txn_prop(db->resource->info->root.txn,
+-                                          propname, NULL, subpool);
++      serr = change_txn_prop(db->resource->info->root.txn, propname,
++                             NULL, subpool);
+     else
+       /* ### VIOLATING deltaV: you can't proppatch a baseline, it's
+          not a working resource!  But this is how we currently
diff --git a/SOURCES/subversion-1.7.14-CVE-2015-3184.patch b/SOURCES/subversion-1.7.14-CVE-2015-3184.patch
new file mode 100644
index 0000000..074afad
--- /dev/null
+++ b/SOURCES/subversion-1.7.14-CVE-2015-3184.patch
@@ -0,0 +1,2088 @@
+# ./pullrev.sh 1692801 1694012
+
+https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2015-3184
+
+http://svn.apache.org/viewvc?view=revision&revision=1692801
+http://svn.apache.org/viewvc?view=revision&revision=1694012
+
+Excludes CVE-2015-3187 changes.  This patch requires an httpd
+patched with the new API introduced for CVE-2015-3185.
+
+--- subversion-1.7.14/build/ac-macros/apache.m4.cve3184
++++ subversion-1.7.14/build/ac-macros/apache.m4
+@@ -85,6 +85,25 @@ VERSION_OKAY
+         AC_MSG_RESULT(no - Unable to locate $APXS_INCLUDE/mod_dav.h)
+         APXS=""
+     fi
++    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" = "backport"; then
++      AC_MSG_NOTICE([Building with httpd as if 2.4.17 or later])
++      HTTPD_VERSION=2.4.17
++      AC_DEFINE(SVN_ALLOW_BROKEN_HTTPD_AUTH, 1,
++                [Defined to allow building against httpd 2.4 with broken auth])
++    elif 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
+ else
+     AC_MSG_RESULT(no)
+ fi
+@@ -157,6 +176,7 @@ AC_SUBST(APXS)
+ AC_SUBST(APACHE_LDFLAGS)
+ AC_SUBST(APACHE_INCLUDES)
+ AC_SUBST(APACHE_LIBEXECDIR)
++AC_SUBST(HTTPD_VERSION)
+ 
+ # there aren't any flags that interest us ...
+ #if test -n "$APXS" && test "$APXS" != "no"; then
+--- subversion-1.7.14/build/run_tests.py.cve3184
++++ subversion-1.7.14/build/run_tests.py
+@@ -29,6 +29,7 @@
+             [--fs-type=<fs-type>] [--fsfs-packing] [--fsfs-sharding=<n>]
+             [--list] [--milestone-filter=<regex>] [--mode-filter=<type>]
+             [--server-minor-version=<version>]
++            [--httpd-version=<version>]
+             [--config-file=<file>]
+             <abs_srcdir> <abs_builddir>
+             <prog ...>
+@@ -81,7 +82,7 @@ class TestHarness:
+                cleanup=None, enable_sasl=None, parallel=None, config_file=None,
+                fsfs_sharding=None, fsfs_packing=None,
+                list_tests=None, svn_bin=None, mode_filter=None,
+-               milestone_filter=None):
++               milestone_filter=None, httpd_version=None):
+     '''Construct a TestHarness instance.
+ 
+     ABS_SRCDIR and ABS_BUILDDIR are the source and build directories.
+@@ -130,6 +131,7 @@ class TestHarness:
+     self.svn_bin = svn_bin
+     self.mode_filter = mode_filter
+     self.log = None
++    self.httpd_version = httpd_version
+     if not sys.stdout.isatty() or sys.platform == 'win32':
+       TextColors.disable()
+ 
+@@ -414,6 +416,8 @@ class TestHarness:
+       svntest.main.options.fsfs_packing = self.fsfs_packing
+     if self.mode_filter is not None:
+       svntest.main.options.mode_filter = self.mode_filter
++    if self.httpd_version is not None:
++      svntest.main.options.httpd_version = self.httpd_version
+ 
+     svntest.main.options.srcdir = self.srcdir
+ 
+@@ -562,7 +566,7 @@ def main():
+                             'fsfs-packing', 'fsfs-sharding=',
+                             'enable-sasl', 'parallel', 'config-file=',
+                             'log-to-stdout', 'list', 'milestone-filter=',
+-                            'mode-filter='])
++                            'mode-filter=', 'httpd-version='])
+   except getopt.GetoptError:
+     args = []
+ 
+@@ -572,9 +576,10 @@ 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= \
++    config_file, log_to_stdout, list_tests, mode_filter, milestone_filter, \
++    httpd_version = \
+             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
+@@ -606,6 +611,8 @@ def main():
+       milestone_filter = val
+     elif opt in ['--mode-filter']:
+       mode_filter = val
++    elif opt in ['--httpd-version']:
++      httpd_version = val
+     else:
+       raise getopt.GetoptError
+ 
+@@ -620,7 +627,8 @@ def main():
+                    base_url, fs_type, http_library, server_minor_version,
+                    verbose, cleanup, enable_sasl, parallel, config_file,
+                    fsfs_sharding, fsfs_packing, list_tests,
+-                   mode_filter=mode_filter, milestone_filter=milestone_filter)
++                   mode_filter=mode_filter, milestone_filter=milestone_filter,
++                   httpd_version=httpd_version)
+ 
+   failed = th.run(args[2:])
+   if failed:
+--- subversion-1.7.14/Makefile.in.cve3184
++++ subversion-1.7.14/Makefile.in
+@@ -319,6 +319,7 @@ INSTALL_EXTRA_SWIG_RB=\
+   done
+ 
+ APXS = @APXS@
++HTTPD_VERSION = @HTTPD_VERSION@
+ 
+ PYTHON = @PYTHON@
+ PERL = @PERL@
+@@ -466,6 +467,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $
+ 	  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;                                                                \
+--- subversion-1.7.14/subversion/mod_authz_svn/mod_authz_svn.c.cve3184
++++ subversion-1.7.14/subversion/mod_authz_svn/mod_authz_svn.c
+@@ -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"
+ 
+ extern module AP_MODULE_DECLARE_DATA authz_svn_module;
+ 
+@@ -65,6 +82,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 1 || 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
+  */
+@@ -682,7 +723,49 @@ 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
+@@ -697,9 +780,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)
+@@ -711,6 +795,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);
+@@ -719,7 +804,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;
+@@ -800,6 +904,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
+  */
+@@ -816,6 +931,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,
+--- subversion-1.7.14/subversion/tests/cmdline/davautocheck.sh.cve3184
++++ subversion-1.7.14/subversion/tests/cmdline/davautocheck.sh
+@@ -248,8 +248,6 @@ LOAD_MOD_AUTHN_CORE="$(get_loadmodule_co
+     || 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"
+ }
+@@ -257,6 +255,10 @@ LOAD_MOD_AUTHN_FILE="$(get_loadmodule_co
+     || 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) \
+@@ -272,6 +274,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'"
+@@ -281,6 +284,14 @@ say "Using directory '$HTTPD_ROOT'..."
+ 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
+ 
+@@ -297,7 +308,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__
+@@ -369,6 +382,151 @@ CustomLog           "$HTTPD_ROOT/ops" "%
+   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}
++  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}
++  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}
++  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}
++  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}
++  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}
++  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}
++  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}
++  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}
++    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}
++    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__
+--- subversion-1.7.14/subversion/tests/cmdline/mod_authz_svn_tests.py.cve3184
++++ subversion-1.7.14/subversion/tests/cmdline/mod_authz_svn_tests.py
+@@ -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.
+--- subversion-1.7.14/subversion/tests/cmdline/README.cve3184
++++ subversion-1.7.14/subversion/tests/cmdline/README
+@@ -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,6 +228,15 @@ just drop the following 2-line snippet i
+ ----------------------------
+ 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.
+@@ -138,6 +274,8 @@ Note [1]: It would be quite too much to
+           ----------------------------
+           jrandom:$apr1$3p1.....$FQW6RceW5QhJ2blWDQgKn0
+           jconstant:$apr1$jp1.....$Usrqji1c9H6AbOxOGAzzb0
++          JRANDOM:$apr1$3p1.....$FQW6RceW5QhJ2blWDQgKn0
++          JCONSTANT:$apr1$jp1.....$Usrqji1c9H6AbOxOGAzzb0
+           ----------------------------
+ 
+ 
+--- subversion-1.7.14/subversion/tests/cmdline/svntest/main.py.cve3184
++++ subversion-1.7.14/subversion/tests/cmdline/svntest/main.py
+@@ -1148,6 +1148,30 @@ def server_enforces_date_syntax():
+ def server_has_atomic_revprop():
+   return options.server_minor_version >= 7
+ 
++
++# 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
++
+ ######################################################################
+ 
+ 
+@@ -1194,6 +1218,8 @@ class TestSpawningThread(threading.Threa
+       args.append('--mode-filter=' + options.mode_filter)
+     if options.milestone_filter:
+       args.append('--milestone-filter=' + options.milestone_filter)
++    if options.httpd_version:
++      args.append('--httpd-version=' + options.httpd_version)
+ 
+     result, stdout_lines, stderr_lines = spawn_process(command, 0, 0, None,
+                                                        *args)
+@@ -1361,6 +1387,36 @@ class TestRunner:
+       sandbox.cleanup_test_paths()
+     return exit_code
+ 
++
++# 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
++
++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
+ 
+@@ -1526,6 +1582,8 @@ def _create_parser():
+                          'useful during test development!')
+   parser.add_option('--srcdir', action='store', dest='srcdir',
+                     help='Source directory.')
++  parser.add_option('--httpd-version', action='store',
++                    help='Assume HTTPD is this version.')
+ 
+   # most of the defaults are None, but some are other values, set them here
+   parser.set_defaults(
+--- subversion-1.7.14/win-tests.py.cve3184
++++ subversion-1.7.14/win-tests.py
+@@ -466,6 +466,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)
+@@ -479,6 +480,7 @@ class Httpd:
+     create_target_dir(self.root_dir)
+ 
+     self._create_users_file()
++    self._create_groups_file()
+     self._create_mime_types_file()
+ 
+     # Determine version.
+@@ -520,6 +522,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'))
+@@ -533,6 +537,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/'
+@@ -562,6 +567,17 @@ class Httpd:
+                                     'jrandom', 'rayjandom'])
+     os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-mb',  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"
+@@ -595,6 +611,153 @@ class Httpd:
+       '  Require         valid-user\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()
+@@ -728,6 +891,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,
+@@ -736,7 +903,8 @@ if not test_javahl:
+                              cleanup, enable_sasl, parallel, config_file,
+                              fsfs_sharding, fsfs_packing,
+                              list_tests, svn_bin, mode_filter,
+-                             milestone_filter)
++                             milestone_filter,
++                             httpd_version=httpd_version)
+   old_cwd = os.getcwd()
+   try:
+     os.chdir(abs_builddir)
diff --git a/SOURCES/subversion-1.7.14-CVE-2015-3187.patch b/SOURCES/subversion-1.7.14-CVE-2015-3187.patch
new file mode 100644
index 0000000..5a8792f
--- /dev/null
+++ b/SOURCES/subversion-1.7.14-CVE-2015-3187.patch
@@ -0,0 +1,343 @@
+# ./pullrev.sh 1692801 1694012
+
+https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2015-3187
+
+http://svn.apache.org/viewvc?view=revision&revision=1692801
+
+- excluding changes from CVE-2015-3184
+
+diff -uap subversion-1.7.14/subversion/libsvn_repos/rev_hunt.c.cve3187 subversion-1.7.14/subversion/libsvn_repos/rev_hunt.c
+--- subversion-1.7.14/subversion/libsvn_repos/rev_hunt.c.cve3187
++++ subversion-1.7.14/subversion/libsvn_repos/rev_hunt.c
+@@ -721,23 +721,6 @@ svn_repos_trace_node_locations(svn_fs_t
+       if (! prev_path)
+         break;
+ 
+-      if (authz_read_func)
+-        {
+-          svn_boolean_t readable;
+-          svn_fs_root_t *tmp_root;
+-
+-          SVN_ERR(svn_fs_revision_root(&tmp_root, fs, revision, currpool));
+-          SVN_ERR(authz_read_func(&readable, tmp_root, path,
+-                                  authz_read_baton, currpool));
+-          if (! readable)
+-            {
+-              svn_pool_destroy(lastpool);
+-              svn_pool_destroy(currpool);
+-
+-              return SVN_NO_ERROR;
+-            }
+-        }
+-
+       /* Assign the current path to all younger revisions until we reach
+          the copy target rev. */
+       while ((revision_ptr < revision_ptr_end)
+@@ -760,6 +743,20 @@ svn_repos_trace_node_locations(svn_fs_t
+       path = prev_path;
+       revision = prev_rev;
+ 
++      if (authz_read_func)
++        {
++          svn_boolean_t readable;
++          SVN_ERR(svn_fs_revision_root(&root, fs, revision, currpool));
++          SVN_ERR(authz_read_func(&readable, root, path,
++                                  authz_read_baton, currpool));
++          if (!readable)
++            {
++              svn_pool_destroy(lastpool);
++              svn_pool_destroy(currpool);
++              return SVN_NO_ERROR;
++            }
++        }
++
+       /* Clear last pool and switch. */
+       svn_pool_clear(lastpool);
+       tmppool = lastpool;
+diff -uap subversion-1.7.14/subversion/tests/cmdline/authz_tests.py.cve3187 subversion-1.7.14/subversion/tests/cmdline/authz_tests.py
+--- subversion-1.7.14/subversion/tests/cmdline/authz_tests.py.cve3187
++++ subversion-1.7.14/subversion/tests/cmdline/authz_tests.py
+@@ -608,8 +608,10 @@ def authz_log_and_tracing_test(sbox):
+ 
+   ## cat
+ 
++  expected_err2 = ".*svn: E195012: Unable to find repository location.*"
++
+   # now see if we can look at the older version of rho
+-  svntest.actions.run_and_verify_svn(None, None, expected_err,
++  svntest.actions.run_and_verify_svn(None, None, expected_err2,
+                                      'cat', '-r', '2', D_url+'/rho')
+ 
+   if sbox.repo_url.startswith('http'):
+@@ -626,10 +628,11 @@ def authz_log_and_tracing_test(sbox):
+   svntest.actions.run_and_verify_svn(None, None, expected_err,
+                                      'diff', '-r', 'HEAD', G_url+'/rho')
+ 
+-  svntest.actions.run_and_verify_svn(None, None, expected_err,
++  # diff treats the unreadable path as indicating an add so no error
++  svntest.actions.run_and_verify_svn(None, None, [],
+                                      'diff', '-r', '2', D_url+'/rho')
+ 
+-  svntest.actions.run_and_verify_svn(None, None, expected_err,
++  svntest.actions.run_and_verify_svn(None, None, [],
+                                      'diff', '-r', '2:4', D_url+'/rho')
+ 
+ # test whether read access is correctly granted and denied
+diff -uap subversion-1.7.14/subversion/tests/libsvn_repos/repos-test.c.cve3187 subversion-1.7.14/subversion/tests/libsvn_repos/repos-test.c
+--- subversion-1.7.14/subversion/tests/libsvn_repos/repos-test.c.cve3187
++++ subversion-1.7.14/subversion/tests/libsvn_repos/repos-test.c
+@@ -2526,6 +2526,246 @@ issue_4060(const svn_test_opts_t *opts,
+   return SVN_NO_ERROR;
+ }
+ 
++static svn_error_t *
++mkdir_delete_copy(svn_repos_t *repos,
++                  const char *src,
++                  const char *dst,
++                  apr_pool_t *pool)
++{
++  svn_fs_t *fs = svn_repos_fs(repos);
++  svn_revnum_t youngest_rev;
++  svn_fs_txn_t *txn;
++  svn_fs_root_t *txn_root, *rev_root;
++
++  SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool));
++  
++  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
++  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
++  SVN_ERR(svn_fs_make_dir(txn_root, "A/T", pool));
++  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
++
++  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
++  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
++  SVN_ERR(svn_fs_delete(txn_root, "A/T", pool));
++  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
++
++  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
++  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
++  SVN_ERR(svn_fs_revision_root(&rev_root, fs, youngest_rev - 1, pool));
++  SVN_ERR(svn_fs_copy(rev_root, src, txn_root, dst, pool));
++  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
++
++  return SVN_NO_ERROR;
++}
++
++struct authz_read_baton_t {
++  apr_hash_t *paths;
++  apr_pool_t *pool;
++  const char *deny;
++};
++
++static svn_error_t *
++authz_read_func(svn_boolean_t *allowed,
++                svn_fs_root_t *root,
++                const char *path,
++                void *baton,
++                apr_pool_t *pool)
++{
++  struct authz_read_baton_t *b = baton;
++
++  if (b->deny && !strcmp(b->deny, path))
++    *allowed = FALSE;
++  else
++    *allowed = TRUE;
++
++  apr_hash_set(b->paths, apr_pstrdup(b->pool, path), APR_HASH_KEY_STRING,
++               (void*)1);
++
++  return SVN_NO_ERROR;
++}
++
++static svn_error_t *
++verify_locations(apr_hash_t *actual,
++                 apr_hash_t *expected,
++                 apr_hash_t *checked,
++                 apr_pool_t *pool)
++{
++  apr_hash_index_t *hi;
++
++  for (hi = apr_hash_first(pool, expected); hi; hi = apr_hash_next(hi))
++    {
++      const svn_revnum_t *rev = svn__apr_hash_index_key(hi);
++      const char *path = apr_hash_get(actual, rev, sizeof(svn_revnum_t));
++
++      if (!path)
++        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
++                                 "expected %s for %d found (null)",
++                                 (char*)svn__apr_hash_index_val(hi),
++                                 (int)*rev);
++      else if (strcmp(path, svn__apr_hash_index_val(hi)))
++        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
++                                 "expected %s for %d found %s",
++                                 (char*)svn__apr_hash_index_val(hi),
++                                 (int)*rev, path);
++
++    }
++
++  for (hi = apr_hash_first(pool, actual); hi; hi = apr_hash_next(hi))
++    {
++      const svn_revnum_t *rev = svn__apr_hash_index_key(hi);
++      const char *path = apr_hash_get(expected, rev, sizeof(svn_revnum_t));
++
++      if (!path)
++        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
++                                 "found %s for %d expected (null)",
++                                 (char*)svn__apr_hash_index_val(hi),
++                                 (int)*rev);
++      else if (strcmp(path, svn__apr_hash_index_val(hi)))
++        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
++                                 "found %s for %d expected %s",
++                                 (char*)svn__apr_hash_index_val(hi),
++                                 (int)*rev, path);
++
++      if (!apr_hash_get(checked, path, APR_HASH_KEY_STRING))
++        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
++                                 "did not check %s", path);
++    }
++
++  return SVN_NO_ERROR;
++}
++
++static void
++set_expected(apr_hash_t *expected,
++             svn_revnum_t rev,
++             const char *path,
++             apr_pool_t *pool)
++{
++  svn_revnum_t *rp = apr_palloc(pool, sizeof(svn_revnum_t));
++  *rp = rev;
++  apr_hash_set(expected, rp, sizeof(svn_revnum_t), path);
++}
++
++static svn_error_t *
++trace_node_locations_authz(const svn_test_opts_t *opts,
++                           apr_pool_t *pool)
++{
++  svn_repos_t *repos;
++  svn_fs_t *fs;
++  svn_revnum_t youngest_rev = 0;
++  svn_fs_txn_t *txn;
++  svn_fs_root_t *txn_root;
++  struct authz_read_baton_t arb;
++  apr_array_header_t *revs = apr_array_make(pool, 10, sizeof(svn_revnum_t));
++  apr_hash_t *locations;
++  apr_hash_t *expected = apr_hash_make(pool);
++  int i;
++
++  /* Create test repository. */
++  SVN_ERR(svn_test__create_repos(&repos, "test-repo-trace-node-locations-authz",
++                                 opts, pool));
++  fs = svn_repos_fs(repos);
++
++  /* r1 create A */
++  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
++  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
++  SVN_ERR(svn_fs_make_dir(txn_root, "A", pool));
++  SVN_ERR(svn_fs_make_file(txn_root, "A/f", pool));
++  SVN_ERR(svn_test__set_file_contents(txn_root, "A/f", "foobar", pool));
++  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
++
++  /* r4 copy A to B */
++  SVN_ERR(mkdir_delete_copy(repos, "A", "B", pool));
++
++  /* r7 copy B to C */
++  SVN_ERR(mkdir_delete_copy(repos, "B", "C", pool));
++
++  /* r10 copy C to D */
++  SVN_ERR(mkdir_delete_copy(repos, "C", "D", pool));
++
++  SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool));
++  SVN_ERR_ASSERT(youngest_rev == 10);
++
++  arb.paths = apr_hash_make(pool);
++  arb.pool = pool;
++  arb.deny = NULL;
++
++  apr_array_clear(revs);
++  for (i = 0; i <= youngest_rev; ++i)
++    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
++  set_expected(expected, 10, "/D/f", pool);
++  set_expected(expected, 8, "/C/f", pool);
++  set_expected(expected, 7, "/C/f", pool);
++  set_expected(expected, 5, "/B/f", pool);
++  set_expected(expected, 4, "/B/f", pool);
++  set_expected(expected, 2, "/A/f", pool);
++  set_expected(expected, 1, "/A/f", pool);
++  apr_hash_clear(arb.paths);
++  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
++                                         authz_read_func, &arb, pool));
++  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
++
++  apr_array_clear(revs);
++  for (i = 1; i <= youngest_rev; ++i)
++    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
++  apr_hash_clear(arb.paths);
++  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
++                                         authz_read_func, &arb, pool));
++  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
++
++  apr_array_clear(revs);
++  for (i = 2; i <= youngest_rev; ++i)
++    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
++  set_expected(expected, 1, NULL, pool);
++  apr_hash_clear(arb.paths);
++  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
++                                         authz_read_func, &arb, pool));
++  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
++
++  apr_array_clear(revs);
++  for (i = 3; i <= youngest_rev; ++i)
++    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
++  set_expected(expected, 2, NULL, pool);
++  apr_hash_clear(arb.paths);
++  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
++                                         authz_read_func, &arb, pool));
++  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
++
++  apr_array_clear(revs);
++  for (i = 6; i <= youngest_rev; ++i)
++    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
++  set_expected(expected, 5, NULL, pool);
++  set_expected(expected, 4, NULL, pool);
++  apr_hash_clear(arb.paths);
++  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
++                                         authz_read_func, &arb, pool));
++  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
++
++  arb.deny = "/B/f";
++  apr_array_clear(revs);
++  for (i = 0; i <= youngest_rev; ++i)
++    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
++  apr_hash_clear(arb.paths);
++  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
++                                         authz_read_func, &arb, pool));
++  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
++
++  apr_array_clear(revs);
++  for (i = 6; i <= youngest_rev; ++i)
++    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
++  apr_hash_clear(arb.paths);
++  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
++                                         authz_read_func, &arb, pool));
++  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
++
++  APR_ARRAY_PUSH(revs, svn_revnum_t) = 0;
++  apr_hash_clear(arb.paths);
++  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
++                                         authz_read_func, &arb, pool));
++  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
++
++  return SVN_NO_ERROR;
++}
++
+ 
+ /* The test table.  */
+ 
+@@ -2562,5 +2802,7 @@ struct svn_test_descriptor_t test_funcs[
+                        "test svn_repos_get_file_revsN"),
+     SVN_TEST_OPTS_PASS(issue_4060,
+                        "test issue 4060"),
++    SVN_TEST_OPTS_PASS(trace_node_locations_authz,
++                       "authz for svn_repos_trace_node_locations"),
+     SVN_TEST_NULL
+   };
diff --git a/SPECS/subversion.spec b/SPECS/subversion.spec
index 9a359f9..0fc0b41 100644
--- a/SPECS/subversion.spec
+++ b/SPECS/subversion.spec
@@ -20,7 +20,7 @@
 Summary: A Modern Concurrent Version Control System
 Name: subversion
 Version: 1.7.14
-Release: 7%{?dist}
+Release: 7%{?dist}.1
 License: ASL 2.0
 Group: Development/Tools
 URL: http://subversion.apache.org/
@@ -45,6 +45,10 @@ Patch12: subversion-1.7.14-CVE-2014-0032.patch
 Patch13: subversion-1.7.14-CVE-2014-3528.patch
 Patch14: subversion-1.7.14-CVE-2014-3580.patch
 Patch15: subversion-1.7.14-CVE-2014-8108.patch
+Patch16: subversion-1.7.14-CVE-2015-0248.patch
+Patch17: subversion-1.7.14-CVE-2015-0251.patch
+Patch18: subversion-1.7.14-CVE-2015-3184.patch
+Patch19: subversion-1.7.14-CVE-2015-3187.patch
 BuildRequires: autoconf, libtool, python, python-devel, texinfo, which
 BuildRequires: libdb-devel, swig >= 1.3.24, gettext
 BuildRequires: apr-devel >= 1.3.0, apr-util-devel >= 1.3.0
@@ -118,12 +122,13 @@ The subversion-kde package adds support for storing Subversion
 passwords in the KDE Wallet.
 %endif
 
+# Require httpd, httpd-devel with API fixing CVE-2015-3185
 %package -n mod_dav_svn
 Group: System Environment/Daemons
 Summary: Apache httpd module for Subversion server
-Requires: httpd-mmn = %{_httpd_mmn}
+Requires: httpd-mmn = %{_httpd_mmn}, httpd >= 2.4.6-31%{?dist}.1
 Requires: subversion-libs%{?_isa} = %{version}-%{release}
-BuildRequires: httpd-devel >= 2.0.45
+BuildRequires: httpd-devel >= 2.4.6-31%{?dist}.1
 
 %description -n mod_dav_svn
 The mod_dav_svn package allows access to a Subversion repository
@@ -189,6 +194,10 @@ This package includes supplementary tools for use with Subversion.
 %patch13 -p1 -b .cve3528
 %patch14 -p1 -b .cve3580
 %patch15 -p1 -b .cve8108
+%patch16 -p1 -b .cve0248
+%patch17 -p1 -b .cve0251
+%patch18 -p1 -b .cve3184
+%patch19 -p1 -b .cve3187
 
 %build
 # Regenerate the buildsystem, so that:
@@ -218,6 +227,7 @@ export CC=gcc CXX=g++ JAVA_HOME=%{jdk_path} CFLAGS="$RPM_OPT_FLAGS"
         --with-ruby-sitedir=%{ruby_vendorarchdir} \
         --with-ruby-test-verbose=verbose \
         --with-apxs=%{_httpd_apxs} --disable-mod-activation \
+        --enable-broken-httpd-auth=backport \
         --disable-static --with-sasl=%{_prefix} \
         --disable-neon-version-check \
         --with-libmagic=%{_prefix} \
@@ -480,6 +490,10 @@ rm -rf ${RPM_BUILD_ROOT}
 %endif
 
 %changelog
+* Wed Aug 12 2015 Joe Orton <jorton@redhat.com> - 1.7.14-7.1
+- add security fixes for CVE-2015-0248, CVE-2015-0251, CVE-2015-3184,
+  CVE-2015-3187
+
 * Fri Jan  9 2015 Joe Orton <jorton@redhat.com> - 1.7.14-7
 - add security fixes for CVE-2014-3528, CVE-2014-3580, CVE-2014-8108