## OpenCA - Command
## (c) 1998-2001 by Massimiliano Pala and OpenCA Group
## (c) Copyright 2002-2004 The OpenCA Project
##
##   File Name: viewCert
##       Brief: Display a certificate
##     Version: $Revision: 1.11 $
## Description: Display certificate data
##  Parameters: dataType, key

## this script supports the following configurable references
##
## INSTALL_CERT
## LDAP
## REVOCATION
## SENDCERT
## SEND_CERT_KEY
## VIEW_CSR
## TOKENHANDLING
## MAIL
## SET_PUBLIC_PASSWD
## DELETE_PUBLIC_PASSWD

use strict;

sub cmdViewCert {

    our ( $query, $self, $db );

    my ($info_list, $cmd_list, $hidden_list, $cmd_panel) = (undef, undef, undef, undef);
    my ($hidden_pos, $info_pos, $cmd_pos) = (0, 0, 0);

    ## Get the Serial Number
    my $key      = $query->param( 'key' );
    my $dataType = $query->param( 'dataType' );
    my ($status, $dataStatus, $newDataType);
    my $reason = undef;

    my @certDataTypes = ( "VALID_CERTIFICATE", "EXPIRED_CERTIFICATE", 
			  "SUSPENDED_CERTIFICATE", "REVOKED_CERTIFICATE" );

    if( not $key and ($key != 0)) {
	configError( gettext ("Error, missing key!") );
    }

    if ( not $dataType ) {
	$dataType = "CERTIFICATE";
    }

    if ( $dataType =~ /CA_CERTIFICATE/ ) {
	$newDataType = "CA_CERTIFICATE";
    } elsif ( $dataType =~ /CERTIFICATE/ ) {
	$newDataType = "CERTIFICATE";
    } else {
	$newDataType = "CERTIFICATE";
	$dataType = "VALID_CERTIFICATE";
    }

    $dataStatus = $dataType;
    $dataStatus =~ s/\_*$newDataType//;

    if ( $dataStatus eq "" ) {
	$dataStatus = "VALID";
    }

    if ( $dataStatus !~ /VALID|EXPIRED|SUSPENDED|REVOKED/ ) {
	generalError (i18nGettext ("DataType not supported (__DATATYPE__)!", 
		"__DATATYPE__", $dataType) . " [ $newDataType; $dataStatus ]");
    }

    my $cert  = $db->getItem( DATATYPE=>$newDataType, KEY=>$key );
    my $tmpStatus = undef;
    my $parsedCert = undef;

    configError( i18nGettext (
		"Error __ERRNO__, unable to get cert from dB! (__ERRVAL__)",
                              "__ERRNO__", $db->errno(),
                              "__ERRVAL__", $db->errval())) if( not $cert );

    $parsedCert = $cert->getParsed();
    $status = ( $cert->getStatus() or $dataStatus);

    if ( $cert->getStatus() =~ /VALID/ ) {
	$status = gettext ( "Valid");
	$tmpStatus = "<font color='green'>" . gettext ( "Valid") . "</font>";
    } elsif ( $cert->getStatus() =~ /EXPIRED/ ) {
	$status = gettext ( "Expired" );
	$tmpStatus = "<font color='red'>" . gettext ( "Expired" ) . "</font>";
    } elsif ( $cert->getStatus() =~ /SUSPENDED/ ) {
	$status = gettext ( "Suspended" );
	$tmpStatus = "<font color='red'>" . gettext ( "Suspended" ) . "</font>";

	foreach my $crrStatus ( "APPROVED", "SIGNED", "PENDING", "NEW" ) {

		my @crrList = $db->searchItems( DATATYPE => "$crrStatus"."_CRR",
			REVOKE_CERTIFICATE_SERIAL => $cert->getSerial());

		print STDERR "vieCert()->crrList is $#crrList (cert serial " .
				$cert->getSerial() . ")";

		if ( $db->{errno} ne 0 ) {
			print STDERR "viewCert()->dbError::" .
					$db->{errno} . "::".$db->{errval}."\n";
			next;
		}

		if( $#crrList >= 0 ) {
			my $crr;

			$crr = $crrList[$#crrList];

			$reason = qq{<font color='red'>} .
					$crr->getParsed()->{REVOKE_REASON} .
					" (CRR " . $crr->getSerial() . ")" .
				  qq{</font>};
			last;
		}
	}
	if ( $reason eq "" ) {
		$reason = qq{<font color='red'>} . gettext ("Unknown") .
			  qq{</font>};
	}

    } elsif ( $cert->getStatus() =~ /REVOKED/ ) {
	$status = gettext ( "Revoked" );
	$tmpStatus = "<font color='red'>" . gettext ( "Revoked" ) . "</font>";

	my @crrList = $db->searchItems ( DATATYPE => "ARCHIVED_CRR",
		REVOKE_CERTIFICATE_SERIAL => $cert->getSerial());

	if ( $db->{errno} ne 0 ) {
		print STDERR "viewCert()->dbError::" .
				$db->{errno} . "::".$db->{errval}."\n";
		next;
	}

	if( $#crrList >= 0 ) {
		my $crr;

		$crr = $crrList[$#crrList];

		$reason = qq{<font color='red'>} .
				$crr->getParsed()->{REVOKE_REASON} .
				" (CRR " . $crr->getSerial() . ")" .
			  qq{</font>};
	} else {
		$reason = qq{<font color='red'>} . gettext ("Unknown") .
			  qq{</font>};
	}

    } else {
	$status = gettext ( "Unknown" );
	$tmpStatus = "<font color='red'>" . gettext ( "Unknown" ) . "</font>";
    }

    ## build emailaddress string
    my $emails = undef;
    foreach my $email (@{$parsedCert->{EMAILADDRESSES}}) {
        $emails .= ", " if ($emails);
        $emails .= $email;
    }

    $hidden_list->{"cmd"}            = "";
    $hidden_list->{"GET_PARAMS_CMD"} = "";
    $hidden_list->{"passwd"}         = "";
    $hidden_list->{"key"}            = $key;
    $hidden_list->{"HIDDEN_key"}     = $key;
    $hidden_list->{"dataType"}       = $dataType;
    $hidden_list->{"dn"}             = $parsedCert->{DN};
    $hidden_list->{"new_dn"}         = "";
    $hidden_list->{"name"}           = "PUBLIC";
    $hidden_list->{"format"}         = "";
    $hidden_list->{"text"}           = "";
    $hidden_list->{"signature"}      = "";

    my $tmpIssuer = $parsedCert->{ISSUER};
    my $tmpDN     = $parsedCert->{DN};

    ## old version - if it can be removed then simply remove it
    $tmpIssuer =~ s/[\/,]\s*(?=[A-Za-z0-9\-]+=)/<BR>\n/g;
    $tmpDN     =~ s/[\/,]\s*(?=[A-Za-z0-9\-]+=)/<BR>\n/g;

    # my $now = timestamp();

    # if ( $tmpStatus =~ /^Valid/i ) {
# 	if ($now >
# 	    $cryptoShell->getNumericDate ($parsedCert->{NOTAFTER})) {
# 		$tmpStatus = gettext("Expired");
# 	}
 #    } elsif ( $tmpStatus =~ /revoked/gi ) {
# 	$tmpStatus = i18nGettext ("Revoked on __DATE__", "__DATE__", $parsedCert->{HEADER}->{REVOKED});
 #    } elsif ( $tmpStatus =~ /^Expired/i ) {
# 	if ($now <=
# 	    $cryptoShell->getNumericDate ($parsedCert->{NOTAFTER})) {
# 		$tmpStatus = gettext("Not Expired");
# 	}
 #    }

    my $download = "";
    my $revoke = "";
    my $certStatus = undef;

    my $ctype = "";

    if ( $dataType =~ /CA_CERTIFICATE/gi ) {
        $download = '?cmd=send_email_cert;type=ca;dataType=$dataType;key='.
		$key; # $cert->getSerial();
	$ctype = "ca";
    } else {
        $download = '?cmd=send_email_cert;type=email;dataType=$dataType;key='.
		$key; # $cert->getSerial();
	$ctype = "email";
        $revoke   = '?cmd=revoke_req;key='.$cert->getSerial();
    }

    # $info_list->{HEAD}->[0] = gettext("Variable");
    # $info_list->{HEAD}->[1] = gettext("Value");

    my $html_download = "<input ".
			"TYPE=\"Submit\" ".
			"Name=\"Submit\" ".
			"Value=\"".gettext("Download")."\" ".
			"Class=\"medium\" " .
			"onClick=\"cmd.value='sendcert'; format_sendcert.value='CER';\">";
    my $text = undef;

    $text = "<table style='width: 500px;'>";
    $text .= "<tr><td style='padding: 10px;'>" .
	     "<a href=\"$self?cmd=send_email_cert;type=$ctype;" .
			"dataType=$dataType;key=" .
			# $cert->getSerial() . "\" alt=\"" .
			$key . "\" alt=\"" .
			gettext ("Install this Certificate" ) . "\">" .
	     "  <img src=\"" . getRequired('HtdocsUrlPrefix') . 
		    "/images/cert-icon.png\" alt='" .
			gettext("Install this Certificate") . "'/></a>" .
	     "</td>";
    $text .= "<td>" ;

    $text .= "  <table style='width: 400px;'>" .
		" <tr><td colspan='2' " .
			"style='font-size: 150%; font-style: bold;'>" .
		  $parsedCert->{DN_HASH}->{CN}[0] .  " [" .
		  $parsedCert->{HEX_SERIAL} . "]</td></tr>";
    $text .= "    <tr><td style='color: #777;'>" .
			"Issued By:</td>" .
	     "      <td style='color: #777'>" . 
			$parsedCert->{ISSUER_HASH}->{O}[0] . "</td>";
    $text .= "    </tr>";
    $text .= "    <tr><td style='color: #777;'>" .
			"Expiration on:</td>" .
	     "      <td style='color: #777;'>" . 
			$parsedCert->{NOTAFTER} . "</td></tr>";
    $text .= "    <tr><td style='color: #777;'> " .
			"Profile:</td>" .
	     "      <td style='color: #777;'>" . 
			$parsedCert->{HEADER}->{ROLE} . "</td></tr>";
    $text .= "    <tr><td style='color: #777;'> " .
			"Status:</td>" .
	     "      <td style='color: #777;'>" . 
			$tmpStatus . "</td></tr>";
    if ( $reason ne "" ) {
    	$text .= "    <tr><td style='color: #777;'> " .
				"Reason:</td>" .
		     "      <td style='color: #777;'>" . 
				$reason . "</td></tr>";
    };

    $text .= "    <tr><td>&nbsp;</td>" .
	     "      <td  style='font-size: 80%; color: #777;'>" .  
			"<a href=\"$self?cmd=viewCertFull;dataType=$dataType;" .
				# "key=" .  $cert->getSerial() . "\" >" .
				"key=$key\" >" .
			gettext ( "More Info" ) . "... </a></td></tr>";
    $text .= "  </table>";

    $text .= "</td>";
    $text .= "</tr>";

    $text .= "<tr><td colspan='2'><hr size='1' style='color: #fff;'/>" .
		"</tr></td>"; 

    $text .= "<tr><td colspan='2'>" . gettext ("Fingerprint" ) . 
		":<br/>";

    $text .= "SHA1:";
    for ( my $i = 0; $i < length( $parsedCert->{FINGERPRINT}); $i += 2 ) {
	$text .= ":" if ( $i > 0 ); 
	$text .= uc ( substr( $parsedCert->{FINGERPRINT}, $i, 2 ));
    }
    $text .= "</td></tr>";
    $text .= "</table>";

    $info_list->{BODY}->[$info_pos++]->[1] = $text;


    #######################################
    ## here starts the filtered commands ##
    ## here starts the filtered commands ##
    ## cmd_list                          ##
    #######################################

    $cmd_list->{HEAD}->[0] = gettext ("Operations");

    my $allow = libGetPermissionHash (getRequiredList ('CmdRefs_viewCert'));

    ## perhaps an operator want to have a look at the request
    if ($allow->{VIEW_CSR} and
        $parsedCert->{HEADER}->{CSR_SERIAL}
       ) {
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("CSR's Serial Number");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = "<a href=\"".
                                             "?cmd=viewCSR&dataType=ARCHIVED_REQUEST&key=".
                                             $parsedCert->{HEADER}->{CSR_SERIAL}."\">".
                                             "$parsedCert->{HEADER}->{CSR_SERIAL}</a>";
        $cmd_pos++;
    }

    ## download certs in different formats
    if ( $allow->{SENDCERT} and
         ($dataType =~ /(VALID|EXPIRED|SUSPENDED)/i)
       ) {
	my $select = "<select " .
		     " class=\"Medium\" name=\"format_sendcert\">\n".
			"<option value=\"pem\">PEM</option>\n".
			"<option value=\"der\">CER</option>\n".
			"<option value=\"pem\">CRT</option>\n".
			"<option value=\"der\">DER</option>\n".
			"<option value=\"txt\">TXT</option>\n".
			"</select>\n";
	my $button = "<input ".
			"TYPE=\"Submit\" ".
			"Name=\"Submit\" ".
			"Value=\"".gettext("Download")."\" ".
			"Class=\"medium\" " .
			"onClick=\"cmd.value='sendcert';\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Certificate");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $select.$button;
        $cmd_pos++;
    }

    ## prepare download of private keys
    if ( $allow->{SEND_CERT_KEY} and
        $parsedCert->{KEY}
       ) {
	my $select = "<select name=\"format_send_cert_key\">\n".
			"<option value=\"openssl\">SSLeay (mod_ssl)</option>\n".
			"<option value=\"pkcs8\">PKCS#8</option>\n".
			"<option value=\"pkcs12\">PKCS#12</option>\n".
			"</select>\n";
	my $button = "<input ".
			"TYPE=\"Submit\" ".
			"Name=\"Submit\" ".
			"Value=\"".gettext("Download")."\" ".
			"Class=\"medium\" " .
			"onClick=\"cmd.value='getParams';GET_PARAMS_CMD.value='send_cert_key';\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Certificate and Keypair");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $select.$button;
        $cmd_pos++;
	## Change passphrase
	my $change_button = "<input ".
                        "TYPE=\"Submit\" ".
                        "Name=\"Submit\" ".
                        "Value=\"".gettext("Change")."\" ".
			"Class=\"medium\" " .
                        "onClick=\"cmd.value='changePasswd'\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Change Passphrase");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $change_button;
        $cmd_pos++;
	## Remove private key from DB
	my $remove_button = "<input ".
                        "TYPE=\"Submit\" ".
                        "Name=\"Submit\" ".
                        "Value=\"".gettext("Remove")."\" ".
			"Class=\"medium\" " .
                        "onClick=\"cmd.value='removeKey'\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Remove Key from database");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $remove_button;
        $cmd_pos++;
    }

    ## prepare the actualization of the LDAP
    if ( $allow->{LDAP} and
         (getRequired ('LDAP') =~ /y/i)
       ) {
	## update cert on LDAP
	my $ldap_button = "<input ".
                        "TYPE=\"Submit\" ".
                        "Name=\"Submit\" ".
                        "Value=\"".gettext("Add to LDAP")."\" ".
			"Class=\"medium\" " .
                        "onClick=\"cmd.value='ldapAddCert'\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Add the certificate to LDAP");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $ldap_button;
        $cmd_pos++;
	## update cert on LDAP with modified DN
	$ldap_button = "<input ".
                        "TYPE=\"Submit\" ".
                        "Name=\"Submit\" ".
                        "Value=\"".gettext("Add to LDAP with modified DN")."\" ".
                        "onClick=\"cmd.value='getParams';GET_PARAMS_CMD.value='ldapAddCertByName';\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Add the certificate to LDAP but with changed DN");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $ldap_button;
        $cmd_pos++;
	## delete cert from LDAP
	$ldap_button = "<input ".
                        "TYPE=\"Submit\" ".
                        "Name=\"Submit\" ".
                        "Value=\"".gettext("Delete from LDAP")."\" ".
			"Class=\"medium\" " .
                        "onClick=\"cmd.value='ldapDeleteCert'\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Delete the certificate from LDAP");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $ldap_button;
        $cmd_pos++;
	## delete cert from LDAP with modified DN
	$ldap_button = "<input ".
                        "TYPE=\"Submit\" ".
                        "Name=\"Submit\" ".
                        "Value=\"".gettext("Delete from LDAP with modified DN")."\" ".
			"Class=\"medium\" " .
                        "onClick=\"cmd.value='getParams';GET_PARAMS_CMD.value='ldapDeleteCertByName';\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Delete the certificate from LDAP but with changed DN");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $ldap_button;
        $cmd_pos++;
    }
    if ($allow->{TOKENHANDLING} and
        not $parsedCert->{IS_CA} and
        $status ne gettext("Revoked") and
        $status ne gettext("Suspended")
       )
    {
	my $ra_button = "<input ".
                        "TYPE=\"Submit\" ".
                        "Name=\"Submit\" ".
			"Class=\"Medium\" " .
                        "Value=\"".gettext("Install Certificate")."\" ".
                        "onClick=\"cmd.value='getcert'\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Tokenhandling");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $ra_button;
        $cmd_pos++;
    }
    if ($allow->{MAIL}) {
	my $ra_button = "<input ".
                        "TYPE=\"Submit\" ".
                        "Name=\"Submit\" ".
                        "Value=\"".gettext("Write a mail")."\" ".
			"Class=\"medium\" " .
                        "onClick=\"cmd.value='writeCertMail'\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Send mail to the User");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $ra_button;
        $cmd_pos++;
    }

    ## set enrollment passphrase for certificate and private key on public gateway
    if ( $allow->{SET_PUBLIC_PASSWD} and
         $parsedCert->{KEY} and
         ($dataType =~ /(VALID|EXPIRED|SUSPENDED)/i)
       ) {
	my $button = "<input ".
			"TYPE=\"Submit\" ".
			"Name=\"Submit\" ".
			"Value=\"".gettext("Set passphrase")."\" ".
			"Class=\"medium\" " .
			"onClick=\"cmd.value='setPasswd';\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Set passphrase for key enrollment");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $button;
        $cmd_pos++;
    }
    if ( $allow->{DELETE_PUBLIC_PASSWD} and
         $parsedCert->{KEY} and
         ($dataType =~ /(VALID|EXPIRED|SUSPENDED)/i)
       ) {
	my $button = "<input ".
			"TYPE=\"Submit\" ".
			"Name=\"Submit\" ".
			"Value=\"".gettext("Delete passphrase")."\" ".
			"Class=\"medium\" " .
			"onClick=\"cmd.value='deletePasswd';\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Delete passphrase for key enrollment");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $button;
        $cmd_pos++;
    }

    ## revoke cert
    if ( $allow->{REVOCATION} and
         $status ne gettext("Revoked")
       )
    {
	my $ra_button = "<input ".
                        "TYPE=\"Submit\" ".
                        "Name=\"Submit\" ".
                        "Value=\"".gettext("Revoke")."\" ".
			"Class=\"medium\" " .
                        "onClick=\"cmd.value='revoke_req'\">";
        $cmd_list->{BODY}->[$cmd_pos]->[0] = gettext("Start Revocation");
        $cmd_list->{BODY}->[$cmd_pos]->[1] = $ra_button;
        $cmd_pos++;
    }

    if ($allow->{INSTALL_CERT}) {
	if ($dataType =~ /(VALID|EXPIRED|SUSPENDED)_CERTIFICATE/) {
            $cmd_panel->[0] = 
			"<a href=\"".$download."\" onClick=\"alert('The Certificate will be installed under Other People Certificates Tab');\">".gettext("Install the certificate")."</a>";
            $cmd_panel->[1] = 
			"<a href=\"".$revoke."\">".gettext("Revoke the certificate")."</a>";
	}
    }

    return libSendReply (
                         "NAME"        => i18nGettext ("__STATUS__ Certificate", "__STATUS__", $status),
                         # "EXPLANATION" => gettext ("Following you can find the certificate details."),
                         # "TIMESTAMP"   => 1,
                         "INFO_LIST"   => $info_list,
                         # "CMD_LIST"    => $cmd_list,
                         # "CMD_PANEL"   => $cmd_panel,
                         "HIDDEN_LIST" => $hidden_list
                        );
}
1;
