package org.eclipse.update.internal.ui;

/*
 * Licensed Materials - Property of IBM,
 * WebSphere Studio Workbench
 * (c) Copyright IBM Corp 1999, 2000
 */

import java.lang.reflect.InvocationTargetException;
import org.eclipse.jface.operation.*;
import org.eclipse.core.runtime.IProgressMonitor;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.Certificate;
import java.util.*;
import java.util.jar.*;
import java.io.*;
import java.net.*;
import org.eclipse.update.internal.core.*;

/**
 * The JarVerifier will check the integrity of the JAR.
 * If the Jar is signed and the integrity is validated,
 * it will check if one of the certificate of each file
 * is in one of the keystore.
 *
 */
 


public class JarVerifier {

	/**
	 * Set of certificates of the JAR file
	 */
	private Collection certificateEntries;
	
	/**
	 * List of certificates of the KeyStores
	 */ 
	private List listOfKeystoreCertifcates;
	
	/**
	 * FUTURE: check validity of keystore
	 * default == FALSE 
	 */ 
	private boolean shouldVerifyKeystore = false;

	/**
	 * FUTURE: check validity of keystore
	 * default == FALSE 
	 */ 
	private boolean shouldRetrieveKeystoreCertificates = false;
	
	/**
	 * Number of files in the JarFile
	 */
	private int entries;

 	/**
 	 * ProgressMonitor during integrity validation
 	 */
 	 private IProgressMonitor monitor;

 	 /**
 	  * JAR File Name: used in the readJarFile.
 	  */  
	 private String jarFileName;

	 /**
	  * ResultCode
	  */
	 private int resultCode;

