## OpenCA - CA Command
## (c) 1998-2001 by Massimiliano Pala and OpenCA Group
##
##   File Name: bpApproveRenewedCSR
##     Version: $Revision: 1.8 $
##       Brief: approve authorized renewed CSRs
## Description: approve renewed CSRs
##  Parameters: key, dataType, passwd

sub cmdBpApproveRenewedCSR {

## get the parameters
## Get the parameters
my $operator = $query->param('operator');
my $role     = $query->param('role');
my $passwd   = $query->param('passwd');

my ($request, $operator_cert, $operator_serial, $signature, $role_sig, $cert);

if (not $operator or not $role or not $passwd) {
	## must be the startpage

	## load page
	my $page = $tools->getFile( getRequired ('BP_ApproveRenewedCSRSheet'));
	configError (gettext ("Cannot load the form for the batch processor for approving pending certificate requests"))
		if (not $page);

        ## set values
	my $html = $query->newInput (
				-regx   => 'LETTERS',
				-intype => 'textfield',
				-size   => 30,
				-name   => 'operator',
				-check  => 'fill',
				-minlen => 3,
				-value  => $operator);
	$page = $query->subVar($page,'@OPERATOR@', $html);
	$html = $query->newInput (
				-regx=>'LETTERS',
				-intype=>'popup_menu',
				-name=>'role',
				-values=>[loadRoles()],
				-default=>$role);
	$page = $query->subVar($page,'@ROLE@', $html);

	## display
	print $page;

	return 1;
}

print startLogPage (gettext ("Approve Renewed Certificate Requests Batch Processor"));

print addLogSection (gettext ("Operator's serial ... "));
print addLogLine    ($operator);
print closeLogSection ();

print addLogSection (gettext ("Requested role ... "));
print addLogLine    ($role);
print closeLogSection ();

print addLogSection (gettext ("Load Operator's certificate and key ..."));
my $operator_cert = $db->getItem (DATATYPE => "CERTIFICATE", KEY => $operator);
if (not $operator_cert) {
	print addPreLogLine (gettext ("Cannot load operator's certificate from database!"));
	print closeLogSection ();
	print closeLogPage();
	return undef;
}
if (not $operator_cert->getParsed()->{KEY}) {
	print addPreLogLine (gettext ("Operator's certificate doesn't contain a private key!"));
	print closeLogSection ();
	print closeLogPage();
	return undef;
}
print addLogLine (gettext ("ok."));
print closeLogSection ();

my $batch_dir = getRequired ("BP_DIR");
my $tmpdir    = getRequired ("TempDir");

print addLogSection (gettext ("Running batch processor ..."));

## loop
## there can never be a request 0
my $key = 0;
while ($request = $db->getNextItem(DATATYPE => "RENEW_REQUEST", KEY => $key)) {

	$key = $request->getSerial ();

	## get the ID
	my $ID = $request->getParsed()->{DN_HASH}->{CN}[0];

	## build the directory path for the ID
	my $id_dir = $batch_dir;
	my $h_id   = $ID;
	while ($h_id !~ /^$/) {
		$id_dir .= "/".substr $h_id, 0, 1;
		$h_id =~ s/^.//;
	}

	## check for automatic handling
	if (not -d $id_dir) {
		# this is not an error !
		next;
	}

	## check the role
	if ($role ne $tools->getFile ($id_dir."/ROLE")) {
		# this is not an error !
		next;
	}

	## check for the ID
	if (not -f $id_dir."/ID") {
		print addPreLogLine (
                i18nGettext (
                  "CSR __CSR_SERIAL__ ignored because the ID is not present in the directory __DIR__.",
                  "__CSR_SERIAL__", $request->getSerial(),
				  "__DIR__", $id_dir));
		next;
	}
	if ($tools->getFile ($id_dir."/ID") ne $ID) {
		print addPreLogLine (
                i18nGettext (
                  "CSR __CSR_SERIAL__ ignored because the directory __DIR__ and the ID __FILE_ID__ in the file ID don't match",
                  "__CSR_SERIAL__", $request->getSerial(),
				  "__DIR__", $id_dir,
				  "__FILE_ID__", $tools->getFile ($id_dir."/ID")));
		next;
	}

	## check for the DN
	my $DN = $tools->getFile ($id_dir."/data/DN");
	if (not $DN) {
		print addPreLogLine (
                i18nGettext (
                  "CSR __CSR_SERIAL__ ignored because the DN is not present in the directory __DIR__.",
                  "__CSR_SERIAL__", $request->getSerial(),
				  "__DIR__", $id_dir));
		next;
	}

	## check for the SUBJECT_ALT_NAME
	my $SUBJECT_ALT_NAME = $tools->getFile ($id_dir."/data/SUBJECT_ALT_NAME");
	if (not $SUBJECT_ALT_NAME) {
		print addPreLogLine (
                i18nGettext (
                  "CSR __CSR_SERIAL__ ignored because the SUBJECT_ALT_NAME is not present in the directory __DIR__.",
                  "__CSR_SERIAL__", $request->getSerial(),
				  "__DIR__", $id_dir));
		next;
	}

	## check for the permission
	if (not -f $id_dir."/acl/approveRenewedCSR") {
		# this is not an error !
		next;
	}

	## compare the hashed PINs
	if (not -f $id_dir."/public/hashedPIN") {
		print addPreLogLine (
                i18nGettext (
                  "CSR __CSR_SERIAL__ ignored because the hashed PIN is not present in the directory __DIR__.",
                  "__CSR_SERIAL__", $request->getSerial(),
				  "__DIR__", $id_dir));
		next;
	}
	if ($tools->getFile ($id_dir."/public/hashedPIN") ne
	    $request->getParsed()->{HEADER}->{PIN}) {
		print addPreLogLine (
                i18nGettext (
                  "CSR __CSR_SERIAL__ ignored because the hashed PIN is __PIN__ in the request and __FILE_PIN__ in the file __FILE__",
                  "__CSR_SERIAL__", $request->getSerial(),
				  "__PIN__", $request->getParsed()->{HEADER}->{PIN},
				  "__FILE_PIN__", $tools->getFile ($id_dir."/public/hashedPIN"),
                  "__FILE__", $id_dir."/public/hashedPIN"));
		next;
	}

	## build request
	my ($header, $text);

	my $beginHeader = "-----BEGIN HEADER-----";
	my $endHeader   = "-----END HEADER-----";
	my $parsed_req  = $request->getParsed();

	$header  = "$beginHeader\n";
	$header .= "TYPE = $parsed_req->{TYPE}\n";
	$header .= "RA = $parsed_req->{HEADER}->{RA}\n";
	$header .= "SERIAL = ".$request->getSerial()."\n";
	$header .= "RENEW = ".$parsed_req->{HEADER}->{RENEW}."\n" if ($parsed_req->{HEADER}->{RENEW});
	$header .= "OPERATOR = ".$operator."\n"
		if ($operator);
	$header .= "NOTBEFORE = $parsed_req->{HEADER}->{NOTBEFORE}\n";
	$header .= "APPROVED = ".$tools->getDate()."\n";
	$header .= "PIN = $parsed_req->{HEADER}->{PIN}\n";
	$header .= "SUBJECT = $DN\n";
	$header .= "ROLE = $role\n";
	$header .= "SUBJECT_ALT_NAME = $SUBJECT_ALT_NAME\n";
	$header .= "$endHeader\n";

	$text = $parsed_req->{BODY};

	my $text_req = $header.$text;

	## sign
	if (not $cryptoShell->sign (
				DATA     => $text_req,
				KEY      => $operator_cert->getParsed()->{KEY},
				CERT     => $operator_cert->getPEM(),
				OUT_FILE => $tmpdir."/${$}_request.sig",
				PASSWD   => $passwd)) {
		print addPreLogLine ("<FONT COLOR=#FF0000>".
			    i18nGettext (
                  "Signing of the request __CSR_SERIAL__ failed. Aborting for security reasons.",
                  "__CSR_SERIAL__", $request->getSerial()).
			    "</FONT>");
		print closeLogSection ();
		print closePage ();
		return undef;
	}

	## build new request object
	$text_req .= "\n".$tools->getFile ($tmpdir."/${$}_request.sig");
	if ($text_req eq $header.$text."\n") {
		print addPreLogLine ("<FONT COLOR=#FF0000>".
			    i18nGettext (
                  "Signing of the request __CSR_SERIAL__ failed. Cannot read signature from file __FILE__. Aborting for security reasons.",
                  "__CSR_SERIAL__", $request->getSerial(),
                  "__FILE__", $tmpdir."/${$}_request.sig").
			    "</FONT>");
		print closeLogSection ();
		print closePage ();
		return undef;
	}
	my $inform;
	if( $request->getParsed()->{HEADER}->{TYPE} =~ /(PKCS#10|IE)/i ) {
	        $inform = "PEM";
	} else {
        	$inform = $parsed_req->{HEADER}->{TYPE};
	}
	my $new_req = new OpenCA::REQ ( SHELL=>$cryptoShell, INFORM=>$inform, DATA=>$text_req );

	## update database
	if ( not $db->updateStatus (
			DATATYPE=>"RENEW_REQUEST",
			OBJECT => $new_req,
			NEWTYPE=>"APPROVED_REQUEST") ) {
		print addPreLogLine ("<FONT COLOR=#FF0000>".
			    i18nGettext (
                  "Cannot update the status of the request __CSR_SERIAL__. Aborting for security reasons.",
                  "__CSR_SERIAL__", $request->getSerial()).
			    "</FONT>");
		print closeLogSection ();
		print closePage ();
		return undef;
	}

	## remove .renewedCSR
	unlink ($id_dir."/acl/renewedCSR");

	##// add the request's serial to the list
	$tools->saveFile (FILENAME => $id_dir."/public/csrList",
			DATA       => $new_req->getSerial()."\n".$tools->getFile ($id_dir."/public/csrList"));

	print addPreLogLine (i18nGettext ("ID: __ID__ - automatically approved", "__ID__", $ID));

}

print addPreLogLine ("");
print addLogLine (gettext ("Batch processor finished"));
print closeLogSection ();

print closePage();

}

1;
