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

sub cmdBpBackupKey {

	print startLogPage (gettext ("Backup Keypair Batch Processor"));

	## datadirectory for the batchprocessor
	my $batch_dir  = getRequired ("BP_DIR");

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

	bpScanDir ($batch_dir, "bpBackupKey");

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

	print closePage();

}

sub bpBackupKey {
	my $dir = $_[0];

	return if (not -f $dir."/ID");

	## use DENY, ALLOW or other keyword without deny and force, FORCE
	if (-e $dir."/acl/backupKey") {
		if (getRequired ("BP_KEY_BACKUP_MODE") =~ /DENY/i) {
			print addPreLogLine ("<FONT COLOR=#FF0000>".
			          i18nGettext (
			              "Cannot backup key because it is generally forbidden - ID __ID__ ignored.",
			              "__ID__", $tools->getFile ($dir."/ID")).
			          "</FONT>");
			return;
		}
	} else {
		if (getRequired ("BP_KEY_BACKUP_MODE") =~ /FORCE/i) {
			## print addPreLogLine ("<FONT COLOR=#00FF00>".
			## 	"Key backup is generally required but for this user not explicit allowed".
			## 	" - try to create a key backup for ID ".$tools->getFile ($dir."/ID")." ...".
			## 	"</FONT>");
		} else {
			return;
		}
	}

	## check that the directory for the keybackup is present
	if (not -d $dir."/keybackup") {
		if (not (umask 0077) or not (mkdir $dir."/keybackup")) {
			print addPreLogLine ("<FONT COLOR=#FF0000>".
			          i18nGettext (
			              "Cannot backup key because the generation of the directory for the keybackups (__DIR__) failed - ID __ID__ ignored.",
			              "__DIR__", $dir/keybackup,
			              "__ID__", $tools->getFile ($dir."/ID")).
			              "</FONT>");
			return;
		}
		umask 0177;
	}

	## check for ID
	if (-f $dir."/private/purePIN") {

		## permissions were already checked

		## load the key
		my $private_key = $tools->getFile ($dir."/private/privateKey");
		if (not $private_key) {
			print addPreLogLine ("<FONT COLOR=#FF0000>".
			          i18nGettext (
			              "Cannot backup key because the loading of the private key failed - ID __ID__ ignored",
			              "__ID__", $tools->getFile ($dir."/ID")).
			          "</FONT>");
			return;
        	}

		## get a hash from the key
		my $digest = $cryptoShell->getDigest (DATA      => $private_key,
		                                      ALGORITHM => "sha1");

		## check that the key is not already backuped
		my $filename = $dir."/keybackup/".$digest.".msg";
		if (-f $filename) {
			## print addPreLogLine (
			## 	"Cannot backup key because it is already backuped".
			## 	" - ID ".$tools->getFile ($dir."/ID")." ignored.");
			return;
		}

		## get an unencrypted key
		my $PIN = $cryptoShell->getSMIME (
		                                  DECRYPT    => 1,
		                                  CERT       => getRequired ("BP_CERTIFICATE"),
		                                  KEY        => getRequired ("BP_KEY"),
		                                  USE_ENGINE => 1,
		                                  PASSWD     => $query->param ('passwd'),
		                                  INFILE     => $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__", $tools->getFile ($dir."/ID")).
			          "</FONT>");
			return;
		}
		my $clear_key = $cryptoShell->dataConvert (DATATYPE  => "KEY",
		                                           INFORM    => "PEM",
		                                           OUTFORM   => "PKCS8",
		                                           INPASSWD  => $PIN,
		                                           OUTPASSWD => "",
		                                           DATA      => $private_key );
		if (not $clear_key) {
			print addPreLogLine ("<FONT COLOR=#FF0000>".
			          i18nGettext (
			               "Cannot backup key because the decryption of the private key failed - ID __ID__ ignored.",
			               "__ID__", $tools->getFile ($dir."/ID")).
			          "</FONT>");
			return;
		}

		## encrypt the key
		if (not $cryptoShell->getSMIME (
		                                ENCRYPT      => 1,
		                                ENCRYPT_CERT => getRequired ("KEY_BACKUP_CERTIFICATE"),
		                                DATA         => $clear_key,
		                                OUTFILE      => $filename,
		                                TO           => getRequired ("SERVICE_MAIL_ACCOUNT"),
		                                FROM         => getRequired ("SERVICE_MAIL_ACCOUNT"),
		                                SUBJECT      => "Key backup")) {
			print addPreLogLine ("<FONT COLOR=#FF0000>".
			          i18nGettext (
			              "Cannot backup key because the encryption of the private key failed - ID __ID__ ignored.",
			              "__ID__", $tools->getFile ($dir."/ID")).
			        "</FONT>");
			return;
		}

		## remove permission to generate this new key
		if (-f $dir."/acl/backupKey" and not unlink ($dir."/acl/backupKey")) {
			print addPreLogLine ("<FONT COLOR=#FF0000>".
			          i18nGettext (
			              "Cannot remove permission to backup key but the key was already backuped - ID __ID__ ignored.",
			              "__ID__", $tools->getFile ($dir."/ID")).
			        "</FONT>");
			return;
		}

		print addPreLogLine (i18nGettext ("Backuped key for ID __ID__.", "__ID__", $tools->getFile ($dir."/ID")));

	}
}

1;
