## OpenCA - Public Web-Gateway Command
## (c) 1998-2001 by OpenCA Group
##
##   File Name: changeCRR
##       Brief: change a pending CRR
## Description: store an edited pending CRR
##  Parameters: head, text

sub cmdChangeCRR {

## To aprove a Request, we need it signed by the RA operator
my $beginHeader = "-----BEGIN HEADER-----";
my $endHeader   = "-----END HEADER-----";

## Reserved variables
my ( $head, $text, $signature, $cert, $certTable );

## Get the parameters
my $serial      = $query->param('serial');
my $crr_serial	= $query->param('crr_serial');
my $reason	= $query->param('reason');

my $crr;
if ($crr_serial) {
	$crr = $db->getItem ( DATATYPE => "PENDING_CRR", KEY => $crr_serial );
	if (not $crr) {
		configError (gettext ("Cannot load CRR from database!"));
	}
	$serial = $crr->getParsed()->{REVOKE_CERTIFICATE_SERIAL};
}

## download the certificate
my $cert = $db->getItem ( DATATYPE => "CERTIFICATE", KEY => $serial );
if (not $cert) {
	##// it's not good to show the user the detailed problem
	configError (i18nGettext ("Error: Cannot find the certificate __CERT_SERIAL__ in the database.",
                                    "__CERT_SERIAL__", $serial));
}
my $parsed = $cert->getParsed();

## Strip html and \n\r code from reason
$reason =~ s/<[^\>]*>/ /g;
$reason =~ s/(\n|\r)/ /g;
$reason =~ s/^\s+//g;
$reason =~ s/[\s]+/ /g;

## variables
if ($crr) {
	## build header
	$head  = "$beginHeader\n";
	$head .= "TYPE = CRR\n";
	$head .= "SERIAL = $crr_serial\n";
	$head .= "SSL_CERT_SERIAL = ".$crr->getParsed()->{HEADER}->{SSL_CERT_SERIAL}."\n";
	$head .= "SSL_CERT_DN = ".$crr->getParsed()->{HEADER}->{SSL_CERT_DN}."\n";
	$head .= "SSL_CERT_ISSUER = ".$crr->getParsed()->{HEADER}->{SSL_CERT_ISSUER}."\n";
	$head .= "$endHeader\n";
	## build body
	$text .= "SUBMIT_DATE = " . $crr->getParsed()->{SUBMIT_DATE}. "\n";
	$text .= "CRIN = ".$crr->getParsed()->{CRIN}."\n";
	$text .= "REVOKE_REASON = $reason\n";
	$text .= "REVOKE_CERTIFICATE_DN = " . $crr->getParsed()->{REVOKE_CERTIFICATE_DN} . "\n";
	$text .= "REVOKE_CERTIFICATE_NOTBEFORE = " . $crr->getParsed()->{REVOKE_CERTIFICATE_NOTBEFORE} . "\n";
	$text .= "REVOKE_CERTIFICATE_NOTAFTER = " . $crr->getParsed()->{REVOKE_CERTIFICATE_NOTAFTER} . "\n";
	$text .= "REVOKE_CERTIFICATE_SERIAL = " . $crr->getParsed()->{REVOKE_CERTIFICATE_SERIAL} . "\n";
	$text .= "REVOKE_CERTIFICATE_ISSUER_DN = " . $crr->getParsed()->{REVOKE_CERTIFICATE_ISSUER_DN} . "\n";
	$text .= "REVOKE_CERTIFICATE_KEY_DIGEST = " . $crr->getParsed()->{REVOKE_CERTIFICATE_KEY_DIGEST} . "\n";
} else {
	## Get the certificate serial number of the submitter
	my $sslCert  =($ENV{'SSL_CLIENT_CERT_SERIAL'} or $ENV{'SSL_CLIENT_M_SERIAL'});
	my $sslDn    = $ENV{'SSL_CLIENT_S_DN'};
	my $issuerDn = $ENV{'SSL_CLIENT_I_DN'};

	$sslDn =~ s/^\///;
	$sslDn =~ s/\/([^=]+)=/\, $1=/g;

	$issuerDn =~ s/^\///;
	$issuerDn =~ s/\/([^=]+)=/\, $1=/g;

	if( $sslCert eq "" ) {
	        $sslCert = "n/a";
	} else {
	        if ( length( $sslCert ) % 2 ) {
	                $sslCert = "0" . $sslCert;
	        }
	}

	my $last_crr = libDBGetLastItem ("CRR");
	my $crr_serial = 0;
	$crr_serial    = $last_crr->getSerial("CRR") if ($last_crr);
	$crr_serial  >>= getRequired ("ModuleShift");
	if (not $serial) {
		##// it's not good to show the user the detailed problem
		## this is a security problem here !!!
		print STDERR "SECURITY ALERT BY PKI: correct CRR cannot be stored because of DB-error (certificate: $serial)\n";
		configError (gettext ("A databaseerror occurs during counting the existing CRRs!"));
	}
	$crr_serial++;
	$crr_serial = ($crr_serial << getRequired ("ModuleShift")) | getRequired ("ModuleID");

	## Set Text to sign
	$head  = "$beginHeader\n";
	$head .= "TYPE = CRR\n";
	$head .= "SERIAL = $crr_serial\n";
	$head .= "SSL_CERT_SERIAL = $sslCert\n";
	$head .= "SSL_CERT_DN = $sslDn\n";
	$head .= "SSL_CERT_ISSUER = $issuerDn\n";
	$head .= "$endHeader\n";

	$text .= "SUBMIT_DATE = " . $tools->getDate() . "\n";
	$text .= "CRIN = $crin\n";
	$text .= "REVOKE_REASON = $reason\n";
	$text .= "REVOKE_CERTIFICATE_DN = " . $parsed->{DN} . "\n";
	$text .= "REVOKE_CERTIFICATE_NOTBEFORE = " . $parsed->{NOTBEFORE} . "\n";
	$text .= "REVOKE_CERTIFICATE_NOTAFTER = " . $parsed->{NOTAFTER} . "\n";
	$text .= "REVOKE_CERTIFICATE_SERIAL = " . $cert->getSerial() . "\n";
	$text .= "REVOKE_CERTIFICATE_ISSUER_DN = " . $parsed->{ISSUER} . "\n";
	$text .= "REVOKE_CERTIFICATE_KEY_DIGEST = " . $parsed->{KEY_DIGEST} . "\n";
}


## Load base page
my $page = $tools->getFile ( $basedoc );
if ( not $page ) {
	configError (i18nGettext ("Cannot load file __FILE__!", "__FILE__", $page));
}

my $req_txt = $head . $body;

## check for the old request
my $list = $db->getItem (DATATYPE => "CRR", KEY => $req->getSerial());

## attach the signatures
$req_txt .= $h->getParsed()->{SIGNATURE};

## Try to build the REQ object
my $req = new OpenCA::REQ ( SHELL=>$cryptoShell, DATA=>$req_txt );

if( not $req ) {
	configError (gettext ("Error while creating the request."));
}

## download the certificate
my $cert = $db->getItem ( DATATYPE => "CERTIFICATE", KEY => $req->getParsed()->{REVOKE_CERTIFICATE_SERIAL} );
if (not $cert) {
	##// it's not good to show the user the detailed problem
	my $basedoc = getRequired ('db_error');
	print $tools->getFile ( $basedoc );
	return undef;
}

if ( not $db->storeItem( OBJECT=>$req, DATATYPE=>"PENDING_CRR", MODE => "UPDATE" )) {
	if ( not $db->storeItem( OBJECT=>$req, DATATYPE=>"PENDING_CRR", MODE => "INSERT" )) {
		print STDERR "SECURITY ALERT BY PKI: database failed during storing a correct CRR which follows\n".
			$req_txt."\n";
		configError (gettext ("Error while storing the request."));
	}
}

$cmd = "viewCRR";

if ( getRequired ('RBAC') =~ /^(YES|ON)$/i ) {
	if (not grantAccess (	SCRIPT => $cmd,
				MODULE => getRequired ('RBAC_MODULE'),
				SERIAL => $ENV{'SSL_CLIENT_M_SERIAL'})
	) {
		configError (gettext ("Access Denied!"));
	}
}

libDoCommand ("viewCSR");

}

1;
