#!/usr/bin/perl
##############################################################
# (C) Written 2017 by Daniel Rohde <d.rohde@cms.hu-berlin.de>
##############################################################
# This script gets user cert from DFN PCA and writes it to
# a PEM file (<cn>.pem).
##############################################################
use strict;
use warnings;

our $VERSION = '1.0';

use Carp;
use Net::LDAP;
use English qw( -no_match_vars );

use vars qw( $LDAPSERVER $BASEDN $OPENSSL );

$LDAPSERVER = 'ldap1.pca.dfn.de';
$BASEDN     = 'o=Humboldt-Universitaet zu Berlin,ou=DFN-PKI,o=DFN-Verein,c=de';

$OPENSSL = '/usr/bin/openssl';

exit ! main(); 

sub main {
    return save_cert_pem( get_cert_from_ldap( get_email_from_arg() ) );
}

sub get_email_from_arg {
    if ( @ARGV != 1 ) {
        croak("Usage: $PROGRAM_NAME <email address>\n");
    }
    return $ARGV[0];
}

sub get_cert_from_ldap {
    my ($mail) = @_;
    my $pubkey = q{};
    my $cn     = q{};
    my $ldap = Net::LDAP->new($LDAPSERVER) or croak($EVAL_ERROR);
    $ldap->bind;
    my $msg = $ldap->search( base => $BASEDN, filter => "mail=$mail", attrs => [qw(userCertificate mail cn)] );
    foreach my $entry ( $msg->entries ) {
        if ( $entry->get_value('mail') eq $mail ) {
            $pubkey = $entry->get_value('userCertificate;binary');
            $cn     = $entry->get_value('cn');
        }
    }
    if ( $pubkey eq q{} ) {
        croak("Cannot find user certificate for email $mail.\n");
    }
    return ( $pubkey, $cn, $mail );

}

sub save_cert_pem {
    my ( $key, $cn, $mail ) = @_;
    my $keyfile = "$cn.pem";
    print "Saving keyfile for $cn <$mail> to $keyfile...\n";
    my $ret = 1;
    if ( open my $in, q{|-}, "$OPENSSL x509 -inform DER -outform PEM -out '$keyfile'" ) {
        print {$in} $key;
        close($in) || carp("Cannot close STDIN of $OPENSSL.");
        print "done.\n";
    }
    else {
        carp("Cannot start $OPENSSL.");
        $ret = 0;
    }
    return $ret;
}
