/*******************************************************************************
 * Copyright (c) 2008, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.internal.security.storage;

import java.io.*;
import java.net.URL;
import java.security.SecureRandom;
import java.util.*;
import java.util.Map.Entry;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.spec.PBEKeySpec;
import org.eclipse.core.runtime.jobs.ILock;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.equinox.internal.security.auth.AuthPlugin;
import org.eclipse.equinox.internal.security.auth.nls.SecAuthMessages;
import org.eclipse.equinox.internal.security.storage.friends.*;
import org.eclipse.equinox.security.storage.StorageException;
import org.eclipse.equinox.security.storage.provider.*;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.util.NLS;

/**
 * Root secure preference node. In addition to usual things it stores location, modified
 * status, encryption algorithm, and performs save and load. 
 */
public class SecurePreferencesRoot extends SecurePreferences implements IStorageConstants {

	private static final String VERSION_KEY = "org.eclipse.equinox.security.preferences.version"; //$NON-NLS-1$
	private static final String VERSION_VALUE = "1"; //$NON-NLS-1$

	/**
	 * Node path reserved for persisted preferences of the modules.
	 */
	static final public String PROVIDER_PATH = "org.eclipse.equinox.security.storage.impl"; //$NON-NLS-1$

	/**
	 * Description of the property file - information only
	 */
	final private static String description = "Equinox secure storage version 1.0"; //$NON-NLS-1$

	/**
	 * The node used by the secure preferences itself
	 */
	private final static String PROVIDER_NODE = "/org.eclipse.equinox.secure.storage"; //$NON-NLS-1$

	/**
	 * Node used to store password verification tokens
	 */
	private final static String PASSWORD_VERIFICATION_NODE = PROVIDER_NODE + "/verification"; //$NON-NLS-1$

	/**
	 * Text used to verify password
	 */
	private final static String PASSWORD_VERIFICATION_SAMPLE = "-> brown fox jumped over lazy dog <-"; //$NON-NLS-1$

	/**
	 * Maximum unsuccessful decryption attempts per operation
	 */
	static protected final int MAX_ATTEMPTS = 20;

	static private ILock lock = Job.getJobManager().newLock();

	private URL location;

	private long timestamp = 0;

	private boolean modified = false;

	private JavaEncryption cipher = new JavaEncryption();

	private Map<String, PasswordExt> passwordCache = new HashMap<>(5); // cached passwords: module ID -> PasswordExt 

	public SecurePreferencesRoot(URL location) throws IOException {
		super(null, null);
		this.location = location;
		load();
	}

	public URL getLocation() {
		return location;
	}

	public JavaEncryption getCipher() {
		return cipher;
	}

	@Override
	public boolean isModified() {
		return modified;
	}

	public void setModified(boolean modified) {
		this.modified = modified;
	}

	public void load() throws IOException {
		if (location == null)
			return;

		Properties properties = new Properties();
		InputStream is = null;
		try {
			is = StorageUtils.getInputStream(location);
			if (is != null) {
				properties.load(is);
				timestamp = getLastModified();
			}
		} catch (IllegalArgumentException e) {
			String msg = NLS.bind(SecAuthMessages.badStorageURL, location.toString());
			AuthPlugin.getDefault().logError(msg, e);
			location = null; // don't attempt to use it 
			return;
		} finally {
			if (is != null)
				is.close();
		}

		// In future new versions could be added
		Object version = properties.get(VERSION_KEY);
		if ((version != null) && !VERSION_VALUE.equals(version))
			return;
		properties.remove(VERSION_KEY);

		// Process encryption algorithms
		if (properties.containsKey(CIPHER_KEY) && properties.containsKey(KEY_FACTORY_KEY)) {
			Object cipherAlgorithm = properties.get(CIPHER_KEY);
			Object keyFactoryAlgorithm = properties.get(KEY_FACTORY_KEY);
			if ((cipherAlgorithm instanceof String) && (keyFactoryAlgorithm instanceof String))
				cipher.setAlgorithms((String) cipherAlgorithm, (String) keyFactoryAlgorithm);
			properties.remove(CIPHER_KEY);
			properties.remove(KEY_FACTORY_KEY);
		}

		for (Entry<Object, Object> entry : properties.entrySet()) {
			Object externalKey = entry.getKey();
			Object value = entry.getValue();
			if (!(externalKey instanceof String))
				continue;
			if (!(value instanceof String))
				continue;
			PersistedPath storedPath = new PersistedPath((String) externalKey);
			if (storedPath.getKey() == null)
				continue;

			SecurePreferences node = node(storedPath.getPath());
			// don't use regular put() method as that would mark node as dirty
			node.internalPut(storedPath.getKey(), (String) value);
		}
	}

