## OpenCA - Command
## (c) 1998-2001 by Massimiliano Pala and OpenCA Group
##
##   File Name: viewCSR
##       Brief: View Request
## Description: Display given Request to the CA Manager
##  Parameters: dataType, key

sub cmdViewCSR {

## Get the Configuration parameters ...
my ( $ou, $ouList, $def, $op, $opCert, $info, $opStatus, $dnLabel);
my ( $sigStatus, $signer, $signature, $myRenew, $myCN, $myEmail, @myDnInfo, $subjectAltName );
my ( @opCertList, $reqDataTable, @cols, $opCert, $serLink, $lnk, $sigInfo );
my ( %labels, @values, $role );
my ( $reqStatus, $cmdsPanel, $reqDesc );

my $dataType = $query->param('dataType' );
my $key      = $query->param('key');

## Required Configuration Key
my $sheetsDir	= getRequired( 'SheetsDir' );
my $includeDir	= getRequired( 'IncludeDir' );
my $txtDir	= getRequired( 'TextDir' );
my $baseDoc	= getRequired('ViewCSRSheet');

my $automatic_subject_alt_name = getRequired ('AUTOMATIC_SUBJECT_ALT_NAME');
my $default_subject_alt_name   = getRequired ('DEFAULT_SUBJECT_ALT_NAME');

configError( gettext ("Error, needed dB key!") ) if ( not $key );

if ( $dataType eq "PENDING_REQUEST" ) {
	$reqStatus = gettext("Waiting for Approval");
	$cmdsPanel = "$includeDir/pending_cmds.inc";
	$reqDesc   = "$txtDir/pending_desc.txt";
} elsif ( $dataType eq "RENEW_REQUEST" ) {
	$reqStatus = gettext("Renewal Request Waiting for Approval");
	$cmdsPanel = "$includeDir/pending_cmds.inc";
	$reqDesc   = "$txtDir/pending_desc.txt";
} elsif ( $dataType eq "DELETED_REQUEST" ) {
	$reqStatus = gettext("Deleted Request");
	$cmdsPanel = "$includeDir/deleted_cmds.inc";
	$reqDesc   = "$txtDir/deleted_desc.txt";
} elsif ( $dataType eq "APPROVED_REQUEST" ) {
	$reqStatus = gettext("Approved Request");
	$cmdsPanel = "$includeDir/approved_cmds.inc";
	$reqDesc   = "$txtDir/approved_desc.txt";
} elsif ( $dataType eq "ARCHIVED_REQUEST" ) {
	$reqStatus = gettext("Archived Request");
	$cmdsPanel = "$includeDir/archived_cmds.inc";
	$reqDesc   = "$txtDir/archived_desc.txt";
} elsif ( $dataType eq "REQUEST" ) {
	## try to determine the datatype
	if ($db->getItem ( DATATYPE => "ARCHIVED_REQUEST", KEY => $key )) {
		$dataType = "ARCHIVED_REQUEST";
		$reqStatus = gettext ("Archived Request");
		$cmdsPanel = "$includeDir/archived_cmds.inc";
		$reqDesc   = "$txtDir/archived_desc.txt";
	} elsif ($db->getItem ( DATATYPE => "APPROVED_REQUEST", KEY => $key )) {
		$dataType = "APPROVED_REQUEST";
		$reqStatus = gettext("Approved Request");
		$cmdsPanel = "$includeDir/approved_cmds.inc";
		$reqDesc   = "$txtDir/approved_desc.txt";
	} elsif ($db->getItem ( DATATYPE => "DELETED_REQUEST", KEY => $key )) {
		$dataType = "DELETED_REQUEST";
		$reqStatus = gettext("Deleted Request");
		$cmdsPanel = "$includeDir/deleted_cmds.inc";
		$reqDesc   = "$txtDir/deleted_desc.txt";
	} elsif ($db->getItem ( DATATYPE => "RENEW_REQUEST", KEY => $key )) {
		$dataType = "RENEW_REQUEST";
		$reqStatus = gettext("Renewal Request Waiting for Approval");
		$cmdsPanel = "$includeDir/pending_cmds.inc";
		$reqDesc   = "$txtDir/pending_desc.txt";
	} elsif ($db->getItem ( DATATYPE => "PENDING_REQUEST", KEY => $key )) {
		$dataType = "PENDING_REQUEST";
		$reqStatus = gettext("Waiting for Approval");
		$cmdsPanel = "$includeDir/pending_cmds.inc";
		$reqDesc   = "$txtDir/pending_desc.txt";
	} else {
		configError ( gettext("Cannot determine status of this request!"));
	}
} else {
	configError ( i18nGettext ("Invalid dataType (__DATATYPE__)!", "__DATATYPE__", $dataType));
}

if( not ( $page = $query->getFile( $baseDoc )) ) {
	configError ( i18nGettext ("Error while loading file __FILE__!", "__FILE__", $baseDoc) );
};

my $req = $db->getItem( DATATYPE=>$dataType, KEY=>$key );

configError ( i18nGettext ("Request __KEY__ not present in DB or the status of the request was changed!",
                           "__KEY__", $key) ) if ( not $req );

## Get the parsed Request
my $parsed_req = $req->getParsed();

## Substitute the cmdsPanel, reqStatus and reqDesc
$page = $query->subVar( $page, '@STATUS@', $reqStatus );
$page = $query->subVar( $page, '@REQDESC@', $tools->getFile( "$reqDesc") );
if ($parsed_req->{HEADER}->{TYPE} =~ /HEADER/i) {
	$cmdsPanel = "$includeDir/pending_header_cmds.inc";
}
$page = $query->subVar( $page, '@CMDSPANEL@', $tools->getFile("$cmdsPanel") );

###########################
## begin support signing ##
###########################

my ($header, $text);

$beginHeader = "-----BEGIN HEADER-----";
$endHeader = "-----END HEADER-----";

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

$text = $parsed_req->{BODY};

$page = $query->subVar( $page, '@HEADER@', "" );
$page = $query->subVar( $page, '@TEXT@',   $header.$text );

#########################
## end support signing ##
#########################

@cols = ( gettext("Variable"), gettext("Value") );
$reqDataTable = $query->startTable( COLS=>[ @cols ],
                                        WIDTH=>"100%",
                                        ## BGCOLOR=>"#F1F0F8",
					PADDING=>"2",
					CELLPADDING=>"4",
					TABLE_BGCOLOR=>"#F1F0F8",
                                        TITLE_BGCOLOR=>"#DDCCFF" );

###############################################
## begin of code taken from issueCertificate ##
###############################################

## Get the serial Number the certificate will have
my $ser = gettext ("cert's serial");

# prepare the DN
my $cert_subject = "";
my $attribute_name;

#// perhaps the request's serial must be stored in the dn
my $use_request_serial = getRequired ('SET_REQUEST_SERIAL_IN_DN');
my $request_serial_name = "";
if ($use_request_serial =~ /^(Y|YES|ON)$/i) {
	$cert_subject .= getRequired ('REQUEST_SERIAL_NAME')."=".$ser.",";
}

#// perhaps the cert's serial must be stored in the dn
my $use_cert_serial = getRequired ('SET_CERTIFICATE_SERIAL_IN_DN');
my $cert_serial_name = "";
if ($use_cert_serial =~ /^(Y|YES|ON)$/i) {
	$cert_subject = getRequired ('CERTIFICATE_SERIAL_NAME')."=".$ser.",";
}

if ($req->getParsed()->{HEADER}->{SUBJECT}) {
	$cert_subject .= $req->getParsed()->{HEADER}->{SUBJECT};
} else {
	$cert_subject .= $req->getParsed()->{DN};
}

## filter email if necessary
if ( getRequired ('DN_WITHOUT_EMAIL') =~ /Y|YES|ON/i ) {
	$cert_subject =~ s/\s*EMAIL\s*=[^,]*//i;
	$cert_subject =~ s/\s*EMAILADDRESS\s*=[^,]*//i;
	$cert_subject =~ s/,\s*$//;
	$cert_subject =~ s/^\s*,//;
	$cert_subject =~ s/,\s*,/,/;
} else {
	$cert_subject =~ s/^\s*EMAILADDRESS\s*=/emailAddress=/i;
	$cert_subject =~ s/^\s*EMAIL\s*=/emailAddress=/i;
	$cert_subject =~ s/,\s*EMAILADDRESS\s*=/,emailAddress=/i;
	$cert_subject =~ s/,\s*EMAIL\s*=/,emailAddress=/i;
}

print "from issueCertificate: \$cert_subject: ".$cert_subject."<br>\n" if ($DEBUG);

#############################################
## end of code taken from issueCertificate ##
#############################################

if ( $req->getParsed()->{HEADER}->{RENEW} ) {
	$lnk = new CGI({cmd=>"viewCSR", dataType=>"REQUEST",
			key=>$req->getParsed()->{HEADER}->{RENEW}});
	$myRenew = $lnk->a({-href=>$lnk->self_url()}, $req->getParsed()->{HEADER}->{RENEW});
} else {
	$myRenew = "";
}

if (  $req->getParsed()->{DN_HASH}->{CN}[0] ne "" ) {
	$lnk = new CGI({cmd=>"search", dataType=>"CERTIFICATE",
			name=>"CN", value=>$req->getParsed()->{DN_HASH}->{CN}[0]} );
	$myCN = $lnk->a({-href=>$lnk->self_url()}, $req->getParsed()->{DN_HASH}->{CN}[0]);
}

## subject alternative name
if (  defined $req->getParsed()->{HEADER}->{SUBJECT_ALT_NAME} ) {
	$subjectAltName = $req->getParsed()->{HEADER}->{SUBJECT_ALT_NAME};
} elsif ( $automatic_subject_alt_name =~ /(Y|YES|ON)/i ) {
	## perhaps we support DNS and IP in the future too
	if ( ($default_subject_alt_name =~ /Email/i) and
	     $req->getParsed()->{DN_HASH}->{EMAILADDRESS}
	   )  {
		$subjectAltName = "email:".$req->getParsed()->{DN_HASH}->{EMAILADDRESS}[0];
	} else {
		$subjectAltName = "";
	}
} else {
	$subjectAltName = "";
};

## email address
my @emails = ();
if ( $subjectAltName ) {
	@subjectAltNames = split (/,/, $subjectAltName);
	foreach my $h (@subjectAltNames) {
		next if ($h !~ /^\s*email:/i);
		$h =~ s/^\s*email://i;
		push (@emails, $h);
	}
}
if (  $req->getParsed()->{EMAILADDRESS} ne "" ) {
	push (@emails, $req->getParsed()->{EMAILADDRESS});
};
@emails = sort @emails;
my $last_email = "";
foreach my $h (@emails) {
	next if ($h eq $last_email);
	$last_email = $h;
	my $lnk = new CGI({cmd=>"search", dataType=>"CERTIFICATE",
			name=>"EMAIL", value=>$h} );
	$myEmail .= ", " if ($myEmail);
	$myEmail .= $lnk->a({-href=>$lnk->self_url()}, $h);
}

## If the Request is signed
if ( $req->getParsed()->{TYPE} =~ /with .*? Signature/i ) {

	$lnk = new CGI({cmd=>"viewSignature", dataType=>$dataType, key=>$key});
	if( libCheckSignature( OBJECT=>$req ) ) {
		$tmp = $query->img({src=>getRequired ('ValidSigImage'),
					border=>"0", align=>"MIDDLE"});
	} else {
		$tmp = $query->img({-src=>getRequired ('SigErrorImage'),
					-border=>"0", -align=>"MIDDLE"});
	}

	$sigInfo = $lnk->a({-href=>$lnk->self_url()}, $tmp );
	
} else {
	$def = "<FONT COLOR=\"RED\">".gettext ("Not Signed")."</FONT>";
	$parsed_req->{OPERATOR} = $def;
}

###########################################
## handle keyless request (TYPE: HEADER) ##
###########################################

if ($parsed_req->{TYPE} =~ /HEADER/i) {
	my $html = "";

	my $first_name	= $req->getParsed()->{DN_HASH}->{CN}[0];
	$first_name	=~ s/\s[^\s]*$//;
	$html .= $query->newInput (
				-intype => 'hidden',
				-name   => 'first_name',
				-value  => $first_name)."\n";

	my $last_name	= $req->getParsed()->{DN_HASH}->{CN}[0];
	$last_name	=~ s/^.*\s//;
	$html .= $query->newInput (
				-intype => 'hidden',
				-name   => 'last_name',
				-value  => $last_name)."\n";

	$html .= $query->newInput (
				-intype => 'hidden',
				-name   => 'emailAddress',
				-value  => $emails[0])."\n";

	$html .= $query->newInput (
				-intype => 'hidden',
				-name   => 'ra',
				-value  => $req->getParsed()->{HEADER}->{RA})."\n";

	my $i = 1;
	foreach my $h (@{$req->getParsed()->{DN_HASH}->{OU}}) {
		$html .= $query->newInput (
					-intype => 'hidden',
					-name   => $i.'.ou',
					-value  => $h)."\n";
		$i++;
	}

	$page = $query->subVar( $page, '@_KEYLESS_DATA@', $html );
} else {
	$page = $query->subVar( $page, '@_KEYLESS_DATA@', "" );
}

###################################################
## end of handle keyless request (TYPE: HEADER) ##
###################################################


## Check if another valid Certificate exists with the same DN of the
## current Request (only for VALID_CERTIFICATE)
$dnLabel = "<B>".gettext("Distinguished Name:")."</B><BR>";

if ( ($use_cert_serial    !~ /^(Y|YES|ON)$/i)       and
     ($use_request_serial !~ /^(Y|YES|ON)$/i)       and
     ($dataType           =~ /^(PENDING|APPROVED)_REQUEST$/i) ) {
	@myDnList = $db->searchItems( DATATYPE=>"VALID_CERTIFICATE",
					MODE=>"RAW",
					DN=>$cert_subject);

	if( $#myDnList > -1 ) {

		$lnk = new CGI({ cmd=>"search", 
				 dataType=>"VALID_CERTIFICATE" });
		$dnLabel .= "<BR><B><FONT SIZE=-1>[".
               i18nGettext ("Warning: __LINK__ exists!",
                            "__LINK__", $lnk->a({-href=>$lnk->self_url()}, gettext ("a certificate with same DN"))).
			   "]</FONT></B>";
	}
}

## load the certificate which was issued from this request

my @certs = $db->searchItems (DATATYPE=>'CERTIFICATE', CSR_SERIAL=>$req->getSerial());

## build table

## $reqDataTable .=$query->addTableLine(DATA=>[ "<B>:</B>",
## 			($parsed_req->{} or "n/a") ]);
$reqDataTable .=$query->addTableLine(DATA=>["<B>".gettext("Request Version:")."</B>",
                        ($parsed_req->{VERSION} or gettext("n/a")) ]);
$reqDataTable .=$query->addTableLine(DATA=>[ "<B>".gettext("Serial Number:")."</B>",
                        ($req->getSerial() or gettext("n/a")) ]);
$reqDataTable .=$query->addTableLine(DATA=>[ "<B>".gettext("Renewed from:")."</B>", $myRenew ])
	if ($myRenew);
$reqDataTable .=$query->addTableLine(DATA=>["<B>".gettext("Request Type:")."</B>",
                        ($parsed_req->{TYPE} or gettext("n/a")) ]);
if (scalar @certs) {
	my $list = "";
	foreach my $cert (@certs) {
		$list .= "<a href=\"$self?cmd=viewCert&key=".$cert->getSerial()."\">".$cert->getSerial()."</a>&nbsp;";
	}
	$reqDataTable .=$query->addTableLine(DATA=>["<B>".gettext("Issued Certificate:")."</B>", $list]);
}
$reqDataTable .=$query->addTableLine(DATA=>[ "<B>".gettext("Common Name:")."</B>",
			($myCN or gettext("n/a")) ]);
$reqDataTable .=$query->addTableLine(DATA=>[ "<B>".gettext("E-Mail:")."</B>",
			($myEmail or gettext("n/a")) ]);
$reqDataTable .=$query->addTableLine(DATA=>[ "<B>".gettext("Subject Alternative Name:")."</B>",
			($subjectAltName or gettext("n/a")) ]);
$reqDataTable .=$query->addTableLine(DATA=>[ "<B>".gettext("Role:")."</B>",
			$parsed_req->{HEADER}->{ROLE} ]);
$reqDataTable .=$query->addTableLine(DATA=>[ "<B>".gettext("Distinguished Name:")."</B>",
                        ($cert_subject or gettext("n/a")) ]);
$reqDataTable .=$query->addTableLine(DATA=>[ "<B>".gettext("Approved on:")."</B>",
                        ($parsed_req->{HEADER}->{APPROVED} or gettext("n/a")) ]);
$reqDataTable.=$query->addTableLine(DATA=>["<B>".gettext("Used Identification PIN:")."</B>",
                        ($parsed_req->{HEADER}->{PIN} or gettext("n/a")) ]);
$reqDataTable .=$query->addTableLine(DATA=>[ "<B>".gettext("Modulus (key size):")."</B>",
                        ($parsed_req->{KEYSIZE} or gettext("n/a")) ]);
$reqDataTable .=$query->addTableLine(DATA=>[ "<B>".gettext("Public Key Algorithm:")."</B>",
                        ($parsed_req->{PK_ALGORITHM} or gettext("n/a")) ]);
$reqDataTable .=$query->addTableLine(DATA=>[ "<B>".gettext("Public Key:")."</B>",
                        "<pre>".($parsed_req->{PUBKEY} or gettext("n/a"))."</pre>" ]);
$reqDataTable .=$query->addTableLine(DATA=>[ "<B>".gettext("Signature Algorithm:")."</B>",
                        ($parsed_req->{SIG_ALGORITHM} or gettext("n/a")) ]);

$reqDataTable .= $query->endTable();

$page = $query->subVar( $page, '@REQDATA@', $reqDataTable );

## Substitute dB coordinates
$page = $query->subVar( $page, '@DATATYPE@', $dataType );
$page = $query->subVar( $page, '@KEY@', $key );
$page = $query->subVar( $page, '@__ROLE__@', $parsed_req->{HEADER}->{ROLE} );

## View the Signature Logo
$page = $query->subVar( $page, '@SIGINFO@',    $sigInfo );

print "$page";

}

1;
