## OpenCA - CA Command
## (c) 1998-2001 by Massimiliano Pala and OpenCA Group
##
##   File Name: bpRecoverCert
##     Version: $Revision: 1.6 $
##       Brief: recover Keypairs for users
## Description: 
##  Parameters:

sub cmdBpRecoverCert {

## datadirectory for the batchprocessor
my $batch_dir  = getRequired ("BP_DIR");
my $tempDir    = getRequired ("TempDir");
my $cacert     = getRequired ('CACertificate');

my $passwd      = $query->param ('passwd');
my $cert_serial = $query->param ('key');
my $format      = $query->param ('format');
my $id          = $query->param ('id');

## 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/^.//;
}

## load the pin
my $pin = $cryptoShell->getSMIME (
                                  DECRYPT    => 1,
                                  CERT       => getRequired ("BP_CERTIFICATE"),
                                  KEY        => getRequired ("BP_KEY"),
                                  USE_ENGINE => 1,
                                  PASSWD     => $query->param ('passwd'),
                                  INFILE     => $id_dir."/private/purePIN",
                                  );
( $pin ) = ( $pin =~ /-----BEGIN PIN-----[\n\r]*([^\n\r]*)[\n\r]*-----END PIN-----/i);
if (not $pin) {
	print addPreLogLine (
	          "<FONT COLOR=#FF0000>".
	          i18nGettext (
		      "Cannot load the PIN because the decryption of the PIN failed - ID __ID__ ignored.",
	              "__ID__", $id).
	          "</FONT>");
	return;
}

## load certificate
my $cert = $db->getItem (DATATYPE=>'CERTIFICATE', KEY=>$cert_serial);
if (not $cert) {
	print "Content-type: text/html\n\n";
	generalError (
		i18nGettext (
          "Cannot recover key because the loading of the certificate __CERT_SERIAL__ failed - ID __ID__ ignored.",
          "__CERT_SERIAL__", $cert_serial,
          "__ID__", $id));
}

## load the digest of the key
my $filename = $id_dir."/keybackup/csr_".$cert->getParsed()->{HEADER}->{CSR_SERIAL}.".keydigest";
my $digest = $tools->getFile ($filename);
if (not $digest) {
	print "Content-type: text/html\n\n";
	generalError (
		i18nGettext (
          "Cannot recover key because the loading of the digest of the private key failed (__FILE__) - ID __ID__ ignored.",
          "__FILE__", $filename,
          "__ID__", $id));
}

## decrypt the key
my $msg = $cryptoShell->getSMIME (
                                  DECRYPT    => 1,
                                  CERT       => getRequired ("KEY_BACKUP_CERTIFICATE"),
                                  KEY        => getRequired ("KEY_BACKUP_KEY"),
                                  USE_ENGINE => 1,
                                  PASSWD     => $query->param ('passwd'),
                                  INFILE     => $id_dir."/keybackup/$digest.msg",
                                  );
if (not $msg) {
	print "Content-type: text/html\n\n";
	generalError (
		i18nGettext (
		  "Cannot recover key because the decryption of the private key failed - ID __ID__ ignored.",
          "__ID__", $id));
}
$msg =~ s/^.*-----BEGIN PRIVATE KEY-----/-----BEGIN PRIVATE KEY-----/;
$msg =~ s/-----END PRIVATE KEY-----.*$/-----BEGIN PRIVATE KEY-----/;

if ($format =~ /PKCS12/i) {

	## BUG-WARNING: OpenSSL cannot handle keys from stdin
	$tools->saveFile ( FILENAME => "$tempDir/${$}_key.pem", DATA => $msg);

	my $p12_data = $cryptoShell->dataConvert (
		DATA      => $cert->getPEM(),
		DATATYPE  => "CERTIFICATE",
		KEYFILE   => $tempDir."/${$}_key.pem",
		INFORM    => "PEM",
		OUTFORM   => "PKCS12",
		PASSWD    => "",
		P12PASSWD => $pin,
		CACERT    => $cacert);

	if (not unlink ("$tempDir/${$}_key.pem")) {
		print "Content-type: text/html\n\n";
		generalError ("<b><FONT COLOR=#ff0000>".
            i18nGettext (
              "WARNING: Private key is in clear text on disk - __FILE__!",
              "__FILE__", "$tempDir/${$}_key.pem").
				"</FONT></b>");
	} elsif (not $p12_data) {
		print "Content-type: text/html\n\n";
		generalError (gettext ("Cannot convert PEM-certificate and PKCS#8-key to PKCS#12-formatted file!"));
	} else {
		print "Content-type: application/x-pkcs12\n\n";
		print $p12_data;
	}
} elsif ($format =~ /(PKCS8|OpenSSL)/i) {

	if ($format =~ /PKCS8/i) {
		$format = "PKCS8";
	} else {
		$format = "PEM";
	}

	my $data = $cryptoShell->dataConvert (
		DATA      => $msg,
		DATATYPE  => "KEY",
		INFORM    => "PEM",
		OUTFORM   => $format,
		INPASSWD  => "",
		OUTPASSWD => $pin);

	if (not $data) {
		print "Content-type: text/html\n\n";
		generalError (gettext ("Cannot convert private key!")."<br>\n".
				$OpenCA::OpenSSL::errval, $OpenCA::OpenSSL::errno);
	}

	##// if we use the correct content-type and don't use 
	## (shift + left mouse button) then netscape tries to import the cert
	## without the key
	## print "Content-type: application/x-X509-user-cert\n\n";
	print "Content-type: text/plain\n\n";
	print $cert->getPEM();
	print $data;
} else {
	## undefined format
	print "Content-type: text/html\n\n";
	generalError (i18nGettext ("Cannot convert because the outputformat is unknown (format: __FORMAT__)!",
                               "__FORMAT__", $format));
}

}

1;
