diff options
author | Simon McVittie <smcv@debian.org> | 2017-01-11 13:16:37 +0000 |
---|---|---|
committer | Simon McVittie <smcv@debian.org> | 2017-01-11 18:11:06 +0000 |
commit | 3964787238ccfd4877c6a583cda5e2744887238b (patch) | |
tree | 12b0f3b99dccd74cdcb8eb4344907139243b0085 /t/passwordauth.t | |
parent | f357856448ead271f6d85ab4d0015220a65877df (diff) | |
download | ikiwiki-3964787238ccfd4877c6a583cda5e2744887238b.tar ikiwiki-3964787238ccfd4877c6a583cda5e2744887238b.tar.gz |
t/passwordauth.t: new automated test for passwordauth
In particular this includes an exploit for OVE-20170111-0001.
(cherry picked from commit fbe207212b1f4a395dc297fb274ef07afd7d68f3)
Diffstat (limited to 't/passwordauth.t')
-rwxr-xr-x | t/passwordauth.t | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/t/passwordauth.t b/t/passwordauth.t new file mode 100755 index 000000000..26d6c2717 --- /dev/null +++ b/t/passwordauth.t @@ -0,0 +1,225 @@ +#!/usr/bin/perl +use warnings; +use strict; + +use Cwd qw(getcwd); +use Test::More; + +BEGIN { + plan(skip_all => "Authen::Passphrase not available") + unless eval q{ + use Authen::Passphrase qw(); + 1; + }; + + plan(skip_all => "CGI not available") + unless eval q{ + use CGI qw(); + 1; + }; + + plan(skip_all => "IPC::Run not available") + unless eval q{ + use IPC::Run qw(run); + 1; + }; + + use_ok('IkiWiki'); + use_ok('IkiWiki::Plugin::passwordauth'); + use_ok('IkiWiki::Setup'); + use_ok('IkiWiki::UserInfo'); + use_ok('YAML::XS'); +} + +# We check for English messages +$ENV{LC_ALL} = 'C'; + +my $installed = $ENV{INSTALLED_TESTS}; + +my @command; +if ($installed) { + @command = qw(ikiwiki); +} +else { + ok(! system("make -s ikiwiki.out")); + @command = ("perl", "-I".getcwd."/blib/lib", './ikiwiki.out', + '--underlaydir='.getcwd.'/underlays/basewiki', + '--set', 'underlaydirbase='.getcwd.'/underlays', + '--templatedir='.getcwd.'/templates'); +} + +sub write_setup_file { + my %setup = ( + wikiname => 'this is the name of my wiki', + srcdir => getcwd.'/t/tmp/in', + destdir => getcwd.'/t/tmp/out', + url => 'http://example.com', + cgiurl => 'http://example.com/cgi-bin/ikiwiki.cgi', + cgi_wrapper => getcwd.'/t/tmp/ikiwiki.cgi', + cgi_wrappermode => '0751', + add_plugins => [qw(anonok attachment lockedit passwordauth recentchanges)], + adminuser => [qw(alice)], + disable_plugins => [qw(emailauth openid)], + locked_pages => '*', + ); + unless ($installed) { + $setup{ENV} = { 'PERL5LIB' => getcwd.'/blib/lib' }; + } + writefile("test.setup", "t/tmp", + "# IkiWiki::Setup::Yaml - YAML formatted setup file\n" . + Dump(\%setup)); + %IkiWiki::config = IkiWiki::defaultconfig(); + IkiWiki::Setup::load("t/tmp/test.setup"); + IkiWiki::loadplugins(); + IkiWiki::checkconfig(); +} + +sub thoroughly_rebuild { + ok(unlink("t/tmp/ikiwiki.cgi") || $!{ENOENT}); + ok(unlink("t/tmp/in/.git/hooks/post-commit") || $!{ENOENT}); + ok(! system(@command, qw(--setup t/tmp/test.setup --rebuild --wrappers))); +} + +sub run_cgi { + my (%args) = @_; + my ($in, $out); + my $method = $args{method} || 'GET'; + my $environ = $args{environ} || {}; + my $params = $args{params} || { do => 'prefs' }; + + my %defaults = ( + SCRIPT_NAME => '/cgi-bin/ikiwiki.cgi', + HTTP_HOST => 'example.com', + ); + + my $cgi = CGI->new($args{params}); + my $query_string = $cgi->query_string(); + + if ($method eq 'POST') { + $defaults{REQUEST_METHOD} = 'POST'; + $in = $query_string; + $defaults{CONTENT_LENGTH} = length $in; + } else { + $defaults{REQUEST_METHOD} = 'GET'; + $defaults{QUERY_STRING} = $query_string; + } + + my %envvars = ( + %defaults, + %$environ, + ); + print("# $query_string\n"); + run(["./t/tmp/ikiwiki.cgi"], \$in, \$out, init => sub { + map { + $ENV{$_} = $envvars{$_} + } keys(%envvars); + }); + + return $out; +} + +sub test_prefs { + my $content; + my $status; + + IkiWiki::userinfo_setall('alice', {regdate => time, email => 'alice@example.com'}); + IkiWiki::userinfo_setall('bob', {regdate => time, email => 'bob@example.com'}); + IkiWiki::userinfo_setall('name', {regdate => time, email => 'nobody@example.com'}); + IkiWiki::Plugin::passwordauth::setpassword('alice', "Alice's password"); + IkiWiki::Plugin::passwordauth::setpassword('bob', "Bob's password"); + + $content = run_cgi( + params => { + do => 'prefs', + }, + ); + + # prefs requires signing in so we are redirected, with the postsignin + # action saved in the session + like($content, qr/<form .*name="signin"/); + + # remember the cookie so we can continue to act in that session + my ($cookie) = ($content =~ m/^Set-Cookie: (.*)$/im); + + # sign in + $content = run_cgi( + environ => { + HTTP_COOKIE => $cookie, + }, + params => { + do => 'signin', + name => 'bob', + password => "Bob's password", + _submit => 'Login', + _submitted_signin => '1', + }, + ); + + # We are signed-in as bob now + like($content, qr{page=bob.*Create your user page}); + like($content, qr{<input.*name="name".*value="bob"}); + like($content, qr{<input.*name="email".*value="bob\@example.com"}); +} + +sub test_formbuilder_disaster { + my $content; + my $status; + + ok(! system(qw(rm -rf t/tmp))); + ok(! system(qw(mkdir t/tmp))); + ok(! system(qw(mkdir t/tmp/in))); + + write_setup_file(); + thoroughly_rebuild(); + + IkiWiki::userinfo_setall('alice', {regdate => time, email => 'alice@example.com'}); + IkiWiki::userinfo_setall('bob', {regdate => time, email => 'bob@example.com'}); + IkiWiki::userinfo_setall('name', {regdate => time, email => 'nobody@example.com'}); + IkiWiki::Plugin::passwordauth::setpassword('alice', "Alice's password"); + IkiWiki::Plugin::passwordauth::setpassword('bob', "Bob's password"); + + $content = run_cgi( + params => { + do => 'prefs', + }, + ); + + # prefs requires signing in so we are redirected, with the postsignin + # action saved in the session + like($content, qr/<form .*name="signin"/); + + # remember the cookie so we can continue to act in that session + my ($cookie) = ($content =~ m/^Set-Cookie: (.*)$/im); + + # sign in + $content = run_cgi( + environ => { + HTTP_COOKIE => $cookie, + }, + params => { + do => 'signin', + name => ['bob', 'name', 'alice'], + password => "Bob's password", + _submit => 'Login', + _submitted_signin => '1', + }, + ); + + like($content, qr{page=bob.*Create your user page}); + like($content, qr{<input.*name="name".*value="bob"}); + like($content, qr{<input.*name="email".*value="bob\@example.com"}); + + unlike($content, qr{alice}); +} + +ok(! system(qw(rm -rf t/tmp))); +ok(! system(qw(mkdir t/tmp))); +ok(! system(qw(mkdir t/tmp/in))); + +write_setup_file(); +thoroughly_rebuild(); + +test_prefs(); +test_formbuilder_disaster(); + +done_testing(); |