	@Override
	synchronized public void flush() throws IOException {
		if (location == null)
			return;
		if (!modified)
			return;

		// check if the file has been modified since the last time it was touched
		if (timestamp != 0 && (timestamp != getLastModified())) {
			IUICallbacks callback = CallbacksProvider.getDefault().getCallback();
			if (callback != null) {
				Boolean response = callback.ask(SecAuthMessages.fileModifiedMsg);
				if (response == null)
					AuthPlugin.getDefault().frameworkLogError(SecAuthMessages.fileModifiedNote, FrameworkLogEntry.WARNING, null);
				else if (!response.booleanValue())
					return; // by default go ahead with save
			}
		}

		Properties properties = new Properties();
		properties.put(VERSION_KEY, VERSION_VALUE);

		// remember encyption algorithms
		String cipherAlgorithm = cipher.getCipherAlgorithm();
		if (cipherAlgorithm != null) {
			properties.put(CIPHER_KEY, cipherAlgorithm);
			properties.put(KEY_FACTORY_KEY, cipher.getKeyFactoryAlgorithm());
		}

		// save all user properties
		flush(properties, null);

		// output
		OutputStream stream = null;
		try {
			stream = StorageUtils.getOutputStream(location);
			properties.store(stream, description);
			modified = false;
		} finally {
			if (stream != null)
				stream.close();
		}
		timestamp = getLastModified();
	}

	/**
	 * Provides password for a new entry using:
	 * 1) default password, if any
	 * 2a) if options specify usage of specific module, that module is polled to produce password
	 * 2b) otherwise, password provider with highest priority is used to produce password
	 */
	public PasswordExt getPassword(String moduleID, IPreferencesContainer container, boolean encryption) throws StorageException {
		if (encryption) { // provides password for a new entry
			PasswordExt defaultPassword = getDefaultPassword(container);
			if (defaultPassword != null)
				return defaultPassword;
			moduleID = getDefaultModuleID(container);
		} else { // provides password for previously encrypted entry using its specified password provider module
			if (moduleID == null)
				throw new StorageException(StorageException.NO_SECURE_MODULE, SecAuthMessages.invalidEntryFormat);
			if (DEFAULT_PASSWORD_ID.equals(moduleID)) { // was default password used?
				PasswordExt defaultPassword = getDefaultPassword(container);
				if (defaultPassword != null)
					return defaultPassword;
				throw new StorageException(StorageException.NO_SECURE_MODULE, SecAuthMessages.noDefaultPassword);
			}
		}
		return getModulePassword(moduleID, container);
	}

