#! /usr/bin/perl

use strict;
use warnings;
use Data::Dumper;
use WWW::Curl;
use WWW::Curl::Easy;
use URI::Escape;
use MIME::Base64;

use lib "/usr/share/doc/libapache2-mod-auth-tkt/examples/cgi/Apache/";
use AuthTkt;

my $failed = 0;

sub test_url {
	my $url = shift;
	my $expected_resp = shift;
	my $cookie = shift;

	my $curl = WWW::Curl::Easy->new;

	$curl->setopt(CURLOPT_URL, $url);

	my $response_body = '';
	my $response_header = '';

	$curl->setopt(CURLOPT_WRITEDATA,\$response_body);
	$curl->setopt(CURLOPT_HEADERDATA,\$response_header);
	if ($cookie) {
		$curl->setopt(CURLOPT_COOKIE,"auth_tkt=".uri_escape($cookie));
	}

	my $retcode = $curl->perform;

	if ($retcode != 0) {
		print("An error happened for $url: $retcode ".$curl->strerror($retcode)." ".$curl->errbuf."\n");
		exit 1;
	}

	my $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);
	if ($response_code != $expected_resp) {
		$failed = 1;
		print("url $url, got $response_code but expected $expected_resp\n");
		if ($cookie) {
			print("used ticket $cookie\n");
			print("decoded ticket: '".decode_base64($cookie)."'\n")
		}
		print("Received headers: $response_header\n");
		print("Received response: $response_body\n");
	} else {
		print("url $url: $response_code\n");
	}
}

my $at = Apache::AuthTkt->new(
        conf => '/etc/apache2/mods-available/auth_tkt.conf',
);

sub get_ticket {
	my $opts = shift;
	unless (defined $opts->{"ip_addr"}) {
		$opts->{"ignore_ip"} = 1;
	}
	unless (defined $opts->{"uid"}) {
		$opts->{"uid"} = "someuser";
	}
	return $at->ticket(%$opts);
}

test_url("http://localhost/public/",200);
test_url("http://localhost/anyuser/",403);
test_url("http://localhost/testuser/",403);

# user someuser
my $ticket = get_ticket({});
print "ticket for user someuser\n";

test_url("http://localhost/anyuser/",200,$ticket);
test_url("http://localhost/testuser/",401,$ticket);


# manually try to edit ticket - this should fail
my $decoded = decode_base64($ticket);
$decoded =~ s/someuser/testuser/;
$ticket = encode_base64($ticket);
print "manually modified ticket\n";

test_url("http://localhost/anyuser/",403,$ticket);
test_url("http://localhost/testuser/",403,$ticket);


# user testuser
$ticket = get_ticket({"uid" => "testuser"});
print "ticket for user testuser\n";

test_url("http://localhost/anyuser/",200,$ticket);
test_url("http://localhost/testuser/",200,$ticket);


# expired ticket
$ticket = get_ticket({"ts" => time()-86400});
print "expired ticket\n";

test_url("http://localhost/anyuser/",401,$ticket);
test_url("http://localhost/testuser/",401,$ticket);


# set ip to localhost
$ticket = get_ticket({"ip_addr" => "127.0.0.1"});
print "ticket for ip 127.0.0.1\n";

test_url("http://127.0.0.1/ipcheck/",200,$ticket);
test_url("http://[::1]/ipcheck/",403,$ticket);


# set ip to localhost
$ticket = get_ticket({"ip_addr" => "1.2.3.4"});
print "ticket for ip 1.2.3.4\n";

test_url("http://127.0.0.1/ipcheck/",403,$ticket);
test_url("http://[::1]/ipcheck/",403,$ticket);


if ($failed) {
	print("failures found\n");
	exit($failed);
} else {
	print("all ok\n");
}
