/************************************************************************
*
* Copyright (c) 2003-2004, C&C Research Laboratories, NEC Europe Ltd.
*
* Copyright in this library belongs to C&C Research Laboratories,
* Rathausallee 10, 53757 Sankt Augustin, Germany.
*
* This software may not be used, sold, licensed, transferred, copied
* or reproduced in whole or in part in any manner or form or in or
* on any media by any person other than in accordance with the terms
* of the Licence Agreement supplied with the software, or otherwise
* without the prior written consent of the copyright owners.
*
* This software is distributed WITHOUT ANY WARRANTY, without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE, except where stated in the Licence Agreement supplied with
* the software.
*
*  Created By :           Federico Crazzolara
*  Created for Project :  GEMSS (IST-2001-37153)
*
************************************************************************/


package de.nece.ccrl.securitycontext.tokenprovider;

import eu.gemss.components.security.SecurityProviderConfiguration;
import eu.gemss.signals.SignalHandler;
import eu.gemss.components.security.token.*;
import eu.gemss.components.security.token.trust.*;
import de.nece.ccrl.securitycontext.token.types.pki.CertificateDescriptor;
import eu.gemss.components.security.token.types.pki.X509CertificateToken;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.FileInputStream;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509CRL;




public class NECTrustProvider implements SecurityTrustProvider{

    String password; 
    String keystore;
    String crl_loc;
    X509CRL crl;
    static TokenDescriptor[] tokentypes;

    static {
	tokentypes = new TokenDescriptor[1];
	tokentypes[0] = new CertificateDescriptor(CertificateDescriptor.X509);
    }
  
    public NECTrustProvider() {
	password = null;
	keystore = null;
	crl_loc = null;
	Security.addProvider(new BouncyCastleProvider());
    }


    public TokenDescriptor[] getSupportedTokenTrustList() {
	return tokentypes;
    }


    public void setKeystore(String location, String password, String crl_loc) {
        this.password = password;
	keystore = location;	
	this.crl_loc = crl_loc;

	// load crl if available
	try{
	    CertificateFactory factory = CertificateFactory.getInstance("X.509","BC");
	    FileInputStream inputstream = new FileInputStream(crl_loc);
	    crl = (X509CRL) factory.generateCRL(inputstream);
	    inputstream.close();
	}catch(Exception e) {
	    System.out.println("WARNING: CRL not available");   
	}	   	
    }


    public void setSignalHandler(SignalHandler channel) {
	// Not used
    }

    public void setTrustProviderConfiguration(SecurityProviderConfiguration conf) {
	// Not used
    }


    public boolean isTrusted(SecurityToken token) throws TrustProviderException {

	// check that the token is a certificate
	if (!(token instanceof X509CertificateToken)) throw new TrustProviderException("Unsupported token type");

	X509Certificate cert = null;
	String issuer = null;
	String owner = null;
	try{
	    cert = ((X509CertificateToken) token).getX509Certificate();
	    issuer = ((X509CertificateToken) token).getIssuerDN();
	    owner = ((X509CertificateToken) token).getSubjectDN();
	}catch(Exception e) {throw new TrustProviderException("Unexpected X509 token exception.");}


	try{
	    cert.checkValidity();
	}catch(Exception e) {throw new TrustProviderException("Certificate is expired");}

	
	
	// Retrieve CA certificate

	NECTokenStoreProvider prov = new NECTokenStoreProvider(); 
	prov.setKeystore(keystore, password); //keystore parameters must be set

	CertificateDescriptor tokendesc = new CertificateDescriptor(CertificateDescriptor.X509,issuer);

	X509Certificate ca_cert = null;
	try{
	    ca_cert = ((X509CertificateToken) prov.getSecurityToken(tokendesc)).getX509Certificate();
	} catch (Exception e) {
	    throw new TrustProviderException("CA certificate of " + issuer + " not in keystore");}
	
	try{
	    cert.verify(ca_cert.getPublicKey());
	} catch (Exception e) {throw new TrustProviderException("UNTRUSTED CERTIFICATE: " + owner);}

	// CRL checks

	if ((crl != null) && (crl.isRevoked(cert))) {
	    System.out.println("WARNING: The certificate of " + owner + " was revoked.");
	    return false;
	} else {
	    //System.out.println("Valid and trusted certificate: " + owner);
	    return true;
	}

	// TODO: 
	// 1) verify that CRL is signed with trusted CA
	// 2) CA certificate needs to be the one of the GEMSS CA and should be valid, selfsigned etc. -- hartcode?
    }



 
}




