/*******************************************************************************
 * Copyright (c) 2007 IBM Corporation and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: IBM Corporation - initial API and implementation
 ******************************************************************************/
package org.eclipse.osgi.internal.signedcontent;

import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.signedcontent.SignerInfo;
import org.eclipse.osgi.util.NLS;

public class SignatureBlockProcessor implements SignedContentConstants {
	private final SignedBundleFile signedBundle;
	private ArrayList signerInfos = new ArrayList();
	private HashMap contentMDResults = new HashMap();
	// map of tsa singers keyed by SignerInfo -> {tsa_SignerInfo, signingTime}
	private HashMap tsaSignerInfos;
	private final int supportFlags;

	public SignatureBlockProcessor(SignedBundleFile signedContent, int supportFlags) {
		this.signedBundle = signedContent;
		this.supportFlags = supportFlags;
	}

	public SignedContentImpl process() throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException {
		BundleFile wrappedBundleFile = signedBundle.getWrappedBundleFile();
		BundleEntry be = wrappedBundleFile.getEntry(META_INF_MANIFEST_MF);
		if (be == null)
			return createUnsignedContent();

		// read all the signature block file names into a list
		Enumeration en = wrappedBundleFile.getEntryPaths(META_INF);
		List signers = new ArrayList(2);
		while (en.hasMoreElements()) {
			String name = (String) en.nextElement();
			if ((name.endsWith(DOT_DSA) || name.endsWith(DOT_RSA)) && name.indexOf('/') == name.lastIndexOf('/'))
				signers.add(name);
		}

		// this means the jar is not signed
		if (signers.size() == 0)
			return createUnsignedContent();

		byte manifestBytes[] = readIntoArray(be);
		// process the signers
		Iterator iSigners = signers.iterator();
		for (int i = 0; iSigners.hasNext(); i++)
			processSigner(wrappedBundleFile, manifestBytes, (String) iSigners.next());

		// done processing now create a SingedContent to return
		SignerInfo[] allSigners = (SignerInfo[]) signerInfos.toArray(new SignerInfo[signerInfos.size()]);
		for (Iterator iResults = contentMDResults.entrySet().iterator(); iResults.hasNext();) {
			Entry entry = (Entry) iResults.next();
			ArrayList[] value = (ArrayList[]) entry.getValue();
			SignerInfo[] entrySigners = (SignerInfo[]) value[0].toArray(new SignerInfo[value[0].size()]);
			byte[][] entryResults = (byte[][]) value[1].toArray(new byte[value[1].size()][]);
			entry.setValue(new Object[] {entrySigners, entryResults});
		}
		SignedContentImpl result = new SignedContentImpl(allSigners, (supportFlags & SignedBundleHook.VERIFY_RUNTIME) != 0 ? contentMDResults : null);
		result.setContent(signedBundle);
		result.setTSASignerInfos(tsaSignerInfos);
		return result;
	}

	private SignedContentImpl createUnsignedContent() {
		SignedContentImpl result = new SignedContentImpl(new SignerInfo[0], contentMDResults);
		result.setContent(signedBundle);
		return result;
	}

	private void processSigner(BundleFile bf, byte[] manifestBytes, String signer) throws IOException, SignatureException, InvalidKeyException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException {
		BundleEntry be = bf.getEntry(signer);
		byte pkcs7Bytes[] = readIntoArray(be);
		int dotIndex = signer.lastIndexOf('.');
		be = bf.getEntry(signer.substring(0, dotIndex) + DOT_SF);
		byte sfBytes[] = readIntoArray(be);

		// Step 1, verify the .SF file is signed by the private key that corresponds to the public key 
		// in the .RSA/.DSA file
		String baseFile = bf.getBaseFile() != null ? bf.getBaseFile().toString() : null;
		PKCS7Processor processor = new PKCS7Processor(pkcs7Bytes, 0, pkcs7Bytes.length, signer, baseFile);
		// call the Step 1 in the Jar File Verification algorithm
		processor.verifySFSignature(sfBytes, 0, sfBytes.length);
		// algorithm used
		String digAlg = getDigAlgFromSF(sfBytes);
		if (digAlg == null)
			throw new SignatureException(NLS.bind(SignedContentMessages.SF_File_Parsing_Error, new String[] {bf.toString()}));
		// get the digest results
		// Process the Step 2 in the Jar File Verification algorithm
		// Get the manifest out of the signature file and make sure
		// it matches MANIFEST.MF
		verifyManifestAndSingatureFile(manifestBytes, sfBytes);

		// create a SignerInfo with the processed information
		SignerInfoImpl signerInfo = new SignerInfoImpl(processor.getCertificates(), null, digAlg);
		if ((supportFlags & SignedBundleHook.VERIFY_RUNTIME) != 0)
			// only populate the manifests digest information for verifying content at runtime
			populateMDResults(manifestBytes, signerInfo);
		signerInfos.add(signerInfo);
		// check for tsa signers
		Certificate[] tsaCerts = processor.getTSACertificates();
		Date signingTime = processor.getSigningTime();
		if (tsaCerts != null && signingTime != null) {
			SignerInfoImpl tsaSignerInfo = new SignerInfoImpl(tsaCerts, null, digAlg);
			if (tsaSignerInfos == null)
				tsaSignerInfos = new HashMap(2);
			tsaSignerInfos.put(signerInfo, new Object[] {tsaSignerInfo, signingTime});
		}
	}

