From: Simon McVittie <smcv@debian.org>
Date: Wed, 11 Jan 2017 13:16:37 +0000 (+0000)
Subject: t/passwordauth.t: new automated test for passwordauth
X-Git-Tag: debian/3.20120629.2+deb7u2~37
X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/commitdiff_plain/8c19da175a2265e63c2e0f07879f01b694c5c34a?ds=inline;hp=7cb42cb1a80854e570b4f19863409ae6cc263680

t/passwordauth.t: new automated test for passwordauth

In particular this includes an exploit for OVE-20170111-0001.
---

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();