#!/usr/bin/perl -w

#----------------------------------------------------------------------
# copyright (C) 1999-2003 Mitel Networks Corporation
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 		
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 		
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
# 
# Technical support for this program is available from Mitel Networks 
# Please visit our web site www.mitel.com/sme/ for details.
#----------------------------------------------------------------------
package esmith;

use strict;
use Errno;
use esmith::ConfigDB;

my $event = $ARGV[0] || "Unknown";

use constant KEYLIFEINDAYS => 365;

my $conf = esmith::ConfigDB->open or die "Could not open config DB\n";;

#--------------------------------------------------------------
# There is no point in generating a certificate until we
# know details about the machine. Let it happen in
# [bootstrap-]console-save
#--------------------------------------------------------------
exit 0 if ($event =~ /^post-(install|upgrade)$/ );

my $modSSL = $conf->get('modSSL');
my $serviceStatus = $modSSL->prop('status') || 'disabled';

my $FQDN = $conf->get_value('SystemName') . '.' .  $conf->get_value('DomainName');

if ($serviceStatus eq "enabled")
{

    my $key = "/home/e-smith/ssl.key/$FQDN.key";
    my $crt = "/home/e-smith/ssl.crt/$FQDN.crt";

    my $customKey = $modSSL->prop("key");
    my $customCrt = $modSSL->prop("crt");

    if ( -f $key and -f $crt )
    {
	exit 0 if ( -M $key < KEYLIFEINDAYS and -M $crt < KEYLIFEINDAYS );
    }

    unless ($customKey)
    {
	# go to somewhere private and safe where we can run programs
	# as root
	unless (-e "/tmp/ssl")
	{
	    mkdir "/tmp/ssl", 0700;
	}
	chdir "/tmp/ssl";
	if (-e $crt)
	{
		# delete certificate - it is useless without the key
		unlink ($crt);
	}
	unless (-d "/home/e-smith/ssl.key")
	{
	    mkdir "/home/e-smith/ssl.key", 0700;
	}

	my $program = "/usr/bin/openssl";

	$SIG{ALRM} = sub { die "whoops, $program pipe broke" };

	my @options =
	(
	    qw(genrsa -rand),
	    join(':',
		qw(
		    /proc/apm
		    /proc/cpuinfo
		    /proc/dma
		    /proc/filesystems
		    /proc/interrupts
		    /proc/ioports
		    /proc/bus/pci/devices
		    /proc/rtc
		    /proc/uptime
		)),
	    '1024'
	);

	my $pid = fork;
	if ($pid)
	{
	    # parent
	    waitpid($pid,0);
	}
	else
	{
	    # child
	    open STDOUT, ">$key"
		  or die "Can't write to $key: $!";
	    chmod 0400, $key;
	    exec($program, @options)
		|| die "can't exec program: $!";
	    # NOTREACHED
	}
    }
    unless ($customCrt)
    {
	unless (-d "/home/e-smith/ssl.crt")
	{
	    mkdir "/home/e-smith/ssl.crt", 0700;
	}

	my $program = "/usr/bin/openssl";

	my @options =
	(
	    qw(req -new -key),
	    $key,
	    qw(-x509 -days), 
	    KEYLIFEINDAYS,
	    qw(-out),
	    $crt
	);

	my $ldap = $conf->get('ldap');
	my $defaultCity = $ldap->prop('defaultCity');
	my $defaultCompany = $ldap->prop('defaultCompany');
	my $defaultDepartment = $ldap->prop('defaultDepartment');
	my $email = "admin\@$FQDN";

	# anonymous sub to crop a variable to a specified size
	my $cropLeft = sub { 
	    my ($var, $len) = @_;
	    if (length($var) > $len) { 
		$var = substr($var, 0, $len);
	    }
	    return $var;
	};

	# crop fields that are too long for X509:
	$defaultCity = &$cropLeft($defaultCity, 128); 
	$defaultCompany = &$cropLeft($defaultCompany, 64); 
	$defaultDepartment = &$cropLeft($defaultDepartment, 64); 
	$FQDN = &$cropLeft($FQDN, 64);
	$email = &$cropLeft($email, 40);

	my @data =
	(
	    "--\n",
	    "----\n",
		"$defaultCity\n",
		"$defaultCompany\n",
		"$defaultDepartment\n",
                "$FQDN\n",
		"$email\n"
	);

	$SIG{ALRM} = sub { die "whoops, $program pipe broke" };

	my $pid = open(RSACERT, "|-");
	if ($pid)
	{
	    # parent
	    for (@data)
	    {
		print RSACERT;
	    }
	    close(RSACERT) || warn "kid exited $?";

	}
	else
	{
	    # child
	    exec($program, @options)
		|| die "can't exec program: $!";
	    # NOTREACHED
	}
    }
}

exit (0);