	/**
	 * Verify the digest listed in each entry in the .SF file with corresponding section in the manifest
	 */
	private void verifyManifestAndSingatureFile(byte[] manifestBytes, byte[] sfBytes) {

		String sf = new String(sfBytes);
		sf = stripContinuations(sf);

		// check if there -Digest-Manfiest: header in the file
		int off = sf.indexOf(digestManifestSearch);
		if (off != -1) {
			int start = sf.lastIndexOf('\n', off);
			String manifestDigest = null;
			if (start != -1) {
				// Signature-Version has to start the file, so there
				// should always be a newline at the start of
				// Digest-Manifest
				String digestName = sf.substring(start + 1, off);
				if (digestName.equalsIgnoreCase(MD5_STR))
					manifestDigest = calculateDigest(getMessageDigest(MD5_STR), manifestBytes);
				else if (digestName.equalsIgnoreCase(SHA1_STR))
					manifestDigest = calculateDigest(getMessageDigest(SHA1_STR), manifestBytes);
				off += digestManifestSearchLen;

				// find out the index of first '\n' after the -Digest-Manifest: 
				int nIndex = sf.indexOf('\n', off);
				String digestValue = sf.substring(off, nIndex - 1);

				// check if the the computed digest value of manifest file equals to the digest value in the .sf file
				if (!digestValue.equals(manifestDigest)) {
					Exception e = new SecurityException(NLS.bind(SignedContentMessages.Security_File_Is_Tampered, new String[] {signedBundle.getBaseFile().toString()}));
					SignedBundleHook.log(e.getMessage(), FrameworkLogEntry.ERROR, e);
					throw (SecurityException) e;
				}
			}
		}
	}

	private void populateMDResults(byte mfBuf[], SignerInfo signerInfo) throws NoSuchAlgorithmException {
		// need to make a string from the MF file data bytes
		String mfStr = new String(mfBuf);

		// start parsing each entry in the MF String
		int entryStartOffset = mfStr.indexOf(MF_ENTRY_NEWLN_NAME);
		int length = mfStr.length();

		while ((entryStartOffset != -1) && (entryStartOffset < length)) {

			// get the start of the next 'entry', i.e. the end of this entry
			int entryEndOffset = mfStr.indexOf(MF_ENTRY_NEWLN_NAME, entryStartOffset + 1);
			if (entryEndOffset == -1) {
				// if there is no next entry, then the end of the string
				// is the end of this entry
				entryEndOffset = mfStr.length();
			}

			// get the string for this entry only, since the entryStartOffset
			// points to the '\n' befor the 'Name: ' we increase it by 1
			// this is guaranteed to not go past end-of-string and be less
			// then entryEndOffset.
			String entryStr = mfStr.substring(entryStartOffset + 1, entryEndOffset);
			entryStr = stripContinuations(entryStr);

			// entry points to the start of the next 'entry'
			String entryName = getEntryFileName(entryStr);

			// if we could retrieve an entry name, then we will extract
			// digest type list, and the digest value list
			if (entryName != null) {

				String aDigestLine = getDigestLine(entryStr, signerInfo.getMessageDigestAlgorithm());

				if (aDigestLine != null) {
					String msgDigestAlgorithm = getDigestAlgorithmFromString(aDigestLine);
					if (!msgDigestAlgorithm.equalsIgnoreCase(signerInfo.getMessageDigestAlgorithm()))
						continue; // TODO log error?
					byte digestResult[] = getDigestResultsList(aDigestLine);

					//
					// only insert this entry into the table if its
					// "well-formed",
					// i.e. only if we could extract its name, digest types, and
					// digest-results
					//
					// sanity check, if the 2 lists are non-null, then their
					// counts must match
					//
					//					if ((msgDigestObj != null) && (digestResultsList != null)
					//							&& (1 != digestResultsList.length)) {
					//						throw new RuntimeException(
					//								"Errors occurs when parsing the manifest file stream!"); //$NON-NLS-1$
					//					}
					ArrayList[] mdResult = (ArrayList[]) contentMDResults.get(entryName);
					if (mdResult == null) {
						mdResult = new ArrayList[2];
						mdResult[0] = new ArrayList();
						mdResult[1] = new ArrayList();
						contentMDResults.put(entryName, mdResult);
					}
					mdResult[0].add(signerInfo);
					mdResult[1].add(digestResult);
				} // could get lines of digest entries in this MF file entry
			} // could retrieve entry name
			// increment the offset to the ending entry...
			entryStartOffset = entryEndOffset;
		}
	}