	  /**
	   * Result Error
	   */
	  private Exception resultException;

	 
	//RESULT VALUES
	public static final int NOT_SIGNED 				= 0;
	public static final int CORRUPTED				= 1;
	public static final int INTEGRITY_VERIFIED 		= 2;
	public static final int SOURCE_VERIFIED 		= 3;
	public static final int UNKNOWN_ERROR 			= 4;
	public static final int VERIFICATION_CANCELLED 	= 5;

/**
 * Default Constructor
 */
public JarVerifier() {
}
/**
 * 
 */
public JarVerifier(IProgressMonitor monitor) {
	this.monitor = monitor;
}
/**
 * Returns the list of certificates of the keystore.
 *
 * Can be optimize, within an operation, we only need to get the
 * list of certificate once.
 * @return a List of Certificate
 */
private List getKeyStoreCertificates() {
	if (listOfKeystoreCertifcates == null || shouldRetrieveKeystoreCertificates) {
		listOfKeystoreCertifcates = new ArrayList(0);
		KeyStores listOfKeystores = new KeyStores();
		InputStream in = null;

		try {
			KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
			while (listOfKeystores.hasNext()) {
				try {
					in = listOfKeystores.next().openStream();
					keystore.load(in, null); // no password
				} catch (NoSuchAlgorithmException e) {
				} catch (CertificateException e) {
				} catch (IOException e) {
					// open error message, the keystore is not valid
				} finally {
					if (in != null) {
						try {
							in.close();
						} catch (IOException e) {
						} // nothing
					}
				} // try loading a keyStore

				// keystore was loaded
				Enumeration enum = keystore.aliases();
				if (enum != null) {
					while (enum.hasMoreElements()) {
						listOfKeystoreCertifcates.add(keystore.getCertificate((String) enum.nextElement()));
					}
				}
			} // while all key stores
			
		} catch (KeyStoreException e) {
			// hum... what to do , what to do ???
			// I cannot instanciate a default keystore...
		}
	}

	return listOfKeystoreCertifcates;
}
/**
 * 
 * @return java.lang.Exception
 */
public Exception getResultException() {
	return resultException;
}
/**
 * initialize instance variables
 */
private void initializeVariables(File jarFile) throws IOException {
	resultCode = UNKNOWN_ERROR;
	resultException = new Exception(UpdateManagerStrings.getString("S_File_is_not_a_valid_JAR_file"));
	JarFile jar = new JarFile(jarFile);
	entries = jar.size();
	try {
		jar.close();
	} catch (java.io.IOException ex) {
		// unchecked
	}
	jarFileName = jarFile.getName();
	certificateEntries = new HashSet();
}
/**
 * Returns true if the 2 collections
 * have an intersection
 *
 * @return a boolean
 * @see #verifySource(InputStream)
 */
private boolean intersect(Collection c1, Collection c2) {
	Iterator e = c1.iterator();
	while (e.hasNext())
	    if(c2.contains(e.next())) return true;

	return false;
}
/**
 * Throws exception or set the resultcode to UNKNOWN_ERROR
 */
private List readJarFile(final JarInputStream jis)
	throws IOException, InterruptedException, InvocationTargetException {
	final List list = new ArrayList(0);

	IRunnableWithProgress op = new IRunnableWithProgress() {
		public void run(IProgressMonitor monitor) {
			byte[] buffer = new byte[4096];
			JarEntry ent;

			if (monitor!=null) monitor.beginTask(UpdateManagerStrings.getString("S_Verify") + ": " + jarFileName, entries);
			try {
				while ((ent = jis.getNextJarEntry()) != null) {
					list.add(ent);
					int n = 0;
					if (monitor!=null) monitor.worked(1);
					while ((n = jis.read(buffer, 0, buffer.length)) != -1) {
					}
				}
			} catch (IOException e) {
				resultCode = UNKNOWN_ERROR;
				resultException = e;
			} finally {
				if (monitor!=null) monitor.done();
			}
		}
	};

	op.run(monitor) ;

	return list;
}
/**
 * 
 * @param newMonitor org.eclipse.core.runtime.IProgressMonitor
 */
public void setMonitor(IProgressMonitor newMonitor) {
	monitor = newMonitor;
}
/**
 * 
 * [future]
 */
public void shouldRetrieveCertificate(boolean value) {
	shouldRetrieveKeystoreCertificates = value;
}
/**
 * 
 * [future]
 */
public void shouldVerifyKeystore(boolean value) {
	shouldVerifyKeystore = value;
}
/**
 * Verifies integrity and the validity of a valid
 * URL representing a JAR file
 * the possible results are:
 *
 * result == NOT_SIGNED	 				if the jar file is not signed.
 * result == INTEGRITY_VERIFIED		 	if the Jar file has not been
 *										modified since it has been
 *										signed
 * result == CORRUPTED 					if the Jar file has been changed
 * 										since it has been signed.
 * result == SOURCE_VERIFIED	 		if all the files in the Jar
 *										have a certificate that is
 * 										present in the keystore
 * result == UNKNOWN_ERROR		 		an occured during process, do
 *                                      not install.
 * result == VERIFICATION.CANCELLED     if process was cancelled, do
 *										not install.
 * @return int
 */
public int verify(File jarFile) {

	try {
		// new verification, clean instance variables
		initializeVariables(jarFile);

				// verify integrity
			verifyIntegrity(jarFile);

			// do not close input stream
			// as verifyIntegrity already did it

			// verify source certificate
			if (resultCode == INTEGRITY_VERIFIED)
				verifyAuthentication();

	} catch (Exception e) {
		resultCode = UNKNOWN_ERROR;
		resultException = e;
	}

	return resultCode;
}
/**
 * Verifies that each file has at least one certificate
 * valid in the keystore
 *
 * At least one certificate from each Certificate Array
 * of the Jar file must be found in the known Certificates
 */
private void verifyAuthentication() {
	
	if (!getKeyStoreCertificates().isEmpty()) {
		Iterator entries = certificateEntries.iterator();
		boolean certificateFound = true;

		// If all the cartificate of an entry are
		// not found in the list of known certifcate
		// we exit the loop.
		while (entries.hasNext() && certificateFound){
			List certs = (List)entries.next();
			certificateFound= intersect(getKeyStoreCertificates(),certs);
		}
		if (certificateFound)
			resultCode = SOURCE_VERIFIED;
		// else installCertificates()[future] 
	}

}
/**
 * Verifies the integrity of the JAR
 *
 * @param jarFileStream the input stream of the Jar file
 * @return a int
 */
private void verifyIntegrity(File jarFile) {

	JarInputStream jis = null;

	try {
		// If the JAR is signed and not valid
		// a security exception will be thrown
		// while reading it
		jis = new JarInputStream(new FileInputStream(jarFile), true);
		List filesInJar = readJarFile(jis);

		// you have to read all the files once
		// before getting the certificates 
		if (jis.getManifest() != null) {
			Iterator iter = filesInJar.iterator();
			boolean certificateFound = false;
			while (iter.hasNext()) {
				Certificate[] certs = ((JarEntry) iter.next()).getCertificates();
				if ((certs != null) && (certs.length != 0)) {
					certificateFound = true;
					certificateEntries.add(Arrays.asList(certs));
				};
			}

			if (certificateFound)
				resultCode = INTEGRITY_VERIFIED;
			else
				resultCode = NOT_SIGNED;
		}
	} catch (SecurityException e) {
		// Jar file is signed
		// but content has changed since signed
		resultCode = CORRUPTED;
	} catch (InterruptedException e) {
		resultCode = VERIFICATION_CANCELLED;
	} catch (Exception e) {
		resultCode = UNKNOWN_ERROR;
		resultException = e;
	} finally {
		if (jis != null) {
			try {
				jis.close();
			} catch (IOException e) {
			} // nothing
		}
	}

}
/**
 * [future]
 */ 
private boolean verifyIntegrityOfKeyStore() {
	return shouldVerifyKeystore;
}
}
