use strict; use warnings FATAL => 'all'; use Apache::Test; use Apache::TestRequest; use Apache::TestUtil qw(t_write_file); use File::Spec; # test RequireAll/RequireAny containers and AuthzMerging plan tests => 168 + 14*24, need need_lwp, need_module('mod_authn_core'), need_module('mod_authz_core'), need_module('mod_authz_host'), need_module('mod_authz_groupfile'), need_min_apache_version('2.3.6'); my $text = ''; sub check { my $rc = shift; my $path = shift; my @args; foreach my $e (@_) { if ($e =~ /user/) { push @args, username => $e, password => $e; } else { push @args, "X-Allowed$e" => 'yes'; } } my $res = GET "/authz_core/$path", @args; my $got = $res->code; print "# got $got, expected $rc [$text: $path @_]\n"; ok($got == $rc); } sub write_htaccess { my $path = shift; my $merging = shift || ""; my $container = shift || ""; $text = "$path $merging $container @_"; my $need_auth; my $content = ""; $content .= "AuthMerging $merging\n" if $merging; if ($container) { $content .= "\n"; } foreach (@_) { my $req = $_; my $not = ""; if ($req =~ s/^\!//) { $not = 'not'; } if ($req =~ /all/) { $content .= "Require $not $req\n"; } elsif ($req =~ /user/) { # 'group' is correct, see comment about mod_authany below $content .= "Require $not group $req\n"; $need_auth = 1; } else { $content .= "Require $not env allowed$req\n"; } } if ($container) { $content .= "\n"; } if ($need_auth) { $content .= "AuthType basic\n"; $content .= "AuthName basic1\n"; $content .= "AuthUserFile basic1\n"; $content .= "AuthGroupFile groups1\n"; } my $file = File::Spec->catfile(Apache::Test::vars('documentroot'), "/authz_core/$path/.htaccess"); t_write_file($file, $content); } # create some users (username == password) my $basic_file = File::Spec->catfile(Apache::Test::vars('serverroot'), 'basic1'); t_write_file($basic_file, << 'EOF' ); user1:NYSYdf7MU5KpU user2:KJ7Yxzr1VVzAI user3:xnpSvZ2iqti/c EOF # mod_authany overrides the 'user' provider, so we can't check users directly :-( # create some groups instead: my $group_file = File::Spec->catfile(Apache::Test::vars('serverroot'), 'groups1'); t_write_file($group_file, << 'EOF' ); user1:user1 user2:user2 user3:user3 EOF write_htaccess("a/", undef, undef); check(200, "a/"); check(200, "a/", 1); check(200, "a/", 2); check(200, "a/", 1, 2); check(200, "a/", 3); write_htaccess("a/", undef, undef, "user1"); check(401, "a/"); check(200, "a/", "user1"); check(401, "a/", "user2"); write_htaccess("a/", undef, "Any", 1, 2); check(403, "a/"); check(200, "a/", 1); check(200, "a/", 2); check(200, "a/", 1, 2); check(403, "a/", 3); write_htaccess("a/b/", undef, "Any", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(200, "a/b/", 2); check(200, "a/b/", 3); write_htaccess("a/b/", "Off", "Any", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(200, "a/b/", 2); check(200, "a/b/", 3); write_htaccess("a/b/", "Or", "Any", 2, 3); check(403, "a/b/"); check(200, "a/b/", 1); check(200, "a/b/", 2); check(200, "a/b/", 3); write_htaccess("a/b/", "And", "Any", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(200, "a/b/", 2); check(403, "a/b/", 3); check(200, "a/b/", 1, 2); check(200, "a/b/", 1, 3); check(200, "a/b/", 2, 3); write_htaccess("a/b/", undef, "All", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 3); check(200, "a/b/", 2, 3); check(403, "a/b/", 1, 3); write_htaccess("a/b/", "Off", "All", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 3); check(200, "a/b/", 2, 3); check(403, "a/b/", 1, 3); write_htaccess("a/b/", "Or", "All", 3, 4); check(403, "a/b/"); check(200, "a/b/", 1); check(200, "a/b/", 2); check(200, "a/b/", 2, 3); check(200, "a/b/", 3, 4); check(403, "a/b/", 3); check(403, "a/b/", 4); write_htaccess("a/b/", "And", "All", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 3); check(403, "a/b/", 1, 2); check(403, "a/b/", 1, 3); check(200, "a/b/", 2, 3); write_htaccess("a/", undef, "All", 1, "!2"); check(403, "a/"); check(200, "a/", 1); check(403, "a/", 2); check(403, "a/", 1, 2); check(403, "a/", 3); write_htaccess("a/b/", undef, "Any", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(200, "a/b/", 2); check(200, "a/b/", 3); write_htaccess("a/b/", "Off", "Any", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(200, "a/b/", 2); check(200, "a/b/", 3); write_htaccess("a/b/", "Or", "Any", 3, 4); check(403, "a/b/"); check(200, "a/b/", 1); check(403, "a/b/", 1, 2); check(200, "a/b/", 1, 2, 3); check(200, "a/b/", 1, 2, 4); check(200, "a/b/", 4); write_htaccess("a/b/", "And", "Any", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 3); check(403, "a/b/", 1, 2); check(200, "a/b/", 1, 3); check(403, "a/b/", 2, 3); # should not inherit AuthMerging And from a/b/ write_htaccess("a/b/c/", undef, "Any", 4); check(403, "a/b/c/", 1, 3); check(200, "a/b/c/", 4); check(200, "a/b/c/", 1, 2, 4); write_htaccess("a/b/", undef, "All", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 3); check(200, "a/b/", 2, 3); check(403, "a/b/", 1, 3); write_htaccess("a/b/", "Off", "All", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 3); check(200, "a/b/", 2, 3); check(403, "a/b/", 1, 3); write_htaccess("a/b/", "Or", "All", 3, 4); check(403, "a/b/"); check(200, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 2, 3); check(200, "a/b/", 3, 4); check(403, "a/b/", 3); check(403, "a/b/", 4); write_htaccess("a/b/", "And", "All", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 3); check(403, "a/b/", 1, 2); check(403, "a/b/", 1, 3); check(403, "a/b/", 2, 3); write_htaccess("a/", undef, "All", 1, 2); check(403, "a/"); check(403, "a/", 1); check(403, "a/", 2); check(200, "a/", 1, 2); write_htaccess("a/b/", undef, "Any", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(200, "a/b/", 2); check(200, "a/b/", 3); write_htaccess("a/b/", "Off", "Any", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(200, "a/b/", 2); check(200, "a/b/", 3); write_htaccess("a/b/", "Or", "Any", 3, 4); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(200, "a/b/", 1, 2); check(200, "a/b/", 3); check(200, "a/b/", 4); write_htaccess("a/b/", "And", "Any", 3, 4); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 3); check(403, "a/b/", 4); check(403, "a/b/", 1, 2); check(200, "a/b/", 1, 2, 3); check(200, "a/b/", 1, 2, 4); check(403, "a/b/", 1, 3, 4); write_htaccess("a/b/", undef, "All", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 3); check(200, "a/b/", 2, 3); check(403, "a/b/", 1, 3); write_htaccess("a/b/", "Off", "All", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 3); check(200, "a/b/", 2, 3); check(403, "a/b/", 1, 3); write_htaccess("a/b/", "Or", "All", 3, 4); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 3); check(403, "a/b/", 4); check(403, "a/b/", 2, 3); check(200, "a/b/", 3, 4); check(200, "a/b/", 1, 2); write_htaccess("a/b/", "And", "All", 2, 3); check(403, "a/b/"); check(403, "a/b/", 1); check(403, "a/b/", 2); check(403, "a/b/", 3); check(403, "a/b/", 1, 2); check(403, "a/b/", 1, 3); check(403, "a/b/", 2, 3); check(200, "a/b/", 1, 2, 3); # # To test merging of a mix of user and non-user authz providers, # we should test all orders. # # helper function to get all permutations of an array # returns array of references sub permutations { my @results = [shift]; foreach my $el (@_) { my @new_results; foreach my $arr (@results) { my $len = scalar(@{$arr}); foreach my $i (0 .. $len) { my @new = @{$arr}; splice @new, $i, 0, $el; push @new_results, \@new; } } @results = @new_results; } return @results; } my @perms = permutations(qw/user1 user2 1 2/); foreach my $p (@perms) { write_htaccess("a/", undef, "All", @{$p}); check(403, "a/"); check(403, "a/", 1); check(403, "a/", "user1"); check(401, "a/", 1, 2); check(401, "a/", 1, 2, "user1"); check(401, "a/", 1, 2, "user3"); check(403, "a/", 1, "user1"); write_htaccess("a/", undef, "Any", @{$p}); check(401, "a/"); check(200, "a/", 1); check(200, "a/", "user1"); check(401, "a/", "user3"); check(200, "a/", 1, 2); check(200, "a/", 1, "user1"); check(200, "a/", 1, "user3"); }