	private static byte[] getDigestResultsList(String digestLines) {
		byte resultsList[] = null;
		if (digestLines != null) {
			// for each digest-line retrieve the digest result
			// for (int i = 0; i < digestLines.length; i++) {
			String sDigestLine = digestLines;
			int indexDigest = sDigestLine.indexOf(MF_DIGEST_PART);
			indexDigest += MF_DIGEST_PART.length();
			// if there is no data to extract for this digest value
			// then we will fail...
			if (indexDigest >= sDigestLine.length()) {
				resultsList = null;
				// break;
			}
			// now attempt to base64 decode the result
			String sResult = sDigestLine.substring(indexDigest);
			try {
				resultsList = Base64.decode(sResult.getBytes());
			} catch (Throwable t) {
				// malformed digest result, no longer processing this entry
				resultsList = null;
			}
		}
		return resultsList;
	}

	private static String getDigestAlgorithmFromString(String digestLines) throws NoSuchAlgorithmException {
		if (digestLines != null) {
			// String sDigestLine = digestLines[i];
			int indexDigest = digestLines.indexOf(MF_DIGEST_PART);
			String sDigestAlgType = digestLines.substring(0, indexDigest);
			if (sDigestAlgType.equalsIgnoreCase(MD5_STR)) {
				// remember the "algorithm type"
				return MD5_STR;
			} else if (sDigestAlgType.equalsIgnoreCase(SHA1_STR)) {
				// remember the "algorithm type" object
				return SHA1_STR;
			} else {
				// unknown algorithm type, we will stop processing this entry
				// break;
				throw new NoSuchAlgorithmException(NLS.bind(SignedContentMessages.Algorithm_Not_Supported, sDigestAlgType));
			}
		}
		return null;
	}

	private static String getEntryFileName(String manifestEntry) {
		// get the beginning of the name
		int nameStart = manifestEntry.indexOf(MF_ENTRY_NAME);
		if (nameStart == -1) {
			return null;
		}
		// check where the name ends
		int nameEnd = manifestEntry.indexOf('\n', nameStart);
		if (nameEnd == -1) {
			return null;
		}
		// if there is a '\r' before the '\n', then we'll strip it
		if (manifestEntry.charAt(nameEnd - 1) == '\r') {
			nameEnd--;
		}
		// get to the beginning of the actual name...
		nameStart += MF_ENTRY_NAME.length();
		if (nameStart >= nameEnd) {
			return null;
		}
		return manifestEntry.substring(nameStart, nameEnd);
	}

	/**
	 * Returns the Base64 encoded digest of the passed set of bytes.
	 */
	private static String calculateDigest(MessageDigest digest, byte[] bytes) {
		return new String(Base64.encode(digest.digest(bytes)));
	}

	static synchronized MessageDigest getMessageDigest(String algorithm) {
		try {
			return MessageDigest.getInstance(algorithm);
		} catch (NoSuchAlgorithmException e) {
			SignedBundleHook.log(e.getMessage(), FrameworkLogEntry.ERROR, e);
		}
		return null;
	}

	/**
	 * Read the .SF file abd assuming that same digest algorithm will be used through out the whole 
	 * .SF file.  That digest algorithm name in the last entry will be returned. 
	 * 
	 * @param SFBuf			a .SF file in bytes 
	 * @return				the digest algorithm name used in the .SF file
	 */
	private static String getDigAlgFromSF(byte SFBuf[]) {
		// need to make a string from the MF file data bytes
		String mfStr = new String(SFBuf);
		String entryStr = null;

		// start parsing each entry in the MF String
		int entryStartOffset = mfStr.indexOf(MF_ENTRY_NEWLN_NAME);
		int length = mfStr.length();

		while ((entryStartOffset != -1) && (entryStartOffset < length)) {

			// get the start of the next 'entry', i.e. the end of this entry
			int entryEndOffset = mfStr.indexOf(MF_ENTRY_NEWLN_NAME, entryStartOffset + 1);
			if (entryEndOffset == -1) {
				// if there is no next entry, then the end of the string
				// is the end of this entry
				entryEndOffset = mfStr.length();
			}

			// get the string for this entry only, since the entryStartOffset
			// points to the '\n' befor the 'Name: ' we increase it by 1
			// this is guaranteed to not go past end-of-string and be less
			// then entryEndOffset.
			entryStr = mfStr.substring(entryStartOffset + 1, entryEndOffset);
			entryStr = stripContinuations(entryStr);
			break;
		}

		if (entryStr != null) {
			// process the entry to retrieve the digest algorith name
			String digestLine = getDigestLine(entryStr, null);

			// throw parsing
			return getMessageDigestName(digestLine);
		}
		return null;
	}