	private PasswordExt getModulePassword(String moduleID, IPreferencesContainer container) throws StorageException {
		if (DEFAULT_PASSWORD_ID.equals(moduleID)) // this should never happen but add this check just in case
			throw new StorageException(StorageException.NO_PASSWORD, SecAuthMessages.loginNoPassword);

		PasswordProviderModuleExt moduleExt = PasswordProviderSelector.getInstance().findStorageModule(moduleID);
		String key = moduleExt.getID();
		String obsoleteKey = moduleExt.getObsoleteID();
		PasswordExt passwordExt = null;
		boolean validPassword = false;
		boolean setupPasswordRecovery = false;
		boolean addedNoPrompt = false;

		try {
			lock.acquire(); // make sure process of password creation is not re-entered by another thread
			// Quick check first: it is cached?
			synchronized (passwordCache) {
				if (passwordCache.containsKey(key))
					return passwordCache.get(key);
			}

			// if this is (a headless run or JUnit) and prompt hint is not set up, set it to "false"
			boolean supressPrompts = !CallbacksProvider.getDefault().runningUI() || InternalExchangeUtils.isJUnitApp();
			if (supressPrompts && container != null && !container.hasOption(IProviderHints.PROMPT_USER)) {
				((SecurePreferencesContainer) container).setOption(IProviderHints.PROMPT_USER, Boolean.FALSE);
				addedNoPrompt = true;
			}

			// is there password verification string already?
			SecurePreferences node = node(PASSWORD_VERIFICATION_NODE);
			if (obsoleteKey != null && node.hasKey(obsoleteKey)) {
				key = obsoleteKey;
			}
			boolean newPassword = !node.hasKey(key);
			int passwordType = newPassword ? PasswordProvider.CREATE_NEW_PASSWORD : 0;

			for (int i = 0; i < MAX_ATTEMPTS; i++) {
				PBEKeySpec password = moduleExt.getPassword(container, passwordType);
				if (password == null)
					return null;
				passwordExt = new PasswordExt(password, key);
				if (newPassword) {
					String test = createTestString();
					CryptoData encryptedValue = getCipher().encrypt(passwordExt, StorageUtils.getBytes(test));
					node.internalPut(key, encryptedValue.toString());
					markModified();
					setupPasswordRecovery = true;
					validPassword = true;
					break;
				}
				// verify password using sample text
				String encryptedData = node.internalGet(key);
				CryptoData data = new CryptoData(encryptedData);
				try {
					byte[] decryptedData = getCipher().decrypt(passwordExt, data);
					String test = StorageUtils.getString(decryptedData);
					if (verifyTestString(test)) {
						validPassword = true;
						break;
					}
				} catch (IllegalBlockSizeException | BadPaddingException e) {
					if (!moduleExt.changePassword(e, container))
						break;
				}
			}
			if (validPassword) {
				synchronized (passwordCache) {
					passwordCache.put(key, passwordExt);
				}
			}
		} finally {
			if (addedNoPrompt) {
				((SecurePreferencesContainer) container).removeOption(IProviderHints.PROMPT_USER);
				addedNoPrompt = false;
			}
			lock.release();
		}

		if (!validPassword)
			throw new StorageException(StorageException.NO_PASSWORD, SecAuthMessages.loginNoPassword);
		if (setupPasswordRecovery)
			CallbacksProvider.getDefault().setupChallengeResponse(key, container);
		return passwordExt;
	}

	/**
	 * Retrieves default password from options, if any
	 */
	private PasswordExt getDefaultPassword(IPreferencesContainer container) {
		if (container.hasOption(IProviderHints.DEFAULT_PASSWORD)) {
			Object passwordHint = container.getOption(IProviderHints.DEFAULT_PASSWORD);
			if (passwordHint instanceof PBEKeySpec)
				return new PasswordExt((PBEKeySpec) passwordHint, DEFAULT_PASSWORD_ID);
		}
		return null;
	}

	/**
	 * Retrieves requested module ID from options, if any
	 */
	private String getDefaultModuleID(IPreferencesContainer container) {
		if (container.hasOption(IProviderHints.REQUIRED_MODULE_ID)) {
			Object idHint = container.getOption(IProviderHints.REQUIRED_MODULE_ID);
			if (idHint instanceof String)
				return (String) idHint;
		}
		return null;
	}

