diff options
-rw-r--r-- | meta/recipes-devtools/subversion/subversion-1.8.11/subversion-CVE-2015-3184.patch | 2082 | ||||
-rw-r--r-- | meta/recipes-devtools/subversion/subversion_1.8.11.bb | 1 |
2 files changed, 2083 insertions, 0 deletions
diff --git a/meta/recipes-devtools/subversion/subversion-1.8.11/subversion-CVE-2015-3184.patch b/meta/recipes-devtools/subversion/subversion-1.8.11/subversion-CVE-2015-3184.patch new file mode 100644 index 0000000000..2daa7c7ac8 --- /dev/null +++ b/meta/recipes-devtools/subversion/subversion-1.8.11/subversion-CVE-2015-3184.patch | |||
@@ -0,0 +1,2082 @@ | |||
1 | Fix CVE-2015-3184 | ||
2 | |||
3 | Patch is from: | ||
4 | http://subversion.apache.org/security/CVE-2015-3184-advisory.txt | ||
5 | |||
6 | Upstream-Status: Backport | ||
7 | |||
8 | Signed-off-by: Wenzong Fan <wenzong.fan@windriver.com> | ||
9 | |||
10 | Index: subversion-1.8.11/Makefile.in | ||
11 | =================================================================== | ||
12 | --- subversion-1.8.11.orig/Makefile.in | ||
13 | +++ subversion-1.8.11/Makefile.in | ||
14 | @@ -357,6 +357,7 @@ TEST_SHLIB_VAR_SWIG_RB=\ | ||
15 | fi; | ||
16 | |||
17 | APXS = @APXS@ | ||
18 | +HTTPD_VERSION = @HTTPD_VERSION@ | ||
19 | |||
20 | PYTHON = @PYTHON@ | ||
21 | PERL = @PERL@ | ||
22 | @@ -509,6 +510,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $ | ||
23 | if test "$(HTTP_LIBRARY)" != ""; then \ | ||
24 | flags="--http-library $(HTTP_LIBRARY) $$flags"; \ | ||
25 | fi; \ | ||
26 | + if test "$(HTTPD_VERSION)" != ""; then \ | ||
27 | + flags="--httpd-version $(HTTPD_VERSION) $$flags"; \ | ||
28 | + fi; \ | ||
29 | if test "$(SERVER_MINOR_VERSION)" != ""; then \ | ||
30 | flags="--server-minor-version $(SERVER_MINOR_VERSION) $$flags"; \ | ||
31 | fi; \ | ||
32 | Index: subversion-1.8.11/build/ac-macros/apache.m4 | ||
33 | =================================================================== | ||
34 | --- subversion-1.8.11.orig/build/ac-macros/apache.m4 | ||
35 | +++ subversion-1.8.11/build/ac-macros/apache.m4 | ||
36 | @@ -160,6 +160,20 @@ if test -n "$APXS" && test "$APXS" != "n | ||
37 | BUILD_APACHE_RULE=apache-mod | ||
38 | INSTALL_APACHE_RULE=install-mods-shared | ||
39 | INSTALL_APACHE_MODS=true | ||
40 | + HTTPD="`$APXS -q sbindir`/`$APXS -q PROGNAME`" | ||
41 | + if ! test -e $HTTPD ; then | ||
42 | + HTTPD="`$APXS -q bindir`/`$APXS -q PROGNAME`" | ||
43 | + fi | ||
44 | + HTTPD_VERSION=["`$HTTPD -v | $SED -e 's@^.*/\([0-9.]*\)\(.*$\)@\1@ ; 1q'`"] | ||
45 | + AC_ARG_ENABLE(broken-httpd-auth, | ||
46 | + AS_HELP_STRING([--enable-broken-httpd-auth], | ||
47 | + [Allow building against httpd 2.4 with broken auth]), | ||
48 | + [broken_httpd_auth=$enableval],[broken_httpd_auth=no]) | ||
49 | + if test "$enable_broken_httpd_auth" = "yes"; then | ||
50 | + AC_MSG_NOTICE([Building with broken httpd auth]) | ||
51 | + AC_DEFINE(SVN_ALLOW_BROKEN_HTTPD_AUTH, 1, | ||
52 | + [Defined to allow building against httpd 2.4 with broken auth]) | ||
53 | + fi | ||
54 | |||
55 | case $host in | ||
56 | *-*-cygwin*) | ||
57 | @@ -178,6 +192,7 @@ AC_SUBST(APACHE_LDFLAGS) | ||
58 | AC_SUBST(APACHE_INCLUDES) | ||
59 | AC_SUBST(APACHE_LIBEXECDIR) | ||
60 | AC_SUBST(INSTALL_APACHE_MODS) | ||
61 | +AC_SUBST(HTTPD_VERSION) | ||
62 | |||
63 | # there aren't any flags that interest us ... | ||
64 | #if test -n "$APXS" && test "$APXS" != "no"; then | ||
65 | Index: subversion-1.8.11/build/run_tests.py | ||
66 | =================================================================== | ||
67 | --- subversion-1.8.11.orig/build/run_tests.py | ||
68 | +++ subversion-1.8.11/build/run_tests.py | ||
69 | @@ -29,6 +29,7 @@ | ||
70 | [--fs-type=<fs-type>] [--fsfs-packing] [--fsfs-sharding=<n>] | ||
71 | [--list] [--milestone-filter=<regex>] [--mode-filter=<type>] | ||
72 | [--server-minor-version=<version>] [--http-proxy=<host>:<port>] | ||
73 | + [--httpd-version=<version>] | ||
74 | [--config-file=<file>] [--ssl-cert=<file>] | ||
75 | <abs_srcdir> <abs_builddir> | ||
76 | <prog ...> | ||
77 | @@ -125,7 +126,7 @@ class TestHarness: | ||
78 | fsfs_sharding=None, fsfs_packing=None, | ||
79 | list_tests=None, svn_bin=None, mode_filter=None, | ||
80 | milestone_filter=None, set_log_level=None, ssl_cert=None, | ||
81 | - http_proxy=None): | ||
82 | + http_proxy=None, httpd_version=None): | ||
83 | '''Construct a TestHarness instance. | ||
84 | |||
85 | ABS_SRCDIR and ABS_BUILDDIR are the source and build directories. | ||
86 | @@ -178,6 +179,7 @@ class TestHarness: | ||
87 | self.log = None | ||
88 | self.ssl_cert = ssl_cert | ||
89 | self.http_proxy = http_proxy | ||
90 | + self.httpd_version = httpd_version | ||
91 | if not sys.stdout.isatty() or sys.platform == 'win32': | ||
92 | TextColors.disable() | ||
93 | |||
94 | @@ -481,6 +483,8 @@ class TestHarness: | ||
95 | svntest.main.options.ssl_cert = self.ssl_cert | ||
96 | if self.http_proxy is not None: | ||
97 | svntest.main.options.http_proxy = self.http_proxy | ||
98 | + if self.httpd_version is not None: | ||
99 | + svntest.main.options.httpd_version = self.httpd_version | ||
100 | |||
101 | svntest.main.options.srcdir = self.srcdir | ||
102 | |||
103 | @@ -645,7 +649,7 @@ def main(): | ||
104 | 'enable-sasl', 'parallel', 'config-file=', | ||
105 | 'log-to-stdout', 'list', 'milestone-filter=', | ||
106 | 'mode-filter=', 'set-log-level=', 'ssl-cert=', | ||
107 | - 'http-proxy=']) | ||
108 | + 'http-proxy=', 'httpd-version=']) | ||
109 | except getopt.GetoptError: | ||
110 | args = [] | ||
111 | |||
112 | @@ -656,9 +660,9 @@ def main(): | ||
113 | base_url, fs_type, verbose, cleanup, enable_sasl, http_library, \ | ||
114 | server_minor_version, fsfs_sharding, fsfs_packing, parallel, \ | ||
115 | config_file, log_to_stdout, list_tests, mode_filter, milestone_filter, \ | ||
116 | - set_log_level, ssl_cert, http_proxy = \ | ||
117 | + set_log_level, ssl_cert, http_proxy, httpd_version = \ | ||
118 | None, None, None, None, None, None, None, None, None, None, None, \ | ||
119 | - None, None, None, None, None, None, None | ||
120 | + None, None, None, None, None, None, None, None | ||
121 | for opt, val in opts: | ||
122 | if opt in ['-u', '--url']: | ||
123 | base_url = val | ||
124 | @@ -696,6 +700,8 @@ def main(): | ||
125 | ssl_cert = val | ||
126 | elif opt in ['--http-proxy']: | ||
127 | http_proxy = val | ||
128 | + elif opt in ['--httpd-version']: | ||
129 | + httpd_version = val | ||
130 | else: | ||
131 | raise getopt.GetoptError | ||
132 | |||
133 | @@ -712,7 +718,7 @@ def main(): | ||
134 | fsfs_sharding, fsfs_packing, list_tests, | ||
135 | mode_filter=mode_filter, milestone_filter=milestone_filter, | ||
136 | set_log_level=set_log_level, ssl_cert=ssl_cert, | ||
137 | - http_proxy=http_proxy) | ||
138 | + http_proxy=http_proxy, httpd_version=httpd_version) | ||
139 | |||
140 | failed = th.run(args[2:]) | ||
141 | if failed: | ||
142 | Index: subversion-1.8.11/subversion/mod_authz_svn/mod_authz_svn.c | ||
143 | =================================================================== | ||
144 | --- subversion-1.8.11.orig/subversion/mod_authz_svn/mod_authz_svn.c | ||
145 | +++ subversion-1.8.11/subversion/mod_authz_svn/mod_authz_svn.c | ||
146 | @@ -48,6 +48,23 @@ | ||
147 | #include "svn_dirent_uri.h" | ||
148 | #include "private/svn_fspath.h" | ||
149 | |||
150 | +/* The apache headers define these and they conflict with our definitions. */ | ||
151 | +#ifdef PACKAGE_BUGREPORT | ||
152 | +#undef PACKAGE_BUGREPORT | ||
153 | +#endif | ||
154 | +#ifdef PACKAGE_NAME | ||
155 | +#undef PACKAGE_NAME | ||
156 | +#endif | ||
157 | +#ifdef PACKAGE_STRING | ||
158 | +#undef PACKAGE_STRING | ||
159 | +#endif | ||
160 | +#ifdef PACKAGE_TARNAME | ||
161 | +#undef PACKAGE_TARNAME | ||
162 | +#endif | ||
163 | +#ifdef PACKAGE_VERSION | ||
164 | +#undef PACKAGE_VERSION | ||
165 | +#endif | ||
166 | +#include "svn_private_config.h" | ||
167 | |||
168 | #ifdef APLOG_USE_MODULE | ||
169 | APLOG_USE_MODULE(authz_svn); | ||
170 | @@ -67,6 +84,30 @@ typedef struct authz_svn_config_rec { | ||
171 | const char *force_username_case; | ||
172 | } authz_svn_config_rec; | ||
173 | |||
174 | +#if AP_MODULE_MAGIC_AT_LEAST(20060110,0) /* version where | ||
175 | + ap_some_auth_required breaks */ | ||
176 | +# if AP_MODULE_MAGIC_AT_LEAST(20120211,47) /* first version with | ||
177 | + force_authn hook and | ||
178 | + ap_some_authn_required() which | ||
179 | + allows us to work without | ||
180 | + ap_some_auth_required() */ | ||
181 | +# define USE_FORCE_AUTHN 1 | ||
182 | +# define IN_SOME_AUTHN_NOTE "authz_svn-in-some-authn" | ||
183 | +# define FORCE_AUTHN_NOTE "authz_svn-force-authn" | ||
184 | +# else | ||
185 | + /* ap_some_auth_required() is busted and no viable alternative exists */ | ||
186 | +# ifndef SVN_ALLOW_BROKEN_HTTPD_AUTH | ||
187 | +# error This version of httpd has a security hole with mod_authz_svn | ||
188 | +# else | ||
189 | + /* user wants to build anyway */ | ||
190 | +# define USE_FORCE_AUTHN 0 | ||
191 | +# endif | ||
192 | +# endif | ||
193 | +#else | ||
194 | + /* old enough that ap_some_auth_required() still works */ | ||
195 | +# define USE_FORCE_AUTHN 0 | ||
196 | +#endif | ||
197 | + | ||
198 | /* | ||
199 | * Configuration | ||
200 | */ | ||
201 | @@ -819,7 +860,49 @@ access_checker(request_rec *r) | ||
202 | &authz_svn_module); | ||
203 | const char *repos_path = NULL; | ||
204 | const char *dest_repos_path = NULL; | ||
205 | - int status; | ||
206 | + int status, authn_required; | ||
207 | + | ||
208 | +#if USE_FORCE_AUTHN | ||
209 | + /* Use the force_authn() hook available in 2.4.x to work securely | ||
210 | + * given that ap_some_auth_required() is no longer functional for our | ||
211 | + * purposes in 2.4.x. | ||
212 | + */ | ||
213 | + int authn_configured; | ||
214 | + | ||
215 | + /* We are not configured to run */ | ||
216 | + if (!conf->anonymous || apr_table_get(r->notes, IN_SOME_AUTHN_NOTE) | ||
217 | + || (! (conf->access_file || conf->repo_relative_access_file))) | ||
218 | + return DECLINED; | ||
219 | + | ||
220 | + /* Authentication is configured */ | ||
221 | + authn_configured = ap_auth_type(r) != NULL; | ||
222 | + if (authn_configured) | ||
223 | + { | ||
224 | + /* If the user is trying to authenticate, let him. It doesn't | ||
225 | + * make much sense to grant anonymous access but deny authenticated | ||
226 | + * users access, even though you can do that with '$anon' in the | ||
227 | + * access file. | ||
228 | + */ | ||
229 | + if (apr_table_get(r->headers_in, | ||
230 | + (PROXYREQ_PROXY == r->proxyreq) | ||
231 | + ? "Proxy-Authorization" : "Authorization")) | ||
232 | + { | ||
233 | + /* Set the note to force authn regardless of what access_checker_ex | ||
234 | + hook requires */ | ||
235 | + apr_table_setn(r->notes, FORCE_AUTHN_NOTE, (const char*)1); | ||
236 | + | ||
237 | + /* provide the proper return so the access_checker hook doesn't | ||
238 | + * prevent the code from continuing on to the other auth hooks */ | ||
239 | + if (ap_satisfies(r) != SATISFY_ANY) | ||
240 | + return OK; | ||
241 | + else | ||
242 | + return HTTP_FORBIDDEN; | ||
243 | + } | ||
244 | + } | ||
245 | + | ||
246 | +#else | ||
247 | + /* Support for older versions of httpd that have a working | ||
248 | + * ap_some_auth_required() */ | ||
249 | |||
250 | /* We are not configured to run */ | ||
251 | if (!conf->anonymous | ||
252 | @@ -834,9 +917,10 @@ access_checker(request_rec *r) | ||
253 | if (ap_satisfies(r) != SATISFY_ANY) | ||
254 | return DECLINED; | ||
255 | |||
256 | - /* If the user is trying to authenticate, let him. If anonymous | ||
257 | - * access is allowed, so is authenticated access, by definition | ||
258 | - * of the meaning of '*' in the access file. | ||
259 | + /* If the user is trying to authenticate, let him. It doesn't | ||
260 | + * make much sense to grant anonymous access but deny authenticated | ||
261 | + * users access, even though you can do that with '$anon' in the | ||
262 | + * access file. | ||
263 | */ | ||
264 | if (apr_table_get(r->headers_in, | ||
265 | (PROXYREQ_PROXY == r->proxyreq) | ||
266 | @@ -848,6 +932,7 @@ access_checker(request_rec *r) | ||
267 | return HTTP_FORBIDDEN; | ||
268 | } | ||
269 | } | ||
270 | +#endif | ||
271 | |||
272 | /* If anon access is allowed, return OK */ | ||
273 | status = req_check_access(r, conf, &repos_path, &dest_repos_path); | ||
274 | @@ -856,7 +941,26 @@ access_checker(request_rec *r) | ||
275 | if (!conf->authoritative) | ||
276 | return DECLINED; | ||
277 | |||
278 | +#if USE_FORCE_AUTHN | ||
279 | + if (authn_configured) { | ||
280 | + /* We have to check to see if authn is required because if so we must | ||
281 | + * return UNAUTHORIZED (401) rather than FORBIDDEN (403) since returning | ||
282 | + * the 403 leaks information about what paths may exist to | ||
283 | + * unauthenticated users. We must set a note here in order | ||
284 | + * to use ap_some_authn_rquired() without triggering an infinite | ||
285 | + * loop since the call will trigger this function to be called again. */ | ||
286 | + apr_table_setn(r->notes, IN_SOME_AUTHN_NOTE, (const char*)1); | ||
287 | + authn_required = ap_some_authn_required(r); | ||
288 | + apr_table_unset(r->notes, IN_SOME_AUTHN_NOTE); | ||
289 | + if (authn_required) | ||
290 | + { | ||
291 | + ap_note_auth_failure(r); | ||
292 | + return HTTP_UNAUTHORIZED; | ||
293 | + } | ||
294 | + } | ||
295 | +#else | ||
296 | if (!ap_some_auth_required(r)) | ||
297 | +#endif | ||
298 | log_access_verdict(APLOG_MARK, r, 0, repos_path, dest_repos_path); | ||
299 | |||
300 | return HTTP_FORBIDDEN; | ||
301 | @@ -937,6 +1041,17 @@ auth_checker(request_rec *r) | ||
302 | return OK; | ||
303 | } | ||
304 | |||
305 | +#if USE_FORCE_AUTHN | ||
306 | +static int | ||
307 | +force_authn(request_rec *r) | ||
308 | +{ | ||
309 | + if (apr_table_get(r->notes, FORCE_AUTHN_NOTE)) | ||
310 | + return OK; | ||
311 | + | ||
312 | + return DECLINED; | ||
313 | +} | ||
314 | +#endif | ||
315 | + | ||
316 | /* | ||
317 | * Module flesh | ||
318 | */ | ||
319 | @@ -953,6 +1068,9 @@ register_hooks(apr_pool_t *p) | ||
320 | * give SSLOptions +FakeBasicAuth a chance to work. */ | ||
321 | ap_hook_check_user_id(check_user_id, mod_ssl, NULL, APR_HOOK_FIRST); | ||
322 | ap_hook_auth_checker(auth_checker, NULL, NULL, APR_HOOK_FIRST); | ||
323 | +#if USE_FORCE_AUTHN | ||
324 | + ap_hook_force_authn(force_authn, NULL, NULL, APR_HOOK_FIRST); | ||
325 | +#endif | ||
326 | ap_register_provider(p, | ||
327 | AUTHZ_SVN__SUBREQ_BYPASS_PROV_GRP, | ||
328 | AUTHZ_SVN__SUBREQ_BYPASS_PROV_NAME, | ||
329 | Index: subversion-1.8.11/subversion/tests/cmdline/README | ||
330 | =================================================================== | ||
331 | --- subversion-1.8.11.orig/subversion/tests/cmdline/README | ||
332 | +++ subversion-1.8.11/subversion/tests/cmdline/README | ||
333 | @@ -83,6 +83,133 @@ paths adjusted appropriately: | ||
334 | Require valid-user | ||
335 | </Location> | ||
336 | |||
337 | + <Location /authz-test-work/anon> | ||
338 | + DAV svn | ||
339 | + SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp | ||
340 | + AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz | ||
341 | + SVNListParentPath On | ||
342 | + # This may seem unnecessary but granting access to everyone here is necessary | ||
343 | + # to exercise a bug with httpd 2.3.x+. The "Require all granted" syntax is | ||
344 | + # new to 2.3.x+ which we can detect with the mod_authz_core.c module | ||
345 | + # signature. Use the "Allow from all" syntax with older versions for symmetry. | ||
346 | + <IfModule mod_authz_core.c> | ||
347 | + Require all granted | ||
348 | + </IfModule> | ||
349 | + <IfModule !mod_authz_core.c> | ||
350 | + Allow from all | ||
351 | + </IfMOdule> | ||
352 | + </Location> | ||
353 | + <Location /authz-test-work/mixed> | ||
354 | + DAV svn | ||
355 | + SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp | ||
356 | + AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz | ||
357 | + SVNListParentPath On | ||
358 | + AuthType Basic | ||
359 | + AuthName "Subversion Repository" | ||
360 | + AuthUserFile /usr/local/apache2/conf/users | ||
361 | + Require valid-user | ||
362 | + Satisfy Any | ||
363 | + </Location> | ||
364 | + <Location /authz-test-work/mixed-noauthwhenanon> | ||
365 | + DAV svn | ||
366 | + SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp | ||
367 | + AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz | ||
368 | + SVNListParentPath On | ||
369 | + AuthType Basic | ||
370 | + AuthName "Subversion Repository" | ||
371 | + AuthUserFile /usr/local/apache2/conf/users | ||
372 | + Require valid-user | ||
373 | + AuthzSVNNoAuthWhenAnonymousAllowed On | ||
374 | + </Location> | ||
375 | + <Location /authz-test-work/authn> | ||
376 | + DAV svn | ||
377 | + SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp | ||
378 | + AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz | ||
379 | + SVNListParentPath On | ||
380 | + AuthType Basic | ||
381 | + AuthName "Subversion Repository" | ||
382 | + AuthUserFile /usr/local/apache2/conf/users | ||
383 | + Require valid-user | ||
384 | + </Location> | ||
385 | + <Location /authz-test-work/authn-anonoff> | ||
386 | + DAV svn | ||
387 | + SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp | ||
388 | + AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz | ||
389 | + SVNListParentPath On | ||
390 | + AuthType Basic | ||
391 | + AuthName "Subversion Repository" | ||
392 | + AuthUserFile /usr/local/apache2/conf/users | ||
393 | + Require valid-user | ||
394 | + AuthzSVNAnonymous Off | ||
395 | + </Location> | ||
396 | + <Location /authz-test-work/authn-lcuser> | ||
397 | + DAV svn | ||
398 | + SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp | ||
399 | + AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz | ||
400 | + SVNListParentPath On | ||
401 | + AuthType Basic | ||
402 | + AuthName "Subversion Repository" | ||
403 | + AuthUserFile /usr/local/apache2/conf/users | ||
404 | + Require valid-user | ||
405 | + AuthzForceUsernameCase Lower | ||
406 | + </Location> | ||
407 | + <Location /authz-test-work/authn-lcuser> | ||
408 | + DAV svn | ||
409 | + SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp | ||
410 | + AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz | ||
411 | + SVNListParentPath On | ||
412 | + AuthType Basic | ||
413 | + AuthName "Subversion Repository" | ||
414 | + AuthUserFile /usr/local/apache2/conf/users | ||
415 | + Require valid-user | ||
416 | + AuthzForceUsernameCase Lower | ||
417 | + </Location> | ||
418 | + <Location /authz-test-work/authn-group> | ||
419 | + DAV svn | ||
420 | + SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp | ||
421 | + AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz | ||
422 | + SVNListParentPath On | ||
423 | + AuthType Basic | ||
424 | + AuthName "Subversion Repository" | ||
425 | + AuthUserFile /usr/local/apache2/conf/users | ||
426 | + AuthGroupFile /usr/local/apache2/conf/groups | ||
427 | + Require group random | ||
428 | + AuthzSVNAuthoritative Off | ||
429 | + </Location> | ||
430 | + <IfModule mod_authz_core.c> | ||
431 | + <Location /authz-test-work/sallrany> | ||
432 | + DAV svn | ||
433 | + SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp | ||
434 | + AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz | ||
435 | + SVNListParentPath On | ||
436 | + AuthType Basic | ||
437 | + AuthName "Subversion Repository" | ||
438 | + AuthUserFile /usr/local/apache2/conf/users | ||
439 | + AuthzSendForbiddenOnFailure On | ||
440 | + Satisfy All | ||
441 | + <RequireAny> | ||
442 | + Require valid-user | ||
443 | + Require expr req('ALLOW') == '1' | ||
444 | + </RequireAny> | ||
445 | + </Location> | ||
446 | + <Location /authz-test-work/sallrall> | ||
447 | + DAV svn | ||
448 | + SVNParentPath /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/local_tmp | ||
449 | + AuthzSVNAccessFile /home/yourusernamehere/projects/svn/subversion/tests/cmdline/svn-test-work/authz | ||
450 | + SVNListParentPath On | ||
451 | + AuthType Basic | ||
452 | + AuthName "Subversion Repository" | ||
453 | + AuthUserFile /usr/local/apache2/conf/users | ||
454 | + AuthzSendForbiddenOnFailure On | ||
455 | + Satisfy All | ||
456 | + <RequireAll> | ||
457 | + Require valid-user | ||
458 | + Require expr req('ALLOW') == '1' | ||
459 | + </RequireAll> | ||
460 | + </Location> | ||
461 | + </IfModule> | ||
462 | + | ||
463 | + | ||
464 | RedirectMatch permanent ^/svn-test-work/repositories/REDIRECT-PERM-(.*)$ /svn-test-work/repositories/$1 | ||
465 | RedirectMatch ^/svn-test-work/repositories/REDIRECT-TEMP-(.*)$ /svn-test-work/repositories/$1 | ||
466 | |||
467 | @@ -101,6 +228,15 @@ just drop the following 2-line snippet i | ||
468 | ---------------------------- | ||
469 | jrandom:xCGl35kV9oWCY | ||
470 | jconstant:xCGl35kV9oWCY | ||
471 | +JRANDOM:xCGl35kV9oWCY | ||
472 | +JCONSTANT:xCGl35kV9oWCY | ||
473 | +---------------------------- | ||
474 | + | ||
475 | +and these lines into the | ||
476 | +/usr/local/apache/conf/groups file: | ||
477 | +---------------------------- | ||
478 | +random: jrandom | ||
479 | +constant: jconstant | ||
480 | ---------------------------- | ||
481 | |||
482 | Now, (re)start Apache and run the tests over mod_dav_svn. | ||
483 | @@ -138,6 +274,8 @@ Note [1]: It would be quite too much to | ||
484 | ---------------------------- | ||
485 | jrandom:$apr1$3p1.....$FQW6RceW5QhJ2blWDQgKn0 | ||
486 | jconstant:$apr1$jp1.....$Usrqji1c9H6AbOxOGAzzb0 | ||
487 | + JRANDOM:$apr1$3p1.....$FQW6RceW5QhJ2blWDQgKn0 | ||
488 | + JCONSTANT:$apr1$jp1.....$Usrqji1c9H6AbOxOGAzzb0 | ||
489 | ---------------------------- | ||
490 | |||
491 | |||
492 | Index: subversion-1.8.11/subversion/tests/cmdline/davautocheck.sh | ||
493 | =================================================================== | ||
494 | --- subversion-1.8.11.orig/subversion/tests/cmdline/davautocheck.sh | ||
495 | +++ subversion-1.8.11/subversion/tests/cmdline/davautocheck.sh | ||
496 | @@ -289,8 +289,6 @@ LOAD_MOD_AUTHN_CORE="$(get_loadmodule_co | ||
497 | || fail "Authn_Core module not found." | ||
498 | LOAD_MOD_AUTHZ_CORE="$(get_loadmodule_config mod_authz_core)" \ | ||
499 | || fail "Authz_Core module not found." | ||
500 | -LOAD_MOD_AUTHZ_HOST="$(get_loadmodule_config mod_authz_host)" \ | ||
501 | - || fail "Authz_Host module not found." | ||
502 | LOAD_MOD_UNIXD=$(get_loadmodule_config mod_unixd) \ | ||
503 | || fail "UnixD module not found" | ||
504 | } | ||
505 | @@ -298,6 +296,10 @@ LOAD_MOD_AUTHN_FILE="$(get_loadmodule_co | ||
506 | || fail "Authn_File module not found." | ||
507 | LOAD_MOD_AUTHZ_USER="$(get_loadmodule_config mod_authz_user)" \ | ||
508 | || fail "Authz_User module not found." | ||
509 | +LOAD_MOD_AUTHZ_GROUPFILE="$(get_loadmodule_config mod_authz_groupfile)" \ | ||
510 | + || fail "Authz_GroupFile module not found." | ||
511 | +LOAD_MOD_AUTHZ_HOST="$(get_loadmodule_config mod_authz_host)" \ | ||
512 | + || fail "Authz_Host module not found." | ||
513 | } | ||
514 | if [ ${APACHE_MPM:+set} ]; then | ||
515 | LOAD_MOD_MPM=$(get_loadmodule_config mod_mpm_$APACHE_MPM) \ | ||
516 | @@ -328,6 +330,7 @@ HTTPD_ERROR_LOG="$HTTPD_ROOT/error_log" | ||
517 | HTTPD_MIME_TYPES="$HTTPD_ROOT/mime.types" | ||
518 | BASE_URL="http://localhost:$HTTPD_PORT" | ||
519 | HTTPD_USERS="$HTTPD_ROOT/users" | ||
520 | +HTTPD_GROUPS="$HTTPD_ROOT/groups" | ||
521 | |||
522 | mkdir "$HTTPD_ROOT" \ | ||
523 | || fail "couldn't create temporary directory '$HTTPD_ROOT'" | ||
524 | @@ -388,6 +391,14 @@ fi | ||
525 | say "Adding users for lock authentication" | ||
526 | $HTPASSWD -bc $HTTPD_USERS jrandom rayjandom | ||
527 | $HTPASSWD -b $HTTPD_USERS jconstant rayjandom | ||
528 | +$HTPASSWD -b $HTTPD_USERS JRANDOM rayjandom | ||
529 | +$HTPASSWD -b $HTTPD_USERS JCONSTANT rayjandom | ||
530 | + | ||
531 | +say "Adding groups for mod_authz_svn tests" | ||
532 | +cat > "$HTTPD_GROUPS" <<__EOF__ | ||
533 | +random: jrandom | ||
534 | +constant: jconstant | ||
535 | +__EOF__ | ||
536 | |||
537 | touch $HTTPD_MIME_TYPES | ||
538 | |||
539 | @@ -405,7 +416,9 @@ $LOAD_MOD_AUTHN_CORE | ||
540 | $LOAD_MOD_AUTHN_FILE | ||
541 | $LOAD_MOD_AUTHZ_CORE | ||
542 | $LOAD_MOD_AUTHZ_USER | ||
543 | +$LOAD_MOD_AUTHZ_GROUPFILE | ||
544 | $LOAD_MOD_AUTHZ_HOST | ||
545 | +$LOAD_MOD_ACCESS_COMPAT | ||
546 | LoadModule authz_svn_module "$MOD_AUTHZ_SVN" | ||
547 | |||
548 | __EOF__ | ||
549 | @@ -489,6 +502,161 @@ CustomLog "$HTTPD_ROOT/ops" "% | ||
550 | SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} | ||
551 | ${SVN_PATH_AUTHZ_LINE} | ||
552 | </Location> | ||
553 | +<Location /authz-test-work/anon> | ||
554 | + DAV svn | ||
555 | + SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" | ||
556 | + AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" | ||
557 | + SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} | ||
558 | + SVNCacheRevProps ${CACHE_REVPROPS_SETTING} | ||
559 | + SVNListParentPath On | ||
560 | + # This may seem unnecessary but granting access to everyone here is necessary | ||
561 | + # to exercise a bug with httpd 2.3.x+. The "Require all granted" syntax is | ||
562 | + # new to 2.3.x+ which we can detect with the mod_authz_core.c module | ||
563 | + # signature. Use the "Allow from all" syntax with older versions for symmetry. | ||
564 | + <IfModule mod_authz_core.c> | ||
565 | + Require all granted | ||
566 | + </IfModule> | ||
567 | + <IfModule !mod_authz_core.c> | ||
568 | + Allow from all | ||
569 | + </IfMOdule> | ||
570 | + ${SVN_PATH_AUTHZ_LINE} | ||
571 | +</Location> | ||
572 | +<Location /authz-test-work/mixed> | ||
573 | + DAV svn | ||
574 | + SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" | ||
575 | + AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" | ||
576 | + SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} | ||
577 | + SVNCacheRevProps ${CACHE_REVPROPS_SETTING} | ||
578 | + SVNListParentPath On | ||
579 | + AuthType Basic | ||
580 | + AuthName "Subversion Repository" | ||
581 | + AuthUserFile $HTTPD_USERS | ||
582 | + Require valid-user | ||
583 | + Satisfy Any | ||
584 | + ${SVN_PATH_AUTHZ_LINE} | ||
585 | +</Location> | ||
586 | +<Location /authz-test-work/mixed-noauthwhenanon> | ||
587 | + DAV svn | ||
588 | + SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" | ||
589 | + AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" | ||
590 | + SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} | ||
591 | + SVNCacheRevProps ${CACHE_REVPROPS_SETTING} | ||
592 | + SVNListParentPath On | ||
593 | + AuthType Basic | ||
594 | + AuthName "Subversion Repository" | ||
595 | + AuthUserFile $HTTPD_USERS | ||
596 | + Require valid-user | ||
597 | + AuthzSVNNoAuthWhenAnonymousAllowed On | ||
598 | + SVNPathAuthz On | ||
599 | +</Location> | ||
600 | +<Location /authz-test-work/authn> | ||
601 | + DAV svn | ||
602 | + SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" | ||
603 | + AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" | ||
604 | + SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} | ||
605 | + SVNCacheRevProps ${CACHE_REVPROPS_SETTING} | ||
606 | + SVNListParentPath On | ||
607 | + AuthType Basic | ||
608 | + AuthName "Subversion Repository" | ||
609 | + AuthUserFile $HTTPD_USERS | ||
610 | + Require valid-user | ||
611 | + ${SVN_PATH_AUTHZ_LINE} | ||
612 | +</Location> | ||
613 | +<Location /authz-test-work/authn-anonoff> | ||
614 | + DAV svn | ||
615 | + SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" | ||
616 | + AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" | ||
617 | + SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} | ||
618 | + SVNCacheRevProps ${CACHE_REVPROPS_SETTING} | ||
619 | + SVNListParentPath On | ||
620 | + AuthType Basic | ||
621 | + AuthName "Subversion Repository" | ||
622 | + AuthUserFile $HTTPD_USERS | ||
623 | + Require valid-user | ||
624 | + AuthzSVNAnonymous Off | ||
625 | + SVNPathAuthz On | ||
626 | +</Location> | ||
627 | +<Location /authz-test-work/authn-lcuser> | ||
628 | + DAV svn | ||
629 | + SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" | ||
630 | + AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" | ||
631 | + SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} | ||
632 | + SVNCacheRevProps ${CACHE_REVPROPS_SETTING} | ||
633 | + SVNListParentPath On | ||
634 | + AuthType Basic | ||
635 | + AuthName "Subversion Repository" | ||
636 | + AuthUserFile $HTTPD_USERS | ||
637 | + Require valid-user | ||
638 | + AuthzForceUsernameCase Lower | ||
639 | + ${SVN_PATH_AUTHZ_LINE} | ||
640 | +</Location> | ||
641 | +<Location /authz-test-work/authn-lcuser> | ||
642 | + DAV svn | ||
643 | + SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" | ||
644 | + AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" | ||
645 | + SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} | ||
646 | + SVNCacheRevProps ${CACHE_REVPROPS_SETTING} | ||
647 | + SVNListParentPath On | ||
648 | + AuthType Basic | ||
649 | + AuthName "Subversion Repository" | ||
650 | + AuthUserFile $HTTPD_USERS | ||
651 | + Require valid-user | ||
652 | + AuthzForceUsernameCase Lower | ||
653 | + ${SVN_PATH_AUTHZ_LINE} | ||
654 | +</Location> | ||
655 | +<Location /authz-test-work/authn-group> | ||
656 | + DAV svn | ||
657 | + SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" | ||
658 | + AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" | ||
659 | + SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} | ||
660 | + SVNCacheRevProps ${CACHE_REVPROPS_SETTING} | ||
661 | + SVNListParentPath On | ||
662 | + AuthType Basic | ||
663 | + AuthName "Subversion Repository" | ||
664 | + AuthUserFile $HTTPD_USERS | ||
665 | + AuthGroupFile $HTTPD_GROUPS | ||
666 | + Require group random | ||
667 | + AuthzSVNAuthoritative Off | ||
668 | + SVNPathAuthz On | ||
669 | +</Location> | ||
670 | +<IfModule mod_authz_core.c> | ||
671 | + <Location /authz-test-work/sallrany> | ||
672 | + DAV svn | ||
673 | + SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" | ||
674 | + AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" | ||
675 | + SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} | ||
676 | + SVNCacheRevProps ${CACHE_REVPROPS_SETTING} | ||
677 | + SVNListParentPath On | ||
678 | + AuthType Basic | ||
679 | + AuthName "Subversion Repository" | ||
680 | + AuthUserFile $HTTPD_USERS | ||
681 | + AuthzSendForbiddenOnFailure On | ||
682 | + Satisfy All | ||
683 | + <RequireAny> | ||
684 | + Require valid-user | ||
685 | + Require expr req('ALLOW') == '1' | ||
686 | + </RequireAny> | ||
687 | + ${SVN_PATH_AUTHZ_LINE} | ||
688 | + </Location> | ||
689 | + <Location /authz-test-work/sallrall> | ||
690 | + DAV svn | ||
691 | + SVNParentPath "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/local_tmp" | ||
692 | + AuthzSVNAccessFile "$ABS_BUILDDIR/subversion/tests/cmdline/svn-test-work/authz" | ||
693 | + SVNAdvertiseV2Protocol ${ADVERTISE_V2_PROTOCOL} | ||
694 | + SVNCacheRevProps ${CACHE_REVPROPS_SETTING} | ||
695 | + SVNListParentPath On | ||
696 | + AuthType Basic | ||
697 | + AuthName "Subversion Repository" | ||
698 | + AuthUserFile $HTTPD_USERS | ||
699 | + AuthzSendForbiddenOnFailure On | ||
700 | + Satisfy All | ||
701 | + <RequireAll> | ||
702 | + Require valid-user | ||
703 | + Require expr req('ALLOW') == '1' | ||
704 | + </RequireAll> | ||
705 | + ${SVN_PATH_AUTHZ_LINE} | ||
706 | + </Location> | ||
707 | +</IfModule> | ||
708 | RedirectMatch permanent ^/svn-test-work/repositories/REDIRECT-PERM-(.*)\$ /svn-test-work/repositories/\$1 | ||
709 | RedirectMatch ^/svn-test-work/repositories/REDIRECT-TEMP-(.*)\$ /svn-test-work/repositories/\$1 | ||
710 | __EOF__ | ||
711 | Index: subversion-1.8.11/subversion/tests/cmdline/mod_authz_svn_tests.py | ||
712 | =================================================================== | ||
713 | --- /dev/null | ||
714 | +++ subversion-1.8.11/subversion/tests/cmdline/mod_authz_svn_tests.py | ||
715 | @@ -0,0 +1,1073 @@ | ||
716 | +#!/usr/bin/env python | ||
717 | +# | ||
718 | +# mod_authz_svn_tests.py: testing mod_authz_svn | ||
719 | +# | ||
720 | +# Subversion is a tool for revision control. | ||
721 | +# See http://subversion.apache.org for more information. | ||
722 | +# | ||
723 | +# ==================================================================== | ||
724 | +# Licensed to the Apache Software Foundation (ASF) under one | ||
725 | +# or more contributor license agreements. See the NOTICE file | ||
726 | +# distributed with this work for additional information | ||
727 | +# regarding copyright ownership. The ASF licenses this file | ||
728 | +# to you under the Apache License, Version 2.0 (the | ||
729 | +# "License"); you may not use this file except in compliance | ||
730 | +# with the License. You may obtain a copy of the License at | ||
731 | +# | ||
732 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
733 | +# | ||
734 | +# Unless required by applicable law or agreed to in writing, | ||
735 | +# software distributed under the License is distributed on an | ||
736 | +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
737 | +# KIND, either express or implied. See the License for the | ||
738 | +# specific language governing permissions and limitations | ||
739 | +# under the License. | ||
740 | +###################################################################### | ||
741 | + | ||
742 | +# General modules | ||
743 | +import os, re, logging | ||
744 | + | ||
745 | +logger = logging.getLogger() | ||
746 | + | ||
747 | +# Our testing module | ||
748 | +import svntest | ||
749 | + | ||
750 | +# (abbreviation) | ||
751 | +Skip = svntest.testcase.Skip_deco | ||
752 | +SkipUnless = svntest.testcase.SkipUnless_deco | ||
753 | +XFail = svntest.testcase.XFail_deco | ||
754 | +Issues = svntest.testcase.Issues_deco | ||
755 | +Issue = svntest.testcase.Issue_deco | ||
756 | +Wimp = svntest.testcase.Wimp_deco | ||
757 | + | ||
758 | +ls_of_D_no_H = '''<html><head><title>repos - Revision 1: /A/D</title></head> | ||
759 | +<body> | ||
760 | + <h2>repos - Revision 1: /A/D</h2> | ||
761 | + <ul> | ||
762 | + <li><a href="../">..</a></li> | ||
763 | + <li><a href="G/">G/</a></li> | ||
764 | + <li><a href="gamma">gamma</a></li> | ||
765 | + </ul> | ||
766 | +</body></html>''' | ||
767 | + | ||
768 | +ls_of_D_H = '''<html><head><title>repos - Revision 1: /A/D</title></head> | ||
769 | +<body> | ||
770 | + <h2>repos - Revision 1: /A/D</h2> | ||
771 | + <ul> | ||
772 | + <li><a href="../">..</a></li> | ||
773 | + <li><a href="G/">G/</a></li> | ||
774 | + <li><a href="H/">H/</a></li> | ||
775 | + <li><a href="gamma">gamma</a></li> | ||
776 | + </ul> | ||
777 | +</body></html>''' | ||
778 | + | ||
779 | +ls_of_H = '''<html><head><title>repos - Revision 1: /A/D/H</title></head> | ||
780 | +<body> | ||
781 | + <h2>repos - Revision 1: /A/D/H</h2> | ||
782 | + <ul> | ||
783 | + <li><a href="../">..</a></li> | ||
784 | + <li><a href="chi">chi</a></li> | ||
785 | + <li><a href="omega">omega</a></li> | ||
786 | + <li><a href="psi">psi</a></li> | ||
787 | + </ul> | ||
788 | +</body></html>''' | ||
789 | + | ||
790 | +user1 = svntest.main.wc_author | ||
791 | +user1_upper = user1.upper() | ||
792 | +user1_pass = svntest.main.wc_passwd | ||
793 | +user1_badpass = 'XXX' | ||
794 | +assert user1_pass != user1_badpass, "Passwords can't match" | ||
795 | +user2 = svntest.main.wc_author2 | ||
796 | +user2_upper = user2.upper() | ||
797 | +user2_pass = svntest.main.wc_passwd | ||
798 | +user2_badpass = 'XXX' | ||
799 | +assert user2_pass != user2_badpass, "Passwords can't match" | ||
800 | + | ||
801 | +def write_authz_file(sbox): | ||
802 | + svntest.main.write_authz_file(sbox, { | ||
803 | + '/': '$anonymous = r\n' + | ||
804 | + 'jrandom = rw\n' + | ||
805 | + 'jconstant = rw', | ||
806 | + '/A/D/H': '$anonymous =\n' + | ||
807 | + '$authenticated =\n' + | ||
808 | + 'jrandom = rw' | ||
809 | + }) | ||
810 | + | ||
811 | +def write_authz_file_groups(sbox): | ||
812 | + authz_name = sbox.authz_name() | ||
813 | + svntest.main.write_authz_file(sbox,{ | ||
814 | + '/': '* =', | ||
815 | + }) | ||
816 | + | ||
817 | +def verify_get(test_area_url, path, user, pw, | ||
818 | + expected_status, expected_body, headers): | ||
819 | + import httplib | ||
820 | + from urlparse import urlparse | ||
821 | + import base64 | ||
822 | + | ||
823 | + req_url = test_area_url + path | ||
824 | + | ||
825 | + loc = urlparse(req_url) | ||
826 | + | ||
827 | + if loc.scheme == 'http': | ||
828 | + h = httplib.HTTPConnection(loc.hostname, loc.port) | ||
829 | + else: | ||
830 | + h = httplib.HTTPSConnection(loc.hostname, loc.port) | ||
831 | + | ||
832 | + if headers is None: | ||
833 | + headers = {} | ||
834 | + | ||
835 | + if user and pw: | ||
836 | + auth_info = user + ':' + pw | ||
837 | + headers['Authorization'] = 'Basic ' + base64.b64encode(auth_info) | ||
838 | + else: | ||
839 | + auth_info = "anonymous" | ||
840 | + | ||
841 | + h.request('GET', req_url, None, headers) | ||
842 | + | ||
843 | + r = h.getresponse() | ||
844 | + | ||
845 | + actual_status = r.status | ||
846 | + if expected_status and expected_status != actual_status: | ||
847 | + | ||
848 | + logger.warn("Expected status '" + str(expected_status) + | ||
849 | + "' but got '" + str(actual_status) + | ||
850 | + "' on url '" + req_url + "' (" + | ||
851 | + auth_info + ").") | ||
852 | + raise svntest.Failure | ||
853 | + | ||
854 | + if expected_body: | ||
855 | + actual_body = r.read() | ||
856 | + if expected_body != actual_body: | ||
857 | + logger.warn("Expected body:") | ||
858 | + logger.warn(expected_body) | ||
859 | + logger.warn("But got:") | ||
860 | + logger.warn(actual_body) | ||
861 | + logger.warn("on url '" + req_url + "' (" + auth_info + ").") | ||
862 | + raise svntest.Failure | ||
863 | + | ||
864 | +def verify_gets(test_area_url, tests): | ||
865 | + for test in tests: | ||
866 | + verify_get(test_area_url, test['path'], test.get('user'), test.get('pw'), | ||
867 | + test['status'], test.get('body'), test.get('headers')) | ||
868 | + | ||
869 | + | ||
870 | +###################################################################### | ||
871 | +# Tests | ||
872 | +# | ||
873 | +# Each test must return on success or raise on failure. | ||
874 | + | ||
875 | + | ||
876 | +#---------------------------------------------------------------------- | ||
877 | + | ||
878 | + | ||
879 | +@SkipUnless(svntest.main.is_ra_type_dav) | ||
880 | +def anon(sbox): | ||
881 | + "test anonymous access" | ||
882 | + sbox.build(read_only = True, create_wc = False) | ||
883 | + | ||
884 | + test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', | ||
885 | + '/authz-test-work/anon') | ||
886 | + | ||
887 | + write_authz_file(sbox) | ||
888 | + | ||
889 | + anon_tests = ( | ||
890 | + { 'path': '', 'status': 301 }, | ||
891 | + { 'path': '/', 'status': 200 }, | ||
892 | + { 'path': '/repos', 'status': 301 }, | ||
893 | + { 'path': '/repos/', 'status': 200 }, | ||
894 | + { 'path': '/repos/A', 'status': 301 }, | ||
895 | + { 'path': '/repos/A/', 'status': 200 }, | ||
896 | + { 'path': '/repos/A/D', 'status': 301 }, | ||
897 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H }, | ||
898 | + { 'path': '/repos/A/D/gamma', 'status': 200 }, | ||
899 | + { 'path': '/repos/A/D/H', 'status': 403 }, | ||
900 | + { 'path': '/repos/A/D/H/', 'status': 403 }, | ||
901 | + { 'path': '/repos/A/D/H/chi', 'status': 403 }, | ||
902 | + # auth isn't configured so nothing should change when passing | ||
903 | + # authn details | ||
904 | + { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
905 | + { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
906 | + { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
907 | + { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
908 | + { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
909 | + { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
910 | + { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
911 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
912 | + 'user': user1, 'pw': user1_pass}, | ||
913 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
914 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
915 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
916 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
917 | + { 'path': '', 'status': 301, 'user': user1, 'pw': user1_badpass}, | ||
918 | + { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_badpass}, | ||
919 | + { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_badpass}, | ||
920 | + { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_badpass}, | ||
921 | + { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_badpass}, | ||
922 | + { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_badpass}, | ||
923 | + { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_badpass}, | ||
924 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
925 | + 'user': user1, 'pw': user1_badpass}, | ||
926 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_badpass}, | ||
927 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
928 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
929 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
930 | + { 'path': '', 'status': 301, 'user': user2, 'pw': user1_pass}, | ||
931 | + { 'path': '/', 'status': 200, 'user': user2, 'pw': user1_pass}, | ||
932 | + { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user1_pass}, | ||
933 | + { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user1_pass}, | ||
934 | + { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user1_pass}, | ||
935 | + { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user1_pass}, | ||
936 | + { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user1_pass}, | ||
937 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
938 | + 'user': user2, 'pw': user1_pass}, | ||
939 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
940 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
941 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
942 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
943 | + { 'path': '', 'status': 301, 'user': user2, 'pw': user2_badpass}, | ||
944 | + { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_badpass}, | ||
945 | + { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_badpass}, | ||
946 | + { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_badpass}, | ||
947 | + { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_badpass}, | ||
948 | + { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_badpass}, | ||
949 | + { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_badpass}, | ||
950 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
951 | + 'user': user2, 'pw': user2_badpass}, | ||
952 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_badpass}, | ||
953 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
954 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
955 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
956 | + ) | ||
957 | + | ||
958 | + verify_gets(test_area_url, anon_tests) | ||
959 | + | ||
960 | + | ||
961 | +@SkipUnless(svntest.main.is_ra_type_dav) | ||
962 | +def mixed(sbox): | ||
963 | + "test mixed anonymous and authenticated access" | ||
964 | + sbox.build(read_only = True, create_wc = False) | ||
965 | + | ||
966 | + test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', | ||
967 | + '/authz-test-work/mixed') | ||
968 | + | ||
969 | + write_authz_file(sbox) | ||
970 | + | ||
971 | + mixed_tests = ( | ||
972 | + { 'path': '', 'status': 301, }, | ||
973 | + { 'path': '/', 'status': 200, }, | ||
974 | + { 'path': '/repos', 'status': 301, }, | ||
975 | + { 'path': '/repos/', 'status': 200, }, | ||
976 | + { 'path': '/repos/A', 'status': 301, }, | ||
977 | + { 'path': '/repos/A/', 'status': 200, }, | ||
978 | + { 'path': '/repos/A/D', 'status': 301, }, | ||
979 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
980 | + }, | ||
981 | + { 'path': '/repos/A/D/gamma', 'status': 200, }, | ||
982 | + { 'path': '/repos/A/D/H', 'status': 401, }, | ||
983 | + { 'path': '/repos/A/D/H/', 'status': 401, }, | ||
984 | + { 'path': '/repos/A/D/H/chi', 'status': 401, }, | ||
985 | + # auth is configured and user1 is allowed access to H | ||
986 | + { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
987 | + { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
988 | + { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
989 | + { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
990 | + { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
991 | + { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
992 | + { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
993 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, | ||
994 | + 'user': user1, 'pw': user1_pass}, | ||
995 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
996 | + { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
997 | + { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, | ||
998 | + { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
999 | + # try with the wrong password for user1 | ||
1000 | + { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1001 | + { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1002 | + { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1003 | + { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1004 | + { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1005 | + { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1006 | + { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1007 | + { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1008 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1009 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1010 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1011 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1012 | + # auth is configured and user2 is not allowed access to H | ||
1013 | + { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1014 | + { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1015 | + { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1016 | + { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1017 | + { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1018 | + { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1019 | + { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1020 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
1021 | + 'user': user2, 'pw': user2_pass}, | ||
1022 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1023 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1024 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1025 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1026 | + # try with the wrong password for user2 | ||
1027 | + { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1028 | + { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1029 | + { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1030 | + { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1031 | + { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1032 | + { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1033 | + { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1034 | + { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1035 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1036 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1037 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1038 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1039 | + ) | ||
1040 | + | ||
1041 | + verify_gets(test_area_url, mixed_tests) | ||
1042 | + | ||
1043 | +@SkipUnless(svntest.main.is_ra_type_dav) | ||
1044 | +@XFail(svntest.main.is_httpd_authz_provider_enabled) | ||
1045 | +# uses the AuthzSVNNoAuthWhenAnonymousAllowed On directive | ||
1046 | +# this is broken with httpd 2.3.x+ since it requires the auth system to accept | ||
1047 | +# r->user == NULL and there is a test for this in server/request.c now. It | ||
1048 | +# was intended as a workaround for the lack of Satisfy Any in 2.3.x+ which | ||
1049 | +# was resolved by httpd with mod_access_compat in 2.3.x+. | ||
1050 | +def mixed_noauthwhenanon(sbox): | ||
1051 | + "test mixed with noauthwhenanon directive" | ||
1052 | + sbox.build(read_only = True, create_wc = False) | ||
1053 | + | ||
1054 | + test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', | ||
1055 | + '/authz-test-work/mixed-noauthwhenanon') | ||
1056 | + | ||
1057 | + write_authz_file(sbox) | ||
1058 | + | ||
1059 | + noauthwhenanon_tests = ( | ||
1060 | + { 'path': '', 'status': 301, }, | ||
1061 | + { 'path': '/', 'status': 200, }, | ||
1062 | + { 'path': '/repos', 'status': 301, }, | ||
1063 | + { 'path': '/repos/', 'status': 200, }, | ||
1064 | + { 'path': '/repos/A', 'status': 301, }, | ||
1065 | + { 'path': '/repos/A/', 'status': 200, }, | ||
1066 | + { 'path': '/repos/A/D', 'status': 301, }, | ||
1067 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
1068 | + }, | ||
1069 | + { 'path': '/repos/A/D/gamma', 'status': 200, }, | ||
1070 | + { 'path': '/repos/A/D/H', 'status': 401, }, | ||
1071 | + { 'path': '/repos/A/D/H/', 'status': 401, }, | ||
1072 | + { 'path': '/repos/A/D/H/chi', 'status': 401, }, | ||
1073 | + # auth is configured and user1 is allowed access to H | ||
1074 | + { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1075 | + { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1076 | + { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1077 | + { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1078 | + { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1079 | + { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1080 | + { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1081 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, | ||
1082 | + 'user': user1, 'pw': user1_pass}, | ||
1083 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1084 | + { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1085 | + { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, | ||
1086 | + { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1087 | + # try with the wrong password for user1 | ||
1088 | + # note that unlike doing this with Satisfy Any this case | ||
1089 | + # actually provides anon access when provided with an invalid | ||
1090 | + # password | ||
1091 | + { 'path': '', 'status': 301, 'user': user1, 'pw': user1_badpass}, | ||
1092 | + { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_badpass}, | ||
1093 | + { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_badpass}, | ||
1094 | + { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_badpass}, | ||
1095 | + { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_badpass}, | ||
1096 | + { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_badpass}, | ||
1097 | + { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_badpass}, | ||
1098 | + { 'path': '/repos/A/D/', 'status': 200, 'user': user1, 'pw': user1_badpass}, | ||
1099 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_badpass}, | ||
1100 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1101 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1102 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1103 | + # auth is configured and user2 is not allowed access to H | ||
1104 | + { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1105 | + { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1106 | + { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1107 | + { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1108 | + { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1109 | + { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1110 | + { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1111 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
1112 | + 'user': user2, 'pw': user2_pass}, | ||
1113 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1114 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1115 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1116 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1117 | + # try with the wrong password for user2 | ||
1118 | + { 'path': '', 'status': 301, 'user': user2, 'pw': user2_badpass}, | ||
1119 | + { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_badpass}, | ||
1120 | + { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_badpass}, | ||
1121 | + { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_badpass}, | ||
1122 | + { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_badpass}, | ||
1123 | + { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_badpass}, | ||
1124 | + { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_badpass}, | ||
1125 | + { 'path': '/repos/A/D/', 'status': 200, 'user': user2, 'pw': user2_badpass}, | ||
1126 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_badpass}, | ||
1127 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1128 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1129 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1130 | + ) | ||
1131 | + | ||
1132 | + verify_gets(test_area_url, noauthwhenanon_tests) | ||
1133 | + | ||
1134 | + | ||
1135 | +@SkipUnless(svntest.main.is_ra_type_dav) | ||
1136 | +def authn(sbox): | ||
1137 | + "test authenticated only access" | ||
1138 | + sbox.build(read_only = True, create_wc = False) | ||
1139 | + | ||
1140 | + test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', | ||
1141 | + '/authz-test-work/authn') | ||
1142 | + | ||
1143 | + write_authz_file(sbox) | ||
1144 | + | ||
1145 | + authn_tests = ( | ||
1146 | + { 'path': '', 'status': 401, }, | ||
1147 | + { 'path': '/', 'status': 401, }, | ||
1148 | + { 'path': '/repos', 'status': 401, }, | ||
1149 | + { 'path': '/repos/', 'status': 401, }, | ||
1150 | + { 'path': '/repos/A', 'status': 401, }, | ||
1151 | + { 'path': '/repos/A/', 'status': 401, }, | ||
1152 | + { 'path': '/repos/A/D', 'status': 401, }, | ||
1153 | + { 'path': '/repos/A/D/', 'status': 401, }, | ||
1154 | + { 'path': '/repos/A/D/gamma', 'status': 401, }, | ||
1155 | + { 'path': '/repos/A/D/H', 'status': 401, }, | ||
1156 | + { 'path': '/repos/A/D/H/', 'status': 401, }, | ||
1157 | + { 'path': '/repos/A/D/H/chi', 'status': 401, }, | ||
1158 | + # auth is configured and user1 is allowed access to H | ||
1159 | + { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1160 | + { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1161 | + { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1162 | + { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1163 | + { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1164 | + { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1165 | + { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1166 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, | ||
1167 | + 'user': user1, 'pw': user1_pass}, | ||
1168 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1169 | + { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1170 | + { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, | ||
1171 | + { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1172 | + # try with upper case username for user1 | ||
1173 | + { 'path': '', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, | ||
1174 | + { 'path': '/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, | ||
1175 | + { 'path': '/repos', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1176 | + { 'path': '/repos/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1177 | + { 'path': '/repos/A', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1178 | + { 'path': '/repos/A/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1179 | + { 'path': '/repos/A/D', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1180 | + { 'path': '/repos/A/D/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1181 | + { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1182 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1183 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1184 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1185 | + # try with the wrong password for user1 | ||
1186 | + { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1187 | + { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1188 | + { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1189 | + { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1190 | + { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1191 | + { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1192 | + { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1193 | + { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1194 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1195 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1196 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1197 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1198 | + # auth is configured and user2 is not allowed access to H | ||
1199 | + { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1200 | + { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1201 | + { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1202 | + { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1203 | + { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1204 | + { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1205 | + { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1206 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
1207 | + 'user': user2, 'pw': user2_pass}, | ||
1208 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1209 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1210 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1211 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1212 | + # try with upper case username for user2 | ||
1213 | + { 'path': '', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, | ||
1214 | + { 'path': '/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, | ||
1215 | + { 'path': '/repos', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1216 | + { 'path': '/repos/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1217 | + { 'path': '/repos/A', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1218 | + { 'path': '/repos/A/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1219 | + { 'path': '/repos/A/D', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1220 | + { 'path': '/repos/A/D/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1221 | + { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1222 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1223 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1224 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1225 | + # try with the wrong password for user2 | ||
1226 | + { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1227 | + { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1228 | + { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1229 | + { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1230 | + { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1231 | + { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1232 | + { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1233 | + { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1234 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1235 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1236 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1237 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1238 | + ) | ||
1239 | + | ||
1240 | + verify_gets(test_area_url, authn_tests) | ||
1241 | + | ||
1242 | +@SkipUnless(svntest.main.is_ra_type_dav) | ||
1243 | +def authn_anonoff(sbox): | ||
1244 | + "test authenticated only access with anonoff" | ||
1245 | + sbox.build(read_only = True, create_wc = False) | ||
1246 | + | ||
1247 | + test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', | ||
1248 | + '/authz-test-work/authn-anonoff') | ||
1249 | + | ||
1250 | + write_authz_file(sbox) | ||
1251 | + | ||
1252 | + anonoff_tests = ( | ||
1253 | + { 'path': '', 'status': 401, }, | ||
1254 | + { 'path': '/', 'status': 401, }, | ||
1255 | + { 'path': '/repos', 'status': 401, }, | ||
1256 | + { 'path': '/repos/', 'status': 401, }, | ||
1257 | + { 'path': '/repos/A', 'status': 401, }, | ||
1258 | + { 'path': '/repos/A/', 'status': 401, }, | ||
1259 | + { 'path': '/repos/A/D', 'status': 401, }, | ||
1260 | + { 'path': '/repos/A/D/', 'status': 401, }, | ||
1261 | + { 'path': '/repos/A/D/gamma', 'status': 401, }, | ||
1262 | + { 'path': '/repos/A/D/H', 'status': 401, }, | ||
1263 | + { 'path': '/repos/A/D/H/', 'status': 401, }, | ||
1264 | + { 'path': '/repos/A/D/H/chi', 'status': 401, }, | ||
1265 | + # auth is configured and user1 is allowed access to H | ||
1266 | + { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1267 | + { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1268 | + { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1269 | + { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1270 | + { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1271 | + { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1272 | + { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1273 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, | ||
1274 | + 'user': user1, 'pw': user1_pass}, | ||
1275 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1276 | + { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1277 | + { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, | ||
1278 | + { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1279 | + # try with upper case username for user1 | ||
1280 | + { 'path': '', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, | ||
1281 | + { 'path': '/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, | ||
1282 | + { 'path': '/repos', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1283 | + { 'path': '/repos/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1284 | + { 'path': '/repos/A', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1285 | + { 'path': '/repos/A/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1286 | + { 'path': '/repos/A/D', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1287 | + { 'path': '/repos/A/D/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1288 | + { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1289 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1290 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1291 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1_upper, 'pw': user1_pass}, | ||
1292 | + # try with the wrong password for user1 | ||
1293 | + { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1294 | + { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1295 | + { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1296 | + { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1297 | + { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1298 | + { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1299 | + { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1300 | + { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1301 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1302 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1303 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1304 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1305 | + # auth is configured and user2 is not allowed access to H | ||
1306 | + { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1307 | + { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1308 | + { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1309 | + { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1310 | + { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1311 | + { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1312 | + { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1313 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
1314 | + 'user': user2, 'pw': user2_pass}, | ||
1315 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1316 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1317 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1318 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1319 | + # try with upper case username for user2 | ||
1320 | + { 'path': '', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, | ||
1321 | + { 'path': '/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, | ||
1322 | + { 'path': '/repos', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1323 | + { 'path': '/repos/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1324 | + { 'path': '/repos/A', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1325 | + { 'path': '/repos/A/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1326 | + { 'path': '/repos/A/D', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1327 | + { 'path': '/repos/A/D/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1328 | + { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1329 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1330 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1331 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1332 | + # try with the wrong password for user2 | ||
1333 | + { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1334 | + { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1335 | + { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1336 | + { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1337 | + { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1338 | + { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1339 | + { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1340 | + { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1341 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1342 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1343 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1344 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1345 | + ) | ||
1346 | + | ||
1347 | + verify_gets(test_area_url, anonoff_tests) | ||
1348 | + | ||
1349 | +@SkipUnless(svntest.main.is_ra_type_dav) | ||
1350 | +def authn_lcuser(sbox): | ||
1351 | + "test authenticated only access with lcuser" | ||
1352 | + sbox.build(read_only = True, create_wc = False) | ||
1353 | + | ||
1354 | + test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', | ||
1355 | + '/authz-test-work/authn-lcuser') | ||
1356 | + | ||
1357 | + write_authz_file(sbox) | ||
1358 | + | ||
1359 | + lcuser_tests = ( | ||
1360 | + # try with upper case username for user1 (works due to lcuser option) | ||
1361 | + { 'path': '', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, | ||
1362 | + { 'path': '/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, | ||
1363 | + { 'path': '/repos', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, | ||
1364 | + { 'path': '/repos/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, | ||
1365 | + { 'path': '/repos/A', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, | ||
1366 | + { 'path': '/repos/A/', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, | ||
1367 | + { 'path': '/repos/A/D', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, | ||
1368 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, | ||
1369 | + 'user': user1_upper, 'pw': user1_pass}, | ||
1370 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, | ||
1371 | + { 'path': '/repos/A/D/H', 'status': 301, 'user': user1_upper, 'pw': user1_pass}, | ||
1372 | + { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1_upper, 'pw': user1_pass}, | ||
1373 | + { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1_upper, 'pw': user1_pass}, | ||
1374 | + # try with upper case username for user2 (works due to lcuser option) | ||
1375 | + { 'path': '', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, | ||
1376 | + { 'path': '/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, | ||
1377 | + { 'path': '/repos', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, | ||
1378 | + { 'path': '/repos/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, | ||
1379 | + { 'path': '/repos/A', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, | ||
1380 | + { 'path': '/repos/A/', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, | ||
1381 | + { 'path': '/repos/A/D', 'status': 301, 'user': user2_upper, 'pw': user2_pass}, | ||
1382 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
1383 | + 'user': user2_upper, 'pw': user2_pass}, | ||
1384 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2_upper, 'pw': user2_pass}, | ||
1385 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1386 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1387 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2_upper, 'pw': user2_pass}, | ||
1388 | + ) | ||
1389 | + | ||
1390 | + verify_gets(test_area_url, lcuser_tests) | ||
1391 | + | ||
1392 | +# authenticated access only by group - a excuse to use AuthzSVNAuthoritative Off | ||
1393 | +# this is terribly messed up, Require group runs after mod_authz_svn. | ||
1394 | +# so if mod_authz_svn grants the access then it doesn't matter what the group | ||
1395 | +# requirement says. If we reject the access then you can use the AuthzSVNAuthoritative Off | ||
1396 | +# directive to fall through to the group check. Overall the behavior of setups like this | ||
1397 | +# is almost guaranteed to not be what users expect. | ||
1398 | +@SkipUnless(svntest.main.is_ra_type_dav) | ||
1399 | +def authn_group(sbox): | ||
1400 | + "test authenticated only access via groups" | ||
1401 | + sbox.build(read_only = True, create_wc = False) | ||
1402 | + | ||
1403 | + test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', | ||
1404 | + '/authz-test-work/authn-group') | ||
1405 | + | ||
1406 | + # Can't use write_authz_file() as most tests because we want to deny all | ||
1407 | + # access with mod_authz_svn so the tests fall through to the group handling | ||
1408 | + authz_name = sbox.authz_name() | ||
1409 | + svntest.main.write_authz_file(sbox, { | ||
1410 | + '/': '* =', | ||
1411 | + }) | ||
1412 | + | ||
1413 | + group_tests = ( | ||
1414 | + { 'path': '', 'status': 401, }, | ||
1415 | + { 'path': '/', 'status': 401, }, | ||
1416 | + { 'path': '/repos', 'status': 401, }, | ||
1417 | + { 'path': '/repos/', 'status': 401, }, | ||
1418 | + { 'path': '/repos/A', 'status': 401, }, | ||
1419 | + { 'path': '/repos/A/', 'status': 401, }, | ||
1420 | + { 'path': '/repos/A/D', 'status': 401, }, | ||
1421 | + { 'path': '/repos/A/D/', 'status': 401, }, | ||
1422 | + { 'path': '/repos/A/D/gamma', 'status': 401, }, | ||
1423 | + { 'path': '/repos/A/D/H', 'status': 401, }, | ||
1424 | + { 'path': '/repos/A/D/H/', 'status': 401, }, | ||
1425 | + { 'path': '/repos/A/D/H/chi', 'status': 401, }, | ||
1426 | + # auth is configured and user1 is allowed access repo including H | ||
1427 | + { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1428 | + { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1429 | + { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1430 | + { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1431 | + { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1432 | + { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1433 | + { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1434 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, | ||
1435 | + 'user': user1, 'pw': user1_pass}, | ||
1436 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1437 | + { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1438 | + { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, | ||
1439 | + { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1440 | + ) | ||
1441 | + | ||
1442 | + verify_gets(test_area_url, group_tests) | ||
1443 | + | ||
1444 | +# This test exists to validate our behavior when used with the new authz | ||
1445 | +# provider system introduced in httpd 2.3.x. The Satisfy directive | ||
1446 | +# determines how older authz hooks are combined and the RequireA(ll|ny) | ||
1447 | +# blocks handles how new authz providers are combined. The overall results of | ||
1448 | +# all the authz providers (combined per the Require* blocks) are then | ||
1449 | +# combined with the other authz hooks via the Satisfy directive. | ||
1450 | +# Meaning this test requires that mod_authz_svn says yes and there is | ||
1451 | +# either a valid user or the ALLOW header is 1. The header may seem | ||
1452 | +# like a silly test but it's easier to excercise than say a host directive | ||
1453 | +# in a repeatable test. | ||
1454 | +@SkipUnless(svntest.main.is_httpd_authz_provider_enabled) | ||
1455 | +def authn_sallrany(sbox): | ||
1456 | + "test satisfy all require any config" | ||
1457 | + sbox.build(read_only = True, create_wc = False) | ||
1458 | + | ||
1459 | + test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', | ||
1460 | + '/authz-test-work/sallrany') | ||
1461 | + | ||
1462 | + write_authz_file(sbox) | ||
1463 | + | ||
1464 | + allow_header = { 'ALLOW': '1' } | ||
1465 | + | ||
1466 | + sallrany_tests = ( | ||
1467 | + #anon access isn't allowed without ALLOW header | ||
1468 | + { 'path': '', 'status': 401, }, | ||
1469 | + { 'path': '/', 'status': 401, }, | ||
1470 | + { 'path': '/repos', 'status': 401, }, | ||
1471 | + { 'path': '/repos/', 'status': 401, }, | ||
1472 | + { 'path': '/repos/A', 'status': 401, }, | ||
1473 | + { 'path': '/repos/A/', 'status': 401, }, | ||
1474 | + { 'path': '/repos/A/D', 'status': 401, }, | ||
1475 | + { 'path': '/repos/A/D/', 'status': 401, }, | ||
1476 | + { 'path': '/repos/A/D/gamma', 'status': 401, }, | ||
1477 | + { 'path': '/repos/A/D/H', 'status': 401, }, | ||
1478 | + { 'path': '/repos/A/D/H/', 'status': 401, }, | ||
1479 | + { 'path': '/repos/A/D/H/chi', 'status': 401, }, | ||
1480 | + # auth is configured and user1 is allowed access repo including H | ||
1481 | + { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1482 | + { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1483 | + { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1484 | + { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1485 | + { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1486 | + { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1487 | + { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1488 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, | ||
1489 | + 'user': user1, 'pw': user1_pass}, | ||
1490 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1491 | + { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass}, | ||
1492 | + { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass}, | ||
1493 | + { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass}, | ||
1494 | + # try with the wrong password for user1 | ||
1495 | + { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1496 | + { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1497 | + { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1498 | + { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1499 | + { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1500 | + { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1501 | + { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1502 | + { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1503 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1504 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1505 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1506 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass}, | ||
1507 | + # auth is configured and user2 is not allowed access to H | ||
1508 | + { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1509 | + { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1510 | + { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1511 | + { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1512 | + { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1513 | + { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1514 | + { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass}, | ||
1515 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
1516 | + 'user': user2, 'pw': user2_pass}, | ||
1517 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass}, | ||
1518 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1519 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1520 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1521 | + # try with the wrong password for user2 | ||
1522 | + { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1523 | + { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1524 | + { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1525 | + { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1526 | + { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1527 | + { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1528 | + { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1529 | + { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1530 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1531 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1532 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1533 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass}, | ||
1534 | + # anon is allowed with the ALLOW header | ||
1535 | + { 'path': '', 'status': 301, 'headers': allow_header }, | ||
1536 | + { 'path': '/', 'status': 200, 'headers': allow_header }, | ||
1537 | + { 'path': '/repos', 'status': 301, 'headers': allow_header }, | ||
1538 | + { 'path': '/repos/', 'status': 200, 'headers': allow_header }, | ||
1539 | + { 'path': '/repos/A', 'status': 301, 'headers': allow_header }, | ||
1540 | + { 'path': '/repos/A/', 'status': 200, 'headers': allow_header }, | ||
1541 | + { 'path': '/repos/A/D', 'status': 301, 'headers': allow_header }, | ||
1542 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, 'headers': allow_header }, | ||
1543 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'headers': allow_header }, | ||
1544 | + # these 3 tests return 403 instead of 401 becasue the config allows | ||
1545 | + # the anon user with the ALLOW header without any auth and the old hook | ||
1546 | + # system has no way of knowing it should return 401 since authentication is | ||
1547 | + # configured and can change the behavior. It could decide to return 401 just on | ||
1548 | + # the basis of authentication being configured but then that leaks info in other | ||
1549 | + # cases so it's better for this case to be "broken". | ||
1550 | + { 'path': '/repos/A/D/H', 'status': 403, 'headers': allow_header }, | ||
1551 | + { 'path': '/repos/A/D/H/', 'status': 403, 'headers': allow_header }, | ||
1552 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'headers': allow_header }, | ||
1553 | + # auth is configured and user1 is allowed access repo including H | ||
1554 | + { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1555 | + { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1556 | + { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1557 | + { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1558 | + { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1559 | + { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1560 | + { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1561 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, | ||
1562 | + 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1563 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1564 | + { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1565 | + { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1566 | + { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1567 | + # try with the wrong password for user1 | ||
1568 | + { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1569 | + { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1570 | + { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1571 | + { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1572 | + { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1573 | + { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1574 | + { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1575 | + { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1576 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1577 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1578 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1579 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1580 | + # auth is configured and user2 is not allowed access to H | ||
1581 | + { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1582 | + { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1583 | + { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1584 | + { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1585 | + { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1586 | + { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1587 | + { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1588 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
1589 | + 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1590 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1591 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1592 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1593 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1594 | + # try with the wrong password for user2 | ||
1595 | + { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1596 | + { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1597 | + { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1598 | + { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1599 | + { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1600 | + { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1601 | + { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1602 | + { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1603 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1604 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1605 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1606 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1607 | + | ||
1608 | + ) | ||
1609 | + | ||
1610 | + verify_gets(test_area_url, sallrany_tests) | ||
1611 | + | ||
1612 | +# See comments on authn_sallrany test for some background on the interaction | ||
1613 | +# of Satisfy Any and the newer Require blocks. | ||
1614 | +@SkipUnless(svntest.main.is_httpd_authz_provider_enabled) | ||
1615 | +def authn_sallrall(sbox): | ||
1616 | + "test satisfy all require all config" | ||
1617 | + sbox.build(read_only = True, create_wc = False) | ||
1618 | + | ||
1619 | + test_area_url = sbox.repo_url.replace('/svn-test-work/local_tmp/repos', | ||
1620 | + '/authz-test-work/sallrall') | ||
1621 | + | ||
1622 | + write_authz_file(sbox) | ||
1623 | + | ||
1624 | + allow_header = { 'ALLOW': '1' } | ||
1625 | + | ||
1626 | + sallrall_tests = ( | ||
1627 | + #anon access isn't allowed without ALLOW header | ||
1628 | + { 'path': '', 'status': 403, }, | ||
1629 | + { 'path': '/', 'status': 403, }, | ||
1630 | + { 'path': '/repos', 'status': 403, }, | ||
1631 | + { 'path': '/repos/', 'status': 403, }, | ||
1632 | + { 'path': '/repos/A', 'status': 403, }, | ||
1633 | + { 'path': '/repos/A/', 'status': 403, }, | ||
1634 | + { 'path': '/repos/A/D', 'status': 403, }, | ||
1635 | + { 'path': '/repos/A/D/', 'status': 403, }, | ||
1636 | + { 'path': '/repos/A/D/gamma', 'status': 403, }, | ||
1637 | + { 'path': '/repos/A/D/H', 'status': 403, }, | ||
1638 | + { 'path': '/repos/A/D/H/', 'status': 403, }, | ||
1639 | + { 'path': '/repos/A/D/H/chi', 'status': 403, }, | ||
1640 | + # auth is configured but no access is allowed without the ALLOW header | ||
1641 | + { 'path': '', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
1642 | + { 'path': '/', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
1643 | + { 'path': '/repos', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
1644 | + { 'path': '/repos/', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
1645 | + { 'path': '/repos/A', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
1646 | + { 'path': '/repos/A/', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
1647 | + { 'path': '/repos/A/D', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
1648 | + { 'path': '/repos/A/D/', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
1649 | + { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
1650 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
1651 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
1652 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_pass}, | ||
1653 | + # try with the wrong password for user1 | ||
1654 | + { 'path': '', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
1655 | + { 'path': '/', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
1656 | + { 'path': '/repos', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
1657 | + { 'path': '/repos/', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
1658 | + { 'path': '/repos/A', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
1659 | + { 'path': '/repos/A/', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
1660 | + { 'path': '/repos/A/D', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
1661 | + { 'path': '/repos/A/D/', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
1662 | + { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
1663 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
1664 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
1665 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user1, 'pw': user1_badpass}, | ||
1666 | + # auth is configured but no access is allowed without the ALLOW header | ||
1667 | + { 'path': '', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1668 | + { 'path': '/', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1669 | + { 'path': '/repos', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1670 | + { 'path': '/repos/', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1671 | + { 'path': '/repos/A', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1672 | + { 'path': '/repos/A/', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1673 | + { 'path': '/repos/A/D', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1674 | + { 'path': '/repos/A/D/', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1675 | + { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1676 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1677 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1678 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass}, | ||
1679 | + # try with the wrong password for user2 | ||
1680 | + { 'path': '', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
1681 | + { 'path': '/', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
1682 | + { 'path': '/repos', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
1683 | + { 'path': '/repos/', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
1684 | + { 'path': '/repos/A', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
1685 | + { 'path': '/repos/A/', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
1686 | + { 'path': '/repos/A/D', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
1687 | + { 'path': '/repos/A/D/', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
1688 | + { 'path': '/repos/A/D/gamma', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
1689 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
1690 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
1691 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_badpass}, | ||
1692 | + # anon is not allowed even with ALLOW header | ||
1693 | + { 'path': '', 'status': 401, 'headers': allow_header }, | ||
1694 | + { 'path': '/', 'status': 401, 'headers': allow_header }, | ||
1695 | + { 'path': '/repos', 'status': 401, 'headers': allow_header }, | ||
1696 | + { 'path': '/repos/', 'status': 401, 'headers': allow_header }, | ||
1697 | + { 'path': '/repos/A', 'status': 401, 'headers': allow_header }, | ||
1698 | + { 'path': '/repos/A/', 'status': 401, 'headers': allow_header }, | ||
1699 | + { 'path': '/repos/A/D', 'status': 401, 'headers': allow_header }, | ||
1700 | + { 'path': '/repos/A/D/', 'status': 401, 'headers': allow_header }, | ||
1701 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'headers': allow_header }, | ||
1702 | + { 'path': '/repos/A/D/H', 'status': 401, 'headers': allow_header }, | ||
1703 | + { 'path': '/repos/A/D/H/', 'status': 401, 'headers': allow_header }, | ||
1704 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'headers': allow_header }, | ||
1705 | + # auth is configured and user1 is allowed access repo including H | ||
1706 | + { 'path': '', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1707 | + { 'path': '/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1708 | + { 'path': '/repos', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1709 | + { 'path': '/repos/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1710 | + { 'path': '/repos/A', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1711 | + { 'path': '/repos/A/', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1712 | + { 'path': '/repos/A/D', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1713 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_H, | ||
1714 | + 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1715 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1716 | + { 'path': '/repos/A/D/H', 'status': 301, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1717 | + { 'path': '/repos/A/D/H/', 'status': 200, 'body': ls_of_H, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1718 | + { 'path': '/repos/A/D/H/chi', 'status': 200, 'user': user1, 'pw': user1_pass, 'headers': allow_header }, | ||
1719 | + # try with the wrong password for user1 | ||
1720 | + { 'path': '', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1721 | + { 'path': '/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1722 | + { 'path': '/repos', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1723 | + { 'path': '/repos/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1724 | + { 'path': '/repos/A', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1725 | + { 'path': '/repos/A/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1726 | + { 'path': '/repos/A/D', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1727 | + { 'path': '/repos/A/D/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1728 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1729 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1730 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1731 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user1, 'pw': user1_badpass, 'headers': allow_header }, | ||
1732 | + # auth is configured and user2 is not allowed access to H | ||
1733 | + { 'path': '', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1734 | + { 'path': '/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1735 | + { 'path': '/repos', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1736 | + { 'path': '/repos/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1737 | + { 'path': '/repos/A', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1738 | + { 'path': '/repos/A/', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1739 | + { 'path': '/repos/A/D', 'status': 301, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1740 | + { 'path': '/repos/A/D/', 'status': 200, 'body': ls_of_D_no_H, | ||
1741 | + 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1742 | + { 'path': '/repos/A/D/gamma', 'status': 200, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1743 | + { 'path': '/repos/A/D/H', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1744 | + { 'path': '/repos/A/D/H/', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1745 | + { 'path': '/repos/A/D/H/chi', 'status': 403, 'user': user2, 'pw': user2_pass, 'headers': allow_header }, | ||
1746 | + # try with the wrong password for user2 | ||
1747 | + { 'path': '', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1748 | + { 'path': '/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1749 | + { 'path': '/repos', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1750 | + { 'path': '/repos/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1751 | + { 'path': '/repos/A', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1752 | + { 'path': '/repos/A/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1753 | + { 'path': '/repos/A/D', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1754 | + { 'path': '/repos/A/D/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1755 | + { 'path': '/repos/A/D/gamma', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1756 | + { 'path': '/repos/A/D/H', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1757 | + { 'path': '/repos/A/D/H/', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1758 | + { 'path': '/repos/A/D/H/chi', 'status': 401, 'user': user2, 'pw': user2_badpass, 'headers': allow_header }, | ||
1759 | + | ||
1760 | + ) | ||
1761 | + | ||
1762 | + verify_gets(test_area_url, sallrall_tests) | ||
1763 | + | ||
1764 | + | ||
1765 | +######################################################################## | ||
1766 | +# Run the tests | ||
1767 | + | ||
1768 | + | ||
1769 | +# list all tests here, starting with None: | ||
1770 | +test_list = [ None, | ||
1771 | + anon, | ||
1772 | + mixed, | ||
1773 | + mixed_noauthwhenanon, | ||
1774 | + authn, | ||
1775 | + authn_anonoff, | ||
1776 | + authn_lcuser, | ||
1777 | + authn_group, | ||
1778 | + authn_sallrany, | ||
1779 | + authn_sallrall, | ||
1780 | + ] | ||
1781 | +serial_only = True | ||
1782 | + | ||
1783 | +if __name__ == '__main__': | ||
1784 | + svntest.main.run_tests(test_list) | ||
1785 | + # NOTREACHED | ||
1786 | + | ||
1787 | + | ||
1788 | +### End of file. | ||
1789 | Index: subversion-1.8.11/subversion/tests/cmdline/svntest/main.py | ||
1790 | =================================================================== | ||
1791 | --- subversion-1.8.11.orig/subversion/tests/cmdline/svntest/main.py | ||
1792 | +++ subversion-1.8.11/subversion/tests/cmdline/svntest/main.py | ||
1793 | @@ -1368,6 +1368,30 @@ def is_plaintext_password_storage_disabl | ||
1794 | return False | ||
1795 | return True | ||
1796 | |||
1797 | + | ||
1798 | +# https://issues.apache.org/bugzilla/show_bug.cgi?id=56480 | ||
1799 | +# https://issues.apache.org/bugzilla/show_bug.cgi?id=55397 | ||
1800 | +__mod_dav_url_quoting_broken_versions = frozenset([ | ||
1801 | + '2.2.27', | ||
1802 | + '2.2.26', | ||
1803 | + '2.2.25', | ||
1804 | + '2.4.9', | ||
1805 | + '2.4.8', | ||
1806 | + '2.4.7', | ||
1807 | + '2.4.6', | ||
1808 | + '2.4.5', | ||
1809 | +]) | ||
1810 | +def is_mod_dav_url_quoting_broken(): | ||
1811 | + if is_ra_type_dav(): | ||
1812 | + return (options.httpd_version in __mod_dav_url_quoting_broken_versions) | ||
1813 | + return None | ||
1814 | + | ||
1815 | +def is_httpd_authz_provider_enabled(): | ||
1816 | + if is_ra_type_dav(): | ||
1817 | + v = options.httpd_version.split('.') | ||
1818 | + return (v[0] == '2' and int(v[1]) >= 3) or int(v[0]) > 2 | ||
1819 | + return None | ||
1820 | + | ||
1821 | ###################################################################### | ||
1822 | |||
1823 | |||
1824 | @@ -1425,6 +1449,8 @@ class TestSpawningThread(threading.Threa | ||
1825 | args.append('--ssl-cert=' + options.ssl_cert) | ||
1826 | if options.http_proxy: | ||
1827 | args.append('--http-proxy=' + options.http_proxy) | ||
1828 | + if options.httpd_version: | ||
1829 | + args.append('--httpd-version=' + options.httpd_version) | ||
1830 | |||
1831 | result, stdout_lines, stderr_lines = spawn_process(command, 0, False, None, | ||
1832 | *args) | ||
1833 | @@ -1590,6 +1616,12 @@ class TestRunner: | ||
1834 | sandbox.cleanup_test_paths() | ||
1835 | return exit_code | ||
1836 | |||
1837 | +def is_httpd_authz_provider_enabled(): | ||
1838 | + if is_ra_type_dav(): | ||
1839 | + v = options.httpd_version.split('.') | ||
1840 | + return (v[0] == '2' and int(v[1]) >= 3) or int(v[0]) > 2 | ||
1841 | + return None | ||
1842 | + | ||
1843 | ###################################################################### | ||
1844 | # Main testing functions | ||
1845 | |||
1846 | @@ -1770,6 +1802,8 @@ def _create_parser(): | ||
1847 | help='Path to SSL server certificate.') | ||
1848 | parser.add_option('--http-proxy', action='store', | ||
1849 | help='Use the HTTP Proxy at hostname:port.') | ||
1850 | + parser.add_option('--httpd-version', action='store', | ||
1851 | + help='Assume HTTPD is this version.') | ||
1852 | parser.add_option('--tools-bin', action='store', dest='tools_bin', | ||
1853 | help='Use the svn tools installed in this path') | ||
1854 | |||
1855 | Index: subversion-1.8.11/win-tests.py | ||
1856 | =================================================================== | ||
1857 | --- subversion-1.8.11.orig/win-tests.py | ||
1858 | +++ subversion-1.8.11/win-tests.py | ||
1859 | @@ -481,6 +481,7 @@ class Httpd: | ||
1860 | self.httpd_config = os.path.join(self.root, 'httpd.conf') | ||
1861 | self.httpd_users = os.path.join(self.root, 'users') | ||
1862 | self.httpd_mime_types = os.path.join(self.root, 'mime.types') | ||
1863 | + self.httpd_groups = os.path.join(self.root, 'groups') | ||
1864 | self.abs_builddir = abs_builddir | ||
1865 | self.abs_objdir = abs_objdir | ||
1866 | self.service_name = 'svn-test-httpd-' + str(httpd_port) | ||
1867 | @@ -494,6 +495,7 @@ class Httpd: | ||
1868 | create_target_dir(self.root_dir) | ||
1869 | |||
1870 | self._create_users_file() | ||
1871 | + self._create_groups_file() | ||
1872 | self._create_mime_types_file() | ||
1873 | self._create_dontdothat_file() | ||
1874 | |||
1875 | @@ -540,6 +542,8 @@ class Httpd: | ||
1876 | if self.httpd_ver >= 2.2: | ||
1877 | fp.write(self._sys_module('auth_basic_module', 'mod_auth_basic.so')) | ||
1878 | fp.write(self._sys_module('authn_file_module', 'mod_authn_file.so')) | ||
1879 | + fp.write(self._sys_module('authz_groupfile_module', 'mod_authz_groupfile.so')) | ||
1880 | + fp.write(self._sys_module('authz_host_module', 'mod_authz_host.so')) | ||
1881 | else: | ||
1882 | fp.write(self._sys_module('auth_module', 'mod_auth.so')) | ||
1883 | fp.write(self._sys_module('alias_module', 'mod_alias.so')) | ||
1884 | @@ -562,6 +566,7 @@ class Httpd: | ||
1885 | # Define two locations for repositories | ||
1886 | fp.write(self._svn_repo('repositories')) | ||
1887 | fp.write(self._svn_repo('local_tmp')) | ||
1888 | + fp.write(self._svn_authz_repo()) | ||
1889 | |||
1890 | # And two redirects for the redirect tests | ||
1891 | fp.write('RedirectMatch permanent ^/svn-test-work/repositories/' | ||
1892 | @@ -592,6 +597,17 @@ class Httpd: | ||
1893 | 'jrandom', 'rayjandom']) | ||
1894 | os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, | ||
1895 | 'jconstant', 'rayjandom']) | ||
1896 | + os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, | ||
1897 | + 'JRANDOM', 'rayjandom']) | ||
1898 | + os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, | ||
1899 | + 'JCONSTANT', 'rayjandom']) | ||
1900 | + | ||
1901 | + def _create_groups_file(self): | ||
1902 | + "Create groups for mod_authz_svn tests" | ||
1903 | + fp = open(self.httpd_groups, 'w') | ||
1904 | + fp.write('random: jrandom\n') | ||
1905 | + fp.write('constant: jconstant\n') | ||
1906 | + fp.close() | ||
1907 | |||
1908 | def _create_mime_types_file(self): | ||
1909 | "Create empty mime.types file" | ||
1910 | @@ -652,6 +668,153 @@ class Httpd: | ||
1911 | ' DontDoThatConfigFile ' + self._quote(self.dontdothat_file) + '\n' \ | ||
1912 | '</Location>\n' | ||
1913 | |||
1914 | + def _svn_authz_repo(self): | ||
1915 | + local_tmp = os.path.join(self.abs_builddir, | ||
1916 | + CMDLINE_TEST_SCRIPT_NATIVE_PATH, | ||
1917 | + 'svn-test-work', 'local_tmp') | ||
1918 | + return \ | ||
1919 | + '<Location /authz-test-work/anon>' + '\n' \ | ||
1920 | + ' DAV svn' + '\n' \ | ||
1921 | + ' SVNParentPath ' + local_tmp + '\n' \ | ||
1922 | + ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ | ||
1923 | + ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ | ||
1924 | + ' SVNListParentPath On' + '\n' \ | ||
1925 | + ' <IfModule mod_authz_core.c>' + '\n' \ | ||
1926 | + ' Require all granted' + '\n' \ | ||
1927 | + ' </IfModule>' + '\n' \ | ||
1928 | + ' <IfModule !mod_authz_core.c>' + '\n' \ | ||
1929 | + ' Allow from all' + '\n' \ | ||
1930 | + ' </IfModule>' + '\n' \ | ||
1931 | + ' SVNPathAuthz ' + self.path_authz_option + '\n' \ | ||
1932 | + '</Location>' + '\n' \ | ||
1933 | + '<Location /authz-test-work/mixed>' + '\n' \ | ||
1934 | + ' DAV svn' + '\n' \ | ||
1935 | + ' SVNParentPath ' + local_tmp + '\n' \ | ||
1936 | + ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ | ||
1937 | + ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ | ||
1938 | + ' SVNListParentPath On' + '\n' \ | ||
1939 | + ' AuthType Basic' + '\n' \ | ||
1940 | + ' AuthName "Subversion Repository"' + '\n' \ | ||
1941 | + ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ | ||
1942 | + ' Require valid-user' + '\n' \ | ||
1943 | + ' Satisfy Any' + '\n' \ | ||
1944 | + ' SVNPathAuthz ' + self.path_authz_option + '\n' \ | ||
1945 | + '</Location>' + '\n' \ | ||
1946 | + '<Location /authz-test-work/mixed-noauthwhenanon>' + '\n' \ | ||
1947 | + ' DAV svn' + '\n' \ | ||
1948 | + ' SVNParentPath ' + local_tmp + '\n' \ | ||
1949 | + ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ | ||
1950 | + ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ | ||
1951 | + ' SVNListParentPath On' + '\n' \ | ||
1952 | + ' AuthType Basic' + '\n' \ | ||
1953 | + ' AuthName "Subversion Repository"' + '\n' \ | ||
1954 | + ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ | ||
1955 | + ' Require valid-user' + '\n' \ | ||
1956 | + ' AuthzSVNNoAuthWhenAnonymousAllowed On' + '\n' \ | ||
1957 | + ' SVNPathAuthz On' + '\n' \ | ||
1958 | + '</Location>' + '\n' \ | ||
1959 | + '<Location /authz-test-work/authn>' + '\n' \ | ||
1960 | + ' DAV svn' + '\n' \ | ||
1961 | + ' SVNParentPath ' + local_tmp + '\n' \ | ||
1962 | + ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ | ||
1963 | + ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ | ||
1964 | + ' SVNListParentPath On' + '\n' \ | ||
1965 | + ' AuthType Basic' + '\n' \ | ||
1966 | + ' AuthName "Subversion Repository"' + '\n' \ | ||
1967 | + ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ | ||
1968 | + ' Require valid-user' + '\n' \ | ||
1969 | + ' SVNPathAuthz ' + self.path_authz_option + '\n' \ | ||
1970 | + '</Location>' + '\n' \ | ||
1971 | + '<Location /authz-test-work/authn-anonoff>' + '\n' \ | ||
1972 | + ' DAV svn' + '\n' \ | ||
1973 | + ' SVNParentPath ' + local_tmp + '\n' \ | ||
1974 | + ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ | ||
1975 | + ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ | ||
1976 | + ' SVNListParentPath On' + '\n' \ | ||
1977 | + ' AuthType Basic' + '\n' \ | ||
1978 | + ' AuthName "Subversion Repository"' + '\n' \ | ||
1979 | + ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ | ||
1980 | + ' Require valid-user' + '\n' \ | ||
1981 | + ' AuthzSVNAnonymous Off' + '\n' \ | ||
1982 | + ' SVNPathAuthz On' + '\n' \ | ||
1983 | + '</Location>' + '\n' \ | ||
1984 | + '<Location /authz-test-work/authn-lcuser>' + '\n' \ | ||
1985 | + ' DAV svn' + '\n' \ | ||
1986 | + ' SVNParentPath ' + local_tmp + '\n' \ | ||
1987 | + ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ | ||
1988 | + ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ | ||
1989 | + ' SVNListParentPath On' + '\n' \ | ||
1990 | + ' AuthType Basic' + '\n' \ | ||
1991 | + ' AuthName "Subversion Repository"' + '\n' \ | ||
1992 | + ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ | ||
1993 | + ' Require valid-user' + '\n' \ | ||
1994 | + ' AuthzForceUsernameCase Lower' + '\n' \ | ||
1995 | + ' SVNPathAuthz ' + self.path_authz_option + '\n' \ | ||
1996 | + '</Location>' + '\n' \ | ||
1997 | + '<Location /authz-test-work/authn-lcuser>' + '\n' \ | ||
1998 | + ' DAV svn' + '\n' \ | ||
1999 | + ' SVNParentPath ' + local_tmp + '\n' \ | ||
2000 | + ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ | ||
2001 | + ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ | ||
2002 | + ' SVNListParentPath On' + '\n' \ | ||
2003 | + ' AuthType Basic' + '\n' \ | ||
2004 | + ' AuthName "Subversion Repository"' + '\n' \ | ||
2005 | + ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ | ||
2006 | + ' Require valid-user' + '\n' \ | ||
2007 | + ' AuthzForceUsernameCase Lower' + '\n' \ | ||
2008 | + ' SVNPathAuthz ' + self.path_authz_option + '\n' \ | ||
2009 | + '</Location>' + '\n' \ | ||
2010 | + '<Location /authz-test-work/authn-group>' + '\n' \ | ||
2011 | + ' DAV svn' + '\n' \ | ||
2012 | + ' SVNParentPath ' + local_tmp + '\n' \ | ||
2013 | + ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ | ||
2014 | + ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ | ||
2015 | + ' SVNListParentPath On' + '\n' \ | ||
2016 | + ' AuthType Basic' + '\n' \ | ||
2017 | + ' AuthName "Subversion Repository"' + '\n' \ | ||
2018 | + ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ | ||
2019 | + ' AuthGroupFile ' + self._quote(self.httpd_groups) + '\n' \ | ||
2020 | + ' Require group random' + '\n' \ | ||
2021 | + ' AuthzSVNAuthoritative Off' + '\n' \ | ||
2022 | + ' SVNPathAuthz On' + '\n' \ | ||
2023 | + '</Location>' + '\n' \ | ||
2024 | + '<IfModule mod_authz_core.c>' + '\n' \ | ||
2025 | + '<Location /authz-test-work/sallrany>' + '\n' \ | ||
2026 | + ' DAV svn' + '\n' \ | ||
2027 | + ' SVNParentPath ' + local_tmp + '\n' \ | ||
2028 | + ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ | ||
2029 | + ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ | ||
2030 | + ' SVNListParentPath On' + '\n' \ | ||
2031 | + ' AuthType Basic' + '\n' \ | ||
2032 | + ' AuthName "Subversion Repository"' + '\n' \ | ||
2033 | + ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ | ||
2034 | + ' AuthzSendForbiddenOnFailure On' + '\n' \ | ||
2035 | + ' Satisfy All' + '\n' \ | ||
2036 | + ' <RequireAny>' + '\n' \ | ||
2037 | + ' Require valid-user' + '\n' \ | ||
2038 | + ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \ | ||
2039 | + ' </RequireAny>' + '\n' \ | ||
2040 | + ' SVNPathAuthz ' + self.path_authz_option + '\n' \ | ||
2041 | + '</Location>' + '\n' \ | ||
2042 | + '<Location /authz-test-work/sallrall>'+ '\n' \ | ||
2043 | + ' DAV svn' + '\n' \ | ||
2044 | + ' SVNParentPath ' + local_tmp + '\n' \ | ||
2045 | + ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ | ||
2046 | + ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ | ||
2047 | + ' SVNListParentPath On' + '\n' \ | ||
2048 | + ' AuthType Basic' + '\n' \ | ||
2049 | + ' AuthName "Subversion Repository"' + '\n' \ | ||
2050 | + ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ | ||
2051 | + ' AuthzSendForbiddenOnFailure On' + '\n' \ | ||
2052 | + ' Satisfy All' + '\n' \ | ||
2053 | + ' <RequireAll>' + '\n' \ | ||
2054 | + ' Require valid-user' + '\n' \ | ||
2055 | + ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \ | ||
2056 | + ' </RequireAll>' + '\n' \ | ||
2057 | + ' SVNPathAuthz ' + self.path_authz_option + '\n' \ | ||
2058 | + '</Location>' + '\n' \ | ||
2059 | + '</IfModule>' + '\n' \ | ||
2060 | + | ||
2061 | def start(self): | ||
2062 | if self.service: | ||
2063 | self._start_service() | ||
2064 | @@ -786,6 +949,10 @@ if not test_javahl: | ||
2065 | log_file = os.path.join(abs_builddir, log) | ||
2066 | fail_log_file = os.path.join(abs_builddir, faillog) | ||
2067 | |||
2068 | + if run_httpd: | ||
2069 | + httpd_version = "%.1f" % daemon.httpd_ver | ||
2070 | + else: | ||
2071 | + httpd_version = None | ||
2072 | th = run_tests.TestHarness(abs_srcdir, abs_builddir, | ||
2073 | log_file, | ||
2074 | fail_log_file, | ||
2075 | @@ -795,6 +962,7 @@ if not test_javahl: | ||
2076 | fsfs_sharding, fsfs_packing, | ||
2077 | list_tests, svn_bin, mode_filter, | ||
2078 | milestone_filter, | ||
2079 | + httpd_version=httpd_version, | ||
2080 | set_log_level=log_level, ssl_cert=ssl_cert) | ||
2081 | old_cwd = os.getcwd() | ||
2082 | try: | ||
diff --git a/meta/recipes-devtools/subversion/subversion_1.8.11.bb b/meta/recipes-devtools/subversion/subversion_1.8.11.bb index a5a5761013..789392950d 100644 --- a/meta/recipes-devtools/subversion/subversion_1.8.11.bb +++ b/meta/recipes-devtools/subversion/subversion_1.8.11.bb | |||
@@ -12,6 +12,7 @@ inherit gettext pythonnative | |||
12 | SRC_URI = "${APACHE_MIRROR}/${BPN}/${BPN}-${PV}.tar.bz2 \ | 12 | SRC_URI = "${APACHE_MIRROR}/${BPN}/${BPN}-${PV}.tar.bz2 \ |
13 | file://libtool2.patch \ | 13 | file://libtool2.patch \ |
14 | file://disable_macos.patch \ | 14 | file://disable_macos.patch \ |
15 | file://subversion-CVE-2015-3184.patch \ | ||
15 | " | 16 | " |
16 | SRC_URI[md5sum] = "766a89bbbb388f8eb76166672d3b9e49" | 17 | SRC_URI[md5sum] = "766a89bbbb388f8eb76166672d3b9e49" |
17 | SRC_URI[sha256sum] = "10b056420e1f194c12840368f6bf58842e6200f9cb8cc5ebbf9be2e89e56e4d9" | 18 | SRC_URI[sha256sum] = "10b056420e1f194c12840368f6bf58842e6200f9cb8cc5ebbf9be2e89e56e4d9" |