	/**
	 * 
	 * @param manifestEntry contains a single MF file entry of the format
	 * 				   "Name: foo"
	 * 				   "MD5-Digest: [base64 encoded MD5 digest data]"
	 * 				   "SHA1-Digest: [base64 encoded SHA1 digest dat]"
	 * 
	 * @param	desireDigestAlg	a string representing the desire digest value to be returned if there are
	 * 							multiple digest lines.
	 * 							If this value is null, return whatever digest value is in the entry.
	 * 
	 * @return this function returns a digest line based on the desire digest algorithm value
	 * 		   (since only MD5 and SHA1 are recognized here),
	 * 		   or a 'null' will be returned if none of the digest algorithms
	 * 		   were recognized.
	 */
	private static String getDigestLine(String manifestEntry, String desireDigestAlg) {
		String result = null;

		// find the first digest line
		int indexDigest = manifestEntry.indexOf(MF_DIGEST_PART);
		// if we didn't find any digests at all, then we are done
		if (indexDigest == -1)
			return null;

		// while we continue to find digest entries
		// note: in the following loop we bail if any of the lines
		//		 look malformed...
		while (indexDigest != -1) {
			// see where this digest line begins (look to left)
			int indexStart = manifestEntry.lastIndexOf('\n', indexDigest);
			if (indexStart == -1)
				return null;
			// see where it ends (look to right)
			int indexEnd = manifestEntry.indexOf('\n', indexDigest);
			if (indexEnd == -1)
				return null;
			// strip off ending '\r', if any
			int indexEndToUse = indexEnd;
			if (manifestEntry.charAt(indexEndToUse - 1) == '\r')
				indexEndToUse--;
			// indexStart points to the '\n' before this digest line
			int indexStartToUse = indexStart + 1;
			if (indexStartToUse >= indexEndToUse)
				return null;

			// now this may be a valid digest line, parse it a bit more
			// to see if this is a preferred digest algorithm
			String digestLine = manifestEntry.substring(indexStartToUse, indexEndToUse);
			String digAlg = getMessageDigestName(digestLine);
			if (desireDigestAlg != null) {
				if (desireDigestAlg.equalsIgnoreCase(digAlg))
					return digestLine;
			}

			// desireDigestAlg is null, always return the digestLine
			result = digestLine;

			// iterate to next digest line in this entry
			indexDigest = manifestEntry.indexOf(MF_DIGEST_PART, indexEnd);
		}

		// if we couldn't find any digest lines, then we are done
		return result;
	}

	/**
	 * Return the Message Digest name
	 * 
	 * @param digLine		the message digest line is in the following format.  That is in the 
	 * 						following format:
	 * 								DIGEST_NAME-digest: digest value
	 * @return				a string representing a message digest.
	 */
	private static String getMessageDigestName(String digLine) {
		String rtvValue = null;
		if (digLine != null) {
			int indexDigest = digLine.indexOf(MF_DIGEST_PART);
			if (indexDigest != -1) {
				rtvValue = digLine.substring(0, indexDigest);
			}
		}
		return rtvValue;
	}

	private static String stripContinuations(String entry) {
		if (entry.indexOf("\n ") < 0) //$NON-NLS-1$
			return entry;
		StringBuffer buffer = new StringBuffer(entry.length());
		int cont = entry.indexOf("\n "); //$NON-NLS-1$
		int start = 0;
		while (cont >= 0) {
			buffer.append(entry.substring(start, cont - 1));
			start = cont + 2;
			cont = cont + 2 < entry.length() ? entry.indexOf("\n ", cont + 2) : -1; //$NON-NLS-1$
		}
		// get the last one continuation
		if (start < entry.length())
			buffer.append(entry.substring(start));
		return buffer.toString();
	}

	private static byte[] readIntoArray(BundleEntry be) throws IOException {
		int size = (int) be.getSize();
		InputStream is = be.getInputStream();
		byte b[] = new byte[size];
		int rc = readFully(is, b);
		if (rc != size) {
			throw new IOException("Couldn't read all of " + be.getName() + ": " + rc + " != " + size); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		return b;
	}

	private static int readFully(InputStream is, byte b[]) throws IOException {
		int count = b.length;
		int offset = 0;
		int rc;
		while ((rc = is.read(b, offset, count)) > 0) {
			count -= rc;
			offset += rc;
		}
		return offset;
	}
}
