All Downloads are FREE. Search and download functionalities are using the official Maven repository.

es.gob.afirma.standalone.ui.restoreconfig.RestoreConfigWindows Maven / Gradle / Ivy

There is a newer version: 1.8.2
Show newest version
/* Copyright (C) 2011 [Gobierno de Espana]
 * This file is part of "Cliente @Firma".
 * "Cliente @Firma" is free software; you can redistribute it and/or modify it under the terms of:
 *   - the GNU General Public License as published by the Free Software Foundation;
 *     either version 2 of the License, or (at your option) any later version.
 *   - or The European Software License; either version 1.1 or (at your option) any later version.
 * You may contact the copyright holder at: [email protected]
 */

package es.gob.afirma.standalone.ui.restoreconfig;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JOptionPane;

import com.sun.jna.platform.win32.Advapi32Util;
import com.sun.jna.platform.win32.WinReg;

import es.gob.afirma.core.misc.AOUtil;
import es.gob.afirma.standalone.AutoFirmaUtil;
import es.gob.afirma.standalone.SimpleAfirmaMessages;
import es.gob.afirma.standalone.ui.restoreconfig.CertUtil.CertPack;
import es.gob.afirma.standalone.ui.restoreconfig.RestoreConfigFirefox.MozillaProfileNotFoundException;

/**
 * Clase que contiene la lógica para realizar las tareas de restauración
 * de la configuración de navegadores para el sistema operativo Windows.
 *
 */
final class RestoreConfigWindows implements RestoreConfig {

	static final Logger LOGGER = Logger.getLogger("es.gob.afirma"); //$NON-NLS-1$

	private static final String SSL_KEYSTORE_FILENAME = "autofirma.pfx"; //$NON-NLS-1$
	private static final String CA_CERTIFICATE_FILENAME = "AutoFirma_ROOT.cer"; //$NON-NLS-1$
	private static final String KS_PASSWORD = "654321"; //$NON-NLS-1$

	private static final String RESTORE_PROTOCOL_EXE = "afirma_register.exe"; //$NON-NLS-1$
	private static final String RESTORE_PROTOCOL_BAT = "afirma_register.bat"; //$NON-NLS-1$

	private static final String REPLACE_PATH_EXE = "$$PATH_EXE$$"; //$NON-NLS-1$
	private static final String REPLACE_INSTALL_DIR = "$$INSTALL_DIR$$"; //$NON-NLS-1$

	/**
     * Caracter de salto de línea para los mensajes de la consola de restauración
     */
	static final String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$

	/**
	 * Ruta de operación de la aplicación
	 */
	private final static File appDir = RestoreConfigUtil.getApplicationDirectory();