	public boolean onChangePassword(IPreferencesContainer container, String moduleID) {
		// validation: must have a password module
		PasswordProviderModuleExt moduleExt;
		try {
			moduleExt = PasswordProviderSelector.getInstance().findStorageModule(moduleID);
		} catch (StorageException e) {
			return false; // no module -> nothing to do
		}

		// obtain new password first
		int passwordType = PasswordProvider.CREATE_NEW_PASSWORD | PasswordProvider.PASSWORD_CHANGE;
		PBEKeySpec password = moduleExt.getPassword(container, passwordType);
		if (password == null)
			return false;

		// create verification node
		String key = moduleExt.getID();
		PasswordExt passwordExt = new PasswordExt(password, key);
		CryptoData encryptedValue;
		try {
			String test = createTestString();
			encryptedValue = getCipher().encrypt(passwordExt, StorageUtils.getBytes(test));
		} catch (StorageException e) {
			String msg = NLS.bind(SecAuthMessages.encryptingError, key, PASSWORD_VERIFICATION_NODE);
			AuthPlugin.getDefault().logError(msg, e);
			return false;
		}

		SecurePreferences node = node(PASSWORD_VERIFICATION_NODE);
		node.internalPut(key, encryptedValue.toString());
		markModified();
		try {
			flush();
		} catch (IOException e) {
			String msg = NLS.bind(SecAuthMessages.encryptingError, key, PASSWORD_VERIFICATION_NODE);
			AuthPlugin.getDefault().logError(msg, e);
			return false;
		}

		// store password in the memory cache
		cachePassword(key, passwordExt);
		CallbacksProvider.getDefault().setupChallengeResponse(key, container);
		return true;
	}

	public void cachePassword(String moduleID, PasswordExt passwordExt) {
		synchronized (passwordCache) {
			passwordCache.put(moduleID, passwordExt);
		}
	}

	public void clearPasswordCache() {
		synchronized (passwordCache) {
			passwordCache.clear();
		}
	}

	private long getLastModified() {
		File file = new File(location.getPath());
		return file.lastModified();
	}

	/**
	 * Generates random string to be stored for password verification. String format:
	 * <random1>\t<random2>\t<random2>\t<random1>
	 */
	private String createTestString() {
		SecureRandom rand = new SecureRandom();
		rand.setSeed(System.currentTimeMillis());

		long num1 = rand.nextInt(10000);
		long num2 = rand.nextInt(10000);

		StringBuilder tmp = new StringBuilder();
		tmp.append(num1);
		tmp.append('\t');
		tmp.append(num2);
		tmp.append('\t');
		tmp.append(num2);
		tmp.append('\t');
		tmp.append(num1);

		return tmp.toString();
	}

	/**
	 * Checks if the string is the hard-coded original password verification sample
	 * or a string generated according to the rules in {@link #createTestString()}.  
	 */
	private boolean verifyTestString(String test) {
		if (test == null || test.length() == 0)
			return false;
		// backward compatibility: check if it is the original hard-coded string 
		if (PASSWORD_VERIFICATION_SAMPLE.equals(test))
			return true;
		String[] parts = test.split("\t"); //$NON-NLS-1$
		if (parts == null || parts.length == 0)
			return false;
		if (parts.length != 4)
			return false;
		long num1 = -1;
		long num2 = -1;
		for (int i = 0; i < 4; i++) {
			if (parts[i] == null || parts[i].length() == 0)
				return false;
			try {
				switch (i) {
					case 0 :
						num1 = Long.decode(parts[i]).longValue();
						break;
					case 1 :
						num2 = Long.decode(parts[i]).longValue();
						break;
					case 2 : {
						long tmp = Long.decode(parts[i]).longValue();
						if (tmp != num2)
							return false;
						break;
					}
					case 3 : {
						long tmp = Long.decode(parts[i]).longValue();
						if (tmp != num1)
							return false;
						break;
					}
				}
			} catch (NumberFormatException e) {
				return false;
			}
		}
		return true;
	}
}
