#!/usr/bin/perl
use Time::Piece;
use Crypt::OpenSSL::X509;
use DBI;
use Nivlheim::Database;

# If the client cert will expire soon, politely ask it to renew
my $timestamp = $ENV{'SSL_CLIENT_V_END'};
$timestamp =~ s/\s+GMT$//;
my $time = Time::Piece->strptime($timestamp, "%b %d %H:%M:%S %Y");
my $left = $time - gmtime;
if ($left->days < 30) {
	print "Status: 400\r\nContent-Type: text/plain\r\n\r\nYour certificate is about to expire, please renew it.\n";
	exit;
}

# If the client cert was signed by a different CA than the one that's currently active,
# politely ask it to renew
my $clientcert = $ENV{'SSL_CLIENT_CERT'};
my $x509 = Crypt::OpenSSL::X509->new_from_string($clientcert);
my $value1 = $x509->issuer();
my $ca = Crypt::OpenSSL::X509->new_from_file('/var/www/nivlheim/CA/nivlheimca.crt');
my $value2 = $ca->subject();
if ($value1 ne $value2) {
	print "Status: 400\r\nContent-Type: text/plain\r\n\r\nThe server has a new CA certificate, please renew your certificate.\n";
	exit;
}

# Compute the client cert fingerprint
my $fingerprint = $x509->fingerprint_sha1();
$fingerprint =~ s/://g;

# Check revoked status
my $dbh = Nivlheim::Database->connect_to_db();
my @row = $dbh->selectrow_array(
	"SELECT revoked FROM certificates WHERE fingerprint=?",
	undef, ($fingerprint));
if (@row && $row[0]) {
	# This certificate is revoked. Reject the client
	print "Status: 403\r\nContent-Type: text/plain\r\n\r\nYour certificate has been revoked.\n";
	$dbh->disconnect;
	exit;
}

# Check if the machine has been renamed (compare commonname with the current hostname)
my $cn = "";
if ($x509->subject() =~ /CN=(\S+)/) { $cn = $1; }
@row = $dbh->selectrow_array("SELECT hostname FROM hostinfo WHERE certfp=?",
	undef, ($fingerprint));
if (@row && defined($row[0]) && $row[0] !~ /^\s*$/ && $row[0] ne $cn) {
	# The machine has been renamed. It should renew its certificate.
	print "Status: 403\r\nContent-Type: text/plain\r\n\r\nPlease renew your certificate.\n";
	$dbh->disconnect;
	exit;
}

$dbh->disconnect;
print "Content-Type: text/plain\r\n\r\npong\n";