	@Override
	public void restore(final RestoreConfigPanel configPanel) {

		// Identificamos el directorio de instalacion
		LOGGER.info("Ruta de appDir: " + appDir.getAbsolutePath()); //$NON-NLS-1$
		configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.3", appDir.getAbsolutePath())); //$NON-NLS-1$

		// Verifica si se tiene permisos para escribir en el directorio de instalacion
		boolean usingAlternativeDirectory;
		File workingDirectory;
		if(Files.isWritable(appDir.toPath())) {
			workingDirectory = appDir;
			usingAlternativeDirectory = false;
		} else {
			workingDirectory = AutoFirmaUtil.getWindowsAlternativeAppDir();
			usingAlternativeDirectory = true;
		}

		LOGGER.info("Ruta de trabajo:  " + workingDirectory.getAbsolutePath()); //$NON-NLS-1$
		// Regeneramos los certificados que sean necesario (raiz y ssl) y los guardamos en disco
		CertificateFile sslRoot;
		try {
			sslRoot = rebuildCertificates(configPanel, workingDirectory);
		}
		catch (final Exception e) {
			LOGGER.severe("No se han podido regenerar los certificados necesarios. No se instalaran en los almacenes de confianza: " + e); //$NON-NLS-1$
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.33")); //$NON-NLS-1$
			sslRoot = null;
		}

		// Instalacion del certificado raiz en Windows
		if (sslRoot != null) {
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.18")); //$NON-NLS-1$
			installRootCAWindowsKeystore(configPanel, sslRoot);
		}

		// Instalacion del certificado raiz en Firefox
		if (sslRoot != null) {
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.13")); //$NON-NLS-1$
			installRootCAMozillaKeystore(configPanel, sslRoot, workingDirectory);
		}

		// Si no se han creado directamente los certificados en el directorio alternativo
		// y este existe, lo copiamos ahora
		if (!usingAlternativeDirectory) {
			final File alternativeDir = AutoFirmaUtil.getWindowsAlternativeAppDir();
			if (alternativeDir.exists()) {
				configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.36")); //$NON-NLS-1$
				try {
					Files.copy(
							new File(workingDirectory, SSL_KEYSTORE_FILENAME).toPath(),
							new File(alternativeDir, SSL_KEYSTORE_FILENAME).toPath(),
							StandardCopyOption.REPLACE_EXISTING);
				} catch (final IOException e) {
					LOGGER.warning("No se ha podido copiar el almacen del certificado SSL al directorio alternativo de instalacion: " + e); //$NON-NLS-1$
					configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.37")); //$NON-NLS-1$
				}
			}
		}

		// Registramos el protocolo afirma
		configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.24")); //$NON-NLS-1$
		try {
			restoreProtocolRegistry(appDir.getAbsoluteFile(), workingDirectory.getAbsoluteFile());
		}
		catch (final Exception e) {
			LOGGER.warning("Error restaurando los valores del protocolo 'afirma': " + e); //$NON-NLS-1$
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.25")); //$NON-NLS-1$
		}

		// Configuramos el protocolo afirma en Chrome para que no muestre advertencias al llamarlo
		configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.23")); //$NON-NLS-1$
		configureChrome();

		configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.8")); //$NON-NLS-1$
	}

	/**
	 * Comprueba si ya existe un almacén de certificados generado.
	 *
	 * @param installDir
	 *            Directorio de la aplicación.
	 * @return {@code true} si ya existe un almacen de certificados SSL,
	 *         {@code false} en caso contrario.
	 */
	private static boolean checkSSLKeyStoreGenerated(final File installDir) {
		return new File(installDir, SSL_KEYSTORE_FILENAME).exists();
	}

	/**
	 * Comprueba si ya existe un certificado raiz generado.
	 *
	 * @param installDir
	 *            Directorio de la aplicación.
	 * @return {@code true} si ya existe un certificado raiz .cer, {@code false}
	 *         en caso contrario.
	 */
	private static boolean checkSSLRootCertificateGenerated(final File installDir) {
		return new File(installDir, CA_CERTIFICATE_FILENAME).exists();
	}


	/**
	 * Configura el protocolo "afirma" en Chrome para todos los usuarios de
	 * Windows.
	 */
	private static void configureChrome() {

		// Solicitamos el cierre del navegador Google Chrome
		closeChrome();

		RestoreRemoveChromeWarning.removeChromeWarningsWindows(null, true);

	}

