aboutsummaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
authorSimon McVittie <smcv@debian.org>2017-01-11 13:16:37 +0000
committerSimon McVittie <smcv@debian.org>2017-01-11 18:11:06 +0000
commit3964787238ccfd4877c6a583cda5e2744887238b (patch)
tree12b0f3b99dccd74cdcb8eb4344907139243b0085 /t
parentf357856448ead271f6d85ab4d0015220a65877df (diff)
downloadikiwiki-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')
-rwxr-xr-xt/passwordauth.t225
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();