From 21e35df191a88635b6cb829ebed52f5b94d5542c Mon Sep 17 00:00:00 2001 From: Alexander Kanavin Date: Mon, 7 Dec 2015 19:46:49 +0200 Subject: subversion: update to 1.9.2 Drop backported CVE fix patches libtool2.patch has been rebased and renamed to 0001-Fix-libtool-name-in-configure.ac.patch LICENSE checksum has been updated because more 3rd party attributions have been added to it, it's otherwise still Apache 2. (From OE-Core rev: b57f57ea092f93bd7e1268b04c7d3c4af2149a77) Signed-off-by: Alexander Kanavin Signed-off-by: Ross Burton Signed-off-by: Richard Purdie --- .../subversion-1.8.13/disable_macos.patch | 68 - .../subversion/subversion-1.8.13/libtool2.patch | 15 - ...erf.m4-Regex-modified-to-allow-D-in-paths.patch | 32 - .../subversion-CVE-2015-3184.patch | 2094 -------------------- .../subversion-CVE-2015-3187.patch | 346 ---- .../0001-Fix-libtool-name-in-configure.ac.patch | 29 + .../subversion/subversion/disable_macos.patch | 68 + ...erf.m4-Regex-modified-to-allow-D-in-paths.patch | 32 + .../subversion/subversion_1.8.13.bb | 55 - .../subversion/subversion_1.9.2.bb | 53 + 10 files changed, 182 insertions(+), 2610 deletions(-) delete mode 100644 meta/recipes-devtools/subversion/subversion-1.8.13/disable_macos.patch delete mode 100644 meta/recipes-devtools/subversion/subversion-1.8.13/libtool2.patch delete mode 100644 meta/recipes-devtools/subversion/subversion-1.8.13/serf.m4-Regex-modified-to-allow-D-in-paths.patch delete mode 100644 meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3184.patch delete mode 100644 meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3187.patch create mode 100644 meta/recipes-devtools/subversion/subversion/0001-Fix-libtool-name-in-configure.ac.patch create mode 100644 meta/recipes-devtools/subversion/subversion/disable_macos.patch create mode 100644 meta/recipes-devtools/subversion/subversion/serf.m4-Regex-modified-to-allow-D-in-paths.patch delete mode 100644 meta/recipes-devtools/subversion/subversion_1.8.13.bb create mode 100644 meta/recipes-devtools/subversion/subversion_1.9.2.bb (limited to 'meta/recipes-devtools/subversion') diff --git a/meta/recipes-devtools/subversion/subversion-1.8.13/disable_macos.patch b/meta/recipes-devtools/subversion/subversion-1.8.13/disable_macos.patch deleted file mode 100644 index ec3be496f3..0000000000 --- a/meta/recipes-devtools/subversion/subversion-1.8.13/disable_macos.patch +++ /dev/null @@ -1,68 +0,0 @@ -These tests don't work in cross compiling, just disable them for now, we don't -build subversion on OS-X at this time. - -RP 1014/7/16 - -Upstream-Status: Pending [needs a rewrite to support a cache value] - -Index: subversion-1.8.9/build/ac-macros/macosx.m4 -=================================================================== ---- subversion-1.8.9.orig/build/ac-macros/macosx.m4 2012-11-26 03:04:27.000000000 +0000 -+++ subversion-1.8.9/build/ac-macros/macosx.m4 2014-07-16 12:28:58.357300403 +0000 -@@ -24,21 +24,7 @@ - AC_DEFUN(SVN_LIB_MACHO_ITERATE, - [ - AC_MSG_CHECKING([for Mach-O dynamic module iteration functions]) -- AC_RUN_IFELSE([AC_LANG_PROGRAM([[ -- #include -- #include -- ]],[[ -- const struct mach_header *header = _dyld_get_image_header(0); -- const char *name = _dyld_get_image_name(0); -- if (name && header) return 0; -- return 1; -- ]])],[ -- AC_DEFINE([SVN_HAVE_MACHO_ITERATE], [1], -- [Is Mach-O low-level _dyld API available?]) -- AC_MSG_RESULT([yes]) -- ],[ - AC_MSG_RESULT([no]) -- ]) - ]) - - dnl SVN_LIB_MACOS_PLIST -@@ -46,34 +32,7 @@ - AC_DEFUN(SVN_LIB_MACOS_PLIST, - [ - AC_MSG_CHECKING([for Mac OS property list utilities]) -- -- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -- #include -- #if !defined(MAC_OS_X_VERSION_MAX_ALLOWED) \ -- || !defined(MAC_OS_X_VERSION_10_0) \ -- || (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_0) -- #error ProperyList API unavailable. -- #endif -- ]],[[]])],[ -- dnl ### Hack. We should only need to pass the -framework options when -- dnl linking libsvn_subr, since it is the only library that uses Keychain. -- dnl -- dnl Unfortunately, libtool 1.5.x doesn't track transitive dependencies for -- dnl OS X frameworks like it does for normal libraries, so we need to -- dnl explicitly pass the option to all the users of libsvn_subr to allow -- dnl static builds to link successfully. -- dnl -- dnl This does mean that all executables we link will be linked directly -- dnl to these frameworks - even when building shared libraries - but that -- dnl shouldn't cause any problems. -- -- LIBS="$LIBS -framework CoreFoundation" -- AC_DEFINE([SVN_HAVE_MACOS_PLIST], [1], -- [Is Mac OS property list API available?]) -- AC_MSG_RESULT([yes]) -- ],[ - AC_MSG_RESULT([no]) -- ]) - ]) - - dnl SVN_LIB_MACOS_KEYCHAIN diff --git a/meta/recipes-devtools/subversion/subversion-1.8.13/libtool2.patch b/meta/recipes-devtools/subversion/subversion-1.8.13/libtool2.patch deleted file mode 100644 index 5cd572bfc8..0000000000 --- a/meta/recipes-devtools/subversion/subversion-1.8.13/libtool2.patch +++ /dev/null @@ -1,15 +0,0 @@ -Upstream-Status: Inappropriate [embedded specific] - ---- a/configure.ac 2011-10-20 21:56:02.230663987 +0200 -+++ b/configure.ac 2011-08-17 15:01:30.000000000 +0200 -@@ -227,8 +227,8 @@ - LIBTOOL="$sh_libtool" - SVN_LIBTOOL="$sh_libtool" - else -- sh_libtool="$abs_builddir/libtool" -- SVN_LIBTOOL="\$(SHELL) $sh_libtool" -+ sh_libtool="$abs_builddir/$host_alias-libtool" -+ SVN_LIBTOOL="\$(SHELL) \$(abs_builddir)/$host_alias-libtool" - fi - AC_SUBST(SVN_LIBTOOL) - diff --git a/meta/recipes-devtools/subversion/subversion-1.8.13/serf.m4-Regex-modified-to-allow-D-in-paths.patch b/meta/recipes-devtools/subversion/subversion-1.8.13/serf.m4-Regex-modified-to-allow-D-in-paths.patch deleted file mode 100644 index 140e522627..0000000000 --- a/meta/recipes-devtools/subversion/subversion-1.8.13/serf.m4-Regex-modified-to-allow-D-in-paths.patch +++ /dev/null @@ -1,32 +0,0 @@ -From f1b6e49f12a18eabe88eb732b578a16281d09499 Mon Sep 17 00:00:00 2001 -From: Jose Lamego -Date: Thu, 2 Jul 2015 11:37:43 +0000 -Subject: [PATCH] serf.m4: Regex modified to allow '-D' in paths - -Upstream-Status: Accepted - -The patch is merged by subversion upstream with replacing '[[:space:]]' with ' '. - -http://svn.apache.org/viewvc/subversion/trunk/build/ac-macros/serf.m4?r1=1594156&r2=1689824 - -Signed-off-by: Jose Lamego ---- - build/ac-macros/serf.m4 | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/build/ac-macros/serf.m4 b/build/ac-macros/serf.m4 -index ae11e75..ff8cbae 100644 ---- a/build/ac-macros/serf.m4 -+++ b/build/ac-macros/serf.m4 -@@ -143,7 +143,7 @@ AC_DEFUN(SVN_SERF_PKG_CONFIG, - if $PKG_CONFIG $serf_major --atleast-version=$serf_check_version; then - AC_MSG_RESULT([yes]) - serf_found=yes -- SVN_SERF_INCLUDES=[`$PKG_CONFIG $serf_major --cflags | $SED -e 's/-D[^ ]*//g'`] -+ SVN_SERF_INCLUDES=[`$PKG_CONFIG $serf_major --cflags | $SED -e 's/[[:space:]]-D[^ ]*//g' -e 's/^-D[^ ]*//g'`] - SVN_SERF_LIBS=`$PKG_CONFIG $serf_major --libs` - break - else --- -1.8.4.5 - diff --git a/meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3184.patch b/meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3184.patch deleted file mode 100644 index 0663bd2719..0000000000 --- a/meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3184.patch +++ /dev/null @@ -1,2094 +0,0 @@ -Fix CVE-2015-3184 - -Patch is from: -http://subversion.apache.org/security/CVE-2015-3184-advisory.txt - -Upstream-Status: Backport - -Signed-off-by: Wenzong Fan - -Index: Makefile.in -=================================================================== ---- a/Makefile.in (revision 1691883) -+++ b/Makefile.in (working copy) -@@ -357,6 +357,7 @@ TEST_SHLIB_VAR_SWIG_RB=\ - fi; - - APXS = @APXS@ -+HTTPD_VERSION = @HTTPD_VERSION@ - - PYTHON = @PYTHON@ - PERL = @PERL@ -@@ -509,6 +510,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $(TEST_DEPS - if test "$(HTTP_LIBRARY)" != ""; then \ - flags="--http-library $(HTTP_LIBRARY) $$flags"; \ - fi; \ -+ if test "$(HTTPD_VERSION)" != ""; then \ -+ flags="--httpd-version $(HTTPD_VERSION) $$flags"; \ -+ fi; \ - if test "$(SERVER_MINOR_VERSION)" != ""; then \ - flags="--server-minor-version $(SERVER_MINOR_VERSION) $$flags"; \ - fi; \ -Index: build/ac-macros/apache.m4 -=================================================================== ---- a/build/ac-macros/apache.m4 (revision 1691883) -+++ b/build/ac-macros/apache.m4 (working copy) -@@ -160,6 +160,20 @@ if test -n "$APXS" && test "$APXS" != "no"; then - BUILD_APACHE_RULE=apache-mod - INSTALL_APACHE_RULE=install-mods-shared - INSTALL_APACHE_MODS=true -+ HTTPD="`$APXS -q sbindir`/`$APXS -q PROGNAME`" -+ if ! test -e $HTTPD ; then -+ HTTPD="`$APXS -q bindir`/`$APXS -q PROGNAME`" -+ fi -+ HTTPD_VERSION=["`$HTTPD -v | $SED -e 's@^.*/\([0-9.]*\)\(.*$\)@\1@ ; 1q'`"] -+ AC_ARG_ENABLE(broken-httpd-auth, -+ AS_HELP_STRING([--enable-broken-httpd-auth], -+ [Allow building against httpd 2.4 with broken auth]), -+ [broken_httpd_auth=$enableval],[broken_httpd_auth=no]) -+ if test "$enable_broken_httpd_auth" = "yes"; then -+ AC_MSG_NOTICE([Building with broken httpd auth]) -+ AC_DEFINE(SVN_ALLOW_BROKEN_HTTPD_AUTH, 1, -+ [Defined to allow building against httpd 2.4 with broken auth]) -+ fi - - case $host in - *-*-cygwin*) -@@ -178,6 +192,7 @@ AC_SUBST(APACHE_LDFLAGS) - AC_SUBST(APACHE_INCLUDES) - AC_SUBST(APACHE_LIBEXECDIR) - AC_SUBST(INSTALL_APACHE_MODS) -+AC_SUBST(HTTPD_VERSION) - - # there aren't any flags that interest us ... - #if test -n "$APXS" && test "$APXS" != "no"; then -Index: build/run_tests.py -=================================================================== ---- a/build/run_tests.py (revision 1691883) -+++ b/build/run_tests.py (working copy) -@@ -29,6 +29,7 @@ - [--fs-type=] [--fsfs-packing] [--fsfs-sharding=] - [--list] [--milestone-filter=] [--mode-filter=] - [--server-minor-version=] [--http-proxy=:] -+ [--httpd-version=] - [--config-file=] [--ssl-cert=] - - -@@ -125,7 +126,7 @@ class TestHarness: - fsfs_sharding=None, fsfs_packing=None, - list_tests=None, svn_bin=None, mode_filter=None, - milestone_filter=None, set_log_level=None, ssl_cert=None, -- http_proxy=None): -+ http_proxy=None, httpd_version=None): - '''Construct a TestHarness instance. - - ABS_SRCDIR and ABS_BUILDDIR are the source and build directories. -@@ -178,6 +179,7 @@ class TestHarness: - self.log = None - self.ssl_cert = ssl_cert - self.http_proxy = http_proxy -+ self.httpd_version = httpd_version - if not sys.stdout.isatty() or sys.platform == 'win32': - TextColors.disable() - -@@ -481,6 +483,8 @@ class TestHarness: - svntest.main.options.ssl_cert = self.ssl_cert - if self.http_proxy is not None: - svntest.main.options.http_proxy = self.http_proxy -+ if self.httpd_version is not None: -+ svntest.main.options.httpd_version = self.httpd_version - - svntest.main.options.srcdir = self.srcdir - -@@ -645,7 +649,7 @@ def main(): - 'enable-sasl', 'parallel', 'config-file=', - 'log-to-stdout', 'list', 'milestone-filter=', - 'mode-filter=', 'set-log-level=', 'ssl-cert=', -- 'http-proxy=']) -+ 'http-proxy=', 'httpd-version=']) - except getopt.GetoptError: - args = [] - -@@ -656,9 +660,9 @@ def main(): - base_url, fs_type, verbose, cleanup, enable_sasl, http_library, \ - server_minor_version, fsfs_sharding, fsfs_packing, parallel, \ - config_file, log_to_stdout, list_tests, mode_filter, milestone_filter, \ -- set_log_level, ssl_cert, http_proxy = \ -+ set_log_level, ssl_cert, http_proxy, httpd_version = \ - None, None, None, None, None, None, None, None, None, None, None, \ -- None, None, None, None, None, None, None -+ None, None, None, None, None, None, None, None - for opt, val in opts: - if opt in ['-u', '--url']: - base_url = val -@@ -696,6 +700,8 @@ def main(): - ssl_cert = val - elif opt in ['--http-proxy']: - http_proxy = val -+ elif opt in ['--httpd-version']: -+ httpd_version = val - else: - raise getopt.GetoptError - -@@ -712,7 +718,7 @@ def main(): - fsfs_sharding, fsfs_packing, list_tests, - mode_filter=mode_filter, milestone_filter=milestone_filter, - set_log_level=set_log_level, ssl_cert=ssl_cert, -- http_proxy=http_proxy) -+ http_proxy=http_proxy, httpd_version=httpd_version) - - failed = th.run(args[2:]) - if failed: -Index: subversion/mod_authz_svn/mod_authz_svn.c -=================================================================== ---- a/subversion/mod_authz_svn/mod_authz_svn.c (revision 1691883) -+++ b/subversion/mod_authz_svn/mod_authz_svn.c (working copy) -@@ -48,6 +48,23 @@ - #include "svn_dirent_uri.h" - #include "private/svn_fspath.h" - -+/* The apache headers define these and they conflict with our definitions. */ -+#ifdef PACKAGE_BUGREPORT -+#undef PACKAGE_BUGREPORT -+#endif -+#ifdef PACKAGE_NAME -+#undef PACKAGE_NAME -+#endif -+#ifdef PACKAGE_STRING -+#undef PACKAGE_STRING -+#endif -+#ifdef PACKAGE_TARNAME -+#undef PACKAGE_TARNAME -+#endif -+#ifdef PACKAGE_VERSION -+#undef PACKAGE_VERSION -+#endif -+#include "svn_private_config.h" - - #ifdef APLOG_USE_MODULE - APLOG_USE_MODULE(authz_svn); -@@ -67,6 +84,30 @@ typedef struct authz_svn_config_rec { - const char *force_username_case; - } authz_svn_config_rec; - -+#if AP_MODULE_MAGIC_AT_LEAST(20060110,0) /* version where -+ ap_some_auth_required breaks */ -+# if AP_MODULE_MAGIC_AT_LEAST(20120211,47) /* first version with -+ force_authn hook and -+ ap_some_authn_required() which -+ allows us to work without -+ ap_some_auth_required() */ -+# define USE_FORCE_AUTHN 1 -+# define IN_SOME_AUTHN_NOTE "authz_svn-in-some-authn" -+# define FORCE_AUTHN_NOTE "authz_svn-force-authn" -+# else -+ /* ap_some_auth_required() is busted and no viable alternative exists */ -+# ifndef SVN_ALLOW_BROKEN_HTTPD_AUTH -+# error This version of httpd has a security hole with mod_authz_svn -+# else -+ /* user wants to build anyway */ -+# define USE_FORCE_AUTHN 0 -+# endif -+# endif -+#else -+ /* old enough that ap_some_auth_required() still works */ -+# define USE_FORCE_AUTHN 0 -+#endif -+ - /* - * Configuration - */ -@@ -819,9 +860,51 @@ access_checker(request_rec *r) - &authz_svn_module); - const char *repos_path = NULL; - const char *dest_repos_path = NULL; -- int status; -+ int status, authn_required; - -+#if USE_FORCE_AUTHN -+ /* Use the force_authn() hook available in 2.4.x to work securely -+ * given that ap_some_auth_required() is no longer functional for our -+ * purposes in 2.4.x. -+ */ -+ int authn_configured; -+ - /* We are not configured to run */ -+ if (!conf->anonymous || apr_table_get(r->notes, IN_SOME_AUTHN_NOTE) -+ || (! (conf->access_file || conf->repo_relative_access_file))) -+ return DECLINED; -+ -+ /* Authentication is configured */ -+ authn_configured = ap_auth_type(r) != NULL; -+ if (authn_configured) -+ { -+ /* If the user is trying to authenticate, let him. It doesn't -+ * make much sense to grant anonymous access but deny authenticated -+ * users access, even though you can do that with '$anon' in the -+ * access file. -+ */ -+ if (apr_table_get(r->headers_in, -+ (PROXYREQ_PROXY == r->proxyreq) -+ ? "Proxy-Authorization" : "Authorization")) -+ { -+ /* Set the note to force authn regardless of what access_checker_ex -+ hook requires */ -+ apr_table_setn(r->notes, FORCE_AUTHN_NOTE, (const char*)1); -+ -+ /* provide the proper return so the access_checker hook doesn't -+ * prevent the code from continuing on to the other auth hooks */ -+ if (ap_satisfies(r) != SATISFY_ANY) -+ return OK; -+ else -+ return HTTP_FORBIDDEN; -+ } -+ } -+ -+#else -+ /* Support for older versions of httpd that have a working -+ * ap_some_auth_required() */ -+ -+ /* We are not configured to run */ - if (!conf->anonymous - || (! (conf->access_file || conf->repo_relative_access_file))) - return DECLINED; -@@ -834,9 +917,10 @@ access_checker(request_rec *r) - if (ap_satisfies(r) != SATISFY_ANY) - return DECLINED; - -- /* If the user is trying to authenticate, let him. If anonymous -- * access is allowed, so is authenticated access, by definition -- * of the meaning of '*' in the access file. -+ /* If the user is trying to authenticate, let him. It doesn't -+ * make much sense to grant anonymous access but deny authenticated -+ * users access, even though you can do that with '$anon' in the -+ * access file. - */ - if (apr_table_get(r->headers_in, - (PROXYREQ_PROXY == r->proxyreq) -@@ -848,6 +932,7 @@ access_checker(request_rec *r) - return HTTP_FORBIDDEN; - } - } -+#endif - - /* If anon access is allowed, return OK */ - status = req_check_access(r, conf, &repos_path, &dest_repos_path); -@@ -856,7 +941,26 @@ access_checker(request_rec *r) - if (!conf->authoritative) - return DECLINED; - -+#if USE_FORCE_AUTHN -+ if (authn_configured) { -+ /* We have to check to see if authn is required because if so we must -+ * return UNAUTHORIZED (401) rather than FORBIDDEN (403) since returning -+ * the 403 leaks information about what paths may exist to -+ * unauthenticated users. We must set a note here in order -+ * to use ap_some_authn_rquired() without triggering an infinite -+ * loop since the call will trigger this function to be called again. */ -+ apr_table_setn(r->notes, IN_SOME_AUTHN_NOTE, (const char*)1); -+ authn_required = ap_some_authn_required(r); -+ apr_table_unset(r->notes, IN_SOME_AUTHN_NOTE); -+ if (authn_required) -+ { -+ ap_note_auth_failure(r); -+ return HTTP_UNAUTHORIZED; -+ } -+ } -+#else - if (!ap_some_auth_required(r)) -+#endif - log_access_verdict(APLOG_MARK, r, 0, repos_path, dest_repos_path); - - return HTTP_FORBIDDEN; -@@ -937,6 +1041,17 @@ auth_checker(request_rec *r) - return OK; - } - -+#if USE_FORCE_AUTHN -+static int -+force_authn(request_rec *r) -+{ -+ if (apr_table_get(r->notes, FORCE_AUTHN_NOTE)) -+ return OK; -+ -+ return DECLINED; -+} -+#endif -+ - /* - * Module flesh - */ -@@ -953,6 +1068,9 @@ register_hooks(apr_pool_t *p) - * give SSLOptions +FakeBasicAuth a chance to work. */ - ap_hook_check_user_id(check_user_id, mod_ssl, NULL, APR_HOOK_FIRST); - ap_hook_auth_checker(auth_checker, NULL, NULL, APR_HOOK_FIRST); -+#if USE_FORCE_AUTHN -+ ap_hook_force_authn(force_authn, NULL, NULL, APR_HOOK_FIRST); -+#endif - ap_register_provider(p, - AUTHZ_SVN__SUBREQ_BYPASS_PROV_GRP, - AUTHZ_SVN__SUBREQ_BYPASS_PROV_NAME, -Index: subversion/tests/cmdline/README -=================================================================== ---- a/subversion/tests/cmdline/README (revision 1691883) -+++ b/subversion/tests/cmdline/README (working copy) -@@ -83,6 +83,133 @@ paths adjusted appropriately: - Require valid-user - - -+ -+ 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. -+ -+ Require all granted -+ -+ -+ Allow from all -+ -+ -+ -+ 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 -+ -+ -+ 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 -+ -+ -+ 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 -+ -+ -+ 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 -+ -+ -+ 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 -+ -+ -+ 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 -+ -+ -+ 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 -+ -+ -+ -+ 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 -+ -+ Require valid-user -+ Require expr req('ALLOW') == '1' -+ -+ -+ -+ 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 -+ -+ Require valid-user -+ Require expr req('ALLOW') == '1' -+ -+ -+ -+ -+ - RedirectMatch permanent ^/svn-test-work/repositories/REDIRECT-PERM-(.*)$ /svn-test-work/repositories/$1 - RedirectMatch ^/svn-test-work/repositories/REDIRECT-TEMP-(.*)$ /svn-test-work/repositories/$1 - -@@ -101,8 +228,17 @@ just drop the following 2-line snippet into the - ---------------------------- - jrandom:xCGl35kV9oWCY - jconstant:xCGl35kV9oWCY -+JRANDOM:xCGl35kV9oWCY -+JCONSTANT:xCGl35kV9oWCY - ---------------------------- - -+and these lines into the -+/usr/local/apache/conf/groups file: -+---------------------------- -+random: jrandom -+constant: jconstant -+---------------------------- -+ - Now, (re)start Apache and run the tests over mod_dav_svn. - - You can run a test script over DAV: -@@ -138,6 +274,8 @@ Note [1]: It would be quite too much to expect tho - ---------------------------- - jrandom:$apr1$3p1.....$FQW6RceW5QhJ2blWDQgKn0 - jconstant:$apr1$jp1.....$Usrqji1c9H6AbOxOGAzzb0 -+ JRANDOM:$apr1$3p1.....$FQW6RceW5QhJ2blWDQgKn0 -+ JCONSTANT:$apr1$jp1.....$Usrqji1c9H6AbOxOGAzzb0 - ---------------------------- - - -Index: subversion/tests/cmdline/davautocheck.sh -=================================================================== ---- a/subversion/tests/cmdline/davautocheck.sh (revision 1691883) -+++ b/subversion/tests/cmdline/davautocheck.sh (working copy) -@@ -289,8 +289,6 @@ LOAD_MOD_AUTHN_CORE="$(get_loadmodule_config mod_a - || fail "Authn_Core module not found." - LOAD_MOD_AUTHZ_CORE="$(get_loadmodule_config mod_authz_core)" \ - || fail "Authz_Core module not found." --LOAD_MOD_AUTHZ_HOST="$(get_loadmodule_config mod_authz_host)" \ -- || fail "Authz_Host module not found." - LOAD_MOD_UNIXD=$(get_loadmodule_config mod_unixd) \ - || fail "UnixD module not found" - } -@@ -298,6 +296,10 @@ LOAD_MOD_AUTHN_FILE="$(get_loadmodule_config mod_a - || fail "Authn_File module not found." - LOAD_MOD_AUTHZ_USER="$(get_loadmodule_config mod_authz_user)" \ - || fail "Authz_User module not found." -+LOAD_MOD_AUTHZ_GROUPFILE="$(get_loadmodule_config mod_authz_groupfile)" \ -+ || fail "Authz_GroupFile module not found." -+LOAD_MOD_AUTHZ_HOST="$(get_loadmodule_config mod_authz_host)" \ -+ || fail "Authz_Host module not found." - } - if [ ${APACHE_MPM:+set} ]; then - LOAD_MOD_MPM=$(get_loadmodule_config mod_mpm_$APACHE_MPM) \ -@@ -328,6 +330,7 @@ HTTPD_ERROR_LOG="$HTTPD_ROOT/error_log" - HTTPD_MIME_TYPES="$HTTPD_ROOT/mime.types" - BASE_URL="http://localhost:$HTTPD_PORT" - HTTPD_USERS="$HTTPD_ROOT/users" -+HTTPD_GROUPS="$HTTPD_ROOT/groups" - - mkdir "$HTTPD_ROOT" \ - || fail "couldn't create temporary directory '$HTTPD_ROOT'" -@@ -388,6 +391,14 @@ fi - say "Adding users for lock authentication" - $HTPASSWD -bc $HTTPD_USERS jrandom rayjandom - $HTPASSWD -b $HTTPD_USERS jconstant rayjandom -+$HTPASSWD -b $HTTPD_USERS JRANDOM rayjandom -+$HTPASSWD -b $HTTPD_USERS JCONSTANT rayjandom -+ -+say "Adding groups for mod_authz_svn tests" -+cat > "$HTTPD_GROUPS" <<__EOF__ -+random: jrandom -+constant: jconstant -+__EOF__ - - touch $HTTPD_MIME_TYPES - -@@ -405,7 +416,9 @@ $LOAD_MOD_AUTHN_CORE - $LOAD_MOD_AUTHN_FILE - $LOAD_MOD_AUTHZ_CORE - $LOAD_MOD_AUTHZ_USER -+$LOAD_MOD_AUTHZ_GROUPFILE - $LOAD_MOD_AUTHZ_HOST -+$LOAD_MOD_ACCESS_COMPAT - LoadModule authz_svn_module "$MOD_AUTHZ_SVN" - - __EOF__ -@@ -497,6 +510,161 @@ CustomLog "$HTTPD_ROOT/ops" "%t %u %{SVN - SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} - ${SVN_PATH_AUTHZ_LINE} - -+ -+ DAV svn -+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" -+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" -+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} -+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} -+ SVNListParentPath On -+ # This may seem unnecessary but granting access to everyone here is necessary -+ # to exercise a bug with httpd 2.3.x+. The "Require all granted" syntax is -+ # new to 2.3.x+ which we can detect with the mod_authz_core.c module -+ # signature. Use the "Allow from all" syntax with older versions for symmetry. -+ -+ Require all granted -+ -+ -+ Allow from all -+ -+ ${SVN_PATH_AUTHZ_LINE} -+ -+ -+ DAV svn -+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" -+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" -+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} -+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} -+ SVNListParentPath On -+ AuthType Basic -+ AuthName "Subversion Repository" -+ AuthUserFile $HTTPD_USERS -+ Require valid-user -+ Satisfy Any -+ ${SVN_PATH_AUTHZ_LINE} -+ -+ -+ DAV svn -+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" -+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" -+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} -+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} -+ SVNListParentPath On -+ AuthType Basic -+ AuthName "Subversion Repository" -+ AuthUserFile $HTTPD_USERS -+ Require valid-user -+ AuthzSVNNoAuthWhenAnonymousAllowed On -+ SVNPathAuthz On -+ -+ -+ DAV svn -+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" -+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" -+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} -+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} -+ SVNListParentPath On -+ AuthType Basic -+ AuthName "Subversion Repository" -+ AuthUserFile $HTTPD_USERS -+ Require valid-user -+ ${SVN_PATH_AUTHZ_LINE} -+ -+ -+ DAV svn -+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" -+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" -+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} -+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} -+ SVNListParentPath On -+ AuthType Basic -+ AuthName "Subversion Repository" -+ AuthUserFile $HTTPD_USERS -+ Require valid-user -+ AuthzSVNAnonymous Off -+ SVNPathAuthz On -+ -+ -+ DAV svn -+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" -+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" -+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} -+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} -+ SVNListParentPath On -+ AuthType Basic -+ AuthName "Subversion Repository" -+ AuthUserFile $HTTPD_USERS -+ Require valid-user -+ AuthzForceUsernameCase Lower -+ ${SVN_PATH_AUTHZ_LINE} -+ -+ -+ DAV svn -+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" -+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" -+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} -+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} -+ SVNListParentPath On -+ AuthType Basic -+ AuthName "Subversion Repository" -+ AuthUserFile $HTTPD_USERS -+ Require valid-user -+ AuthzForceUsernameCase Lower -+ ${SVN_PATH_AUTHZ_LINE} -+ -+ -+ DAV svn -+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" -+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" -+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} -+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} -+ SVNListParentPath On -+ AuthType Basic -+ AuthName "Subversion Repository" -+ AuthUserFile $HTTPD_USERS -+ AuthGroupFile $HTTPD_GROUPS -+ Require group random -+ AuthzSVNAuthoritative Off -+ SVNPathAuthz On -+ -+ -+ -+ DAV svn -+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" -+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" -+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} -+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} -+ SVNListParentPath On -+ AuthType Basic -+ AuthName "Subversion Repository" -+ AuthUserFile $HTTPD_USERS -+ AuthzSendForbiddenOnFailure On -+ Satisfy All -+ -+ Require valid-user -+ Require expr req('ALLOW') == '1' -+ -+ ${SVN_PATH_AUTHZ_LINE} -+ -+ -+ DAV svn -+ SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" -+ AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" -+ SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} -+ SVNCacheRevProps ${CACHE_REVPROPS_SETTING} -+ SVNListParentPath On -+ AuthType Basic -+ AuthName "Subversion Repository" -+ AuthUserFile $HTTPD_USERS -+ AuthzSendForbiddenOnFailure On -+ Satisfy All -+ -+ Require valid-user -+ Require expr req('ALLOW') == '1' -+ -+ ${SVN_PATH_AUTHZ_LINE} -+ -+ - RedirectMatch permanent ^/svn-test-work/repositories/REDIRECT-PERM-(.*)\$ /svn-test-work/repositories/\$1 - RedirectMatch ^/svn-test-work/repositories/REDIRECT-TEMP-(.*)\$ /svn-test-work/repositories/\$1 - __EOF__ -Index: subversion/tests/cmdline/mod_authz_svn_tests.py -=================================================================== ---- a/subversion/tests/cmdline/mod_authz_svn_tests.py (nonexistent) -+++ b/subversion/tests/cmdline/mod_authz_svn_tests.py (working copy) -@@ -0,0 +1,1073 @@ -+#!/usr/bin/env python -+# -+# mod_authz_svn_tests.py: testing mod_authz_svn -+# -+# Subversion is a tool for revision control. -+# See http://subversion.apache.org for more information. -+# -+# ==================================================================== -+# Licensed to the Apache Software Foundation (ASF) under one -+# or more contributor license agreements. See the NOTICE file -+# distributed with this work for additional information -+# regarding copyright ownership. The ASF licenses this file -+# to you under the Apache License, Version 2.0 (the -+# "License"); you may not use this file except in compliance -+# with the License. You may obtain a copy of the License at -+# -+# http://www.apache.org/licenses/LICENSE-2.0 -+# -+# Unless required by applicable law or agreed to in writing, -+# software distributed under the License is distributed on an -+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -+# KIND, either express or implied. See the License for the -+# specific language governing permissions and limitations -+# under the License. -+###################################################################### -+ -+# General modules -+import os, re, logging -+ -+logger = logging.getLogger() -+ -+# Our testing module -+import svntest -+ -+# (abbreviation) -+Skip = svntest.testcase.Skip_deco -+SkipUnless = svntest.testcase.SkipUnless_deco -+XFail = svntest.testcase.XFail_deco -+Issues = svntest.testcase.Issues_deco -+Issue = svntest.testcase.Issue_deco -+Wimp = svntest.testcase.Wimp_deco -+ -+ls_of_D_no_H = '''repos - Revision 1: /A/D -+ -+

repos - Revision 1: /A/D

-+ -+''' -+ -+ls_of_D_H = '''repos - Revision 1: /A/D -+ -+

repos - Revision 1: /A/D

-+ -+''' -+ -+ls_of_H = '''repos - Revision 1: /A/D/H -+ -+

repos - Revision 1: /A/D/H

-+ -+''' -+ -+user1 = svntest.main.wc_author -+user1_upper = user1.upper() -+user1_pass = svntest.main.wc_passwd -+user1_badpass = 'XXX' -+assert user1_pass != user1_badpass, "Passwords can't match" -+user2 = svntest.main.wc_author2 -+user2_upper = user2.upper() -+user2_pass = svntest.main.wc_passwd -+user2_badpass = 'XXX' -+assert user2_pass != user2_badpass, "Passwords can't match" -+ -+def write_authz_file(sbox): -+ svntest.main.write_authz_file(sbox, { -+ '/': '$anonymous = r\n' + -+ 'jrandom = rw\n' + -+ 'jconstant = rw', -+ '/A/D/H': '$anonymous =\n' + -+ '$authenticated =\n' + -+ 'jrandom = rw' -+ }) -+ -+def write_authz_file_groups(sbox): -+ authz_name = sbox.authz_name() -+ svntest.main.write_authz_file(sbox,{ -+ '/': '* =', -+ }) -+ -+def verify_get(test_area_url, path, user, pw, -+ expected_status, expected_body, headers): -+ import httplib -+ from urlparse import urlparse -+ import base64 -+ -+ req_url = test_area_url + path -+ -+ loc = urlparse(req_url) -+ -+ if loc.scheme == 'http': -+ h = httplib.HTTPConnection(loc.hostname, loc.port) -+ else: -+ h = httplib.HTTPSConnection(loc.hostname, loc.port) -+ -+ if headers is None: -+ headers = {} -+ -+ if user and pw: -+ auth_info = user + ':' + pw -+ headers['Authorization'] = 'Basic ' + base64.b64encode(auth_info) -+ else: -+ auth_info = "anonymous" -+ -+ h.request('GET', req_url, None, headers) -+ -+ r = h.getresponse() -+ -+ actual_status = r.status -+ if expected_status and expected_status != actual_status: -+ -+ logger.warn("Expected status '" + str(expected_status) + -+ "' but got '" + str(actual_status) + -+ "' on url '" + req_url + "' (" + -+ auth_info + ").") -+ raise svntest.Failure -+ -+ if expected_body: -+ actual_body = r.read() -+ if expected_body != actual_body: -+ logger.warn("Expected body:") -+ logger.warn(expected_body) -+ logger.warn("But got:") -+ logger.warn(actual_body) -+ logger.warn("on url '" + req_url + "' (" + auth_info + ").") -+ raise svntest.Failure -+ -+def verify_gets(test_area_url, tests): -+ for test in tests: -+ verify_get(test_area_url, test['path'], test.get('user'), test.get('pw'), -+ test['status'], test.get('body'), test.get('headers')) -+ -+ -+###################################################################### -+# Tests -+# -+# Each test must return on success or raise on failure. -+ -+ -+#---------------------------------------------------------------------- -+ -+ -+@SkipUnless(svntest.main.is_ra_type_dav) -+def anon(sbox): -+ "test anonymous access" -+ sbox.build(read_only = True, create_wc = False) -+ -+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', -+ '/authz-test-work/anon') -+ -+ write_authz_file(sbox) -+ -+ anon_tests = ( -+ { 'path': '', 'status': 301 }, -+ { 'path': '/', 'status': 200 }, -+ { 'path': '/repos', 'status': 301 }, -+ { 'path': '/repos/', 'status': 200 }, -+ { 'path': '/repos/A', 'status': 301 }, -+ { 'path': '/repos/A/', 'status': 200 }, -+ { 'path': '/repos/A/D', 'status': 301 }, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H }, -+ { 'path': '/repos/A/D/gamma', 'status': 200 }, -+ { 'path': '/repos/A/D/H', 'status': 403 }, -+ { 'path': '/repos/A/D/H/', 'status': 403 }, -+ { 'path': '/repos/A/D/H/chi', 'status': 403 }, -+ # auth isn't configured so nothing should change when passing -+ # authn details -+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '', 'status': 301, 'user': user2, 'pw': user1_pass}, -+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user1_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user1_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user1_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user1_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user1_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ 'user': user2, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ ) -+ -+ verify_gets(test_area_url, anon_tests) -+ -+ -+@SkipUnless(svntest.main.is_ra_type_dav) -+def mixed(sbox): -+ "test mixed anonymous and authenticated access" -+ sbox.build(read_only = True, create_wc = False) -+ -+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', -+ '/authz-test-work/mixed') -+ -+ write_authz_file(sbox) -+ -+ mixed_tests = ( -+ { 'path': '', 'status': 301, }, -+ { 'path': '/', 'status': 200, }, -+ { 'path': '/repos', 'status': 301, }, -+ { 'path': '/repos/', 'status': 200, }, -+ { 'path': '/repos/A', 'status': 301, }, -+ { 'path': '/repos/A/', 'status': 200, }, -+ { 'path': '/repos/A/D', 'status': 301, }, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ }, -+ { 'path': '/repos/A/D/gamma', 'status': 200, }, -+ { 'path': '/repos/A/D/H', 'status': 401, }, -+ { 'path': '/repos/A/D/H/', 'status': 401, }, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, }, -+ # auth is configured and user1 is allowed access to H -+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, -+ 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ # try with the wrong password for user1 -+ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ # auth is configured and user2 is not allowed access to H -+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ # try with the wrong password for user2 -+ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ ) -+ -+ verify_gets(test_area_url, mixed_tests) -+ -+@SkipUnless(svntest.main.is_ra_type_dav) -+@XFail(svntest.main.is_httpd_authz_provider_enabled) -+# uses the AuthzSVNNoAuthWhenAnonymousAllowed On directive -+# this is broken with httpd 2.3.x+ since it requires the auth system to accept -+# r->user == NULL and there is a test for this in server/request.c now. It -+# was intended as a workaround for the lack of Satisfy Any in 2.3.x+ which -+# was resolved by httpd with mod_access_compat in 2.3.x+. -+def mixed_noauthwhenanon(sbox): -+ "test mixed with noauthwhenanon directive" -+ sbox.build(read_only = True, create_wc = False) -+ -+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', -+ '/authz-test-work/mixed-noauthwhenanon') -+ -+ write_authz_file(sbox) -+ -+ noauthwhenanon_tests = ( -+ { 'path': '', 'status': 301, }, -+ { 'path': '/', 'status': 200, }, -+ { 'path': '/repos', 'status': 301, }, -+ { 'path': '/repos/', 'status': 200, }, -+ { 'path': '/repos/A', 'status': 301, }, -+ { 'path': '/repos/A/', 'status': 200, }, -+ { 'path': '/repos/A/D', 'status': 301, }, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ }, -+ { 'path': '/repos/A/D/gamma', 'status': 200, }, -+ { 'path': '/repos/A/D/H', 'status': 401, }, -+ { 'path': '/repos/A/D/H/', 'status': 401, }, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, }, -+ # auth is configured and user1 is allowed access to H -+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, -+ 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ # try with the wrong password for user1 -+ # note that unlike doing this with Satisfy Any this case -+ # actually provides anon access when provided with an invalid -+ # password -+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ # auth is configured and user2 is not allowed access to H -+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ # try with the wrong password for user2 -+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ ) -+ -+ verify_gets(test_area_url, noauthwhenanon_tests) -+ -+ -+@SkipUnless(svntest.main.is_ra_type_dav) -+def authn(sbox): -+ "test authenticated only access" -+ sbox.build(read_only = True, create_wc = False) -+ -+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', -+ '/authz-test-work/authn') -+ -+ write_authz_file(sbox) -+ -+ authn_tests = ( -+ { 'path': '', 'status': 401, }, -+ { 'path': '/', 'status': 401, }, -+ { 'path': '/repos', 'status': 401, }, -+ { 'path': '/repos/', 'status': 401, }, -+ { 'path': '/repos/A', 'status': 401, }, -+ { 'path': '/repos/A/', 'status': 401, }, -+ { 'path': '/repos/A/D', 'status': 401, }, -+ { 'path': '/repos/A/D/', 'status': 401, }, -+ { 'path': '/repos/A/D/gamma', 'status': 401, }, -+ { 'path': '/repos/A/D/H', 'status': 401, }, -+ { 'path': '/repos/A/D/H/', 'status': 401, }, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, }, -+ # auth is configured and user1 is allowed access to H -+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, -+ 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ # try with upper case username for user1 -+ { 'path': '', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ # try with the wrong password for user1 -+ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ # auth is configured and user2 is not allowed access to H -+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ # try with upper case username for user2 -+ { 'path': '', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ # try with the wrong password for user2 -+ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ ) -+ -+ verify_gets(test_area_url, authn_tests) -+ -+@SkipUnless(svntest.main.is_ra_type_dav) -+def authn_anonoff(sbox): -+ "test authenticated only access with anonoff" -+ sbox.build(read_only = True, create_wc = False) -+ -+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', -+ '/authz-test-work/authn-anonoff') -+ -+ write_authz_file(sbox) -+ -+ anonoff_tests = ( -+ { 'path': '', 'status': 401, }, -+ { 'path': '/', 'status': 401, }, -+ { 'path': '/repos', 'status': 401, }, -+ { 'path': '/repos/', 'status': 401, }, -+ { 'path': '/repos/A', 'status': 401, }, -+ { 'path': '/repos/A/', 'status': 401, }, -+ { 'path': '/repos/A/D', 'status': 401, }, -+ { 'path': '/repos/A/D/', 'status': 401, }, -+ { 'path': '/repos/A/D/gamma', 'status': 401, }, -+ { 'path': '/repos/A/D/H', 'status': 401, }, -+ { 'path': '/repos/A/D/H/', 'status': 401, }, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, }, -+ # auth is configured and user1 is allowed access to H -+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, -+ 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ # try with upper case username for user1 -+ { 'path': '', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, -+ # try with the wrong password for user1 -+ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ # auth is configured and user2 is not allowed access to H -+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ # try with upper case username for user2 -+ { 'path': '', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ # try with the wrong password for user2 -+ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ ) -+ -+ verify_gets(test_area_url, anonoff_tests) -+ -+@SkipUnless(svntest.main.is_ra_type_dav) -+def authn_lcuser(sbox): -+ "test authenticated only access with lcuser" -+ sbox.build(read_only = True, create_wc = False) -+ -+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', -+ '/authz-test-work/authn-lcuser') -+ -+ write_authz_file(sbox) -+ -+ lcuser_tests = ( -+ # try with upper case username for user1 (works due to lcuser option) -+ { 'path': '', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, -+ 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1_upper, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, -+ # try with upper case username for user2 (works due to lcuser option) -+ { 'path': '', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, -+ ) -+ -+ verify_gets(test_area_url, lcuser_tests) -+ -+# authenticated access only by group - a excuse to use AuthzSVNAuthoritative Off -+# this is terribly messed up, Require group runs after mod_authz_svn. -+# so if mod_authz_svn grants the access then it doesn't matter what the group -+# requirement says. If we reject the access then you can use the AuthzSVNAuthoritative Off -+# directive to fall through to the group check. Overall the behavior of setups like this -+# is almost guaranteed to not be what users expect. -+@SkipUnless(svntest.main.is_ra_type_dav) -+def authn_group(sbox): -+ "test authenticated only access via groups" -+ sbox.build(read_only = True, create_wc = False) -+ -+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', -+ '/authz-test-work/authn-group') -+ -+ # Can't use write_authz_file() as most tests because we want to deny all -+ # access with mod_authz_svn so the tests fall through to the group handling -+ authz_name = sbox.authz_name() -+ svntest.main.write_authz_file(sbox, { -+ '/': '* =', -+ }) -+ -+ group_tests = ( -+ { 'path': '', 'status': 401, }, -+ { 'path': '/', 'status': 401, }, -+ { 'path': '/repos', 'status': 401, }, -+ { 'path': '/repos/', 'status': 401, }, -+ { 'path': '/repos/A', 'status': 401, }, -+ { 'path': '/repos/A/', 'status': 401, }, -+ { 'path': '/repos/A/D', 'status': 401, }, -+ { 'path': '/repos/A/D/', 'status': 401, }, -+ { 'path': '/repos/A/D/gamma', 'status': 401, }, -+ { 'path': '/repos/A/D/H', 'status': 401, }, -+ { 'path': '/repos/A/D/H/', 'status': 401, }, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, }, -+ # auth is configured and user1 is allowed access repo including H -+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, -+ 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ ) -+ -+ verify_gets(test_area_url, group_tests) -+ -+# This test exists to validate our behavior when used with the new authz -+# provider system introduced in httpd 2.3.x. The Satisfy directive -+# determines how older authz hooks are combined and the RequireA(ll|ny) -+# blocks handles how new authz providers are combined. The overall results of -+# all the authz providers (combined per the Require* blocks) are then -+# combined with the other authz hooks via the Satisfy directive. -+# Meaning this test requires that mod_authz_svn says yes and there is -+# either a valid user or the ALLOW header is 1. The header may seem -+# like a silly test but it's easier to excercise than say a host directive -+# in a repeatable test. -+@SkipUnless(svntest.main.is_httpd_authz_provider_enabled) -+def authn_sallrany(sbox): -+ "test satisfy all require any config" -+ sbox.build(read_only = True, create_wc = False) -+ -+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', -+ '/authz-test-work/sallrany') -+ -+ write_authz_file(sbox) -+ -+ allow_header = { 'ALLOW': '1' } -+ -+ sallrany_tests = ( -+ #anon access isn't allowed without ALLOW header -+ { 'path': '', 'status': 401, }, -+ { 'path': '/', 'status': 401, }, -+ { 'path': '/repos', 'status': 401, }, -+ { 'path': '/repos/', 'status': 401, }, -+ { 'path': '/repos/A', 'status': 401, }, -+ { 'path': '/repos/A/', 'status': 401, }, -+ { 'path': '/repos/A/D', 'status': 401, }, -+ { 'path': '/repos/A/D/', 'status': 401, }, -+ { 'path': '/repos/A/D/gamma', 'status': 401, }, -+ { 'path': '/repos/A/D/H', 'status': 401, }, -+ { 'path': '/repos/A/D/H/', 'status': 401, }, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, }, -+ # auth is configured and user1 is allowed access repo including H -+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, -+ 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, -+ # try with the wrong password for user1 -+ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, -+ # auth is configured and user2 is not allowed access to H -+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ # try with the wrong password for user2 -+ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, -+ # anon is allowed with the ALLOW header -+ { 'path': '', 'status': 301, 'headers': allow_header }, -+ { 'path': '/', 'status': 200, 'headers': allow_header }, -+ { 'path': '/repos', 'status': 301, 'headers': allow_header }, -+ { 'path': '/repos/', 'status': 200, 'headers': allow_header }, -+ { 'path': '/repos/A', 'status': 301, 'headers': allow_header }, -+ { 'path': '/repos/A/', 'status': 200, 'headers': allow_header }, -+ { 'path': '/repos/A/D', 'status': 301, 'headers': allow_header }, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, 'headers': allow_header }, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'headers': allow_header }, -+ # these 3 tests return 403 instead of 401 becasue the config allows -+ # the anon user with the ALLOW header without any auth and the old hook -+ # system has no way of knowing it should return 401 since authentication is -+ # configured and can change the behavior. It could decide to return 401 just on -+ # the basis of authentication being configured but then that leaks info in other -+ # cases so it's better for this case to be "broken". -+ { 'path': '/repos/A/D/H', 'status': 403, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'headers': allow_header }, -+ # auth is configured and user1 is allowed access repo including H -+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, -+ 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ # try with the wrong password for user1 -+ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ # auth is configured and user2 is not allowed access to H -+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ # try with the wrong password for user2 -+ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ -+ ) -+ -+ verify_gets(test_area_url, sallrany_tests) -+ -+# See comments on authn_sallrany test for some background on the interaction -+# of Satisfy Any and the newer Require blocks. -+@SkipUnless(svntest.main.is_httpd_authz_provider_enabled) -+def authn_sallrall(sbox): -+ "test satisfy all require all config" -+ sbox.build(read_only = True, create_wc = False) -+ -+ test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', -+ '/authz-test-work/sallrall') -+ -+ write_authz_file(sbox) -+ -+ allow_header = { 'ALLOW': '1' } -+ -+ sallrall_tests = ( -+ #anon access isn't allowed without ALLOW header -+ { 'path': '', 'status': 403, }, -+ { 'path': '/', 'status': 403, }, -+ { 'path': '/repos', 'status': 403, }, -+ { 'path': '/repos/', 'status': 403, }, -+ { 'path': '/repos/A', 'status': 403, }, -+ { 'path': '/repos/A/', 'status': 403, }, -+ { 'path': '/repos/A/D', 'status': 403, }, -+ { 'path': '/repos/A/D/', 'status': 403, }, -+ { 'path': '/repos/A/D/gamma', 'status': 403, }, -+ { 'path': '/repos/A/D/H', 'status': 403, }, -+ { 'path': '/repos/A/D/H/', 'status': 403, }, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, }, -+ # auth is configured but no access is allowed without the ALLOW header -+ { 'path': '', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_pass}, -+ # try with the wrong password for user1 -+ { 'path': '', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_badpass}, -+ # auth is configured but no access is allowed without the ALLOW header -+ { 'path': '', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, -+ # try with the wrong password for user2 -+ { 'path': '', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_badpass}, -+ # anon is not allowed even with ALLOW header -+ { 'path': '', 'status': 401, 'headers': allow_header }, -+ { 'path': '/', 'status': 401, 'headers': allow_header }, -+ { 'path': '/repos', 'status': 401, 'headers': allow_header }, -+ { 'path': '/repos/', 'status': 401, 'headers': allow_header }, -+ { 'path': '/repos/A', 'status': 401, 'headers': allow_header }, -+ { 'path': '/repos/A/', 'status': 401, 'headers': allow_header }, -+ { 'path': '/repos/A/D', 'status': 401, 'headers': allow_header }, -+ { 'path': '/repos/A/D/', 'status': 401, 'headers': allow_header }, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H', 'status': 401, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'headers': allow_header }, -+ # auth is configured and user1 is allowed access repo including H -+ { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, -+ 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, -+ # try with the wrong password for user1 -+ { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, -+ # auth is configured and user2 is not allowed access to H -+ { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, -+ 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, -+ # try with the wrong password for user2 -+ { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, -+ -+ ) -+ -+ verify_gets(test_area_url, sallrall_tests) -+ -+ -+######################################################################## -+# Run the tests -+ -+ -+# list all tests here, starting with None: -+test_list = [ None, -+ anon, -+ mixed, -+ mixed_noauthwhenanon, -+ authn, -+ authn_anonoff, -+ authn_lcuser, -+ authn_group, -+ authn_sallrany, -+ authn_sallrall, -+ ] -+serial_only = True -+ -+if __name__ == '__main__': -+ svntest.main.run_tests(test_list) -+ # NOTREACHED -+ -+ -+### End of file. - -Property changes on: subversion/tests/cmdline/mod_authz_svn_tests.py -___________________________________________________________________ -Added: svn:eol-style -## -0,0 +1 ## -+native -\ No newline at end of property -Index: subversion/tests/cmdline/svntest/main.py -=================================================================== ---- a/subversion/tests/cmdline/svntest/main.py (revision 1691883) -+++ b/subversion/tests/cmdline/svntest/main.py (working copy) -@@ -1378,6 +1378,30 @@ def is_plaintext_password_storage_disabled(): - return False - return True - -+ -+# https://issues.apache.org/bugzilla/show_bug.cgi?id=56480 -+# https://issues.apache.org/bugzilla/show_bug.cgi?id=55397 -+__mod_dav_url_quoting_broken_versions = frozenset([ -+ '2.2.27', -+ '2.2.26', -+ '2.2.25', -+ '2.4.9', -+ '2.4.8', -+ '2.4.7', -+ '2.4.6', -+ '2.4.5', -+]) -+def is_mod_dav_url_quoting_broken(): -+ if is_ra_type_dav(): -+ return (options.httpd_version in __mod_dav_url_quoting_broken_versions) -+ return None -+ -+def is_httpd_authz_provider_enabled(): -+ if is_ra_type_dav(): -+ v = options.httpd_version.split('.') -+ return (v[0] == '2' and int(v[1]) >= 3) or int(v[0]) > 2 -+ return None -+ - ###################################################################### - - -@@ -1435,6 +1459,8 @@ class TestSpawningThread(threading.Thread): - args.append('--ssl-cert=' + options.ssl_cert) - if options.http_proxy: - args.append('--http-proxy=' + options.http_proxy) -+ if options.httpd_version: -+ args.append('--httpd-version=' + options.httpd_version) - - result, stdout_lines, stderr_lines = spawn_process(command, 0, False, None, - *args) -@@ -1600,6 +1626,12 @@ class TestRunner: - sandbox.cleanup_test_paths() - return exit_code - -+def is_httpd_authz_provider_enabled(): -+ if is_ra_type_dav(): -+ v = options.httpd_version.split('.') -+ return (v[0] == '2' and int(v[1]) >= 3) or int(v[0]) > 2 -+ return None -+ - ###################################################################### - # Main testing functions - -@@ -1780,6 +1812,8 @@ def _create_parser(): - help='Path to SSL server certificate.') - parser.add_option('--http-proxy', action='store', - help='Use the HTTP Proxy at hostname:port.') -+ parser.add_option('--httpd-version', action='store', -+ help='Assume HTTPD is this version.') - parser.add_option('--tools-bin', action='store', dest='tools_bin', - help='Use the svn tools installed in this path') - -Index: win-tests.py -=================================================================== ---- a/win-tests.py (revision 1691883) -+++ b/win-tests.py (working copy) -@@ -481,6 +481,7 @@ class Httpd: - self.httpd_config = os.path.join(self.root, 'httpd.conf') - self.httpd_users = os.path.join(self.root, 'users') - self.httpd_mime_types = os.path.join(self.root, 'mime.types') -+ self.httpd_groups = os.path.join(self.root, 'groups') - self.abs_builddir = abs_builddir - self.abs_objdir = abs_objdir - self.service_name = 'svn-test-httpd-' + str(httpd_port) -@@ -494,6 +495,7 @@ class Httpd: - create_target_dir(self.root_dir) - - self._create_users_file() -+ self._create_groups_file() - self._create_mime_types_file() - self._create_dontdothat_file() - -@@ -540,6 +542,8 @@ class Httpd: - if self.httpd_ver >= 2.2: - fp.write(self._sys_module('auth_basic_module', 'mod_auth_basic.so')) - fp.write(self._sys_module('authn_file_module', 'mod_authn_file.so')) -+ fp.write(self._sys_module('authz_groupfile_module', 'mod_authz_groupfile.so')) -+ fp.write(self._sys_module('authz_host_module', 'mod_authz_host.so')) - else: - fp.write(self._sys_module('auth_module', 'mod_auth.so')) - fp.write(self._sys_module('alias_module', 'mod_alias.so')) -@@ -562,6 +566,7 @@ class Httpd: - # Define two locations for repositories - fp.write(self._svn_repo('repositories')) - fp.write(self._svn_repo('local_tmp')) -+ fp.write(self._svn_authz_repo()) - - # And two redirects for the redirect tests - fp.write('RedirectMatch permanent ^/svn-test-work/repositories/' -@@ -592,7 +597,18 @@ class Httpd: - 'jrandom', 'rayjandom']) - os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, - 'jconstant', 'rayjandom']) -+ os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, -+ 'JRANDOM', 'rayjandom']) -+ os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, -+ 'JCONSTANT', 'rayjandom']) - -+ def _create_groups_file(self): -+ "Create groups for mod_authz_svn tests" -+ fp = open(self.httpd_groups, 'w') -+ fp.write('random: jrandom\n') -+ fp.write('constant: jconstant\n') -+ fp.close() -+ - def _create_mime_types_file(self): - "Create empty mime.types file" - fp = open(self.httpd_mime_types, 'w') -@@ -652,6 +668,153 @@ class Httpd: - ' DontDoThatConfigFile ' + self._quote(self.dontdothat_file) + '\n' \ - '\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 \ -+ '' + '\n' \ -+ ' DAV svn' + '\n' \ -+ ' SVNParentPath ' + local_tmp + '\n' \ -+ ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ -+ ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ -+ ' SVNListParentPath On' + '\n' \ -+ ' ' + '\n' \ -+ ' Require all granted' + '\n' \ -+ ' ' + '\n' \ -+ ' ' + '\n' \ -+ ' Allow from all' + '\n' \ -+ ' ' + '\n' \ -+ ' SVNPathAuthz ' + self.path_authz_option + '\n' \ -+ '' + '\n' \ -+ '' + '\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' \ -+ '' + '\n' \ -+ '' + '\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' \ -+ '' + '\n' \ -+ '' + '\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' \ -+ '' + '\n' \ -+ '' + '\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' \ -+ '' + '\n' \ -+ '' + '\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' \ -+ '' + '\n' \ -+ '' + '\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' \ -+ '' + '\n' \ -+ '' + '\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' \ -+ '' + '\n' \ -+ '' + '\n' \ -+ '' + '\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' \ -+ ' ' + '\n' \ -+ ' Require valid-user' + '\n' \ -+ ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \ -+ ' ' + '\n' \ -+ ' SVNPathAuthz ' + self.path_authz_option + '\n' \ -+ '' + '\n' \ -+ ''+ '\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' \ -+ ' ' + '\n' \ -+ ' Require valid-user' + '\n' \ -+ ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \ -+ ' ' + '\n' \ -+ ' SVNPathAuthz ' + self.path_authz_option + '\n' \ -+ '' + '\n' \ -+ '' + '\n' \ -+ - def start(self): - if self.service: - self._start_service() -@@ -786,6 +949,10 @@ if not test_javahl: - log_file = os.path.join(abs_builddir, log) - fail_log_file = os.path.join(abs_builddir, faillog) - -+ if run_httpd: -+ httpd_version = "%.1f" % daemon.httpd_ver -+ else: -+ httpd_version = None - th = run_tests.TestHarness(abs_srcdir, abs_builddir, - log_file, - fail_log_file, -@@ -795,6 +962,7 @@ if not test_javahl: - fsfs_sharding, fsfs_packing, - list_tests, svn_bin, mode_filter, - milestone_filter, -+ httpd_version=httpd_version, - set_log_level=log_level, ssl_cert=ssl_cert) - old_cwd = os.getcwd() - try: diff --git a/meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3187.patch b/meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3187.patch deleted file mode 100644 index 494e11c6c7..0000000000 --- a/meta/recipes-devtools/subversion/subversion-1.8.13/subversion-CVE-2015-3187.patch +++ /dev/null @@ -1,346 +0,0 @@ -Fix CVE-2015-3187 - -Patch is from: -http://subversion.apache.org/security/CVE-2015-3187-advisory.txt - -Upstream-Status: Backport - -Signed-off-by: Wenzong Fan - -Index: subversion/libsvn_repos/rev_hunt.c -=================================================================== ---- a/subversion/libsvn_repos/rev_hunt.c (revision 1685077) -+++ b/subversion/libsvn_repos/rev_hunt.c (working copy) -@@ -726,23 +726,6 @@ svn_repos_trace_node_locations(svn_fs_t *fs, - 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) -@@ -765,6 +748,20 @@ svn_repos_trace_node_locations(svn_fs_t *fs, - 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; -Index: subversion/tests/cmdline/authz_tests.py -=================================================================== ---- a/subversion/tests/cmdline/authz_tests.py (revision 1685077) -+++ b/subversion/tests/cmdline/authz_tests.py (working copy) -@@ -609,8 +609,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'): -@@ -627,10 +629,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 -Index: subversion/tests/libsvn_repos/repos-test.c -=================================================================== ---- a/subversion/tests/libsvn_repos/repos-test.c (revision 1685077) -+++ b/subversion/tests/libsvn_repos/repos-test.c (working copy) -@@ -3524,6 +3524,245 @@ test_load_r0_mergeinfo(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; -+ -+ svn_hash_sets(b->paths, apr_pstrdup(b->pool, path), (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 (!svn_hash_gets(checked, path)) -+ 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. */ - - struct svn_test_descriptor_t test_funcs[] = -@@ -3573,5 +3812,7 @@ struct svn_test_descriptor_t test_funcs[] = - "test dumping with r0 mergeinfo"), - SVN_TEST_OPTS_PASS(test_load_r0_mergeinfo, - "test loading with r0 mergeinfo"), -+ SVN_TEST_OPTS_PASS(trace_node_locations_authz, -+ "authz for svn_repos_trace_node_locations"), - SVN_TEST_NULL - }; diff --git a/meta/recipes-devtools/subversion/subversion/0001-Fix-libtool-name-in-configure.ac.patch b/meta/recipes-devtools/subversion/subversion/0001-Fix-libtool-name-in-configure.ac.patch new file mode 100644 index 0000000000..5a1b10b2e1 --- /dev/null +++ b/meta/recipes-devtools/subversion/subversion/0001-Fix-libtool-name-in-configure.ac.patch @@ -0,0 +1,29 @@ +From cbcfe0399347989e45a8fb695f55c855d6b3da72 Mon Sep 17 00:00:00 2001 +From: Alexander Kanavin +Date: Mon, 7 Dec 2015 17:11:02 +0200 +Subject: [PATCH] Fix libtool name in configure.ac + +Upstream-Status: Inappropriate [embedded specific] +Signed-off-by: Alexander Kanavin +--- + configure.ac | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 4ed66d4..ceb64f9 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -221,8 +221,8 @@ if test "$experimental_libtool" = "yes"; then + LIBTOOL="$sh_libtool" + SVN_LIBTOOL="$sh_libtool" + else +- sh_libtool="$abs_builddir/libtool" +- SVN_LIBTOOL="\$(SHELL) \"$sh_libtool\"" ++ sh_libtool="$abs_builddir/$host_alias-libtool" ++ SVN_LIBTOOL="\$(SHELL) \$(abs_builddir)/$host_alias-libtool" + fi + AC_SUBST(SVN_LIBTOOL) + +-- +2.6.2 + diff --git a/meta/recipes-devtools/subversion/subversion/disable_macos.patch b/meta/recipes-devtools/subversion/subversion/disable_macos.patch new file mode 100644 index 0000000000..ec3be496f3 --- /dev/null +++ b/meta/recipes-devtools/subversion/subversion/disable_macos.patch @@ -0,0 +1,68 @@ +These tests don't work in cross compiling, just disable them for now, we don't +build subversion on OS-X at this time. + +RP 1014/7/16 + +Upstream-Status: Pending [needs a rewrite to support a cache value] + +Index: subversion-1.8.9/build/ac-macros/macosx.m4 +=================================================================== +--- subversion-1.8.9.orig/build/ac-macros/macosx.m4 2012-11-26 03:04:27.000000000 +0000 ++++ subversion-1.8.9/build/ac-macros/macosx.m4 2014-07-16 12:28:58.357300403 +0000 +@@ -24,21 +24,7 @@ + AC_DEFUN(SVN_LIB_MACHO_ITERATE, + [ + AC_MSG_CHECKING([for Mach-O dynamic module iteration functions]) +- AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +- #include +- #include +- ]],[[ +- const struct mach_header *header = _dyld_get_image_header(0); +- const char *name = _dyld_get_image_name(0); +- if (name && header) return 0; +- return 1; +- ]])],[ +- AC_DEFINE([SVN_HAVE_MACHO_ITERATE], [1], +- [Is Mach-O low-level _dyld API available?]) +- AC_MSG_RESULT([yes]) +- ],[ + AC_MSG_RESULT([no]) +- ]) + ]) + + dnl SVN_LIB_MACOS_PLIST +@@ -46,34 +32,7 @@ + AC_DEFUN(SVN_LIB_MACOS_PLIST, + [ + AC_MSG_CHECKING([for Mac OS property list utilities]) +- +- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +- #include +- #if !defined(MAC_OS_X_VERSION_MAX_ALLOWED) \ +- || !defined(MAC_OS_X_VERSION_10_0) \ +- || (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_0) +- #error ProperyList API unavailable. +- #endif +- ]],[[]])],[ +- dnl ### Hack. We should only need to pass the -framework options when +- dnl linking libsvn_subr, since it is the only library that uses Keychain. +- dnl +- dnl Unfortunately, libtool 1.5.x doesn't track transitive dependencies for +- dnl OS X frameworks like it does for normal libraries, so we need to +- dnl explicitly pass the option to all the users of libsvn_subr to allow +- dnl static builds to link successfully. +- dnl +- dnl This does mean that all executables we link will be linked directly +- dnl to these frameworks - even when building shared libraries - but that +- dnl shouldn't cause any problems. +- +- LIBS="$LIBS -framework CoreFoundation" +- AC_DEFINE([SVN_HAVE_MACOS_PLIST], [1], +- [Is Mac OS property list API available?]) +- AC_MSG_RESULT([yes]) +- ],[ + AC_MSG_RESULT([no]) +- ]) + ]) + + dnl SVN_LIB_MACOS_KEYCHAIN diff --git a/meta/recipes-devtools/subversion/subversion/serf.m4-Regex-modified-to-allow-D-in-paths.patch b/meta/recipes-devtools/subversion/subversion/serf.m4-Regex-modified-to-allow-D-in-paths.patch new file mode 100644 index 0000000000..9fed3cf6c8 --- /dev/null +++ b/meta/recipes-devtools/subversion/subversion/serf.m4-Regex-modified-to-allow-D-in-paths.patch @@ -0,0 +1,32 @@ +From f1b6e49f12a18eabe88eb732b578a16281d09499 Mon Sep 17 00:00:00 2001 +From: Jose Lamego +Date: Thu, 2 Jul 2015 11:37:43 +0000 +Subject: [PATCH] serf.m4: Regex modified to allow '-D' in paths + +Upstream-Status: Accepted + +The patch is merged by subversion upstream with replacing '[[:space:]]' with ' '. + +http://svn.apache.org/viewvc/subversion/trunk/build/ac-macros/serf.m4?r1=1594156&r2=1689824 + +Signed-off-by: Jose Lamego +--- + build/ac-macros/serf.m4 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/build/ac-macros/serf.m4 b/build/ac-macros/serf.m4 +index ae11e75..ff8cbae 100644 +--- a/build/ac-macros/serf.m4 ++++ b/build/ac-macros/serf.m4 +@@ -168,7 +168,7 @@ + if $PKG_CONFIG $serf_pc_arg --atleast-version=$serf_check_version; then + AC_MSG_RESULT([yes]) + serf_found=yes +- SVN_SERF_INCLUDES=[`$PKG_CONFIG $serf_pc_arg --cflags | $SED -e 's/-D[^ ]*//g'`] ++ SVN_SERF_INCLUDES=[`$PKG_CONFIG $serf_pc_arg --cflags | $SED -e 's/ -D[^ ]*//g' -e 's/^-D[^ ]*//g'`] + SVN_SERF_LIBS=`$PKG_CONFIG $serf_pc_arg --libs-only-l` + dnl don't use --libs-only-L because then we might miss some options + LDFLAGS=["$LDFLAGS `$PKG_CONFIG $serf_pc_arg --libs | $SED -e 's/-l[^ ]*//g'`"] +-- +1.8.4.5 + diff --git a/meta/recipes-devtools/subversion/subversion_1.8.13.bb b/meta/recipes-devtools/subversion/subversion_1.8.13.bb deleted file mode 100644 index 68934b7e02..0000000000 --- a/meta/recipes-devtools/subversion/subversion_1.8.13.bb +++ /dev/null @@ -1,55 +0,0 @@ -SUMMARY = "Subversion (svn) version control system client" -SECTION = "console/network" -DEPENDS = "apr-util serf sqlite3 file" -DEPENDS_append_class-native = " file-replacement-native" -RDEPENDS_${PN} = "serf" -LICENSE = "Apache-2" -HOMEPAGE = "http://subversion.tigris.org" - -BBCLASSEXTEND = "native" - -inherit gettext pythonnative - -SRC_URI = "${APACHE_MIRROR}/${BPN}/${BPN}-${PV}.tar.bz2 \ - file://libtool2.patch \ - file://disable_macos.patch \ - file://serf.m4-Regex-modified-to-allow-D-in-paths.patch \ - file://subversion-CVE-2015-3184.patch \ - file://subversion-CVE-2015-3187.patch \ -" -SRC_URI[md5sum] = "4413417b529d7bdf82f74e50df02e88b" -SRC_URI[sha256sum] = "1099cc68840753b48aedb3a27ebd1e2afbcc84ddb871412e5d500e843d607579" - -LIC_FILES_CHKSUM = "file://LICENSE;md5=1c2f0119e478700b5428e26386cff923" - -PACKAGECONFIG[sasl] = "--with-sasl,--without-sasl,cyrus-sasl" -PACKAGECONFIG[gnome-keyring] = "--with-gnome-keyring,--without-gnome-keyring,glib-2.0 gnome-keyring" - -EXTRA_OECONF = " \ - --without-berkeley-db --without-apxs \ - --without-swig --with-apr=${STAGING_BINDIR_CROSS} \ - --with-apr-util=${STAGING_BINDIR_CROSS} \ - --disable-keychain \ - ac_cv_path_RUBY=none" - -inherit autotools - -export LDFLAGS += " -L${STAGING_LIBDIR} " -CPPFLAGS += "-P" -BUILD_CPPFLAGS += "-P" - -acpaths = "-I build/ -I build/ac-macros/" - -do_configure_prepend () { - rm -f ${S}/libtool - rm -f ${S}/build/libtool.m4 ${S}/build/ltmain.sh ${S}/build/ltoptions.m4 ${S}/build/ltsugar.m4 ${S}/build/ltversion.m4 ${S}/build/lt~obsolete.m4 - rm -f ${S}/aclocal.m4 - sed -i -e 's:with_sasl="/usr/local":with_sasl="${STAGING_DIR}":' ${S}/build/ac-macros/sasl.m4 -} - -#| x86_64-linux-libtool: install: warning: `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/work/x86_64-linux/subversion-native/1.8.9-r0/build/subversion/libsvn_ra_local/libsvn_ra_local-1.la' has not been installed in `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/sysroots/x86_64-linux/usr/lib'| x86_64-linux-libtool: install: warning: `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/work/x86_64-linux/subversion-native/1.8.9-r0/build/subversion/libsvn_repos/libsvn_repos-1.la' has not been installed in `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/sysroots/x86_64-linux/usr/lib'| /usr/bin/ld: cannot find -lsvn_delta-1| collect2: ld returned 1 exit status| x86_64-linux-libtool: install: warning: `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/work/x86_64-linux/subversion-native/1.8.9-r0/build/subversion/libsvn_ra_svn/libsvn_ra_svn-1.la' has not been installed in `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/sysroots/x86_64-linux/usr/lib'| x86_64-linux-libtool: install: warning: `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/work/x86_64-linux/subversion-native/1.8.9-r0/build/subversion/libsvn_ra_serf/libsvn_ra_serf-1.la' has not been installed in `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/sysroots/x86_64-linux/usr/lib' -#| x86_64-linux-libtool: install: error: relink `libsvn_ra_serf-1.la' with the above command before installing it -#| x86_64-linux-libtool: install: warning: `../../subversion/libsvn_repos/libsvn_repos-1.la' has not been installed in `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/sysroots/x86_64-linux/usr/lib' -#| /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/work/x86_64-linux/subversion-native/1.8.9-r0/subversion-1.8.9/build-outputs.mk:1090: recipe for target 'install-serf-lib' failed -#| make: *** [install-serf-lib] Error 1 -PARALLEL_MAKEINST = "" diff --git a/meta/recipes-devtools/subversion/subversion_1.9.2.bb b/meta/recipes-devtools/subversion/subversion_1.9.2.bb new file mode 100644 index 0000000000..f432b8fe78 --- /dev/null +++ b/meta/recipes-devtools/subversion/subversion_1.9.2.bb @@ -0,0 +1,53 @@ +SUMMARY = "Subversion (svn) version control system client" +SECTION = "console/network" +DEPENDS = "apr-util serf sqlite3 file" +DEPENDS_append_class-native = " file-replacement-native" +RDEPENDS_${PN} = "serf" +LICENSE = "Apache-2" +HOMEPAGE = "http://subversion.tigris.org" + +BBCLASSEXTEND = "native" + +inherit gettext pythonnative + +SRC_URI = "${APACHE_MIRROR}/${BPN}/${BPN}-${PV}.tar.bz2 \ + file://disable_macos.patch \ + file://serf.m4-Regex-modified-to-allow-D-in-paths.patch \ + file://0001-Fix-libtool-name-in-configure.ac.patch \ + " +SRC_URI[md5sum] = "0a7e55bb58fe77072f19e108a56b468b" +SRC_URI[sha256sum] = "023da881139b4514647b6f8a830a244071034efcaad8c8e98c6b92393122b4eb" + +LIC_FILES_CHKSUM = "file://LICENSE;md5=af81ae49ba359e70626c05e9bf313709" + +PACKAGECONFIG[sasl] = "--with-sasl,--without-sasl,cyrus-sasl" +PACKAGECONFIG[gnome-keyring] = "--with-gnome-keyring,--without-gnome-keyring,glib-2.0 gnome-keyring" + +EXTRA_OECONF = " \ + --without-berkeley-db --without-apxs \ + --without-swig --with-apr=${STAGING_BINDIR_CROSS} \ + --with-apr-util=${STAGING_BINDIR_CROSS} \ + --disable-keychain \ + ac_cv_path_RUBY=none" + +inherit autotools + +export LDFLAGS += " -L${STAGING_LIBDIR} " +CPPFLAGS += "-P" +BUILD_CPPFLAGS += "-P" + +acpaths = "-I build/ -I build/ac-macros/" + +do_configure_prepend () { + rm -f ${S}/libtool + rm -f ${S}/build/libtool.m4 ${S}/build/ltmain.sh ${S}/build/ltoptions.m4 ${S}/build/ltsugar.m4 ${S}/build/ltversion.m4 ${S}/build/lt~obsolete.m4 + rm -f ${S}/aclocal.m4 + sed -i -e 's:with_sasl="/usr/local":with_sasl="${STAGING_DIR}":' ${S}/build/ac-macros/sasl.m4 +} + +#| x86_64-linux-libtool: install: warning: `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/work/x86_64-linux/subversion-native/1.8.9-r0/build/subversion/libsvn_ra_local/libsvn_ra_local-1.la' has not been installed in `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/sysroots/x86_64-linux/usr/lib'| x86_64-linux-libtool: install: warning: `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/work/x86_64-linux/subversion-native/1.8.9-r0/build/subversion/libsvn_repos/libsvn_repos-1.la' has not been installed in `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/sysroots/x86_64-linux/usr/lib'| /usr/bin/ld: cannot find -lsvn_delta-1| collect2: ld returned 1 exit status| x86_64-linux-libtool: install: warning: `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/work/x86_64-linux/subversion-native/1.8.9-r0/build/subversion/libsvn_ra_svn/libsvn_ra_svn-1.la' has not been installed in `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/sysroots/x86_64-linux/usr/lib'| x86_64-linux-libtool: install: warning: `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/work/x86_64-linux/subversion-native/1.8.9-r0/build/subversion/libsvn_ra_serf/libsvn_ra_serf-1.la' has not been installed in `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/sysroots/x86_64-linux/usr/lib' +#| x86_64-linux-libtool: install: error: relink `libsvn_ra_serf-1.la' with the above command before installing it +#| x86_64-linux-libtool: install: warning: `../../subversion/libsvn_repos/libsvn_repos-1.la' has not been installed in `/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/sysroots/x86_64-linux/usr/lib' +#| /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-logrotate/build/build/tmp/work/x86_64-linux/subversion-native/1.8.9-r0/subversion-1.8.9/build-outputs.mk:1090: recipe for target 'install-serf-lib' failed +#| make: *** [install-serf-lib] Error 1 +PARALLEL_MAKEINST = "" -- cgit 1.2.3-korg