	/**
	 * Comprueba si un proceso está ejecutándose en Windows
	 * @param process Cadena que identifica al proceso
	 * @return ({@code true}}) Si está ejecutándose, ({@code false}}) en caso contrario
	 */
	private static Boolean isProcessRunningWindows(final String process) {

		String line;
		String pidInfo = ""; //$NON-NLS-1$
		Boolean isRunning = Boolean.FALSE;

		Process p;
		try {

			final ProcessBuilder pb = new ProcessBuilder(System.getenv("windir") + "\\system32\\" + "tasklist.exe"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

			p = pb.start();

			try (final BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) {

				while ((line = input.readLine()) != null) {
					pidInfo += line;
				}
			}

		} catch (final IOException e) {
			LOGGER.severe("Ha ocurrido un error al ejecutar el comando " + process + " en Windows. " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
		}

		if (pidInfo.contains(process)) {
			isRunning = Boolean.TRUE;
		}

		return isRunning;
	}

	/**
	 * Pide al usuario que cierre el navegador Mozilla Firefox y no permite continuar hasta que lo hace.
	 */
	private static void closeFirefox() {

		while (isProcessRunningWindows("firefox.exe").booleanValue()) { //$NON-NLS-1$
			JOptionPane.showMessageDialog(
					null,
					SimpleAfirmaMessages.getString("RestoreAutoFirma.7"), //$NON-NLS-1$
					SimpleAfirmaMessages.getString("RestoreAutoFirma.9"), //$NON-NLS-1$
					JOptionPane.WARNING_MESSAGE);
		}
	}

	/**
	 * Pide al usuario que cierre el navegador Mozilla Firefox y no permite continuar hasta que lo hace.
	 */
	private static void closeChrome() {

		while (isProcessRunningWindows("chrome.exe").booleanValue()) { //$NON-NLS-1$
			JOptionPane.showMessageDialog(
					null,
					SimpleAfirmaMessages.getString("RestoreAutoFirma.8"), //$NON-NLS-1$
					SimpleAfirmaMessages.getString("RestoreAutoFirma.9"), //$NON-NLS-1$
					JOptionPane.WARNING_MESSAGE);
		}
	}

	/** Instala el certificado raíz CA de AutoFirma
	 * en el almacén raíz de Windows.
	 * @param configPanel Panel de configuración con las trazas de ejecución.
	 * @param certFile El certificado a instalar. */
	private static void installRootCAWindowsKeystore(final RestoreConfigPanel configPanel, final CertificateFile certFile) {

		final KeyStore ks;
		try {
			ks = KeyStore.getInstance("Windows-ROOT"); //$NON-NLS-1$
			ks.load(null, null);
		}
		catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
			LOGGER.severe("No se ha podido cargar el almacen de certificados de confianza de Windows: " + e); //$NON-NLS-1$
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.20")); //$NON-NLS-1$
			return;
		}

		// Comprobamos si el certificado ya esta instalado en el almacen
		try {
			final Certificate currentCert = ks.getCertificate(RestoreConfigUtil.CERT_ALIAS_BROWSER);
			if (currentCert != null && currentCert.equals(certFile.getCert())) {
				LOGGER.info("El certificado raiz ya se encontraba instalado en el almacen del sistema"); //$NON-NLS-1$
				configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.26")); //$NON-NLS-1$
				return;
			}
		}
		catch (final Exception e) {
			LOGGER.warning("No se pudo comprobar si el certificado ya estaba en el almacen: " + e); //$NON-NLS-1$
		}

		// Antes de la instalacion, intentamos desinstalar cualquier otro certificado con el
		// mismo alias que se encuentre en el almacen
		configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.22")); //$NON-NLS-1$
		try {
			while (ks.getCertificate(RestoreConfigUtil.CERT_ALIAS_BROWSER) != null) {
				configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.35")); //$NON-NLS-1$
				ks.deleteEntry(RestoreConfigUtil.CERT_ALIAS_BROWSER);
			}
		}
		catch (final KeyStoreException ke) {
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.34")); //$NON-NLS-1$
			LOGGER.info("No se ha podido eliminar alguna importacion previa del certificado raiz del almacen de Windows: " + ke.getMessage()); //$NON-NLS-1$
		}

		// Instalamos el certificado
		boolean installed = false;
		do {
			try {
				ks.setCertificateEntry(RestoreConfigUtil.CERT_ALIAS_BROWSER, certFile.getCert());
				installed = true;
			}
			catch (final KeyStoreException e) {
				LOGGER.warning(
					"No se pudo instalar la CA del certificado SSL para el socket en el almacen de Windows: " + e //$NON-NLS-1$
				);
				final int result = JOptionPane.showConfirmDialog(
					null,
					SimpleAfirmaMessages.getString("RestoreConfigWindows.0"), //$NON-NLS-1$
					SimpleAfirmaMessages.getString("RestoreConfigWindows.1"), //$NON-NLS-1$
					JOptionPane.OK_CANCEL_OPTION,
					JOptionPane.WARNING_MESSAGE
				);
				if (result == JOptionPane.CANCEL_OPTION) {
					LOGGER.severe("El usuario cancelo la instalacion del certificado SSL para el socket: " + e); //$NON-NLS-1$
					configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.32")); //$NON-NLS-1$
					return;
				}
			}
		}
		while (!installed);
	}

	/** Instala el certificado raíz CA de AutoFirma
	 * en el almacén raíz de Mozilla.
	 *  @param configPanel Panel de configuración con las trazas de ejecución.
	 *  @param certFile El certificado a instalar.
	 *  @param installDir Directorio de instalación. */
	private static void installRootCAMozillaKeystore(final RestoreConfigPanel configPanel,
			                                         final CertificateFile certFile,
			                                         final File installDir) {
		try {
			// Obligamos a que se cierre Firefox antes de manipular el
			// certificado en su almacen
			closeFirefox();

			// Es necesario copiar a disco certutil
			RestoreConfigFirefox.copyConfigurationFiles(installDir);

			// certutil no lanza ningun error si hay algun problema a partir de Firefox 50

			// Desinstalamos versiones previas
			LOGGER.info("Desinstalamos el certificado raiz del almacen de Firefox"); //$NON-NLS-1$
			RestoreConfigFirefox.uninstallRootCAMozillaKeyStore(installDir);
			// Vuelvo a instalar lo que habia o el nuevo cer generado
			RestoreConfigFirefox.installRootCAMozillaKeyStore(installDir, certFile.getFile());
			// Elimino certutil tras su uso
			RestoreConfigFirefox.removeConfigurationFiles(installDir);

		}
		catch (final IOException | KeyStoreException e) {
			LOGGER.log(Level.SEVERE, "Error instalando el certificado raiz: " + e, e); //$NON-NLS-1$
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.31", installDir.getAbsolutePath())); //$NON-NLS-1$
		}
		catch (final MozillaProfileNotFoundException e) {
			LOGGER.warning("No se ha encontrado el perfil de Mozilla en Windows: " + e); //$NON-NLS-1$
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.12")); //$NON-NLS-1$
		}
	}

	/**
	 * Restaura los valores del protocolo afirma en el registro de Windows.
	 * Se sobreescriben las distintas subkeys con los valores adecuados.
	 * @param installDir Directorio de instalación en el que copiar los ficheros que sean necesarios.
	 * @param workingDir Directorio de trabajo dependiendo si se tienen permisos de escritura sobre
	 * el directorio de instalación.
	 * @throws GeneralSecurityException Cuando no se puede actualizar la entrada del protocolo
	 * "afirma" en el registro.
	 */
	private static void restoreProtocolRegistry(final File installDir, final File workingDir) throws GeneralSecurityException {

		try {
			// Crear la key "afirma" si no existe
			if (!Advapi32Util.registryKeyExists(WinReg.HKEY_CLASSES_ROOT, "afirma")) { //$NON-NLS-1$
				Advapi32Util.registryCreateKey(WinReg.HKEY_CLASSES_ROOT, "afirma"); //$NON-NLS-1$
			}
			// Sobreescribir los valores correctos
			Advapi32Util.registrySetStringValue(WinReg.HKEY_CLASSES_ROOT, "afirma", "", "URL:Afirma Protocol"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			Advapi32Util.registrySetStringValue(WinReg.HKEY_CLASSES_ROOT, "afirma", "URL Protocol", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

			// Crear la key "afirma\\DefaultIcon"
			if (!Advapi32Util.registryKeyExists(WinReg.HKEY_CLASSES_ROOT, "afirma\\DefaultIcon")) { //$NON-NLS-1$
				Advapi32Util.registryCreateKey(WinReg.HKEY_CLASSES_ROOT, "afirma\\DefaultIcon"); //$NON-NLS-1$
			}
			// Sobreescribir los valores correctos
			Advapi32Util.registrySetStringValue(WinReg.HKEY_CLASSES_ROOT, "afirma\\DefaultIcon", "", installDir + "\\ic_firmar.ico"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

			// Crear la key "afirma\\shell\\open\\command" si no existe
			if (!Advapi32Util.registryKeyExists(WinReg.HKEY_CLASSES_ROOT, "afirma\\shell\\open\\command")) { //$NON-NLS-1$
				Advapi32Util.registryCreateKey(WinReg.HKEY_CLASSES_ROOT, "afirma\\shell\\open\\command"); //$NON-NLS-1$
			}
			// Sobreescribir los valores correctos
			Advapi32Util.registrySetStringValue(WinReg.HKEY_CLASSES_ROOT, "afirma\\shell\\open\\command", "", installDir + "\\AutoFirma.exe %1"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

		} catch (final Exception e) {

			LOGGER.warning("No se pudo actualizar el registro con los permisos del usuario, se solicita elevar privilegios: " + e); //$NON-NLS-1$

			// No se pudo actualizar el registro con los permisos del usuario,
			// se usara la biblioteca nativa
			final int result = restoreProtocolRegistryByApp(installDir, workingDir.getAbsolutePath());
			if (result != 0) {
				throw new GeneralSecurityException("No se pudo registrar el protocolo afirma. Codigo de error: " + result); //$NON-NLS-1$
			}
		}

		LOGGER.info("Configurado afirma en registro Windows"); //$NON-NLS-1$
	}

	/**
	 * Comprueba si es necesario volver a generar el almacén de claves y/o el certificado para
	 * comunicación SSL y, en caso afirmativo, los genera.
	 * @param configPanel Panel de configuración con las trazas de ejecución.
	 * @param installDir Directorio de instalación en el que se deben encontrar los certificados SSL.
	 * @return El certificado raíz.
	 * @throws IOException Cuando ocurre un error al generar o copiar a disco los certificados.
	 */
	private static CertificateFile rebuildCertificates(final RestoreConfigPanel configPanel, final File installDir) throws IOException {
		// SSLKeystore --> pfx, SSLRoot --> cer
		CertificateFile sslRoot = null;

		// Si no existe el pfx, debo generar el certificado raiz y el certificado SSL
		if (!checkSSLKeyStoreGenerated(installDir)) {

			// Eliminando de disco las versiones previas de los certificados
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.16")); //$NON-NLS-1$
			try {
				deleteCertificatesFromDisk(installDir);
			} catch (final IOException e) {
				configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.17")); //$NON-NLS-1$
				LOGGER.log(Level.SEVERE, "Error al eliminar los certificados SSL anteriores de disco: " + e); //$NON-NLS-1$
			}

			// Generamos los certificados
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.5")); //$NON-NLS-1$
			CertPack certPack;
			try {
				certPack = CertUtil.getCertPackForLocalhostSsl(RestoreConfigUtil.CERT_ALIAS, KS_PASSWORD);
				sslRoot = new CertificateFile(certPack.getCaCertificate());
			}
			catch (final GeneralSecurityException e) {
				LOGGER.severe("No se ha podido generar el certificado SSL: " + e); //$NON-NLS-1$
				throw new IOException("No se ha podido generar el certificado SSL", e); //$NON-NLS-1$
			}

			// Copiamos los certificados a disco
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.11")); //$NON-NLS-1$
			File sslRootFile = new File(installDir, CA_CERTIFICATE_FILENAME);
			try {
				RestoreConfigUtil.installFile(certPack.getPkcs12(), new File(installDir, SSL_KEYSTORE_FILENAME));
				RestoreConfigUtil.installFile(certPack.getCaCertificate().getEncoded(), sslRootFile);
			}
			catch (final Exception e) {
				LOGGER.severe("No se ha podido guardar en disco los certificados SSL. Los almacenaresmos en un directorio alternativo:  " + e); //$NON-NLS-1$
				final File alternativeDir = AutoFirmaUtil.getWindowsAlternativeAppDir();
				if (!alternativeDir.isDirectory() && !alternativeDir.mkdirs()) {
					throw new IOException("No se ha podido guardar en disco los certificados SSL. Error al crear el directorio alternativo"); //$NON-NLS-1$
				}
				try {
					sslRootFile = new File(alternativeDir, CA_CERTIFICATE_FILENAME);
					RestoreConfigUtil.installFile(certPack.getPkcs12(), new File(alternativeDir, SSL_KEYSTORE_FILENAME));
					RestoreConfigUtil.installFile(certPack.getCaCertificate().getEncoded(), sslRootFile);
				}
				catch (final Exception ex) {
					LOGGER.severe("No se ha podido guardar en el directorio alternativo los certificados SSL: " + e); //$NON-NLS-1$
					throw new IOException("Error guardando en el directorio alternativo los certificados SSL", e); //$NON-NLS-1$
				}
			}
			sslRoot.setFile(sslRootFile);
		}
		// Si solo no existe el certificado raiz, lo extraigo del almacen del certificado SSL
		else if (!checkSSLRootCertificateGenerated(installDir)) {

			// Cargo el pfx y extraigo el certificado raiz
			try (FileInputStream fis = new FileInputStream(new File(installDir, SSL_KEYSTORE_FILENAME))) {
				final KeyStore ks = KeyStore.getInstance("PKCS12"); //$NON-NLS-1$
				ks.load(fis, KS_PASSWORD.toCharArray());
				final Certificate[] chain = ks.getCertificateChain(RestoreConfigUtil.CERT_ALIAS);
				sslRoot = new CertificateFile(chain[chain.length - 1]);
			}
			catch(final Exception e) {
				LOGGER.log(Level.SEVERE, "Error al extraer el certificado raiz del PKCS#12: " + e); //$NON-NLS-1$
				throw new IOException("Error al generar el certificado SSL", e); //$NON-NLS-1$
			}

			// Copio a disco el certificado raiz
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.11")); //$NON-NLS-1$
			File sslRootFile = new File(installDir, CA_CERTIFICATE_FILENAME);
			try {
				RestoreConfigUtil.installFile(sslRoot.getCert().getEncoded(), sslRootFile);
			}
			catch (final Exception e) {
				LOGGER.severe("No se ha podido guardar en disco el certificado raiz SSL. Lo extraemos a un directorio alternativo: " + e); //$NON-NLS-1$
				final File alternativeDir = AutoFirmaUtil.getWindowsAlternativeAppDir();
				if (!alternativeDir.isDirectory() && !alternativeDir.mkdirs()) {
					throw new IOException("No se ha podido guardar en disco el certificado raiz SSL. Error al crear el directorio alternativo"); //$NON-NLS-1$
				}
				try {
					RestoreConfigUtil.installFile(sslRoot.getCert().getEncoded(), alternativeDir);
					sslRootFile = new File(alternativeDir, CA_CERTIFICATE_FILENAME);
				}
				catch (final Exception ex) {
					LOGGER.severe("No se ha podido guardar en disco el certificado raiz SSL: " + e); //$NON-NLS-1$
					throw new IOException("Error guardando en disco el certificado raiz SSL", e); //$NON-NLS-1$
				}
			}
			sslRoot.setFile(sslRootFile);
		}
		// Si existen ambos no hago nada
		else {
			configPanel.appendMessage(SimpleAfirmaMessages.getString("RestoreConfigWindows.14")); //$NON-NLS-1$
			final File sslRootFile = new File(installDir, CA_CERTIFICATE_FILENAME);
			sslRoot = new CertificateFile(CertUtil.loadCertificate(sslRootFile));
			sslRoot.setFile(sslRootFile);
		}

		return sslRoot;
	}


	/** Elimina los ficheros de certificado raíz y almacén SSL del disco
	 * como paso previo a volver a generarlos.
	 * @param installDir Ruta del directorio de la aplicación.
	 * @throws IOException Si hay problemas borrando los ficheros. */
	private static void deleteCertificatesFromDisk(final File installDir) throws IOException {

		if (checkSSLKeyStoreGenerated(installDir)) {

			Files.delete(new File(installDir, SSL_KEYSTORE_FILENAME).toPath());
		}

		if (checkSSLRootCertificateGenerated(installDir)) {

			Files.delete(new File(installDir, CA_CERTIFICATE_FILENAME).toPath());
		}
	}

	/**
	 * Restaura la configuración del protocolo "afirma" para que se invoque a la
	 * aplicación. Lo hace a través de una aplicación externa preparada
	 * para tal fin.
	 * @param installDir Directorio de instalación donde se puedan crear los ficheros
	 * @param workingDir Directorio de trabajo donde se puedan crear los ficheros
	 * necesarios para ejecutar la operación.
	 * @return El valor cero en caso de éxito, -1 si no se proporciona un parámetro
	 * o cualquier otro código de error del sistema.
	 * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx)
	 */
	private static int restoreProtocolRegistryByApp(final File installDir, final String workingDir) {

		// Copiamos al directorio de instalacion la aplicacion para restaurar el protocolo
		final File exeFile = new File(workingDir, RESTORE_PROTOCOL_EXE);
		try (final FileOutputStream os = new FileOutputStream(exeFile);
				final InputStream is = RestoreConfigWindows.class.getResourceAsStream("/windows/" + RESTORE_PROTOCOL_EXE);) { //$NON-NLS-1$
			os.write(AOUtil.getDataFromInputStream(is));
			os.flush();
		}
		catch (final Exception e) {
			LOGGER.warning("No se pudo copiar a disco la aplicacion de restauracion. Se abortara su ejecucion: " + e); //$NON-NLS-1$
			return 2; // ERROR_FILE_NOT_FOUND
		}

		// Copiamos a disco y completamos el script para ejecutar la aplicacion con
		// permisos de administrador
		final File batFile = new File(workingDir, RESTORE_PROTOCOL_BAT);
		try (final FileOutputStream os = new FileOutputStream(batFile);
				final InputStream is = RestoreConfigWindows.class.getResourceAsStream("/windows/" + RESTORE_PROTOCOL_BAT);) { //$NON-NLS-1$
			String batchScript = new String(AOUtil.getDataFromInputStream(is));
			batchScript = batchScript
					.replace(REPLACE_PATH_EXE, exeFile.getAbsolutePath().replace("\\", "\\\\")) //$NON-NLS-1$ //$NON-NLS-2$
					.replace(REPLACE_INSTALL_DIR, installDir.getAbsolutePath().replace("\\", "\\\\")); //$NON-NLS-1$ //$NON-NLS-2$
			os.write(batchScript.getBytes());
			os.flush();
		}
		catch (final Exception e) {
			LOGGER.warning("No se pudo copiar a disco la aplicacion de restauracion. Se abortara su ejecucion: " + e); //$NON-NLS-1$
			return 2; // ERROR_FILE_NOT_FOUND
		}

		// Ejecumos el script
		int result = -2;
		try {
			final Process process = Runtime.getRuntime().exec(new String[] {
					batFile.getAbsolutePath()
			});
			result = process.waitFor();
		}
		catch (final Exception e) {
			LOGGER.log(Level.WARNING, "Error durante la ejecucion del proceso de restauracion del protocolo \"afirma\": " + e, e); //$NON-NLS-1$
		}

		// Esperamos 1 segundo para poder eliminar los ficheros
		try {
			Thread.sleep(1000);
		}
		catch (final InterruptedException e) {
			// No hacemos nada
		}

		// Eliminamos los ficheros
		try {
			Files.delete(exeFile.toPath());
			Files.delete(batFile.toPath());
		}
		catch (final IOException e) {
			LOGGER.warning("No se pudo eliminar el ejecutable para el registro del protocolo \"afirma\": " + e); //$NON-NLS-1$
		}

		return result;
	}

	static class CertificateFile {

		private final Certificate cert;
		private File file;

		public CertificateFile(final Certificate cert) {
			this.cert = cert;
		}

		public File getFile() {
			return this.file;
		}

		public void setFile(final File file) {
			this.file = file;
		}

		public Certificate getCert() {
			return this.cert;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy