diff --git a/team/bundles/org.eclipse.core.pki/.classpath b/team/bundles/org.eclipse.core.pki/.classpath new file mode 100644 index 00000000000..4bcc2fdd95a --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/.classpath @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/team/bundles/org.eclipse.core.pki/.project b/team/bundles/org.eclipse.core.pki/.project new file mode 100644 index 00000000000..b81c017542e --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/.project @@ -0,0 +1,28 @@ + + + org.eclipse.core.pki + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.core.resources.prefs b/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..99f26c0203a --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.jdt.core.prefs b/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..7808d37d739 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=18 +org.eclipse.jdt.core.compiler.compliance=18 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=18 \ No newline at end of file diff --git a/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.m2e.core.prefs b/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 00000000000..f897a7f1cb2 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.pde.core.prefs b/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000000..706f07e8a5d --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +pluginProject.extensions=true +resolve.requirebundle=false diff --git a/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.pde.ds.annotations.prefs b/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.pde.ds.annotations.prefs new file mode 100644 index 00000000000..8a427256a59 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/.settings/org.eclipse.pde.ds.annotations.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +enabled=true +path=OSGI-INF +validationErrorLevel=error +validationErrorLevel.missingImplicitUnbindMethod=error +generateBundleActivationPolicyLazy=true diff --git a/team/bundles/org.eclipse.core.pki/META-INF/MANIFEST.MF b/team/bundles/org.eclipse.core.pki/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..84055c31b9e --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/META-INF/MANIFEST.MF @@ -0,0 +1,28 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: PKI Core +Bundle-Localization: plugin +Bundle-ClassPath: ., org.eclipse.core.pki +Bundle-SymbolicName: org.eclipse.core.pki; singleton:=true +Require-Bundle: org.eclipse.equinox.common;bundle-version="3.12.0", + org.eclipse.ui.workbench, + org.eclipse.ui, + org.eclipse.debug.core, + org.eclipse.osgi;bundle-version="3.4.0", + org.eclipse.core.runtime +Bundle-Version: 1.0.3.qualifier +Bundle-Activator: org.eclipse.core.pki.auth.PKISetup +Export-Package: org.eclipse.core.pki;version="0.0.0", + org.eclipse.core.pki.auth;version="0.0.0", + org.eclipse.core.pki.pkiselection;version="0.0.0", + org.eclipse.core.pki.util;version="0.0.0", + org.eclipse.core.pki.exception;version="0.0.0" +Import-Package: org.eclipse.core.internal.net, + org.eclipse.core.net.proxy, + org.eclipse.core.resources, + org.eclipse.core.runtime;version="3.7.0", + org.eclipse.jface.dialogs, + org.osgi.framework;resolution:=optional +Bundle-Vendor: Delmarva Security +Automatic-Module-Name: org.eclipse.core.pki +Bundle-ActivationPolicy: lazy diff --git a/team/bundles/org.eclipse.core.pki/about.html b/team/bundles/org.eclipse.core.pki/about.html new file mode 100644 index 00000000000..164f781a8fd --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/about.html @@ -0,0 +1,36 @@ + + + + +About + + +

About This Content

+ +

November 30, 2017

+

License

+ +

+ The Eclipse Foundation makes available all content in this plug-in + ("Content"). Unless otherwise indicated below, the Content + is provided to you under the terms and conditions of the Eclipse + Public License Version 2.0 ("EPL"). A copy of the EPL is + available at http://www.eclipse.org/legal/epl-2.0. + For purposes of the EPL, "Program" will mean the Content. +

+ +

+ If you did not receive this Content directly from the Eclipse + Foundation, the Content is being redistributed by another party + ("Redistributor") and different terms and conditions may + apply to your use of any object code in the Content. Check the + Redistributor's license that was provided with the Content. If no such + license exists, contact the Redistributor. Unless otherwise indicated + below, the terms and conditions of the EPL still apply to any source + code in the Content and such source code may be obtained at http://www.eclipse.org. +

+ + + \ No newline at end of file diff --git a/team/bundles/org.eclipse.core.pki/build.properties b/team/bundles/org.eclipse.core.pki/build.properties new file mode 100644 index 00000000000..7533524e526 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/build.properties @@ -0,0 +1,22 @@ +############################################################################### +# Copyright (c) 2023 Security Team 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: +# Security Team - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.properties,\ + plugin.xml,\ + icons/, \ + about.html +src.includes = about.html diff --git a/team/bundles/org.eclipse.core.pki/icons/icons8-password-48.png b/team/bundles/org.eclipse.core.pki/icons/icons8-password-48.png new file mode 100644 index 00000000000..3aefb07473c Binary files /dev/null and b/team/bundles/org.eclipse.core.pki/icons/icons8-password-48.png differ diff --git a/team/bundles/org.eclipse.core.pki/plugin.properties b/team/bundles/org.eclipse.core.pki/plugin.properties new file mode 100644 index 00000000000..9a503da6054 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/plugin.properties @@ -0,0 +1,23 @@ +############################################################################### +# Copyright (c) 2000, 2014 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 +# yyyymmdd bug Email and other contact information +# -------- -------- ----------------------------------------------------------- +# 20070201 154100 pmoogk@ca.ibm.com - Peter Moogk, Port internet code from WTP to Eclipse base. +############################################################################### + +# +# Messages in plugin.xml. +# +PLUGIN_NAME=Internet PKI Core Management +PLUGIN_PROVIDER=Eclipse.org +TRACE_COMPONENT_LABEL=Platform Core PKI diff --git a/team/bundles/org.eclipse.core.pki/plugin.xml b/team/bundles/org.eclipse.core.pki/plugin.xml new file mode 100644 index 00000000000..1d90d00cf3d --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/plugin.xml @@ -0,0 +1,36 @@ + + + + + + + + + + diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/AuthenticationBase.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/AuthenticationBase.java new file mode 100644 index 00000000000..48a28264a27 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/AuthenticationBase.java @@ -0,0 +1,342 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki; + +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.InvalidParameterException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.ProviderException; +import java.security.SecureRandom; +import java.security.Security; +import java.util.ArrayList; +import java.util.Optional; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.eclipse.core.pki.AuthenticationService; +import org.eclipse.core.pki.util.ConfigureTrust; +import org.eclipse.core.pki.util.KeyStoreManager; +import org.eclipse.core.pki.util.LogUtil; + +public enum AuthenticationBase implements AuthenticationService { + INSTANCE; + + protected SSLContext sslContext; + protected String pin; + static KeyStore.PasswordProtection pp = new KeyStore.PasswordProtection("".toCharArray()); //$NON-NLS-1$ + // private static final String javaVersion = System.getProperty("java.version"); + protected boolean is9; + protected String pkiProvider = "SunPKCS11"; // or could be FIPS provider :SunPKCS11-FIPS //$NON-NLS-1$ + protected String providerName = null; + protected String cfgDirectory = null; + protected String fingerprint; + KeyStore keyStore = null; + @Override + public KeyStore initialize(char[] p) { + // TODO Auto-generated method stub + pp = new KeyStore.PasswordProtection(p); + String pin = new String(p); + try { + + //LogUtil.logInfo("Before configure keyStore with PIN:"+pin); //$NON-NLS-1$ + + OptionalkeyStoreContainer = Optional.ofNullable(configure()); + //LogUtil.logInfo("Before configured keyStore with PIN:"+pin); //$NON-NLS-1$ + if (keyStoreContainer.isEmpty() ) { + return null; + } else { + keyStore=keyStoreContainer.get(); + } + try { + /* + * Only load the store if the pin is a valuye other than the default setting of + * "pin" Otherwise the store will be preloaded by the default loading of the + * keystore, dynamically + */ + if (!(pin.equalsIgnoreCase("pin"))) { //$NON-NLS-1$ + PkiCallbackHandler pkiCB = new PkiCallbackHandler(); + PkiLoadParameter lp = new PkiLoadParameter(); + lp.setWaitForSlot(true); + lp.setProtectionParameter(pp); + + lp.setEventHandler(pkiCB); + keyStore.load(lp); + sslContext=AuthenticationBase.INSTANCE.setSSLContext(keyStore); + System.out.println("AuthenticationBase SSL context PROTOCOL:" + sslContext.getProtocol()); //$NON-NLS-1$ + } + + } catch (Exception e) { + /* + * An incorrect PiN could have been entered. AND thats OK, they can try again. + */ + LogUtil.logError("Unable to load KeyStore, Bad Pin?", e); //$NON-NLS-1$ + return null; + } + // System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11"); + System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11"); //$NON-NLS-1$ //$NON-NLS-2$ + System.setProperty("https.protocols", "TLSv1.1,TLSv1.2,TLSv1.3"); //$NON-NLS-1$ //$NON-NLS-2$ + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + /* + * TDB: TODO: Set the context AFTER you set the keystore... + */ + +// this.sslContext= setSSLContext(keyStore ); + return keyStore; + } + + private KeyStore configure() { + Optional configurationDirectory = null; + OptionalproviderContainer = null; + Provider prototype = null; + String securityProvider = null; + //String cfgDirectory = "TBD"; //$NON-NLS-1$ + KeyStore keyStore = null; + String errorMessage=null; + is9 = true; + + // System.out.println("In configure CFG STORED FILE LOC:" + + + configurationDirectory = Optional.ofNullable(System.getProperty("javax.net.ssl.cfgFileLocation")); //$NON-NLS-1$ + if (configurationDirectory.isEmpty()) { + // Where is it for Windoz + //TBD: find default setting + setCfgDirectory(new String("/etc/opensc")); //$NON-NLS-1$ + } else { + setCfgDirectory(configurationDirectory.get().toString()); + } + + if (Files.exists(Paths.get(getCfgDirectory()))) { + LogUtil.logInfo("AuthenticationBase - PKCS11 configure DIR:" + getCfgDirectory()); //$NON-NLS-1$ + providerContainer=Optional.ofNullable( + System.getProperty("javax.net.ssl.keyStoreProvider")); //$NON-NLS-1$ + + if (providerContainer.isEmpty() ) { + securityProvider = pkiProvider; + } else { + securityProvider = providerContainer.get().toString(); + } + prototype = Security.getProvider(securityProvider); + if (prototype == null) { + LogUtil.logInfo("In configure PROVIDER NOT FOUND"); //$NON-NLS-1$ + } + + try { + Provider provider = prototype.configure(getCfgDirectory()); + providerName = provider.getName(); + Security.addProvider(provider); + keyStore = KeyStore.getInstance("pkcs11", provider.getName() ); //$NON-NLS-1$ + setPkiProvider(provider.getName()); + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + errorMessage=e.getMessage()+" Problem loading the keystore."; + } catch (InvalidParameterException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + errorMessage=e.getMessage()+" You have provided an invalid parameter."; + } catch (UnsupportedOperationException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + errorMessage=e.getMessage()+" Operation is not supported at this time."; + } catch (NullPointerException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + errorMessage=e.getMessage()+" A Null Pointer was found."; + } catch (NoSuchProviderException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + errorMessage=e.getMessage()+" The PKCS11 provider could not be found."; + } catch (ProviderException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + errorMessage=e.getMessage()+" No PKCS11 Configuration found."; + } + Optional errorContainer = Optional.ofNullable(errorMessage); + if ( !(errorContainer.isEmpty())) { + Security.removeProvider(providerName); + LogUtil.logError(errorMessage, null); + } + } + + // listProviders(); + + return keyStore; + } + public KeyStore getKeyStore() { + return keyStore; + } + + public SSLContext getSSLContext() { + return this.sslContext; + } + + + public boolean isPkcs11Setup() { + + if ((getCfgDirectory() !=null ) && ( getPkiProvider() != null)) { + return true; + } + return false; + + } + + public SSLContext setSSLContext(KeyStore keyStore) { + + try { + //System.out.println("In setSSLContext initialize TLS"); //$NON-NLS-1$ + // sslContext = SSLContext.getInstance("TLS"); + sslContext = SSLContext.getInstance("TLSv1.3"); //$NON-NLS-1$ + + Optional PKIXtrust = ConfigureTrust.MANAGER.setUp(); + if (PKIXtrust.isEmpty()) { + LogUtil.logError("Invalid TrustManager Initialization.", null); //$NON-NLS-1$ + } else { + + KeyManager[] km = new KeyManager[] { KeyStoreManager.INSTANCE }; + TrustManager[] tm = new TrustManager[] { ConfigureTrust.MANAGER }; + + sslContext.init(km, tm, new SecureRandom()); + SSLContext.setDefault(sslContext); + HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return sslContext; + } + + public String getPkiProvider() { + return pkiProvider; + } + + public void setPkiProvider(String pkiProvider) { + this.pkiProvider = pkiProvider; + } + + public boolean isJava9() { + return is9; + } + + public String getFingerprint() { + return fingerprint; + } + + public static void setFingerprint(String fingerprint) { + AuthenticationBase.INSTANCE.fingerprint = fingerprint; + } + + public KeyManager getCustomKeyManager(KeyStore keyStore) { + CustomKeyManager keyManager = null; + try { + keyManager = new CustomKeyManager(keyStore, "".toCharArray(), null); //$NON-NLS-1$ + keyManager.setSelectedFingerprint(getFingerprint()); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return keyManager; + } + public ArrayList getList() { + return EclipseKeyStoreCollection.PILE.getList(keyStore); + } + + public boolean isJavaModulesBased() { + try { + Class.forName("java.lang.Module"); //$NON-NLS-1$ + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + + public String getCfgDirectory() { + return cfgDirectory; + } + + public void setCfgDirectory(String cfgDirectory) { + this.cfgDirectory = cfgDirectory; + } + public String getPin() { + return pin; + } + public void setPin(String pin) { + this.pin = pin; + pp = new KeyStore.PasswordProtection(pin.toCharArray()); + } + public void logoff() { + try { + //System.out.println("SSLPkcs11Provider LOGOFF INVOKATION:"); + //provider.clear(); + + //System.out.println("SSLPkcs11Provider LOGOFF DONE"); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + public boolean login() { + //System.out.println("SSLPkcs11Provider LOGIN"); + Provider provider = Security.getProvider(getPkiProvider()); + if ( provider != null) { + + try { + provider.clear(); + return true; + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + return false; + } + + /* + * private static void listProviders() { + * + * Provider[] providers = Security.getProviders(); for (Provider provider : + * providers) { System.out.println("In configurejdk9 PROVIDER:" + + * provider.getName()); //$NON-NLS-1$ + * System.out.println("In configurejdk9 PROVIDER INFO:" + + * provider.getInfo()); //$NON-NLS-1$ } } + */ + + /* + * private static boolean isFips() { boolean enabled = false; Provider[] + * providers = Security.getProviders(); for (Provider provider : providers) { if + * (provider.getName().contains("FIPS")) { //$NON-NLS-1$ + * + * for (Provider.Service service : provider.getServices() ) { + * System.out.println("FIPS Algorithm:"+ service.getAlgorithm()); } + * + * System.out.println("FIPS Provider:" + provider.getName()); //$NON-NLS-1$ + * enabled = true; } + * + * } return enabled; } + */ +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/AuthenticationService.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/AuthenticationService.java new file mode 100644 index 00000000000..4c02a00cb46 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/AuthenticationService.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki; + +import java.security.KeyStore; + +public interface AuthenticationService { + public KeyStore initialize(char[] p); +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/CreateCFGfile.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/CreateCFGfile.java new file mode 100644 index 00000000000..6cf670bd7a5 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/CreateCFGfile.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.text.MessageFormat; +import java.util.ArrayList; + + +public class CreateCFGfile { + + + private static final String charsetName = "UTF-8"; //$NON-NLS-1$ + private static final String line1 = "name = Vendor Open Source "; //$NON-NLS-1$ + private static final String bit64DLL = "opensc-pkcs11.dll"; //$NON-NLS-1$ + private static final String line3 = "description = ISC_OpenSC"; //$NON-NLS-1$ + private static final String line4 = "slot = 1"; //$NON-NLS-1$ + private static final String line5 = "attributes = compatibility"; //$NON-NLS-1$ + public static String initialize( String Pkcs11cfgHome ) { + StringBuffer sb = new StringBuffer(); + + try { + System.out.println("CreateCFGfile ---- Pkcs11cfgHome:" + Pkcs11cfgHome); //$NON-NLS-1$ + Charset charset = Charset.forName(charsetName); + sb.append(System.getProperty("user.home")); //$NON-NLS-1$ + sb.append(FileSystems.getDefault().getSeparator()); + sb.append(".cspid"); //$NON-NLS-1$ + sb.append(FileSystems.getDefault().getSeparator()); + Path cspidDir = Paths.get (sb.toString() ); + Files.createDirectories( cspidDir ); + sb.append("java_pkcs11.cfg"); //$NON-NLS-1$ + System.out.println("CreateCFGfile ---- NEW CFG FILE::" + sb.toString()); //$NON-NLS-1$ + Path path = Paths.get (sb.toString() ); + + if (!(path.toFile().exists() )) { + Files.deleteIfExists(path); + Files.createFile(path); + ArrayList a = fileContents(Pkcs11cfgHome); + Files.write( path, a, charset, StandardOpenOption.TRUNCATE_EXISTING ); + } + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return sb.toString(); + } + private static ArrayList fileContents(String lib) { + ArrayLista = new ArrayList<>(); + + a.add(line1); + a.add(getLibraryLocation(lib)); + a.add(line3); + a.add(line4); + a.add(line5); + + return a; + } + private static String getLibraryLocation(String libraryLocation ) { + StringBuffer sb = new StringBuffer(); + sb.append(libraryLocation); + sb.append(File.separator); + sb.append(File.separator); + sb.append(bit64DLL); + Object[] args = {sb.toString() }; + String lib = "library = {0}"; //$NON-NLS-1$ + MessageFormat mf = new MessageFormat(lib); + String location = mf.format(args); + return location; + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/CustomKeyManager.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/CustomKeyManager.java new file mode 100644 index 00000000000..5fcda303b93 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/CustomKeyManager.java @@ -0,0 +1,235 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki; + +import java.net.InetAddress; +import java.net.Socket; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.Principal; +import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashMap; + +import javax.net.ssl.X509ExtendedKeyManager; +import javax.net.ssl.X509KeyManager; + +public class CustomKeyManager extends X509ExtendedKeyManager implements X509KeyManager { + private static final int KEY_ENCIPHERMENT = 2; + private static final int DIGITAL_SIGNATURE = 0; + private KeyStore keyStore; + private char[] password; + protected static String selectedFingerprint = "NOTSET"; //$NON-NLS-1$ + + public CustomKeyManager(KeyStore keyStore, char[] passwd, HashMap hosts) { + this.keyStore=keyStore; + this.setPassword(new String(passwd).toCharArray()); + } + + @Override + public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2) { + // TODO Auto-generated method stub + String message = "Presenting X509 fingerprint:"; //$NON-NLS-1$ + String amessage = " using certificate alias:"; //$NON-NLS-1$ + StringBuilder sb=new StringBuilder(); + String selectedAlias=null; + String alias = null; + String fingerprint=null; + boolean isOK=true; + + try { + + + Enumeration aliases = this.keyStore.aliases(); + sb.append(message); + while ( aliases.hasMoreElements() ) { + alias = aliases.nextElement(); + if ( this.getPrivateKey(alias) != null ) { + X509Certificate x509 = (X509Certificate) this.keyStore.getCertificate(alias); + try { + x509.checkValidity(); + if (!(isKeyEncipherment(x509.getKeyUsage()))) { + //selectedAlias=alias; + fingerprint = FingerprintX509.INSTANCE.getFingerPrint(x509, "MD5"); //$NON-NLS-1$ + System.out.println("KeyManager - SELECTED finger:" + getSelectedFingerprint()); //$NON-NLS-1$ + //System.err.println("KeyManager - DUMP OUT DATA:"+info); + + if ( getSelectedFingerprint() != null ) { + if (getSelectedFingerprint().equals("NOTSET")) { //$NON-NLS-1$ + setSelectedFingerprint(fingerprint); + } + } else { + setSelectedFingerprint(fingerprint); + } + if ( getSelectedFingerprint().equals(fingerprint)) { + isOK=true; + selectedAlias=alias; + sb.append(fingerprint); + sb.append(amessage); + sb.append(alias); + message = sb.toString(); + break; + } + } + } catch (CertificateExpiredException e) { + // TODO Auto-generated catch block + System.err.println("KeyManager: Please remove EXPIRED certificate:" + alias //$NON-NLS-1$ + + " using your pkcs11 Manager."); //$NON-NLS-1$ + //e.printStackTrace(); + } catch (CertificateNotYetValidException e) { + // TODO Auto-generated catch block + System.err.println("KeyManager: Please check invalid certificate:" + alias //$NON-NLS-1$ + + " using your pkcs11 Manager."); //$NON-NLS-1$ + //e.printStackTrace(); + } + } + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if (!(isOK)) { + message = (selectedAlias == null) ? "PKI misconfiguration. Please check pkcs11" : message + selectedAlias; //$NON-NLS-1$ + System.out.println("KeyManager: " + message); //$NON-NLS-1$ + } + return selectedAlias; + } + private static boolean isDigitalSignature(boolean[] ba) { + if ( ba != null) { + + return ba[DIGITAL_SIGNATURE]; + } else { + return false; + } + } + + private static boolean isKeyEncipherment(boolean[] ba) { + if ( ba != null) { + + return ba[KEY_ENCIPHERMENT]; + } else { + return false; + } + } + + @Override + public String chooseServerAlias(String arg0, Principal[] arg1, Socket arg2) { + // TODO Auto-generated method stub + return null; + } + + @Override + public X509Certificate[] getCertificateChain(String alias) { + // TODO Auto-generated method stub + + X509Certificate[] X509Certs=null; + X509Certificate X509Cert=null; + try { + Certificate[] certificates = this.keyStore.getCertificateChain(alias); + if ( certificates != null ) { + X509Certs = new X509Certificate[ certificates.length ]; + for(int i=0; i < certificates.length; i++) { + X509Cert= (X509Certificate ) certificates[i]; + if (!(isKeyEncipherment(X509Cert.getKeyUsage()))) { + X509Certs[i] = X509Cert; + } else { + if ((isKeyEncipherment(X509Cert.getKeyUsage())) && alias.contains("PKI")) { //$NON-NLS-1$ + X509Certs[i] = X509Cert; + } + } + } + + } else { + X509Cert = (X509Certificate) this.keyStore.getCertificate(alias); + if ( X509Cert != null ) { + X509Certs = new X509Certificate[1]; + if (isDigitalSignature(X509Cert.getKeyUsage()) ) { + X509Certs[0] = X509Cert; + } else { + if (alias.contains("PKI")) { //$NON-NLS-1$ + X509Certs[0] = X509Cert; + } + } + } + + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + //return X509Certs; + try { + X509Certs = new X509Certificate[1]; + X509Certs[0] = (X509Certificate) this.keyStore.getCertificate(alias); + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return X509Certs; + } + + @Override + public String[] getClientAliases(String arg0, Principal[] arg1) { + // TODO Auto-generated method stub + //return null; + return new String[] {chooseClientAlias(null, arg1, null) }; + + } + + @Override + public PrivateKey getPrivateKey(String alias) { + // TODO Auto-generated method stub + PrivateKey privateKey = null; + try { + privateKey = (PrivateKey) keyStore.getKey(alias, "".toCharArray()); //$NON-NLS-1$ + } catch (UnrecoverableKeyException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return privateKey; + } + + @Override + public String[] getServerAliases(String arg0, Principal[] arg1) { + // TODO Auto-generated method stub + return null; + } + public static String getSelectedFingerprint() { + return selectedFingerprint; + } + public void setSelectedFingerprint(String selectedFingerprint) { + CustomKeyManager.selectedFingerprint = selectedFingerprint; + } + + public char[] getPassword() { + return password; + } + + public void setPassword(char[] password) { + this.password = password; + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/CustomTrustManager.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/CustomTrustManager.java new file mode 100644 index 00000000000..a901f78b391 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/CustomTrustManager.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki; + +import java.net.Socket; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.Security; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509ExtendedTrustManager; +import javax.net.ssl.X509TrustManager; + + +public class CustomTrustManager extends X509ExtendedTrustManager implements TrustManager { + private KeyStore trustStore; + private CollectiontrustedCerts; + protected X509TrustManager trustManager; + protected CustomTrustManager() {} + + public CustomTrustManager(KeyStore trustStore) { + super(); + this.trustStore=trustStore; + System.out.println("CustomTrustManager -- CONSTRUCTOR ALG:" + TrustManagerFactory.getDefaultAlgorithm()); //$NON-NLS-1$ + try { + Security.getAlgorithms("PKCS11"); //$NON-NLS-1$ + TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); //$NON-NLS-1$ + tmf.init(trustStore); + TrustManager tms[] = tmf.getTrustManagers(); + for (TrustManager tm : tms) { + if (tm instanceof X509TrustManager) { + trustManager = (X509TrustManager) tm; + break; + } + } + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + // TODO Auto-generated method stub + trustManager.checkClientTrusted(chain, authType); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + // TODO Auto-generated method stub + trustManager.checkClientTrusted(chain, authType); + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + // TODO Auto-generated method stub + X509Certificate X509cert=null; + X509Certificate[] X509certs=null; + + this.trustedCerts = new ArrayList<>(); + + String alias=null; + try { + Enumeration aliases=this.trustStore.aliases(); + while ( aliases.hasMoreElements() ) { + alias = aliases.nextElement(); + if (alias.startsWith("IC")) { //$NON-NLS-1$ + X509cert = (X509Certificate) this.trustStore.getCertificate(alias); + trustedCerts.add(X509cert); + System.out.println("CustomTrustManager-FOUND TRUSTORE FOR IC"); //$NON-NLS-1$ + } + } + System.out.println("CustomTrustManager-COMPLETED TRUSTSTORE SEARCH"); //$NON-NLS-1$ + int i = 0; + X509certs = new X509Certificate[ trustedCerts.size() ]; + Iterator it = trustedCerts.iterator(); + while ( it.hasNext() ) { + X509certs[i]=it.next(); + i++; + } + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return X509certs; + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType, Socket arg2) throws CertificateException { + // TODO Auto-generated method stub + trustManager.checkClientTrusted(chain, authType); + } + + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1, SSLEngine arg2) throws CertificateException { + // TODO Auto-generated method stub + System.out.println("CustomTrustManager -- checkClientTrusted"); //$NON-NLS-1$ + } + + @Override + public void checkServerTrusted(X509Certificate[] x509incoming, String arg1, Socket socket) throws CertificateException { + System.out.println("CustomTrustManager checkServerTrusted based on socket"); //$NON-NLS-1$ + if (x509incoming != null) { + System.out.println("CustomTrustManager checkServerTrusted INCOMING SIZE:" + x509incoming.length); //$NON-NLS-1$ + for(X509Certificate x509 : x509incoming) { + System.out.println("CustomTrustManager checkServerTrusted INCOMING:" + x509.getSubjectDN().getName()); //$NON-NLS-1$ + x509.checkValidity(); + + } + return; + } + + } + + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1, SSLEngine arg2) throws CertificateException { + // TODO Auto-generated method stub + System.out.println("CustomTrustManager checkServerTrusted with SSLEngine"); //$NON-NLS-1$ + } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/DynamicFileFinder.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/DynamicFileFinder.java new file mode 100644 index 00000000000..14b1cdc3247 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/DynamicFileFinder.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki; + +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; + + +public class DynamicFileFinder extends SimpleFileVisitor { + private boolean found=false; + private String location= null; + private ArrayList list = new ArrayList<>(); + private PathMatcher pathMatcher; + private String pattern = "glob:[s][u][n]*[1][1].jar"; //$NON-NLS-1$ + public DynamicFileFinder(Path path) { + pathMatcher = FileSystems.getDefault().getPathMatcher ( pattern ); + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attr) { + Path name = file.getFileName(); + if ( pathMatcher.matches(name)) { + System.out.println("FILE:" + name.toString()); //$NON-NLS-1$ + System.out.println("path:" + file.toString()); //$NON-NLS-1$ + list.add( file ); + location = file.toString(); + found=true; + } + System.out.println("NOT A MATCH FILE:" + name.toString()); //$NON-NLS-1$ + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult visitFileFailed( Path file, IOException e) { + return FileVisitResult.SKIP_SUBTREE; + } + @Override + public FileVisitResult preVisitDirectory( Path dir, BasicFileAttributes attr) { + System.out.println("SKIPPING dir:" + dir.toString()); //$NON-NLS-1$ + Path name = dir.getFileName(); + if ( pathMatcher.matches(name)) { + System.out.println("DIR FILE:" + name.toString()); //$NON-NLS-1$ + System.out.println("DIR path:" + dir.toString()); //$NON-NLS-1$ + } + System.out.println(" DIR NOT A MATCH FILE:" + name.toString()); //$NON-NLS-1$ + return FileVisitResult.CONTINUE; + } + public boolean isFound() { + return found; + } + public String getLocation() { + return location; + } + + public String getPattern() { + return pattern; + } + + public void setPattern(String pattern) { + this.pattern = pattern; + pathMatcher = FileSystems.getDefault().getPathMatcher ( this.pattern ); + } + + public ArrayList getList() { + return list; + } + + public void setList(ArrayList list) { + this.list = list; + } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/EclipseKeyStoreCollection.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/EclipseKeyStoreCollection.java new file mode 100644 index 00000000000..7fc172d36d9 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/EclipseKeyStoreCollection.java @@ -0,0 +1,77 @@ +package org.eclipse.core.pki; + +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Enumeration; +import org.eclipse.core.pki.pkiselection.PKIProperties; +import org.eclipse.core.pki.util.LogUtil; + + +public enum EclipseKeyStoreCollection { + PILE; + protected final int DIGITAL_SIGNATURE=0; + private final int KEY_ENCIPHERMENT = 2; + protected static PKIProperties pkiProperties=PKIProperties.getInstance();; + public ArrayList getList(KeyStore keyStore) { + ArrayList list = new ArrayList(); + try { + String alias=null; + Enumeration aliases = keyStore.aliases(); + while (aliases.hasMoreElements()) { + alias = (String) aliases.nextElement(); + X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); + certificate.checkValidity(); + if ( isDigitalSignature(certificate.getKeyUsage()) ) { + PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, null); + if ( privateKey != null) { + list.add( alias ); + } + } + } + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (CertificateExpiredException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (CertificateNotYetValidException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (UnrecoverableKeyException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + LogUtil.logInfo("EclipseKeyStoreCollection list COUNT:"+list.size() ); + if (!( list.isEmpty())) { + LogUtil.logInfo("EclipseKeyStoreCollection list item:"+list.get(0)); + } + return list; + + } + private boolean isDigitalSignature(boolean[] ba) { + if ( ba != null) { + + return ba[DIGITAL_SIGNATURE]; + } else { + return false; + } + } + private boolean isKeyEncipherment(boolean[] ba) { + if ( ba != null) { + + return ba[KEY_ENCIPHERMENT]; + } else { + return false; + } + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/FingerprintX509.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/FingerprintX509.java new file mode 100644 index 00000000000..77d130673e3 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/FingerprintX509.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; + +public enum FingerprintX509 { + INSTANCE; + private static final char[] HEX= {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + private static final String cryptoAlg = "SHA-256"; //$NON-NLS-1$ + public String getFingerPrint(Certificate cert, String alg) { + String fingerPrint=null; + byte[] encodedCert=null; + + try { + alg = cryptoAlg; + encodedCert = cert.getEncoded(); + MessageDigest md = MessageDigest.getInstance(alg); + md.update(encodedCert); + byte[] digest = md.digest(); + fingerPrint = getHexValue(digest); + + } catch (CertificateEncodingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + //System.err.println("FingerprintX509 -----------------------------------PRINT:"+fingerPrint); + return fingerPrint; + } + protected String getHexValue( byte[] bytes ) { + StringBuffer sb = new StringBuffer(bytes.length * 2); + try { + for( int i=0; i < bytes.length; i++) { + sb.append(HEX[(bytes[i] & 0xf0) >> 4 ]); + sb.append(HEX[bytes[i] & 0xf]); + if ( i < bytes.length-1) { + sb.append(":"); //$NON-NLS-1$ + } + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return sb.toString(); + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/Pkcs11FixConfigFile.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/Pkcs11FixConfigFile.java new file mode 100644 index 00000000000..889b0871e14 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/Pkcs11FixConfigFile.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + + +public class Pkcs11FixConfigFile { + private static final String programFiles = "Program Files (x86)"; //$NON-NLS-1$ + private static final CharSequence none = ""; //$NON-NLS-1$ + private static final CharSequence quotes = "\""; //$NON-NLS-1$ + private static final CharSequence sslash = "\\"; //$NON-NLS-1$ + private static final CharSequence bslash = "\\\\"; //$NON-NLS-1$ + private static final String biT32 = "cspid.dll"; //$NON-NLS-1$ + private static final String biT64 = "cspidx64.dll"; //$NON-NLS-1$ + private String cfgFilePath=null; + private static String cspidHome; + private static Pkcs11FixConfigFile configFile=null; + private static StringBuffer sb = new StringBuffer(); + public static Pkcs11FixConfigFile getCfgInstance(String fileLocation) { + if ( configFile == null ) { + synchronized(Pkcs11FixConfigFile.class) { + if ( configFile == null ) { + configFile = new Pkcs11FixConfigFile(); + cspidHome = fileLocation; + System.out.println("Pkcs11FixConfigFile -- incoming path:" + fileLocation); //$NON-NLS-1$ + sb.append(fileLocation); + initialize(); + } + } + } + return configFile; + } + public static void initialize() { + try { + sb.append(FileSystems.getDefault().getSeparator()); + sb.append("java_pkcs11.cfg"); //$NON-NLS-1$ + Path path = openFile( sb.toString()); + Files.setAttribute(path, "dos:readonly", Boolean.valueOf(false)); //$NON-NLS-1$ + List list = readFile(path); + List edit = editFile(list); + Path outputPath = setOutputDirectory(); + saveFile(edit, outputPath); + //listEditedFile(edit); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + public static Path setOutputDirectory() { + Path path = null; + StringBuilder sb = new StringBuilder(); + try { + String appData = System.getenv("AppData"); //$NON-NLS-1$ + appData = Paths.get(appData).toAbsolutePath().toString().replace(sslash, bslash); + if ( appData != null ) { + sb.append(appData); + } else { + sb.append(System.getProperty("user.dir")); //$NON-NLS-1$ + } + sb.append(FileSystems.getDefault().getSeparator()); + sb.append(FileSystems.getDefault().getSeparator()); + sb.append("cspid"); //$NON-NLS-1$ + sb.append(FileSystems.getDefault().getSeparator()); + sb.append(FileSystems.getDefault().getSeparator()); + sb.append("java_pkcs11.cfg"); //$NON-NLS-1$ + + path = Paths.get(sb.toString()); + //setCfgFilePath( sb.toString()); + System.out.println("Pkcs11FixCOnfigFile ---- cspidHome:" + cspidHome); //$NON-NLS-1$ + setCfgFilePath( CreateCFGfile.initialize( cspidHome )); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return path; + } + public static Path openFile(String s) { + return FileSystems.getDefault().getPath(s); + } + public static List readFile(Path path) { + List list = null; + try { + list = Files.readAllLines(path, Charset.defaultCharset()); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return list; + } + public static List editFile(List list) { + ArrayList edit = new ArrayList<>(); + StringBuffer sb = new StringBuffer(); + + for ( String s : list) { + CharSequence ch = "/"; //$NON-NLS-1$ + + if ((s.contains("library")) && (System.getenv("PKCS11_HOME") != null)) { //$NON-NLS-1$ //$NON-NLS-2$ + sb.append("library="); //$NON-NLS-1$ + sb.append(System.getenv("PKCS11_HOME")); //$NON-NLS-1$ + sb.append(ch); + sb.append(biT64); + s=sb.toString(); + } + + if (!(s.startsWith("#"))) { //$NON-NLS-1$ + if ((s.contains(biT32)) && (System.getProperty("os.arch").contains("64"))) { //$NON-NLS-1$ //$NON-NLS-2$ + s = s.replaceAll(biT32, biT64); + } + } + if ( s.contains(quotes)) { + s=s.replace(quotes, none); + } + + if ( s.contains(programFiles)) { + if (System.getenv("PKCS11_HOME") != null) { //$NON-NLS-1$ + s = System.getenv("PKCS11_HOME"); //$NON-NLS-1$ + } else { + s = s.replace(programFiles, "Progra~2"); //$NON-NLS-1$ + } + edit.add(s); + } else { + if (!( s.trim().isEmpty() )) { + edit.add(s); + } + } + } + return edit; + } + public static void saveFile( List list , Path path) { + try { + Files.write(path, list, StandardCharsets.UTF_8); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public String getCfgFilePath() { + return cfgFilePath; + } + public static void setCfgFilePath(String cfgFilePath) { + configFile.cfgFilePath = cfgFilePath; + } + /* + * private static void listEditedFile( List list ) { + * System.out.println("PKCS11FixConfigFile ---- ARCH:" + + * System.getProperty("os.arch")); //$NON-NLS-1$ //$NON-NLS-2$ for ( String s : + * list) { System.out.println("PKCS11FixConfigFile ---- edited line:" + s); + * //$NON-NLS-1$ } } + */ +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/PkiCallbackHandler.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/PkiCallbackHandler.java new file mode 100644 index 00000000000..15dfc51e184 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/PkiCallbackHandler.java @@ -0,0 +1,17 @@ +package org.eclipse.core.pki; + +import java.io.IOException; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; + +public class PkiCallbackHandler implements CallbackHandler { + + @Override + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + // TODO Auto-generated method stub + + } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/PkiLoadParameter.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/PkiLoadParameter.java new file mode 100644 index 00000000000..85978c239cd --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/PkiLoadParameter.java @@ -0,0 +1,64 @@ +package org.eclipse.core.pki; + +import java.security.KeyStore.LoadStoreParameter; +import java.security.KeyStore.ProtectionParameter; + +import javax.security.auth.callback.CallbackHandler; + +public class PkiLoadParameter implements LoadStoreParameter{ + ProtectionParameter protectionParameter; + ProtectionParameter SOProtectionParameter; + CallbackHandler eventHandler; + boolean waitForSlot; + Long slotId; + boolean writeEnabled; + @Override + public ProtectionParameter getProtectionParameter() { + // TODO Auto-generated method stub + return protectionParameter; + } + public ProtectionParameter getSOProtectionParameter() { + return SOProtectionParameter; + } + + public void setSOProtectionParameter(ProtectionParameter sOProtectionParameter) { + SOProtectionParameter = sOProtectionParameter; + } + + public CallbackHandler getEventHandler() { + return eventHandler; + } + + public void setEventHandler(CallbackHandler eventHandler) { + this.eventHandler = eventHandler; + } + + public boolean isWaitForSlot() { + return waitForSlot; + } + + public void setWaitForSlot(boolean waitForSlot) { + this.waitForSlot = waitForSlot; + } + + public Long getSlotId() { + return slotId; + } + + public void setSlotId(Long slotId) { + this.slotId = slotId; + } + + public boolean isWriteEnabled() { + return writeEnabled; + } + + public void setWriteEnabled(boolean writeEnabled) { + this.writeEnabled = writeEnabled; + } + + public void setProtectionParameter(ProtectionParameter protectionParameter) { + this.protectionParameter = protectionParameter; + } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/SecurePKIVersionInfo.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/SecurePKIVersionInfo.java new file mode 100644 index 00000000000..531fee964bb --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/SecurePKIVersionInfo.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki; + +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +//import org.eclipse.ui.pki.AuthenticationBase; + + +public enum SecurePKIVersionInfo { + INSTANCE; + + @SuppressWarnings("resource") + public static String getVersion() { + String version = null; + Path path = null; + //System.out.println("[GeT Version of this Build]"); + + try { + + /* + * See if this is a valid path check to see if its eclipse testing + */ + path = Paths.get("PKI.jar"); //$NON-NLS-1$ + + if (Files.exists(path, LinkOption.NOFOLLOW_LINKS)) { + //System.out.println(" GOOD PATH"); + } else { + + try { + /* + * path = + * Paths.get(AuthenticationBase.class.getProtectionDomain().getCodeSource(). + * getLocation().toURI()); if (Files.exists(path, LinkOption.NOFOLLOW_LINKS)) { + * DebugLogger.printDebug("PKIVersionInfo -- PATH:"+path.toAbsolutePath()); } + * else { path = null; } + */ + } catch (Exception e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + version = null; + } + } + + if (path != null) { + try { + //System.out.println("PATH:" + path.toAbsolutePath()); + Manifest manifest = new JarFile(path.toAbsolutePath().toString()).getManifest(); + Attributes attributes = manifest.getMainAttributes(); + version = attributes.getValue("Build-Label"); //$NON-NLS-1$ + System.out.println(" VALUE:" + version); //$NON-NLS-1$ + } catch (Exception e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + version = null; + } + } + + if (version == null) { + version = "isEmbeded?"; //$NON-NLS-1$ + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return version; + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/SpecialClassLoader.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/SpecialClassLoader.java new file mode 100644 index 00000000000..eb8275b8d00 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/SpecialClassLoader.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class SpecialClassLoader extends ClassLoader { + + private String findThisClassAt = null; + + public SpecialClassLoader(String classlocation){ + findThisClassAt = classlocation; + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException{ + try{ + byte[] classBytes = null; + classBytes = loadClassbytes(name); + Class cl = defineClass(name, classBytes, 0, classBytes.length); + if (cl == null) throw new ClassNotFoundException(name); + return cl; + } catch (IOException e){ + throw new ClassNotFoundException(name); + } + } + + private byte[] loadClassbytes(String name) throws IOException { + + return Files.readAllBytes(Paths.get(findThisClassAt)); + } + + public String getFindThisClassAtLocation() { + return findThisClassAt; + } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/ContextObservable.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/ContextObservable.java new file mode 100644 index 00000000000..3d5e2eece09 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/ContextObservable.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2014 Codetrails GmbH. + * 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: + * Marcel Bruch - initial API and implementation. + */ +package org.eclipse.core.pki.auth; + +import java.util.Observable; +import org.eclipse.core.pki.util.LogUtil; + +public class ContextObservable extends Observable { + + public ContextObservable() { + + } + public void onchange(String s) { + //LogUtil.logWarning("ContextObservable- BREAK for INPUT"); + + try { + setChanged(); + // notify observers for change + notifyObservers(s); + } catch (Exception e) { + LogUtil.logError("ContextObservable - Failed to notify observers, PKI password input.", e); //$NON-NLS-1$ + } + /* + * try { Thread.sleep(1000); } catch (InterruptedException e) { + * System.out.println("Error Occurred."); } + */ + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/EventConstant.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/EventConstant.java new file mode 100644 index 00000000000..707d436c869 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/EventConstant.java @@ -0,0 +1,14 @@ +package org.eclipse.core.pki.auth; + +public enum EventConstant { + DONE(0), + CANCEL(2), + SETUP(10); + private int value; + EventConstant( int request ) { + value=request; + } + public int getValue() { + return value; + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/IncomingSystemProperty.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/IncomingSystemProperty.java new file mode 100644 index 00000000000..0fe92fcc3a2 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/IncomingSystemProperty.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2023 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.core.pki.auth; + +import java.util.Optional; + +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.core.pki.util.NormalizeGCM; + +public enum IncomingSystemProperty { + SETTINGS; + + public boolean checkType() { + Optional type = null; + + type = Optional.ofNullable(System.getProperty("javax.net.ssl.keyStoreType")); //$NON-NLS-1$ + if (type.isEmpty()) { + LogUtil.logError("No incoming System Properties are set for PKI.", null); //$NON-NLS-1$ + return false; + } + if (type.get().equalsIgnoreCase("PKCS11")) { //$NON-NLS-1$ + PKIState.CONTROL.setPKCS11on(true); + return true; + } + if (type.get().equalsIgnoreCase("PKCS12")) { //$NON-NLS-1$ + PKIState.CONTROL.setPKCS12on(true); + return true; + } + return false; + } + + public boolean checkKeyStore(String pin) { + byte[] salt = new byte[16]; + Optional keyStore = null; + Optional keyStorePassword = null; + Optional PasswordEncrypted = null; + Optional PasswordDecrypted = null; + keyStore = Optional.ofNullable(System.getProperty("javax.net.ssl.keyStore")); //$NON-NLS-1$ + if (keyStore.isEmpty()) { + PKIState.CONTROL.setPKCS11on(false); + PKIState.CONTROL.setPKCS12on(false); + LogUtil.logError("No Keystore is set, javax.net.ssl.keyStore", null); //$NON-NLS-1$ + return false; + } + keyStorePassword = Optional.ofNullable(System.getProperty("javax.net.ssl.keyStorePassword")); //$NON-NLS-1$ + if (keyStorePassword.isEmpty()) { + LogUtil.logError("A Keystore Password is required, javax.net.ssl.keyStorePassword", null); //$NON-NLS-1$ + return false; + } else { + PasswordDecrypted = Optional.ofNullable(System.getProperty("javax.net.ssl.decryptedPassword")); //$NON-NLS-1$ + PasswordEncrypted = Optional.ofNullable(System.getProperty("javax.net.ssl.encryptedPassword")); //$NON-NLS-1$ + if ((PasswordEncrypted.isEmpty()) || (!(PasswordDecrypted.isEmpty()))) { + // Password is not encrypted + // LogUtil.logInfo("IncomingSystemProperty - is DecryptedPasswd:" + + // PasswordDecrypted.get().toString()); //$NON-NLS-1$ + } else { + if (PasswordEncrypted.get().toString().equalsIgnoreCase("true")) { //$NON-NLS-1$ + salt = new String(System.getProperty("user.name") + pin).getBytes(); //$NON-NLS-1$ + String passwd = NormalizeGCM.DECRYPT.decrypt(keyStorePassword.get().toString(), pin, + new String(salt)); + LogUtil.logInfo("IncomingSystemProperty - decrypt passwd:" + passwd); //$NON-NLS-1$ + System.setProperty("javax.net.ssl.keyStorePassword", passwd); //$NON-NLS-1$ + } + } + } + return true; + } + + public boolean checkTrustStoreType() { + Optional type = null; + + type = Optional.ofNullable(System.getProperty("javax.net.ssl.trustStoreType")); //$NON-NLS-1$ + if (type.isEmpty()) { + LogUtil.logError("No incoming System Properties are set for PKI.", null); //$NON-NLS-1$ + return false; + } + return true; + + } + + public boolean checkTrustStore() { + Optional trustStore = null; + Optional trustStorePassword = null; + trustStore = Optional.ofNullable(System.getProperty("javax.net.ssl.trustStore")); //$NON-NLS-1$ + if (trustStore.isEmpty()) { + LogUtil.logError("No truststore is set, javax.net.ssl.trustStore", null); //$NON-NLS-1$ + return false; + } + trustStorePassword = Optional.ofNullable(System.getProperty("javax.net.ssl.trustStorePassword")); //$NON-NLS-1$ + if (trustStorePassword.isEmpty()) { + LogUtil.logError("A truststore Password is required, javax.net.ssl.trustStorePassword", null); //$NON-NLS-1$ + return false; + } + return true; + } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/KeystoreSetup.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/KeystoreSetup.java new file mode 100644 index 00000000000..090f3fb7fc2 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/KeystoreSetup.java @@ -0,0 +1,251 @@ +/** + * Copyright (c) 2014 Codetrails GmbH. + * 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: + * Marcel Bruch - initial API and implementation. + */ +package org.eclipse.core.pki.auth; + + +import java.util.Optional; +import java.io.File; +import java.util.Collection; +import java.util.Enumeration; +import java.util.List; +import java.util.Properties; +import java.security.SecureRandom; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import org.eclipse.core.runtime.RegistryFactory; +import org.eclipse.core.runtime.spi.RegistryStrategy; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.core.pki.util.ConfigureTrust; +import org.eclipse.core.pki.util.KeyStoreManager; +import org.eclipse.core.pki.util.KeyStoreFormat; + + +import org.eclipse.core.pki.pkiselection.PKIProperties; + + +public class KeystoreSetup { + static boolean isPkcs11Installed = false; + static boolean isKeyStoreLoaded = false; + PKIProperties pkiInstance = null; + Properties pkiProperties = null; + SSLContext sslContext = null; + protected static KeyStore keyStore = null; + private static final int DIGITAL_SIGNATURE = 0; + private static final int KEY_CERT_SIGN = 5; + private static final int CRL_SIGN = 6; + private static KeystoreSetup INSTANCE; + public KeystoreSetup() {} + public static KeystoreSetup getInstance() { + if(INSTANCE == null) { + INSTANCE = new KeystoreSetup(); + } + + return INSTANCE; + } + public void installKeystore() { + Optional keystoreContainer = null; + + //LogUtil.logWarning("KeystoreSetup- BREAK for INPUT:"); + + try { + + keystoreContainer = Optional.ofNullable( + KeyStoreManager.INSTANCE.getKeyStore(System.getProperty("javax.net.ssl.keyStore"), //$NON-NLS-1$ + System.getProperty("javax.net.ssl.keyStorePassword"), //$NON-NLS-1$ + KeyStoreFormat.valueOf(System.getProperty("javax.net.ssl.keyStoreType")))); //$NON-NLS-1$ + + if ((keystoreContainer.isEmpty()) || (!(KeyStoreManager.INSTANCE.isKeyStoreInitialized()))) { + LogUtil.logError("PKISetup - Failed to Load a Keystore.", null); //$NON-NLS-1$ + PKIState.CONTROL.setPKCS12on(false); + System.clearProperty("javax.net.ssl.keyStoreType"); //$NON-NLS-1$ + System.clearProperty("javax.net.ssl.keyStore"); //$NON-NLS-1$ + System.clearProperty("javax.net.ssl.keyStoreProvider"); //$NON-NLS-1$ + System.clearProperty("javax.net.ssl.keyStorePassword"); //$NON-NLS-1$ + SecurityFileSnapshot.INSTANCE.restoreProperties(); + } else { + LogUtil.logError("A Keystore and Password are detected.", null); //$NON-NLS-1$ + keyStore = keystoreContainer.get(); + setKeyStoreLoaded(true); + setPkiContext(); + } + } catch (Exception e) { + LogUtil.logError("Failed to Load Keystore.", e); //$NON-NLS-1$ + } + } + public void setPkiContext() { + if ((IncomingSystemProperty.SETTINGS.checkTrustStoreType()) && (isKeyStoreLoaded())) { + if ((IncomingSystemProperty.SETTINGS.checkTrustStore()) + && (KeyStoreManager.INSTANCE.isKeyStoreInitialized())) { + LogUtil.logInfo("A KeyStore and Truststore are detected."); //$NON-NLS-1$ + Optional PKIXtrust = ConfigureTrust.MANAGER.setUp(); + + try { + KeyManager[] km = new KeyManager[] { KeyStoreManager.INSTANCE }; + TrustManager[] tm = new TrustManager[] { ConfigureTrust.MANAGER }; + if (PKIXtrust.isEmpty()) { + LogUtil.logError("Invalid TrustManager Initialization.", null); //$NON-NLS-1$ + } else { + SSLContext ctx = SSLContext.getInstance("TLS");//$NON-NLS-1$ + ctx.init(km, tm, null); + SSLContext.setDefault(ctx); + HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); + setSSLContext(ctx); + pkiInstance = PKIProperties.getInstance(); + pkiInstance.load(); + setUserEmail(); + // Grab a handle to registry + //File[] storageDirs = null; + //boolean[] cacheReadOnly = null; + //String token = "core.pki"; + /* + * try { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); // + * IResource resource = // + * ResourcesPlugin.getWorkspace().getAdapter(IResource.class); IMarker marker = + * root.createMarker("virtual.core.pki.context"); marker.setAttribute(token, + * ctx); } catch (Exception imarkerErr) { imarkerErr.printStackTrace(); } + */ + /* + * IExtensionRegistry registry = Platform.getExtensionRegistry(); + * IConfigurationElement[] extensions = + * registry.getConfigurationElementsFor(EXTENSION_POINT); for + * (IConfigurationElement element : extensions) { [..] } + */ + + // InjectorFactory.getDefault().addBinding(MyPart.class).implementedBy(MyFactory.class) + // RegistryStrategy strategy = RegistryFactory.createOSGiStrategy(File[] + // storageDirs, boolean[] cacheReadOnly, Object token) +// RegistryStrategy strategy = RegistryFactory.createOSGiStrategy(storageDirs, +// cacheReadOnly, token); +// // IExtensionRegistry registry = RegistryFactory.getRegistry(); +// IExtensionRegistry registry = RegistryFactory.createRegistry(strategy, token, ctx); +// +// setupAdapter(); + LogUtil.logInfo("PKISetup default SSLContext has been configured."); //$NON-NLS-1$ + } + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + LogUtil.logError("Initialization Error", e); //$NON-NLS-1$ + } catch (KeyManagementException e) { + // TODO Auto-generated catch block + LogUtil.logError("Initialization Error", e); //$NON-NLS-1$ + } + } else { + LogUtil.logError("Valid KeyStore and Truststore not found.", null); //$NON-NLS-1$ + } + } else { + LogUtil.logError("Valid Truststore not found.", null); //$NON-NLS-1$ + } + } + public SSLContext getSSLContext() { + return INSTANCE.sslContext; + } + + public void setSSLContext(SSLContext context) { + this.sslContext = context; + } + public boolean isKeyStoreLoaded() { + return PKISetup.isKeyStoreLoaded; + } + + private void setKeyStoreLoaded(boolean isKeyStoreLoaded) { + PKISetup.isKeyStoreLoaded = isKeyStoreLoaded; + } + private void setUserEmail() { + try { + Enumeration en = keyStore.aliases(); + while (en.hasMoreElements()) { + String alias = en.nextElement(); + // System.out.println(" " + alias); + Certificate cert = keyStore.getCertificate(alias); + if (cert.getType().equalsIgnoreCase("X.509")) { + X509Certificate X509 = (X509Certificate) cert; + + // + // we need to make sure this is a digital certificate instead of a server + // cert or something + // + if (isDigitalSignature(X509.getKeyUsage())) { + Collection> altnames = X509.getSubjectAlternativeNames(); + if (altnames != null) { + for (List item : altnames) { + Integer type = (Integer) item.get(0); + if (type == 1) + try { + String userEmail = item.toArray()[1].toString(); + System.setProperty("mail.smtp.user", userEmail); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + } + + } + } + } catch (Exception err) { + + } + } + + private static boolean isDigitalSignature(boolean[] ba) { + if (ba != null) { + return ba[DIGITAL_SIGNATURE] && !ba[KEY_CERT_SIGN] && !ba[CRL_SIGN]; + } else { + return false; + } + } + +// private void setupAdapter() { +// +// IAdapterFactory pr = new IAdapterFactory() { +// @Override +// public Class[] getAdapterList() { +// return new Class[] { SSLContext.class }; +// } +// +// @Override +// public T getAdapter(Object adaptableObject, Class adapterType) { +// IResource res = (IResource) adaptableObject; +// SSLContext v = null; +// QualifiedName key = new QualifiedName("org.eclipse.core.pki", "context"); +// try { +// v = (SSLContext) res.getSessionProperty(key); +// if (v == null) { +// v = getSSLContext(); +// res.setSessionProperty(key, v); +// } +// } catch (CoreException e) { +// // unable to access session property - ignore +// } +// return (T)v; +// } +// }; +// Platform.getAdapterManager().registerAdapters(pr,IResource.class); +// } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PKISetup.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PKISetup.java new file mode 100644 index 00000000000..d55ab8d1507 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PKISetup.java @@ -0,0 +1,359 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.auth; + +import org.eclipse.core.runtime.ServiceCaller; + +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.util.Optional; +import java.util.Properties; +import java.util.Collection; +import java.util.Enumeration; +import java.util.List; +import java.io.File; +import java.security.SecureRandom; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.eclipse.core.pki.AuthenticationBase; +import org.eclipse.core.pki.pkiselection.PKIProperties; +import org.eclipse.core.pki.util.ConfigureTrust; +import org.eclipse.core.pki.util.KeyStoreFormat; +import org.eclipse.core.pki.util.KeyStoreManager; +import org.eclipse.core.pki.util.LogUtil; + +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.RegistryFactory; +import org.eclipse.core.runtime.spi.RegistryStrategy; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.ILog; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.Platform; +//import org.eclipse.jface.preference.IPreferenceStore; +//import org.eclipse.osgi.framework.eventmgr.EventManager; +//import org.eclipse.osgi.framework.eventmgr.ListenerQueue; +import org.eclipse.ui.IStartup; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class PKISetup implements BundleActivator, IStartup { + public static final String ID = "org.eclipse.core.pki"; //$NON-NLS-1$ + protected final String pin = "#Gone2Boat@Bay"; //$NON-NLS-1$ + private static PKISetup instance; + static boolean isPkcs11Installed = false; + static boolean isKeyStoreLoaded = false; + private BundleContext context; + SSLContext sslContext = null; + private static final ServiceCaller logger = new ServiceCaller(PKISetup.class, ILog.class); + // ListenerQueue queue = null; + protected static KeyStore keyStore = null; + PKIProperties pkiInstance = null; + Properties pkiProperties = null; + Optional keystoreContainer = null; + private static final int DIGITAL_SIGNATURE = 0; + private static final int KEY_CERT_SIGN = 5; + private static final int CRL_SIGN = 6; + + public PKISetup() { + super(); + setInstance(this); + } + + @Override + public void start(BundleContext context) throws Exception { + // TODO Auto-generated method stub + // System.out.println("PKISetup PKISetup ------------------- START"); + this.context = context; + + Startup(); + } + + @Override + public void earlyStartup() { + // TODO Auto-generated method stub + // System.out.println("PKISetup PKISetup -------------------early + // START");//$NON-NLS-1$ + } + + @Override + public void stop(BundleContext context) throws Exception { + // TODO Auto-generated method stub + + } + + public static PKISetup getInstance() { + return instance; + } + + public static void setInstance(PKISetup instance) { + PKISetup.instance = instance; + } + + public void log(String message) { + logger.call(logger -> logger.info(message)); + } + + public void Startup() { + + // log("Startup method is now running"); //$NON-NLS-1$ + + Optional type = null; + Optional decryptedPw; + + PKIState.CONTROL.setPKCS11on(false); + PKIState.CONTROL.setPKCS12on(false); + /* + * First see if parameters were passed into eclipse via the command line -D + */ + type = Optional.ofNullable(System.getProperty("javax.net.ssl.keyStoreType")); //$NON-NLS-1$ + + if (type.isEmpty()) { + // + // Incoming parameter as -DkeystoreType was empty so CHECK in .pki file + // + PKIState.CONTROL.setPKCS11on(false); + PKIState.CONTROL.setPKCS12on(false); + if (PublicKeySecurity.INSTANCE.isTurnedOn()) { + PublicKeySecurity.INSTANCE.getPkiPropertyFile(pin); + } + } + // LogUtil.logInfo("PKISetup - now looking at incoming"); //$NON-NLS-1$ + if (IncomingSystemProperty.SETTINGS.checkType()) { + if (IncomingSystemProperty.SETTINGS.checkKeyStore(pin)) { + KeystoreSetup setup = KeystoreSetup.getInstance(); + if (PKIState.CONTROL.isPKCS12on()) { + + setup.installKeystore(); + + } + if (PKIState.CONTROL.isPKCS11on()) { + String pkcs11Pin = ""; + LogUtil.logInfo("PKISetup - Processing PKCS11"); //$NON-NLS-1$ + decryptedPw = Optional.ofNullable(System.getProperty("javax.net.ssl.keyStorePassword")); + if (!decryptedPw.isEmpty()) { + pkcs11Pin = decryptedPw.get(); + } + keystoreContainer = Optional + .ofNullable(AuthenticationBase.INSTANCE.initialize(pkcs11Pin.toCharArray()));// $NON-NLS-1$ + if (keystoreContainer.isEmpty()) { + LogUtil.logError("PKISetup - Failed to Load a Keystore.", null); //$NON-NLS-1$ + PKIState.CONTROL.setPKCS11on(false); + System.clearProperty("javax.net.ssl.keyStoreType"); //$NON-NLS-1$ + System.clearProperty("javax.net.ssl.keyStore"); //$NON-NLS-1$ + System.clearProperty("javax.net.ssl.keyStoreProvider"); //$NON-NLS-1$ + System.clearProperty("javax.net.ssl.keyStorePassword"); //$NON-NLS-1$ + SecurityFileSnapshot.INSTANCE.restoreProperties(); + } else { + LogUtil.logError("A Keystore and Password are detected.", null); //$NON-NLS-1$ + keyStore = keystoreContainer.get(); + KeyStoreManager.INSTANCE.setKeyStore(keyStore); + setKeyStoreLoaded(true); + setup.setPkiContext(); + } + } + +// if ((IncomingSystemProperty.SETTINGS.checkTrustStoreType()) && (isKeyStoreLoaded())) { +// if ((IncomingSystemProperty.SETTINGS.checkTrustStore()) +// && (KeyStoreManager.INSTANCE.isKeyStoreInitialized())) { +// LogUtil.logInfo("A KeyStore and Truststore are detected."); //$NON-NLS-1$ +// Optional PKIXtrust = ConfigureTrust.MANAGER.setUp(); +// +// try { +// KeyManager[] km = new KeyManager[] { KeyStoreManager.INSTANCE }; +// TrustManager[] tm = new TrustManager[] { ConfigureTrust.MANAGER }; +// if (PKIXtrust.isEmpty()) { +// LogUtil.logError("Invalid TrustManager Initialization.", null); //$NON-NLS-1$ +// } else { +// SSLContext ctx = SSLContext.getInstance("TLS");//$NON-NLS-1$ +// ctx.init(km, tm, new SecureRandom()); +// SSLContext.setDefault(ctx); +// HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); +// setSSLContext(ctx); +// pkiInstance = PKIProperties.getInstance(); +// pkiInstance.load(); +// setUserEmail(); +// // Grab a handle to registry +// File[] storageDirs = null; +// boolean[] cacheReadOnly = null; +// String token = "core.pki"; +// try { +// IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); +// // IResource resource = +// // ResourcesPlugin.getWorkspace().getAdapter(IResource.class); +// IMarker marker = root.createMarker("virtual.core.pki.context"); +// marker.setAttribute(token, ctx); +// } catch (Exception imarkerErr) { +// imarkerErr.printStackTrace(); +// } +// /* +// * IExtensionRegistry registry = Platform.getExtensionRegistry(); +// * IConfigurationElement[] extensions = +// * registry.getConfigurationElementsFor(EXTENSION_POINT); for +// * (IConfigurationElement element : extensions) { [..] } +// */ +// +// // InjectorFactory.getDefault().addBinding(MyPart.class).implementedBy(MyFactory.class) +// // RegistryStrategy strategy = RegistryFactory.createOSGiStrategy(File[] +// // storageDirs, boolean[] cacheReadOnly, Object token) +// RegistryStrategy strategy = RegistryFactory.createOSGiStrategy(storageDirs, +// cacheReadOnly, token); +// // IExtensionRegistry registry = RegistryFactory.getRegistry(); +// IExtensionRegistry registry = RegistryFactory.createRegistry(strategy, token, ctx); +// +// setupAdapter(); +// LogUtil.logInfo("PKISetup default SSLContext has been configured."); //$NON-NLS-1$ +// } +// } catch (NoSuchAlgorithmException e) { +// // TODO Auto-generated catch block +// LogUtil.logError("Initialization Error", e); //$NON-NLS-1$ +// } catch (KeyManagementException e) { +// // TODO Auto-generated catch block +// LogUtil.logError("Initialization Error", e); //$NON-NLS-1$ +// } +// } else { +// LogUtil.logError("Valid KeyStore and Truststore not found.", null); //$NON-NLS-1$ +// } +// +// } + } + } + } + + public SSLContext getSSLContext() { + return sslContext; + } + + public void setSSLContext(SSLContext context) { + this.sslContext = context; + } + + private boolean isKeyStoreLoaded() { + return isKeyStoreLoaded; + } + + private void setKeyStoreLoaded(boolean isKeyStoreLoaded) { + PKISetup.isKeyStoreLoaded = isKeyStoreLoaded; + } + + private static boolean isDigitalSignature(boolean[] ba) { + if (ba != null) { + return ba[DIGITAL_SIGNATURE] && !ba[KEY_CERT_SIGN] && !ba[CRL_SIGN]; + } else { + return false; + } + } + + private void setupAdapter() { + + IAdapterFactory pr = new IAdapterFactory() { + @Override + public Class[] getAdapterList() { + return new Class[] { SSLContext.class }; + } + + @Override + public T getAdapter(Object adaptableObject, Class adapterType) { + IResource res = (IResource) adaptableObject; + SSLContext v = null; + QualifiedName key = new QualifiedName("org.eclipse.core.pki", "context"); + try { + v = (SSLContext) res.getSessionProperty(key); + if (v == null) { + v = getSSLContext(); + res.setSessionProperty(key, v); + } + } catch (CoreException e) { + // unable to access session property - ignore + } + return (T)v; + } + }; + Platform.getAdapterManager().registerAdapters(pr,IResource.class); + } + +/** + * @see AuthenticationPlugin#setSystemProperties() + */ + +/* + * private void installTrustStore() { final String USER_HOME = + * System.getProperty("user.home"); //$NON-NLS-1$ final File PKI_ECLIPSE_DIR = + * new File(USER_HOME, ".eclipse_pki"); //$NON-NLS-1$ final String PKI_DIR = + * "eclipse_pki"; //$NON-NLS-1$ //final Path pkiHome = + * Paths.get(PKI_ECLIPSE_DIR.getAbsolutePath() + File.separator + PKI_DIR); + * + * final Path pkiHome = Paths.get(PKI_ECLIPSE_DIR.getAbsolutePath() + + * File.separator + PKI_DIR); createSigintEclipseDir(pkiHome); + * + * TODO: Create an enum of the IC comms and utilize the correct trust + * + * + * String filename = "cacert"; //$NON-NLS-1$ File localTrustStore = new + * File(PKI_ECLIPSE_DIR, filename); + * + * // System.out.println("Install Truststore - local -> " + localTrustStore); + * + * // // we want to install the new one anyway // // + * if(!localTrustStore.exists()) { FileChannel fc = null; ReadableByteChannel + * rbc = null; FileOutputStream os = null; try { + * localTrustStore.createNewFile(); os = new FileOutputStream(localTrustStore); + * fc = os.getChannel(); + * + * + * // //File ConfigurationFile = new + * File(ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString() + + * File.separator // + "configuration" + File.separator // + "cacert"); + * + * File ConfigurationFile = new File(File.separator + "configuration" + + * File.separator //$NON-NLS-1$ + "cacert"); //$NON-NLS-1$ InputStream is = new + * FileInputStream(ConfigurationFile); + * + * // // copy the contents of the eclipse/ cacerts file to our .pki directory // + * rbc = Channels.newChannel(is); ByteBuffer buffer = ByteBuffer.allocate(1024); + * buffer.clear(); while (rbc.read(buffer) != -1) { buffer.flip(); + * fc.write(buffer); buffer.compact(); } + * + * } catch (IOException e) { + * //LogUtil.logError("Issue writing default trust store to disk.", e); } // } + * //AuthenticationPlugin.getDefault().getPreferenceStore().setValue( + * AuthenticationPreferences.TRUST_STORE_LOCATION, // + * localTrustStore.getAbsolutePath()); + * + * } + */ + +/* + * private void createSigintEclipseDir(Path pkiHome) { Lock fsLock = new + * ReentrantLock(); fsLock.lock(); try { if (Files.notExists(pkiHome)) { + * Files.createDirectories(pkiHome); } } catch (IOException e) { // TODO + * Auto-generated catch block e.printStackTrace(); } finally { fsLock.unlock(); + * } } + */ +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PKIState.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PKIState.java new file mode 100644 index 00000000000..553b89465de --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PKIState.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.auth; + +public enum PKIState { + CONTROL; + private boolean isPKCS11on=false; + private boolean isPKCS12on=false; + public boolean isPKCS11on() { + return isPKCS11on; + } + public void setPKCS11on(boolean isPKCS11on) { + this.isPKCS11on = isPKCS11on; + } + public boolean isPKCS12on() { + return isPKCS12on; + } + public void setPKCS12on(boolean isPKCS12on) { + this.isPKCS12on = isPKCS12on; + } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PasswordObserver.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PasswordObserver.java new file mode 100644 index 00000000000..0cd7790ae04 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PasswordObserver.java @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2014 Codetrails GmbH. + * 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: + * Marcel Bruch - initial API and implementation. + */ +package org.eclipse.core.pki.auth; + +import java.util.Observable; +import java.util.Observer; +import java.util.Optional; +import java.io.File; +import java.util.Collection; +import java.util.Enumeration; +import java.util.List; +import java.util.Properties; +import java.security.SecureRandom; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.concurrent.Flow.Subscriber; +import java.util.concurrent.Flow.Subscription; + + +import org.eclipse.core.runtime.RegistryFactory; +import org.eclipse.core.runtime.spi.RegistryStrategy; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.core.pki.util.ConfigureTrust; +import org.eclipse.core.pki.util.KeyStoreManager; +import org.eclipse.core.pki.util.KeyStoreFormat; +import org.eclipse.core.pki.pkiselection.SecurityOpRequest; + +import org.eclipse.core.pki.pkiselection.PKIProperties; + +@SuppressWarnings("restriction") +public class PasswordObserver implements Observer, Subscriber { + static boolean isPkcs11Installed = false; + static boolean isKeyStoreLoaded = false; + PKIProperties pkiInstance = null; + Properties pkiProperties = null; + //SSLContext sslContext = null; + private Subscription subscription; + protected static KeyStore keyStore = null; + private static final int DIGITAL_SIGNATURE = 0; + private static final int KEY_CERT_SIGN = 5; + private static final int CRL_SIGN = 6; + public PasswordObserver() { + + } + + public void update(Observable obj, Object arg) { + Optional keystoreContainer = null; + String pw = (String) arg; + //LogUtil.logWarning("PasswordObserver- BREAK for INPUT:"+pw); + System.setProperty("javax.net.ssl.keyStorePassword", pw); //$NON-NLS-1$ + KeystoreSetup setup = KeystoreSetup.getInstance(); + setup.installKeystore(); + } + public void onSubscribe(Subscription subscription) { + // TODO Auto-generated method stub + this.subscription = subscription; + } + + public void onNext(Object item) { + // TODO Auto-generated method stub + SecurityOpRequest.INSTANCE.setConnected(true); + } + + public void onError(Throwable throwable) { + // TODO Auto-generated method stub + } + + public void onComplete() { + // TODO Auto-generated method stub + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PokeInConsole.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PokeInConsole.java new file mode 100644 index 00000000000..701084912b0 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PokeInConsole.java @@ -0,0 +1,47 @@ +package org.eclipse.core.pki.auth; + +import java.io.BufferedReader; +import java.io.Console; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Serializable; + +public enum PokeInConsole implements Serializable { + PASSWD; + protected static final String ENTER="Enter password:"; + public void get() { + try { + Console console = System.console(); + if (console == null) { + + //System.out.println("PokeInConsole - Couldn't get Console instance"); + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + System.out.print(ENTER); + String name=new String(); + try { + //System.out.println((char)27 + "[37mWHITE"); + //System.out.println((char)27 + "[37m"); + System.out.println((char)27 + "[8m"); + name = reader.readLine(); + System.out.flush(); + //System.out.println((char)27 + "[30mBLACK"); + System.out.println((char)27 + "[0m"); + System.out.println((char)27 + "[30m"); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + System.setProperty("javax.net.ssl.keyStorePassword", name); + } else { + char[] ch = console.readPassword( ENTER ); + String pw = new String(ch); + System.setProperty("javax.net.ssl.keyStorePassword", pw); + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/Proxies.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/Proxies.java new file mode 100644 index 00000000000..40019849455 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/Proxies.java @@ -0,0 +1,158 @@ +/** + * Copyright (c) 2014 Codetrails GmbH. + * 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: + * Marcel Bruch - initial API and implementation. + */ +package org.eclipse.core.pki.auth; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.URI; +import java.net.UnknownHostException; +//import org.apache.commons.httpclient.HttpHost; +//import org.apache.commons.lang3.StringUtils; +import java.net.http.HttpClient; +//import java.net.http.HttpClient.Builder; +import java.util.Optional; +import java.util.concurrent.Executor; + +import org.eclipse.core.net.proxy.IProxyData; + +@SuppressWarnings("restriction") +public final class Proxies { + + private Proxies() { + // Not meant to be instantiated + } + + private static final String DOUBLEBACKSLASH = "\\\\"; //$NON-NLS-1$ + private static final String ENV_USERDOMAIN = "USERDOMAIN"; //$NON-NLS-1$ + private static final String PROP_HTTP_AUTH_NTLM_DOMAIN = "http.auth.ntlm.domain"; //$NON-NLS-1$ + + /** + * Returns the domain of the current machine- if any. + * + * @param userName + * the user name which may be null. On windows it may contain the domain name as prefix "domain\\username". + */ + public static Optional getUserDomain(String userName) { + + // check the app's system properties + String domain = System.getProperty(PROP_HTTP_AUTH_NTLM_DOMAIN); + if (domain != null) { + return Optional.of(domain); + } + + // check the OS environment + domain = System.getenv(ENV_USERDOMAIN); + if (domain != null) { + return Optional.of(domain); + } + + // test the user's name whether it may contain an information about the domain name + //if (StringUtils.contains(userName, DOUBLEBACKSLASH)) { + if (userName.contains(DOUBLEBACKSLASH)) { + //return Optional.of(substringBefore(userName, DOUBLEBACKSLASH)); + userName.substring(0, userName.indexOf(DOUBLEBACKSLASH)-1); + return Optional.of(userName.substring(0, userName.indexOf(DOUBLEBACKSLASH)-1)); + } + + // no domain name found + return Optional.empty(); + } + + /** + * Returns the host name of this workstation (localhost) + */ + public static Optional getWorkstation() { + try { + return Optional.of(InetAddress.getLocalHost().getHostName()); + } catch (UnknownHostException e) { + return Optional.empty(); + } + } + + /** + * Returns the user name without a (potential) domain prefix + * + * @param userName + * a String that may look like "domain\\userName" + */ + public static Optional getUserName(String userName) { + if (userName == null) { + return Optional.empty(); + } + //return contains(userName, DOUBLEBACKSLASH) ? of(substringAfterLast(userName, DOUBLEBACKSLASH)) : of(userName); + return userName.contains(DOUBLEBACKSLASH) ? + Optional.of(userName.substring(userName.indexOf(DOUBLEBACKSLASH))) : Optional.of(userName); + } + //public static Optional getProxyHost(URI target) { + public static Optional getProxyHost(URI target) { + //IProxyData proxy = getProxyData(target).orNull(); + IProxyData proxy = getProxyData(target).orElse(null); + if (proxy == null) { + return Optional.empty(); + } + //return Optional.of(new HttpHost(proxy.getHost(), proxy.getPort())); + return Optional.of(HttpClient.newBuilder() + .proxy(ProxySelector.of( + new InetSocketAddress(proxy.getHost(), proxy.getPort()))).build()); + } + + public static Executor proxyAuthentication(Executor executor, URI target) throws IOException { + IProxyData proxy = getProxyData(target).orElse(null); + if (proxy != null) { + //HttpHost proxyHost = new HttpHost(proxy.getHost(), proxy.getPort()); + HttpClient.newBuilder().proxy(ProxySelector.of(new InetSocketAddress(proxy.getHost(), proxy.getPort()))); + if (proxy.getUserId() != null) { + // String userId = getUserName(proxy.getUserId()).orElse(null); + // String pass = proxy.getPassword(); + // String workstation = getWorkstation().orElse(null); + // String domain = getUserDomain(proxy.getUserId()).orElse(null); + + System.out.println("Proxies - proxyAuthentication needs to be FIXED"); //$NON-NLS-1$ + //return executor.auth(proxyHost, userId, pass, workstation, domain); + //return executor. auth(proxyHost, userId, pass, workstation, domain); + } else { + return executor; + } + } + return executor; + } + + private static Optional getProxyData(URI target) { + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(target.getHost(), target.getPort())); + //IProxyData[] proxies = ProxyManager.getProxyManager().select(target); + + Optional op = Optional.of(proxy); + if (op.isEmpty()) { + return Optional.empty(); + } + //return Optional.of(proxies[0]); + return op; + } + + public static Optional getProxyUser(URI target) { + IProxyData proxy = getProxyData(target).orElse(null); + if ((proxy == null) || (proxy.getUserId() == null)) { + return Optional.empty(); + } + return getUserName(proxy.getUserId()); + } + + public static Optional getProxyPassword(URI target) { + IProxyData proxy = getProxyData(target).orElse(null); + if ((proxy == null) || (proxy.getUserId() == null)) { + return Optional.empty(); + } + return Optional.ofNullable(proxy.getPassword()); + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PublicKeySecurity.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PublicKeySecurity.java new file mode 100644 index 00000000000..00f00d3dbb9 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PublicKeySecurity.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.auth; + +import java.util.Properties; + +public enum PublicKeySecurity { + INSTANCE; + protected byte[] salt = new byte[16]; + public boolean isTurnedOn() { + return SecurityFileSnapshot.INSTANCE.image(); + } + public void setupPKIfile() { + + SecurityFileSnapshot.INSTANCE.createPKI(); + + } + + public Properties getPkiPropertyFile(String pin) { + salt = new String(System.getProperty("user.name") + pin).getBytes(); //$NON-NLS-1$ + return SecurityFileSnapshot.INSTANCE.load(pin, new String(salt)); + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PublishPasswordUpdate.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PublishPasswordUpdate.java new file mode 100644 index 00000000000..5b3a288a5f0 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PublishPasswordUpdate.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2014 Codetrails GmbH. + * 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: + * Marcel Bruch - initial API and implementation. + */ +package org.eclipse.core.pki.auth; + +import java.util.Observable; +import java.util.ArrayList; +import java.util.List; +import org.eclipse.core.pki.util.LogUtil; +import java.util.concurrent.Flow.*; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; + +public enum PublishPasswordUpdate implements PublishPasswordUpdateIfc { + INSTANCE; + private final ExecutorService executor = Executors.newFixedThreadPool(10); + private List> subscribers = new ArrayList<>(); + + public void subscribe(Subscriber subscriber) { + //LogUtil.logWarning(" PublishPasswordUpdate-------subscribe"); //$NON-NLS-1$ + subscribers.add(subscriber); + System.out.println("PublishPasswordUpdate adding subscriber COUNT:"+subscribers.size()); + //return subscribers.size(); + } + public int getSubscriberCount() { + return subscribers.size(); + } + + public void publishMessage(String message) { + System.out.println("PublishPasswordUpdate publish"); + subscribers.forEach(subscriber -> { + executor.submit(() -> { + subscriber.onNext(message); + }); + }); + } + public void close() { + subscribers.forEach(Subscriber::onComplete); + executor.shutdown(); + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PublishPasswordUpdateIfc.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PublishPasswordUpdateIfc.java new file mode 100644 index 00000000000..b6d18a0eb3d --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/PublishPasswordUpdateIfc.java @@ -0,0 +1,13 @@ +package org.eclipse.core.pki.auth; + +import java.util.concurrent.Flow.Publisher; +import java.util.concurrent.Flow.Subscriber; + +public interface PublishPasswordUpdateIfc extends Publisher{ + + //public static PublishPasswordUpdate getInstance(); + public void subscribe(Subscriber subscriber); + public int getSubscriberCount(); + public void publishMessage(String message); + public void close(); +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/SecurityFileSnapshot.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/SecurityFileSnapshot.java new file mode 100644 index 00000000000..c5e3a4c68ef --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/auth/SecurityFileSnapshot.java @@ -0,0 +1,327 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.auth; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.InputStream; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.charset.Charset; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.nio.file.attribute.PosixFileAttributeView; +import java.nio.file.attribute.PosixFilePermission; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Properties; +import java.util.Set; + +import org.eclipse.core.pki.util.DotPkiPropertiesRequired; +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.core.pki.util.NormalizeGCM; +import org.eclipse.core.pki.util.SecureGCM; +import org.eclipse.core.pki.util.TemplateForPKIfile; +import org.eclipse.core.pki.pkiselection.PkiPasswordInputUI; +import org.eclipse.core.pki.pkiselection.PkiPasswordGrabberWidget; +import org.eclipse.core.pki.pkiselection.SecurityOpRequest; + +public enum SecurityFileSnapshot { + INSTANCE; + + Path pkiFile = null; + Path userM2Home = null; + Path userHome = null; + Path userDotEclipseHome = null; + Properties originalProperties = new Properties(); + public static final String DotEclipse = ".eclipse"; + public static final String USER_HOME = System.getProperty("user.home"); //$NON-NLS-1$ + + public boolean image() { + /* + * CHeck if .pki file is present. + */ + try { + Optional eclipseHome = Optional.ofNullable(Files.exists(Paths.get(USER_HOME))); // $NON-NLS-1$ + if (!(eclipseHome.isEmpty())) { + if (Files.exists(Paths.get(USER_HOME + FileSystems.getDefault().getSeparator() + DotEclipse + + FileSystems.getDefault().getSeparator() + ".pki"))) { + + userDotEclipseHome = Paths.get(USER_HOME + FileSystems.getDefault().getSeparator() + DotEclipse + + FileSystems.getDefault().getSeparator() + ".pki"); + if (!DotPkiPropertiesRequired.CHECKER.testFile(userDotEclipseHome)) { + TemplateForPKIfile.CREATION.setup(); + return false; + } + } else { + LogUtil.logWarning("NO PKI file detected"); + /* + * Files.createFile(Paths.get(USER_HOME+ + * FileSystems.getDefault().getSeparator()+DotEclipse+ + * FileSystems.getDefault().getSeparator()+ ".pki")); + */ + TemplateForPKIfile.CREATION.setup(); + return false; + } + } + + } catch (Exception e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + //isSecurityFileRequired(""); //$NON-NLS-1$ + if (Files.exists(userDotEclipseHome)) { + LogUtil.logWarning("A PKI file detected;" + userDotEclipseHome.toString()); //$NON-NLS-1$ + return true; + } + return false; + } + public boolean createPKI() { + Optional eclipseHome = Optional.ofNullable(Files.exists(Paths.get(USER_HOME))); // $NON-NLS-1$ + if (!(eclipseHome.isEmpty())) { + if (!(Files.exists(Paths.get(USER_HOME + FileSystems.getDefault().getSeparator() + DotEclipse + + FileSystems.getDefault().getSeparator() + ".pki")))) { + String pkiFileFQN=USER_HOME + FileSystems.getDefault().getSeparator() + DotEclipse + + FileSystems.getDefault().getSeparator() + ".pki"; + + userDotEclipseHome = Paths.get(pkiFileFQN); + // create the PKI file + try { + Files.createFile(userDotEclipseHome); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + isSecurityFileRequired(pkiFileFQN); + return true; + } else { + //PKI file already exists + return false; + } + } + return false; + } + + public Properties load(String password, String salt) { + Properties properties = new Properties(); + String passwd = null; + try { + FileChannel fileChannel = FileChannel.open(userDotEclipseHome, StandardOpenOption.READ); + FileChannel updateChannel = FileChannel.open(userDotEclipseHome, StandardOpenOption.WRITE); + FileLock lock = fileChannel.lock(0L, Long.MAX_VALUE, true); + InputStream fileInputStream = Channels.newInputStream(fileChannel); + properties.load(fileInputStream); + originalProperties.putAll(properties); + for (Entry entry : properties.entrySet()) { + entry.setValue(entry.getValue().toString().trim()); + } + + Optional passwdContainer = Optional + .ofNullable(properties.getProperty("javax.net.ssl.keyStorePassword")); //$NON-NLS-1$ + Optional encryptedPasswd = Optional + .ofNullable(properties.getProperty("javax.net.ssl.encryptedPassword")); //$NON-NLS-1$ + if (passwdContainer.isEmpty()) { + Optional keyStoreContainer = Optional.ofNullable( + properties.getProperty("javax.net.ssl.keyStore")); //$NON-NLS-1$ + if (!(keyStoreContainer.isEmpty() )) { + System.setProperty("javax.net.ssl.keyStore", keyStoreContainer.get().toString().trim()); + } + Optional keyStoreTypeContainer = Optional.ofNullable( + properties.getProperty("javax.net.ssl.keyStoreType")); //$NON-NLS-1$ + if (!(keyStoreTypeContainer.isEmpty() )) { + String keyStoreType = keyStoreTypeContainer.get().toString().trim(); + if (keyStoreType.equalsIgnoreCase("PKCS12" )) { //$NON-NLS-1$ + System.setProperty("javax.net.ssl.keyStoreType", keyStoreType);//$NON-NLS-1$ + // get the passwd from console + //PokeInConsole.PASSWD.get(); + //String pw=PkiPasswordInputUI.DO.get(); + try { + try { + Optional testKeyContainer = Optional.ofNullable( + System.getProperty("core.key")); + if (!(testKeyContainer.isEmpty() )) { + String testKey = testKeyContainer.get().toString().trim(); + System.out.println("SecurityFileSnapshot TESTING:"+testKey); + if (testKey.equalsIgnoreCase("eclipse.core.pki.testing")) { + return properties; + } + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + String pw=PkiPasswordGrabberWidget.INSTANCE.getInput(); + + LogUtil.logWarning("SecurityFileSnapshot - PASSWORD HAS BEEN INPUT");//$NON-NLS-1$ + + //System.out.println("SecurityFileSnapshot PASSWD:"+pw); + System.setProperty("javax.net.ssl.keyStorePassword", pw);//$NON-NLS-1$ + } catch(Exception xe) { + // User may have said cancel + } + + + } else { + System.setProperty("javax.net.ssl.keyStorePassword", "");//$NON-NLS-1$ + } + } + } else { + if ((encryptedPasswd.isEmpty()) && (!(passwdContainer.isEmpty()))) { + // System.out.println("ILoadProperties empty encrypted passwd NOT found"); + // //$NON-NLS-1$ + + properties.setProperty("javax.net.ssl.encryptedPassword", "true"); //$NON-NLS-1$ //$NON-NLS-2$ + passwd = passwdContainer.get(); + properties.setProperty("javax.net.ssl.keyStorePassword", //$NON-NLS-1$ + // SecureAES256.ENCRYPT.encrypt(passwd, password, salt)); + SecureGCM.ENCRYPT.encrypt(passwd, password, salt)); + OutputStream os = Channels.newOutputStream(updateChannel); + properties.save(os, null); + // After saving encrypted passwd to properties file, switch to unencrypted + properties.setProperty("javax.net.ssl.keyStorePassword", passwd); //$NON-NLS-1$ + SecurityOpRequest.INSTANCE.setConnected(true); + //PublishPasswordUpdateImpl publisher = PublishPasswordUpdateImpl.getInstance(); + //publisher.publishMessage(passwd); + PublishPasswordUpdate.INSTANCE.publishMessage(passwd); + } else { + + // String ePasswd = properties.getProperty("javax.net.ssl.keyStorePassword"); + // //$NON-NLS-1$ + String ePasswd = passwdContainer.get(); + passwd = NormalizeGCM.DECRYPT.decrypt(ePasswd, password, salt); + System.setProperty("javax.net.ssl.decryptedPassword", "true"); //$NON-NLS-1$ //$NON-NLS-2$ + properties.setProperty("javax.net.ssl.keyStorePassword", passwd); //$NON-NLS-1$ + properties.setProperty("javax.net.ssl.decryptedPassword", "true"); //$NON-NLS-1$ //$NON-NLS-2$ + + } + } + + properties.setProperty("javax.net.ssl.decryptedPassword", "true"); //$NON-NLS-1$ //$NON-NLS-2$ + + System.getProperties().putAll(properties); + + lock.release(); + LogUtil.logWarning("SecurityFileSnapshot - Loaded PKI System Properties"); //$NON-NLS-1$ + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return properties; + + } + + public void restoreProperties() { + try { + Files.deleteIfExists(userDotEclipseHome); + Files.createFile(userDotEclipseHome); + FileChannel updateChannel = FileChannel.open(userDotEclipseHome, StandardOpenOption.WRITE); + OutputStream os = Channels.newOutputStream(updateChannel); + String date = new SimpleDateFormat("dd-MM-yyyy").format(new Date()); + originalProperties.store(os, "Restored to Original:" + date); + os.flush(); + os.close(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + private static void isSecurityFileRequired(String securityFileLocation) { + Path dir = null; + StringBuilder sb = new StringBuilder(); + + try { + sb.append(securityFileLocation); + sb.append(FileSystems.getDefault().getSeparator()); + // sb.append("TESTDIR"); // testing + // sb.append(FileSystems.getDefault().getSeparator()); + dir = Paths.get(sb.toString()); + try { + //just in case it hasnt been created yet + Files.createDirectories(dir); + } catch(Exception createFileErr) {} + + Path path = Paths.get(sb.toString()); + + if (!(path.toFile().exists())) { + Files.deleteIfExists(path); + Files.createFile(path); + Charset charset = Charset.forName("UTF-8");//$NON-NLS-1$ + LogUtil.logWarning("SecurityFileSnapshot - loading Properties"); //$NON-NLS-1$ + ArrayList a = fileContents(); + if (FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) { //$NON-NLS-1$ + LogUtil.logWarning("SecurityFileSnapshot - posix save properties"); //$NON-NLS-1$ + PosixFileAttributeView posixAttributes = Files.getFileAttributeView(path, + PosixFileAttributeView.class); + Set permissions = posixAttributes.readAttributes().permissions(); + permissions.remove(PosixFilePermission.GROUP_READ); + posixAttributes.setPermissions(permissions); + Files.write(path, a, charset, StandardOpenOption.TRUNCATE_EXISTING); + + permissions.remove(PosixFilePermission.OWNER_WRITE); + posixAttributes.setPermissions(permissions); + } else { + LogUtil.logWarning("SecurityFileSnapshot - non-posix save properties"); //$NON-NLS-1$ + // Windoerz + // DosFileAttributeView dosAttributes = Files.getFileAttributeView(path, + // DosFileAttributeView.class); + // DosFileAttributes standardPermissions = dosAttributes.readAttributes(); + Files.write(path, a, charset, StandardOpenOption.TRUNCATE_EXISTING); + Files.setAttribute(path, "dos:hidden", Boolean.valueOf(true));//$NON-NLS-1$ + } + } + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private static ArrayList fileContents() { + + ArrayList a = new ArrayList<>(); + + try { + a.add("javax.net.ssl.trustStoreType=" + System.getProperty("javax.net.ssl.trustStoreType"));//$NON-NLS-1$ //$NON-NLS-2$ + a.add("javax.net.ssl.trustStorePassword=" + System.getProperty("javax.net.ssl.trustStorePassword"));//$NON-NLS-1$ //$NON-NLS-2$ + a.add("javax.net.ssl.trustStore=" + System.getProperty("javax.net.ssl.trustStore"));//$NON-NLS-1$ //$NON-NLS-2$ + a.add("");//$NON-NLS-1$ + + if (System.getProperty("javax.net.ssl.keyStoreType") != null) {//$NON-NLS-1$ + a.add("javax.net.ssl.keyStoreType=" + System.getProperty("javax.net.ssl.keyStoreType"));//$NON-NLS-1$ //$NON-NLS-2$ + a.add("javax.net.ssl.keyStore=" + System.getProperty("javax.net.ssl.keyStore")); //$NON-NLS-1$ //$NON-NLS-2$ + if (System.getProperty("javax.net.ssl.keyStoreType").equalsIgnoreCase("PKCS12")) { //$NON-NLS-1$ //$NON-NLS-2$ + // a.add("javax.net.ssl.keyStorePassword="+ + // System.getProperty("javax.net.ssl.keyStorePassword")); + } else { + a.add("javax.net.ssl.keyStorePassword=");//$NON-NLS-1$ + a.add("javax.net.ssl.keyStoreProvider=" + System.getProperty("javax.net.ssl.keyStoreProvider")); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return a; + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/CertificateDoesNotExistException.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/CertificateDoesNotExistException.java new file mode 100644 index 00000000000..61e3a931346 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/CertificateDoesNotExistException.java @@ -0,0 +1,36 @@ +package org.eclipse.core.pki.exception; +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ + + +public class CertificateDoesNotExistException extends InvalidPkcs12StreamException { + + private static final long serialVersionUID = -2415838781812652429L; + + public CertificateDoesNotExistException() { + super(); + } + + public CertificateDoesNotExistException( String arg0 ) { + super( arg0 ); + } + + public CertificateDoesNotExistException( Throwable arg0 ) { + super( arg0 ); + } + + public CertificateDoesNotExistException( String arg0, Throwable arg1 ) { + super( arg0, arg1 ); + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/InvalidPkcs12StreamException.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/InvalidPkcs12StreamException.java new file mode 100644 index 00000000000..aaef0fda94a --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/InvalidPkcs12StreamException.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.exception; + +import java.security.cert.CertificateException; + +public class InvalidPkcs12StreamException extends + CertificateException { + + private static final long serialVersionUID = 548968883742412291L; + + public InvalidPkcs12StreamException() { + } + + public InvalidPkcs12StreamException( String arg0 ) { + super( arg0 ); + } + + public InvalidPkcs12StreamException( Throwable arg0 ) { + super( arg0 ); + } + + public InvalidPkcs12StreamException( String arg0, Throwable arg1 ) { + super( arg0, arg1 ); + } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/NonDigitalSignatureCertificateException.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/NonDigitalSignatureCertificateException.java new file mode 100644 index 00000000000..5dbcfff63ea --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/NonDigitalSignatureCertificateException.java @@ -0,0 +1,25 @@ +package org.eclipse.core.pki.exception; + +import java.security.cert.CertificateException; + +public class NonDigitalSignatureCertificateException extends + CertificateException { + + private static final long serialVersionUID = 8626994851137646007L; + + public NonDigitalSignatureCertificateException() { + } + + public NonDigitalSignatureCertificateException( String arg0 ) { + super( arg0 ); + } + + public NonDigitalSignatureCertificateException( Throwable arg0 ) { + super( arg0 ); + } + + public NonDigitalSignatureCertificateException( String arg0, Throwable arg1 ) { + super( arg0, arg1 ); + } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/UserCanceledException.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/UserCanceledException.java new file mode 100644 index 00000000000..657356900e0 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/UserCanceledException.java @@ -0,0 +1,41 @@ +package org.eclipse.core.pki.exception; + +public class UserCanceledException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * + */ + public UserCanceledException() { + super(); + } + + /** + * @param message + * @param cause + */ + public UserCanceledException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param message + */ + public UserCanceledException(String message) { + super(message); + } + + /** + * @param cause + */ + public UserCanceledException(Throwable cause) { + super(cause); + } + + + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/WrongPasswordException.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/WrongPasswordException.java new file mode 100644 index 00000000000..850f218d18d --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/exception/WrongPasswordException.java @@ -0,0 +1,25 @@ +package org.eclipse.core.pki.exception; + +import java.security.cert.CertificateException; + +public class WrongPasswordException extends + CertificateException { + + private static final long serialVersionUID = 6845666941431518872L; + + public WrongPasswordException() { + } + + public WrongPasswordException( String arg0 ) { + super( arg0 ); + } + + public WrongPasswordException( Throwable arg0 ) { + super( arg0 ); + } + + public WrongPasswordException( String arg0, Throwable arg1 ) { + super( arg0, arg1 ); + } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PKI.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PKI.java new file mode 100644 index 00000000000..311c883b0c1 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PKI.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.pkiselection; + +public class PKI { + private String keyStore = ""; //$NON-NLS-1$ + private String keyStoreType = ""; //$NON-NLS-1$ + private String keyStoreProvider = ""; //$NON-NLS-1$ + private transient String keyStorePassword = ""; //$NON-NLS-1$ + private boolean isSecureStorage=false; + public PKI() {} + public String getKeyStore() { + return keyStore; + } + public void setKeyStore(String keyStore) { + this.keyStore = keyStore; + } + public String getKeyStoreType() { + return keyStoreType; + } + public void setKeyStoreType(String keyStoreType) { + this.keyStoreType = keyStoreType; + } + public String getKeyStoreProvider() { + return keyStoreProvider; + } + public void setKeyStoreProvider(String keyStoreProvider) { + this.keyStoreProvider = keyStoreProvider; + } + public String getKeyStorePassword() { + return keyStorePassword; + } + public void setKeyStorePassword(String keyStorePassword) { + this.keyStorePassword = keyStorePassword; + } + + public boolean isSecureStorage() { + return isSecureStorage; + } + public void setSecureStorage(boolean isSecureStorage) { + this.isSecureStorage = isSecureStorage; + } + public void reSetSystem() { + try { + if ( this.getKeyStore() != null ) { + System.setProperty("javax.net.ssl.keyStore", this.getKeyStore()); //$NON-NLS-1$ + } else { + System.clearProperty("javax.net.ssl.keyStore"); //$NON-NLS-1$ + } + + if ( this.getKeyStoreType() != null ) { + System.setProperty("javax.net.ssl.keyStoreType", this.getKeyStoreType()); //$NON-NLS-1$ + } else { + System.clearProperty("javax.net.ssl.keyStoreType"); //$NON-NLS-1$ + } + + if( this.getKeyStoreProvider() != null) { + // System.out.println("PKI - CLEARING keystoreprovider"); //$NON-NLS-1$ + if ( this.getKeyStoreProvider().isEmpty()) { + System.clearProperty("javax.net.ssl.keyStoreProvider"); //$NON-NLS-1$ + } else { + if (this.getKeyStoreType().equalsIgnoreCase("PKCS12")) { //$NON-NLS-1$ + System.clearProperty("javax.net.ssl.keyStoreProvider"); //$NON-NLS-1$ + } else { + System.setProperty("javax.net.ssl.keyStoreProvider", this.getKeyStoreProvider()); //$NON-NLS-1$ + } + } + } else { + System.clearProperty("javax.net.ssl.keyStoreProvider"); //$NON-NLS-1$ + } + + if ( this.getKeyStorePassword() != null) { + System.setProperty("javax.net.ssl.keyStorePassword", getKeyStorePassword()); //$NON-NLS-1$ + } else { + System.clearProperty("javax.net.ssl.keyStorePassword"); //$NON-NLS-1$ + } + } catch(Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PKIProperties.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PKIProperties.java new file mode 100644 index 00000000000..e32567f8667 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PKIProperties.java @@ -0,0 +1,201 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.pkiselection; + +import java.net.Authenticator; +import java.net.PasswordAuthentication; +import java.util.Optional; + +import org.eclipse.core.pki.util.LogUtil; +//import org.eclipse.core.runtime.IStatus; +//import org.eclipse.core.runtime.Status; + +public class PKIProperties extends Authenticator { + + + private String keyStore = ""; //$NON-NLS-1$ + private String keyStoreType = ""; //$NON-NLS-1$ + private String keyStoreProvider = ""; //$NON-NLS-1$ + private String username = null; + private transient String keyStorePassword = ""; //$NON-NLS-1$ + private static PKI lastPKI=null; + private static PKIProperties sslProperties=null; + public static PKIProperties getNewInstance() { + return new PKIProperties(); + } + public static PKIProperties getInstance() { + if ( sslProperties == null ) { + synchronized(PKIProperties.class) { + if ( sslProperties == null ) { + sslProperties = new PKIProperties(); + try { + sslProperties.load(); + } catch(Exception ignoreException) { + ignoreException.printStackTrace(); + } + } + } + } + return sslProperties; + } + private PKIProperties() {} + @Override + public PasswordAuthentication getPasswordAuthentication() { + PasswordAuthentication auth = null; + + try { + auth = new PasswordAuthentication(this.getUsername(), this.getKeyStorePassword().toCharArray() ); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return auth; + } + public String getKeyStore() { + return keyStore; + } + public void setKeyStore(String keyStore) { + this.keyStore = keyStore; + } + public String getKeyStoreType() { + return keyStoreType; + } + public void setKeyStoreType(String keyStoreType) { + this.keyStoreType = keyStoreType; + } + public String getKeyStoreProvider() { + return keyStoreProvider; + } + public void setKeyStoreProvider(String keyStoreProvider) { + this.keyStoreProvider = keyStoreProvider; + } + public String getKeyStorePassword() { + return keyStorePassword; + } + public void setKeyStorePassword(String keyStorePassword) { + this.keyStorePassword = keyStorePassword; + } + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + public void restore() { + // System.out.println("PKIProperties - restore"); //$NON-NLS-1$ + try { + if (( this.getKeyStore() != null ) && + ( this.getKeyStoreType() != null ) && + ( this.getKeyStoreProvider() != null) && + ( this.getKeyStorePassword() != null) ) { + + if ( !(this.getKeyStore().isEmpty()) ) { + System.setProperty("javax.net.ssl.keyStore", this.getKeyStore()); //$NON-NLS-1$ + } + + if ( !(this.getKeyStoreType().isEmpty()) ) { + System.setProperty("javax.net.ssl.keyStoreType", this.getKeyStoreType()); //$NON-NLS-1$ + } + + if ( !(this.getKeyStoreProvider().isEmpty() )) { + System.setProperty("javax.net.ssl.keyStoreProvider", this.getKeyStoreProvider()); //$NON-NLS-1$ + } + + if ( !(this.getKeyStorePassword().isEmpty() )) { + if ( lastPKI != null ) { + if ( lastPKI.getKeyStorePassword().isEmpty() ) { + System.clearProperty("javax.net.ssl.keyStorePassword"); //$NON-NLS-1$ + } + } else { + System.setProperty("javax.net.ssl.keyStorePassword", getKeyStorePassword()); //$NON-NLS-1$ + } + } + } else { + clear(); + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + public void load() { + Optional keyStoreType = null; + Optional keyStore = null; + Optional keyStorePassword = null; + Optional keyStoreProvider = null; + LogUtil.logInfo("PKIProperties loading...."); + keyStore = Optional.ofNullable(System.getProperty("javax.net.ssl.keyStore")); //$NON-NLS-1$ + if (keyStore.isEmpty()) { + sslProperties.setKeyStore(""); //$NON-NLS-1$ + } else { + // LogUtil.logInfo("PKIProperties keystorePKI" + + // System.getProperty("javax.net.ssl.keyStore")); //$NON-NLS-1$ //$NON-NLS-2$ + sslProperties.setKeyStore(keyStore.get().toString()); + } + + keyStoreType = Optional.ofNullable(System.getProperty("javax.net.ssl.keyStoreType")); //$NON-NLS-1$ + if (keyStoreType.isEmpty()) { + sslProperties.setKeyStoreType(""); //$NON-NLS-1$ + } else { + sslProperties.setKeyStoreType(keyStoreType.get().toString()); + } + keyStoreProvider = Optional.ofNullable(System.getProperty("javax.net.ssl.keyStoreProvider")); //$NON-NLS-1$ + if (keyStoreProvider.isEmpty()) { + sslProperties.setKeyStoreProvider(""); //$NON-NLS-1$ + } else { + sslProperties.setKeyStoreProvider(keyStoreType.get().toString()); + if (sslProperties.getKeyStoreType().equalsIgnoreCase("pkcs12")) {//$NON-NLS-1$ + System.clearProperty("javax.net.ssl.keyStoreProvider"); //$NON-NLS-1$ + sslProperties.setKeyStoreProvider(""); //$NON-NLS-1$ + } + } + + + keyStorePassword = Optional.ofNullable(System.getProperty("javax.net.ssl.keyStorePassword")); //$NON-NLS-1$ + if (keyStoreType.isEmpty()) { + sslProperties.setKeyStorePassword(""); //$NON-NLS-1$ + } else { + sslProperties.setKeyStorePassword(keyStorePassword.get().toString()); + } + + sslProperties.setUsername(System.getProperty("user.name")); //$NON-NLS-1$ + } + public void setLastPkiValue( PKI pki ) { + lastPKI = pki; + } + public void clear() { + // System.out.println("PKIProperties - CLESAR ALL PROPR"); //$NON-NLS-1$ + System.clearProperty("javax.net.ssl.keyStoreProvider"); //$NON-NLS-1$ + System.clearProperty("javax.net.ssl.keyStore"); //$NON-NLS-1$ + System.clearProperty("javax.net.ssl.keyStoreProvider"); //$NON-NLS-1$ + System.clearProperty("javax.net.ssl.keyStorePassword"); //$NON-NLS-1$ + } + public void dump() { + StringBuffer sb = new StringBuffer(); + sb.append("javax.net.ssl.keyStore="); //$NON-NLS-1$ + sb.append(sslProperties.getKeyStore()); + sb.append("\n"); //$NON-NLS-1$ + sb.append("javax.net.ssl.keyStoreType="); //$NON-NLS-1$ + sb.append(sslProperties.getKeyStoreType()); + sb.append("\n"); //$NON-NLS-1$ + sb.append("javax.net.ssl.keyStoreProvider="); //$NON-NLS-1$ + sb.append(sslProperties.getKeyStoreProvider()); + sb.append("\n"); //$NON-NLS-1$ + + // Status status = new Status(IStatus.INFO, sb.toString(), null); + LogUtil.logInfo(sb.toString()); + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PkiPasswordDialog.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PkiPasswordDialog.java new file mode 100644 index 00000000000..c25ee84721b --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PkiPasswordDialog.java @@ -0,0 +1,207 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.pkiselection; + +import java.util.Optional; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Display; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.widgets.MessageBox; +//import org.eclipse.swt.widgets.Dialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.internal.Callback; +import org.eclipse.core.pki.auth.ContextObservable; +import org.eclipse.core.pki.auth.PublishPasswordUpdate; +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.core.pki.util.KeyStoreManager; +import org.eclipse.core.pki.util.KeyStoreFormat; + +public class PkiPasswordDialog extends Dialog implements Runnable { + + protected Object result; + protected Shell shell; + protected Text passwdField; + protected String pw = null; + boolean uninitialzed = true; + boolean isReady = true; + ContextObservable observable = null; + //PublishPasswordUpdateImpl publisher = null; + + //public PkiPasswordDialog(Shell parent, ContextObservable ob,PublishPasswordUpdate pwu ) { + public PkiPasswordDialog(Shell parent, ContextObservable ob) { + super(parent); + observable = ob; + //publisher=pwu; + // LogUtil.logWarning("PkiPasswordDialog CONSTRUCTOR"); + // Display.getDefault().asyncExec(this); + Display.getDefault().asyncExec(this); // main thread waits + } + + @Override + protected void okPressed() { + Optional keystoreContainer = null; + // LogUtil.logWarning("PkiPasswordDialog OK pressed"); + String _passphrase = passwdField.getText(); + // LogUtil.logWarning("PkiPasswordDialog OK pressed TEXT:"+_passphrase); + if (_passphrase == null || _passphrase.length() == 0) { + return; + } + pw = _passphrase; + System.setProperty("javax.net.ssl.keyStorePassword", pw); //$NON-NLS-1$ + keystoreContainer = Optional + .ofNullable(KeyStoreManager.INSTANCE.getKeyStore(System.getProperty("javax.net.ssl.keyStore"), //$NON-NLS-1$ + System.getProperty("javax.net.ssl.keyStorePassword"), //$NON-NLS-1$ + KeyStoreFormat.valueOf(System.getProperty("javax.net.ssl.keyStoreType")))); //$NON-NLS-1$ + if ((keystoreContainer.isEmpty()) || (!(KeyStoreManager.INSTANCE.isKeyStoreInitialized()))) { + passwdField.setText(""); + MessageBox boxDialog = new MessageBox(shell, SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL); + boxDialog.setText("Password Error Message"); + boxDialog.setMessage("The password you entered is incorrect?"); + System.clearProperty("javax.net.ssl.keyStorePassword"); //$NON-NLS-1$ + int returnCode = boxDialog.open(); + } else { + PublishPasswordUpdate.INSTANCE.publishMessage(pw); + observable.onchange(pw); + setReturnCode(OK); + super.okPressed(); + + close(); + } + } + + @Override + protected void cancelPressed() { + // LogUtil.logWarning("PkiPasswordDialog CANCEL pressed"); + pw = null; + super.cancelPressed(); + close(); + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + + Font font = new Font(shell.getDisplay(), new FontData("Arial", 25, SWT.BOLD)); + shell.setFont(font); + shell.setText("PKCS12 PKI Password Input Field"); + + // LogUtil.logWarning("PkiPasswordDialog configureShell"); + } + + @Override + public void create() { + super.create(); + passwdField.setFocus(); + // LogUtil.logWarning("PkiPasswordDialog create"); + } + + public String getPW() { + // LogUtil.logWarning("PkiPasswordDialog getPW"); + return pw; + } + + protected Control createDialogArea(Composite parent) { + // LogUtil.logWarning("PkiPasswordDialog createDialogArea"); + initializeDialogUnits(parent); + // Composite main = new Composite(parent, SWT.NONE); + Composite main = new Composite(parent, SWT.BORDER); + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 5; + gridLayout.marginTop = 20; + // main.setSize(800, 500); + main.setLayout(gridLayout); + main.setLayoutData(new GridData(GridData.FILL_BOTH)); + // main.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); + // main.pack(); + setup(main); + Dialog.applyDialogFont(main); + + return main; + + } + + public void run() { + // LogUtil.logWarning("PkiPasswordDialog run methid top"); + try { + if (uninitialzed) { + uninitialzed = false; + this.create(); + shell = createShell(); + shell.layout(); + // configureShell(shell); + Control control = createDialogArea(getContents().getParent()); + + control.pack(); + + // LogUtil.logWarning("PkiPasswordDialog run methid NOW OPEN"); + + open(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + protected Point getInitialSize() { + return new Point(500, 200); + } + + public void setup(Composite parent) { + if (isReady) { + isReady = false; + // LogUtil.logWarning("PkiPasswordDialog setup"); + + passwdField = new Text(parent, SWT.SINGLE | SWT.BORDER | SWT.PASSWORD); + passwdField.setTextLimit(25); + Font font = new Font(parent.getDisplay(), new FontData("Arial", 12, SWT.BOLD)); + passwdField.setFont(font); + + passwdField.setText(""); + passwdField.setEchoChar('*'); + GridData data = new GridData(GridData.BEGINNING, GridData.FILL, false, false); + data.widthHint = 130; + passwdField.setLayoutData(data); + + Button button = new Button(parent, SWT.PUSH); + button.setText("Show Password"); + + Label labelInfo = new Label(parent, SWT.NONE); + labelInfo.setText("*"); + + button.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + // LogUtil.logWarning("PkiPasswordDialog WIDGET pressed"); + labelInfo.setText(passwdField.getText()); + labelInfo.pack(); + } + }); + + } + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PkiPasswordGrabberWidget.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PkiPasswordGrabberWidget.java new file mode 100644 index 00000000000..d2ddaba5a56 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PkiPasswordGrabberWidget.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.pkiselection; + +import java.util.Optional; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.SwingConstants; + +import org.eclipse.core.pki.auth.PublishPasswordUpdate; +import org.eclipse.core.pki.util.KeyStoreFormat; +import org.eclipse.core.pki.util.KeyStoreManager; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; + +public enum PkiPasswordGrabberWidget { + INSTANCE; + JFrame frame = null; + Icon icon = null; + + JPasswordField pword = null; + + public String getInput() { + + //PublishPasswordUpdateImpl publisher = PublishPasswordUpdateImpl.getInstance(); + + Optional keystoreContainer = null; + JPanel panel = new JPanel(); + JLabel label = new JLabel("Enter Password:"); + JLabel blankie = new JLabel("\n", SwingConstants.CENTER); + pword = new JPasswordField(17); + String pw=null; + panel.add(label); + panel.add(blankie); + panel.add(pword); + try { + + icon = new ImageIcon(getClass().getResource("/icons/icons8-password-48.png")); + } catch (Exception iconErr) { + //iconErr.printStackTrace(); + } + + panel.requestFocus(); + char[] password = null; + while (true) { + String[] options = new String[] {"cancel", "submit"}; + + //showOptionDialog(Component parentComponent, + // Object message, String title, int optionType, + // int messageType, Icon icon, Object[] options, + // Object initialValue) + + int option = JOptionPane.showOptionDialog(null, panel, "Eclipse PKI Password/PiN Entry", + JOptionPane.INFORMATION_MESSAGE, JOptionPane.PLAIN_MESSAGE, + icon, options, options[1]); + + //System.out.println("Your ENTRY OPTION is: " + option); + + if (option == 0) { + //System.out.println("PkiPasswordGrabberWidget CANCEL value NO_OPTION "); + JOptionPane.showMessageDialog(null,"CANCELED",null, + JOptionPane.ERROR_MESSAGE); + + break; + } else if(option == 1) { + password = pword.getPassword(); + pw=new String(password); + //System.out.println("Your password is: " + new String(password)); + + System.setProperty("javax.net.ssl.keyStorePassword", pw); //$NON-NLS-1$ + + keystoreContainer = Optional + .ofNullable(KeyStoreManager.INSTANCE.getKeyStore(System.getProperty("javax.net.ssl.keyStore"), //$NON-NLS-1$ + System.getProperty("javax.net.ssl.keyStorePassword"), //$NON-NLS-1$ + KeyStoreFormat.valueOf(System.getProperty("javax.net.ssl.keyStoreType")))); //$NON-NLS-1$ + if ((keystoreContainer.isEmpty()) || (!(KeyStoreManager.INSTANCE.isKeyStoreInitialized()))) { + JOptionPane.showMessageDialog(null,"Incorrect Password",null, + JOptionPane.ERROR_MESSAGE); + System.clearProperty("javax.net.ssl.keyStorePassword"); //$NON-NLS-1$ + pword.setText(""); + } else { + //System.out.println("Your password is GOOD"); + PublishPasswordUpdate.INSTANCE.publishMessage(pw); + break; + } + } else { + System.out.println("wtf"); + break; + } + + } + return pw; + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PkiPasswordInputUI.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PkiPasswordInputUI.java new file mode 100644 index 00000000000..f13583e2b2b --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/PkiPasswordInputUI.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.pkiselection; + +import java.lang.reflect.*; +import java.util.concurrent.Flow.Subscriber; +import org.eclipse.swt.widgets.Dialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +import org.eclipse.core.pki.auth.PublishPasswordUpdate; +import org.eclipse.core.pki.auth.ContextObservable; +import org.eclipse.core.pki.auth.PasswordObserver; +import org.eclipse.core.pki.util.LogUtil; + +public enum PkiPasswordInputUI { + DO; + PkiPasswordDialog dialog=null; + String passwordString = "NOPASSWD"; + + public String get() { + // prompt for password + //System.out.println("PkiPasswordInputUI get method running"); + //LogUtil.logWarning("PkiPasswordInputUI - get method running"); //$NON-NLS-1$ + /* + * Display.getDefault().asyncExec(new Runnable() { + * + * @Override public void run() { + * System.out.println("PkiPasswordInputUI RUN RUN RUN RUN"); dialog = new + * PkiPasswordDialog(null); if (dialog.open() == 0) { passwordString = + * dialog.getPW(); } } }); + */ + //Display.getDefault().asyncExec(runner); + + + ContextObservable ob = new ContextObservable(); + //PublishPasswordUpdateImpl up = PublishPasswordUpdateImpl.getInstance(); + + PasswordObserver observer = new PasswordObserver(); + + try { + Class pubClass = Class.forName("org.eclipse.ecf.internal.ssl.ECFpwSubscriber"); //$NON-NLS-1$ + Constructor constructor = pubClass.getDeclaredConstructor(); + constructor.setAccessible(true); + Object obj = constructor.newInstance(); + try { + Subscriber ecfSubscriber = (Subscriber) obj; + PublishPasswordUpdate.INSTANCE.subscribe(ecfSubscriber); + } catch (Exception e) { + + LogUtil.logError("PkiPasswordInputUI - ECF Object Failed", e); //$NON-NLS-1$ + } + LogUtil.logInfo("PkiPasswordInputUI - Loaded ECF SUBSCRIBER."); //$NON-NLS-1$ + } catch (Exception e) { + + LogUtil.logError("PkiPasswordInputUI - Cant get ECF:", e); //$NON-NLS-1$ + } + PublishPasswordUpdate.INSTANCE.subscribe(observer); + ob.addObserver(observer); + //dialog=new PkiPasswordDialog(null, ob, PublishPasswordUpdate); + dialog=new PkiPasswordDialog(null, ob); + passwordString=dialog.getPW(); + passwordString = "NOPASSWD"; + return passwordString; + } + public void set(String pw) { + //LogUtil.logWarning("PkiPasswordInputUI - set method running"); //$NON-NLS-1$ + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/SecurityOpRequest.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/SecurityOpRequest.java new file mode 100644 index 00000000000..c2ff76a02c8 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/pkiselection/SecurityOpRequest.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2014 Codetrails GmbH. + * 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: + * Delmarva Security - implementation. + */ +package org.eclipse.core.pki.pkiselection; + +public enum SecurityOpRequest { + INSTANCE; + public boolean isConnected=false; + + public boolean getConnected() { + return isConnected; + } + public void setConnected(boolean b) { + isConnected=b; + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/ConfigureTrust.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/ConfigureTrust.java new file mode 100644 index 00000000000..f248a60d892 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/ConfigureTrust.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2023 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.core.pki.util; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Optional; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +public enum ConfigureTrust implements X509TrustManager { + MANAGER; + + protected X509TrustManager pkixTrustManager = null; + + public Optional setUp() { + KeyStore keyStore = null; + String storeLocation = null; + String trustType = null; + String passwd = "changeit"; //$NON-NLS-1$ + try { + Optional trustStoreFile = Optional.ofNullable(System.getProperty("javax.net.ssl.trustStore")); //$NON-NLS-1$ + if (trustStoreFile.isEmpty()) { + storeLocation = System.getProperty("java.home") + //$NON-NLS-1$ + "/lib/security/cacerts" //$NON-NLS-1$ + .replace("/", FileSystems.getDefault().getSeparator()); //$NON-NLS-1$ + } else { + storeLocation = trustStoreFile.get().toString(); + } + //FileInputStream fs = new FileInputStream(storeLocation); + + InputStream fs = Files.newInputStream(Paths.get(storeLocation)); + + Optional trustStoreFileType = Optional + .ofNullable(System.getProperty("javax.net.ssl.trustStoreType")); //$NON-NLS-1$ + if (trustStoreFileType.isEmpty()) { + trustType = KeyStore.getDefaultType(); + } else { + trustType = trustStoreFileType.get().toString(); + } + keyStore = KeyStore.getInstance(trustType); + + Optional trustStorePassword = Optional + .ofNullable(System.getProperty("javax.net.ssl.trustStorePassword")); //$NON-NLS-1$ + if (trustStorePassword.isEmpty()) { + LogUtil.logInfo("ConfigureTrust using default Password since none provided."); + passwd="changeit"; + } else { + passwd = trustStorePassword.get().toString(); + } + + keyStore.load(fs, passwd.toCharArray()); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); //$NON-NLS-1$ + tmf.init(keyStore); + TrustManager tms[] = tmf.getTrustManagers(); + for (TrustManager tm : tms) { + if (tm instanceof X509TrustManager) { + pkixTrustManager = (X509TrustManager) tm; + LogUtil.logInfo("Initialization PKIX Trust Manager Complete"); //$NON-NLS-1$ + break; + } + } + + + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + LogUtil.logError("ConfigureTrust - No algorythm found, ", e); //$NON-NLS-1$ + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + LogUtil.logError("ConfigureTrust - Initialize keystore Error, ", e); //$NON-NLS-1$ + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + LogUtil.logError("ConfigureTrust - No File Found:", e); //$NON-NLS-1$ + } catch (CertificateException e) { + // TODO Auto-generated catch block + LogUtil.logError("ConfigureTrust - Certificate Error", e); //$NON-NLS-1$ + } catch (IOException e) { + // TODO Auto-generated catch block + LogUtil.logError("ConfigureTrust - I/O Error, bad password?", e); //$NON-NLS-1$ + } + return Optional.ofNullable(pkixTrustManager); + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + // TODO Auto-generated method stub + pkixTrustManager.checkClientTrusted(chain, authType); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + // TODO Auto-generated method stub + pkixTrustManager.checkServerTrusted(chain, authType); + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + // TODO Auto-generated method stub + return pkixTrustManager.getAcceptedIssuers(); + + } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/DotPkiPropertiesRequired.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/DotPkiPropertiesRequired.java new file mode 100644 index 00000000000..066030f95fd --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/DotPkiPropertiesRequired.java @@ -0,0 +1,76 @@ +package org.eclipse.core.pki.util; + +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.Properties; +import java.util.Set; + +public enum DotPkiPropertiesRequired { + CHECKER; + List list = get(); + public boolean testFile(Path path) { + Properties properties=new Properties(); + //System.out.println("DotPkiPropertiesRequired testFile:"+path.toString()); + try { + if (Files.exists(path)) { + final FileChannel channel = FileChannel.open(path, StandardOpenOption.READ); + final FileLock lock = channel.lock(0L, Long.MAX_VALUE, true); + properties.load(Channels.newInputStream(channel)); + Set keys=properties.keySet(); + lock.close(); + for ( Object key: keys ) { + isProperty((String)key); + } + if ( list.isEmpty()) { + //System.out.println("DotPkiPropertiesRequired All proeprties exist:"+list.size()); + return true; + } else { + Optional pkiType = Optional.ofNullable(properties.get("javax.net.ssl.keyStoreType")); + if ( !(pkiType.isEmpty())) { + if (pkiType.get().toString().contains("12")) { //PKCS12 type. no cfg needed, no provider needed + isProperty("javax.net.ssl.cfgFileLocation"); + isProperty("javax.net.ssl.keyStoreProvider"); + } + } + if (!(list.isEmpty())) { + LogUtil.logWarning("Missing properies;"+ list.toString()); + } else { + return true; + } + } + } else { + LogUtil.logWarning("DotPkiPropertiesRequired- NO PKI file detected"); + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return false; + } + private void isProperty(String s) { + if ( list.contains(s)) { + list.remove(s); + } + + } + private List get() { + List l = new LinkedList(); + l = Arrays.asList("javax.net.ssl.trustStore","javax.net.ssl.trustStoreType", + "javax.net.ssl.trustStorePassword","javax.net.ssl.keyStoreType", + "javax.net.ssl.keyStoreProvider","javax.net.ssl.cfgFileLocation", + "javax.net.ssl.keyStore"); + List list = new ArrayList(l); + return list; + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/ExpiredCertCheck.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/ExpiredCertCheck.java new file mode 100644 index 00000000000..fc9e7117569 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/ExpiredCertCheck.java @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.util; + + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509Certificate; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Enumeration; + +import javax.security.auth.x500.X500Principal; + + +public enum ExpiredCertCheck { + INSTANCE; + + // private String expiredDN=null; + public String getDate(String userKeyStoreLocation, char[] pin ) { + KeyStore keyStore = getStore(userKeyStoreLocation, pin); + ExpiredX509CertificateData expiredCert=null; + ArrayList expiredCertList=new ArrayList<>(); + // Date today = Calendar.getInstance().getTime(); + String expirationDate = null; + try { + Enumeration aliasesEnum = keyStore.aliases(); + while (aliasesEnum.hasMoreElements()) { + String alias = aliasesEnum.nextElement(); + //System.out.println("ALIAS:"+ alias); + X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); + Date goodUntil = certificate.getNotAfter(); + DateFormat sdf = DateFormat.getDateInstance(); + expirationDate = sdf.format(goodUntil); + //System.out.println("EXPIRATION:"+ expirationDate); + + try { + certificate.checkValidity(); + } catch (CertificateExpiredException e) { + BigInteger sn = certificate.getSerialNumber(); + X500Principal subject = certificate.getSubjectX500Principal(); + X500Principal issuer = certificate.getIssuerX500Principal(); + expiredCert = new ExpiredX509CertificateData(); + expiredCert.setAlias(alias); + expiredCert.setCertLocation(userKeyStoreLocation); + expiredCert.setExpirationDate(expirationDate); + expiredCert.setDistinguishedName(subject.getName()); + expiredCert.setIssuedBy(issuer.getName()); + expiredCert.setSerialNumber(sn.toString()); + + // TODO Auto-generated catch block + //e.printStackTrace(); + //System.out.println("ExpiredCertCheck found an Expired Cert"); + // IStatus status = new Status (IStatus.WARNING, + // AuthenticationPlugin.getPluginId()," EXPIRED CERT..."+expirationDate); + // ILog logger = Platform.getLog(this.getClass()); + // logger.log(status); + } catch (CertificateNotYetValidException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + expiredCertList.add(expiredCert); + + } + + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } +// IWorkspace workspace = ResourcesPlugin.getWorkspace(); +// IResource resource = workspace.getRoot(); +// +// try { +// IMarker[] markers = resource.findMarkers(IMarker.MARKER, true, IResource.SHALLOW); +// for (IMarker m : markers) { +// //System.out.println("ExpiredCertCheck - MARKER MSG:" + m.getAttribute(IMarker.MESSAGE)); +// if ( m.getAttribute(IMarker.MESSAGE).toString().contains("DN")) { +// expiredDN = new String("EXPIRED"); +// } +// } +// +// +// if ( expiredDN == null ) { +// IMarker marker = null; +// ExpiredX509CertificateData data = null; +// for (Object d : expiredCertList.toArray()) { +// data = (ExpiredX509CertificateData) d; +// marker = resource.createMarker(IMarker.PROBLEM); +// marker.setAttribute(IMarker.MESSAGE, "Expired Certificate in your KeyStore;"); +// marker.setAttribute(IMarker.LOCATION, data.getCertLocation()); +// marker = resource.createMarker(IMarker.PROBLEM); +// marker.setAttribute(IMarker.MESSAGE, "DN:" + data.getDistinguishedName()); +// marker = resource.createMarker(IMarker.PROBLEM); +// marker.setAttribute(IMarker.MESSAGE, "EXPIRATION DATE:" + data.getExpirationDate()); +// } +// } +// +// } catch (CoreException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + return ("EXPIRATION:" + expirationDate); //$NON-NLS-1$ + } + public KeyStore getStore(String userKeyStoreLocation, char[] pin) { + KeyStore keyStore=null; + try { + FileInputStream fis = new FileInputStream(userKeyStoreLocation); + keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(fis, pin); + + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (CertificateException e) { + // TODO Auto-generated catch block + System.out.println("ExpiredCertCheck found an Expired Cert"); //$NON-NLS-1$ + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return keyStore; + + } + +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/ExpiredX509CertificateData.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/ExpiredX509CertificateData.java new file mode 100644 index 00000000000..a47f98f7021 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/ExpiredX509CertificateData.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.util; + +public class ExpiredX509CertificateData { + private String alias; + private String certLocation; + private String distinguishedName; + private String expirationDate; + private String issuedBy; + private String serialNumber; + + public ExpiredX509CertificateData() {} + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public String getCertLocation() { + return certLocation; + } + + public void setCertLocation(String certLocation) { + this.certLocation = certLocation; + } + + public String getDistinguishedName() { + return distinguishedName; + } + + public void setDistinguishedName(String distinguishedName) { + this.distinguishedName = distinguishedName; + } + + public String getExpirationDate() { + return expirationDate; + } + + public void setExpirationDate(String expirationDate) { + this.expirationDate = expirationDate; + } + + public String getIssuedBy() { + return issuedBy; + } + + public void setIssuedBy(String issuedBy) { + this.issuedBy = issuedBy; + } + + public String getSerialNumber() { + return serialNumber; + } + + public void setSerialNumber(String serialNumber) { + this.serialNumber = serialNumber; + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/KeyStoreFormat.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/KeyStoreFormat.java new file mode 100644 index 00000000000..578d31ac88b --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/KeyStoreFormat.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.util; + +public enum KeyStoreFormat +{ + JKS("JKS"), //$NON-NLS-1$ + PKCS12("PKCS12"), //$NON-NLS-1$ + PKCS11("PKCS11"); //$NON-NLS-1$ + + private String value; + + KeyStoreFormat (String value) + { + this.value = value; + } + + public String getValue() + { + return value; + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/KeyStoreManager.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/KeyStoreManager.java new file mode 100644 index 00000000000..00481ffe4c2 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/KeyStoreManager.java @@ -0,0 +1,487 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.util; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.Socket; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Principal; +import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Optional; + +import javax.net.ssl.X509KeyManager; + +import org.eclipse.core.pki.FingerprintX509; + +//import sun.security.pkcs11.wrapper.PKCS11Exception; + +public enum KeyStoreManager implements X509KeyManager { + INSTANCE; + + protected final int KEY_ENCIPHERMENT = 2; + protected final int DIGITAL_SIGNATURE = 0; + protected boolean isKeyStoreInitialized = false; + protected String selectedFingerprint = "NOSET"; //$NON-NLS-1$ + protected KeyStore keyStore = null; + + public KeyStore getKeyStore(String fileLocation, String password, KeyStoreFormat format) { + InputStream in = null; + try { + + try { + // NOT FIPS complient + //in = new FileInputStream(fileLocation); + //in = new BufferedInputStream(in); + + Path p = Paths.get(fileLocation); + in = Files.newInputStream(p); + + keyStore = KeyStore.getInstance(format.getValue()); + keyStore.load(in, password.toCharArray()); + + setKeyStoreInitialized(true); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + LogUtil.logError("Configure KeyStore - No File Found:", e); //$NON-NLS-1$ + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + LogUtil.logError("Configure KeyStore - Initialize keystore, bad password? ", e); //$NON-NLS-1$ + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + LogUtil.logError("Configure KeyStore - No algorythm found, ", e); //$NON-NLS-1$ + } catch (CertificateException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + LogUtil.logError("Configure KeyStore - Certificate Error", e); //$NON-NLS-1$ + } catch (IOException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + LogUtil.logError("Configure KeyStore - I/O Error, bad password?", e); //$NON-NLS-1$ + } + if ( keyStore != null) { + return keyStore; + } + return null; + } finally { + try { + in.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + /** + * Returns a KeyStore object loaded from provided {@link InputStream} and decrypted with given password + * @param in + * @param password + * @param format "JKS", "PKCS12", "PKCS11" + * @throws NoSuchAlgorithmException + * @throws CertificateException + * @throws IOException + */ + + public KeyStore getKeyStore(InputStream in, String password, KeyStoreFormat format) + throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { + + keyStore = KeyStore.getInstance(format.getValue()); + char pwd[] = null; + if(password != null) + pwd = password.toCharArray(); + + keyStore.load(in, pwd); + return keyStore; + + } + + public KeyStore getKeyStore(KeyStoreFormat format) + throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, NoSuchProviderException { + + String pin = ""; //$NON-NLS-1$ + KeyStore.PasswordProtection pp = new KeyStore.PasswordProtection(pin.toCharArray()); + keyStore = KeyStore.getInstance("pkcs11", "SunPKCS11"); //$NON-NLS-1$ //$NON-NLS-2$ + try { + keyStore.load(null, pp.getPassword()); + + setKeyStoreInitialized(true); + } catch (IOException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + //System.out.println("KeyStoreUtil ------ The user elected to press cancel, KEYSOTRE is NOT initialized."); + keyStore = null; + } + return keyStore; + } + + public KeyStore getKeyStore() { + return keyStore; + } + public void setKeyStore(KeyStore keyStore) { + this.keyStore=keyStore; + setKeyStoreInitialized(true); + } + + public Hashtable getCertificates(KeyStore keyStore) { + + Hashtable table = new Hashtable<>(); + PrivateKey privateKey=null; + + try { + if (isKeyStoreInitialized()) { + Enumeration aliasesEnum = keyStore.aliases(); + while (aliasesEnum.hasMoreElements()) + { + String alias = aliasesEnum.nextElement(); + X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); + try { + if ( isDigitalSignature(certificate.getKeyUsage()) ) { + privateKey = (PrivateKey) keyStore.getKey(alias, null); + if ( privateKey != null) { + table.put(certificate, privateKey); + } + } + } catch (UnrecoverableKeyException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return table; + + } + + public ArrayList getAliases(KeyStore keyStore) { + + ArrayListaliasList = new ArrayList<>(); + // PrivateKey privateKey=null; + try { + Enumeration aliasesEnum = keyStore.aliases(); + while (aliasesEnum.hasMoreElements()) + { + String alias = aliasesEnum.nextElement(); + X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); + try { + if ( isDigitalSignature(certificate.getKeyUsage()) ) { +// privateKey = (PrivateKey) keyStore.getKey(alias, null); +// if ( privateKey != null) { +// aliasList.add(alias); +// } + aliasList.add(alias); + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + //System.out.println("END OF WHILE STATUEM"); + } + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return aliasList; + + } + public boolean checkUserKeystorePass(String certPath, String password, String certType) + { + StringBuilder message = new StringBuilder(); + message.append("Problem reading your certificate. \n\r \n\r"); //$NON-NLS-1$ + + KeyStore keyStore; + try { + InputStream in = null; + + in = new FileInputStream(certPath); + in = new BufferedInputStream(in); + + keyStore = KeyStore.getInstance(certType); + char pwd[] = null; + if (password != null) + pwd = password.toCharArray(); + + keyStore.load(in, pwd); + + getAliases(keyStore); + return true; + + } catch (KeyStoreException e) { + message.append("The selected file does not appear "); //$NON-NLS-1$ + message.append("to be a valid PKCS file. Please "); //$NON-NLS-1$ + message.append("select a different file and/or "); //$NON-NLS-1$ + message.append("check the logs for more information."); //$NON-NLS-1$ + System.err.printf("%s\n", message.toString()); //$NON-NLS-1$ + } catch (NoSuchAlgorithmException e) { + message.append("An unexpected error '"); //$NON-NLS-1$ + message.append(e.getClass().getName()); + message.append("' occurred: "); //$NON-NLS-1$ + message.append(e.getMessage()); + message.append(" Please select a different file and/or "); //$NON-NLS-1$ + message.append("check the logs for more information."); //$NON-NLS-1$ + System.err.printf("%s\n", message.toString()); //$NON-NLS-1$ + } catch (CertificateException e) { + message.append("Either your password was incorrect or the "); //$NON-NLS-1$ + message.append("the selected file is corrupt. Please try "); //$NON-NLS-1$ + message.append("a different password or PKCS file."); //$NON-NLS-1$ + System.err.printf("%s CertificateException: %s\n", message.toString(), e.getMessage()); //$NON-NLS-1$ + } catch (IOException e) { + if (e.getCause().toString().contains("FailedLoginException")) { //$NON-NLS-1$ + message.append("\tYou entered an incorrect password. \n\r"); //$NON-NLS-1$ + message.append("\tPlease check your password and re-enter it. \n\r \n\r"); //$NON-NLS-1$ + System.err.printf("%s IOException: %s\n", message.toString(), e.getMessage()); //$NON-NLS-1$ + } else { + + message.append("Either your password was incorrect or the "); //$NON-NLS-1$ + message.append("selected file is corrupt. Please try "); //$NON-NLS-1$ + message.append("a different password or PKCS file."); //$NON-NLS-1$ + System.err.printf("%s IOException: %s\n", message.toString(), e.getMessage()); //$NON-NLS-1$ + } + } + + //System.out.println("KeyStoreUtil ----------checkUserKeystorePass NEEDS TO RETURN FALSE and its NOT"); + return false; + } + + @Override + public String[] getClientAliases(String keyType, Principal[] issuers) { + // TODO Auto-generated method stub + return new String[] { chooseClientAlias(null, issuers, null) }; + } + + @Override + public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { + // TODO Auto-generated method stub + String message = "Presenting X509 fingerprint:"; //$NON-NLS-1$ + String amessage = " using certificate alias:"; //$NON-NLS-1$ + StringBuilder sb = new StringBuilder(); + String selectedAlias = "testX509"; + String alias = null; + String fingerprint = null; + boolean isOK = true; + + try { + + Enumeration aliases = this.keyStore.aliases(); + sb.append(message); + while (aliases.hasMoreElements()) { + alias = aliases.nextElement(); + //System.out.println("KeyManager - alias:"+alias); + LogUtil.logInfo(amessage+alias); + if (this.getPrivateKey(alias) != null) { + X509Certificate x509 = (X509Certificate) this.keyStore.getCertificate(alias); + try { + x509.checkValidity(); + if (!(isKeyEncipherment(x509.getKeyUsage()))) { + // selectedAlias=alias; + fingerprint = FingerprintX509.INSTANCE.getFingerPrint(x509, "SHA-256"); //$NON-NLS-1$ + //System.out.println("KeyManager - SELECTED finger:" + getSelectedFingerprint()); //$NON-NLS-1$ + // System.err.println("KeyManager - DUMP OUT DATA:"+info); + + if (getSelectedFingerprint() != null) { + if (getSelectedFingerprint().equals("NOTSET")) { //$NON-NLS-1$ + setSelectedFingerprint(fingerprint); + } + } else { + setSelectedFingerprint(fingerprint); + } + if (getSelectedFingerprint().equals(fingerprint)) { + isOK = true; + selectedAlias = alias; + sb.append(fingerprint); + sb.append(amessage); + sb.append(alias); + message = sb.toString(); + break; + } + } else { + System.err.println("KeyManager: Please verify keyEncipherment, maybe Test x509"); + selectedAlias = "testX509"; + } + } catch (CertificateExpiredException e) { + // TODO Auto-generated catch block + System.err.println("KeyManager: Please remove EXPIRED certificate:" + alias //$NON-NLS-1$ + + " using your pkcs11 Manager."); //$NON-NLS-1$ + // e.printStackTrace(); + } catch (CertificateNotYetValidException e) { + // TODO Auto-generated catch block + System.err.println("KeyManager: Please check invalid certificate:" + alias //$NON-NLS-1$ + + " using your pkcs11 Manager."); //$NON-NLS-1$ + // e.printStackTrace(); + } + } + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if (!(isOK)) { + message = (selectedAlias == null) ? "PKI misconfiguration. Please check " : message + selectedAlias; //$NON-NLS-1$ + System.out.println("KeyManager: " + message); //$NON-NLS-1$ + } + return selectedAlias; + } + + public boolean isKeyStoreInitialized() { + return isKeyStoreInitialized; + } + + private void setKeyStoreInitialized(boolean isKeyStoreInitialized) { + this.isKeyStoreInitialized = isKeyStoreInitialized; + } + + private boolean isDigitalSignature(boolean[] ba) { + if (ba != null) { + + return ba[DIGITAL_SIGNATURE]; + } else { + return false; + } + } + + private boolean isKeyEncipherment(boolean[] ba) { + if (ba != null) { + + return ba[KEY_ENCIPHERMENT]; + } else { + return false; + } + } + + @Override + public String[] getServerAliases(String keyType, Principal[] issuers) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { + // TODO Auto-generated method stub + return null; + } + + @Override + public X509Certificate[] getCertificateChain(String alias) { + // TODO Auto-generated method stub + X509Certificate[] X509Certs = null; + X509Certificate X509Cert = null; + try { + Certificate[] certificates = this.keyStore.getCertificateChain(alias); + if (certificates != null) { + X509Certs = new X509Certificate[certificates.length]; + for (int i = 0; i < certificates.length; i++) { + X509Cert = (X509Certificate) certificates[i]; + if (!(isKeyEncipherment(X509Cert.getKeyUsage()))) { + X509Certs[i] = X509Cert; + } else { + if ((isKeyEncipherment(X509Cert.getKeyUsage())) && alias.contains("PKI")) { //$NON-NLS-1$ + X509Certs[i] = X509Cert; + } + } + } + + } else { + X509Cert = (X509Certificate) this.keyStore.getCertificate(alias); + if (X509Cert != null) { + X509Certs = new X509Certificate[1]; + if (isDigitalSignature(X509Cert.getKeyUsage())) { + X509Certs[0] = X509Cert; + } else { + if (alias.contains("PKI")) { //$NON-NLS-1$ + X509Certs[0] = X509Cert; + } + } + } + + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + System.out.println("KeyStoreManager CERTIFICATE CHAIN COUNT:" + X509Certs.length); //$NON-NLS-1$ + // return X509Certs; + try { + X509Certs = new X509Certificate[1]; + X509Certs[0] = (X509Certificate) this.keyStore.getCertificate(alias); + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + System.out.println("CustomKeyManager CERTIFICATE CHAIN COUNT:" + X509Certs.length); //$NON-NLS-1$ + return X509Certs; + } + + public String getSelectedFingerprint() { + return selectedFingerprint; + } + + public void setSelectedFingerprint(String selectedFingerprint) { + this.selectedFingerprint = selectedFingerprint; + } + @Override + public PrivateKey getPrivateKey(String alias) { + // TODO Auto-generated method stub + PrivateKey privateKey = null; + try { + //System.out.println("KeyStoreManager - getPrivateKey ALIAS:"+alias); + String passwd = System.getProperty("javax.net.ssl.keyStorePassword"); + //System.out.println("KeyStoreManager - javax.net.ssl.keystorePassword:"+passwd); + privateKey = (PrivateKey) keyStore.getKey(alias, passwd.toCharArray()); //$NON-NLS-1$ + } catch (UnrecoverableKeyException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return privateKey; + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/LogUtil.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/LogUtil.java new file mode 100644 index 00000000000..1a3e664e8c3 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/LogUtil.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.pki.util; + +import org.eclipse.core.runtime.ILog; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.ServiceCaller; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugPlugin; + + +/** + * A logging utility class + */ +public class LogUtil { + + public static void logInfo(String message) { + StackWalker stackWalker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + final var pluginName = stackWalker.getCallerClass(); + final ServiceCaller log = new ServiceCaller<>(pluginName, ILog.class); + log.call(logger -> logger.info(message)); + } + public static void logError(String message, Throwable t) { + StackWalker stackWalker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + final var pluginName = stackWalker.getCallerClass(); + final ServiceCaller log = new ServiceCaller<>(pluginName, ILog.class); + log.call(logger -> logger.error(message)); + } + + public static void logWarning(String message) { + StackWalker stackWalker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + final var pluginName = stackWalker.getCallerClass(); + final ServiceCaller log = new ServiceCaller<>(pluginName, ILog.class); + IStatus status = new Status(IStatus.WARNING, pluginName.getPackageName(), message); + log.call(logger -> logger.warn(message)); + } + public static void logDebug(String message) { + StackWalker stackWalker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + final var pluginName = stackWalker.getCallerClass(); + final ServiceCaller log = new ServiceCaller<>(pluginName, DebugPlugin.class); + IStatus status = new Status(IStatus.WARNING, pluginName.getPackageName(), message); + log.call(logger -> DebugPlugin.logDebugMessage(message)); + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/NormalizeGCM.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/NormalizeGCM.java new file mode 100644 index 00000000000..a4498376b8d --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/NormalizeGCM.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2024 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.core.pki.util; + +import java.security.spec.KeySpec; +import java.util.Arrays; +import java.util.Base64; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; + +public enum NormalizeGCM { + DECRYPT; + + private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding"; //$NON-NLS-1$ + private static final String FACTORY_INSTANCE = "PBKDF2WithHmacSHA512"; //$NON-NLS-1$ + private static final int GCM_IV_LENGTH = 12; + private static final int KEY_LENGTH = 256; + private static final int ITERATION_COUNT = 65536; + public String decrypt(String strToDecrypt, String secretKey, String salt) { + try { + byte[] encryptedData = Base64.getDecoder().decode(strToDecrypt); + byte[] initVector = Arrays.copyOfRange(encryptedData, 0, GCM_IV_LENGTH); + GCMParameterSpec spec = new GCMParameterSpec(KEY_LENGTH / 2, initVector); + SecretKeyFactory factory = SecretKeyFactory.getInstance(FACTORY_INSTANCE); + KeySpec keySpec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), ITERATION_COUNT, KEY_LENGTH); + SecretKey tmp = factory.generateSecret(keySpec); + SecretKeySpec secretKeySpec = new SecretKeySpec(tmp.getEncoded(), "AES"); //$NON-NLS-1$ + Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, spec); + byte[] decryptedText = cipher.doFinal(encryptedData, GCM_IV_LENGTH, encryptedData.length - GCM_IV_LENGTH); + return new String(decryptedText, "UTF-8"); //$NON-NLS-1$ + } catch (Exception e) { + // Handle the exception properly + e.printStackTrace(); + return null; + } + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/SecureGCM.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/SecureGCM.java new file mode 100644 index 00000000000..00a0a073e33 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/SecureGCM.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2024 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.core.pki.util; + +import java.security.SecureRandom; +import java.security.spec.KeySpec; +import java.util.Base64; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; + +public enum SecureGCM { + ENCRYPT; + + private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding"; //$NON-NLS-1$ + private static final String FACTORY_INSTANCE = "PBKDF2WithHmacSHA512"; //$NON-NLS-1$ + private static final int GCM_IV_LENGTH = 12; + private static final int KEY_LENGTH = 256; + private static final int ITERATION_COUNT = 65536; + + public String encrypt(String strToEncrypt, String secretKey, String salt) { + try { + SecureRandom secureRandom = SecureRandom.getInstanceStrong(); + byte[] iv = new byte[GCM_IV_LENGTH]; + secureRandom.nextBytes(iv); + GCMParameterSpec spec = new GCMParameterSpec(KEY_LENGTH / 2, iv); + SecretKeyFactory factory = SecretKeyFactory.getInstance(FACTORY_INSTANCE); + KeySpec skey = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), ITERATION_COUNT, KEY_LENGTH); + SecretKey tmp = factory.generateSecret(skey); + SecretKeySpec secretKeySpec = new SecretKeySpec(tmp.getEncoded(), "AES"); //$NON-NLS-1$ + Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, spec); + byte[] cipherText = cipher.doFinal(strToEncrypt.getBytes("UTF-8")); //$NON-NLS-1$ + byte[] encryptedData = new byte[iv.length + cipherText.length]; + System.arraycopy(iv, 0, encryptedData, 0, iv.length); + System.arraycopy(cipherText, 0, encryptedData, iv.length, cipherText.length); + return Base64.getEncoder().encodeToString(encryptedData); + } catch (Exception e) { + // Handle the exception properly + e.printStackTrace(); + return null; + } + } +} diff --git a/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/TemplateForPKIfile.java b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/TemplateForPKIfile.java new file mode 100644 index 00000000000..77935cea601 --- /dev/null +++ b/team/bundles/org.eclipse.core.pki/src/org/eclipse/core/pki/util/TemplateForPKIfile.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2024 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.core.pki.util; + +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; + +public enum TemplateForPKIfile { + CREATION; + public final String hashTag = "############################################################"; //$NON-NLS-1$ + public final String shortHashTag = "################"; //$NON-NLS-1$ + public static final String DotEclipse = ".eclipse"; + public final String USER_HOME = System.getProperty("user.home"); //$NON-NLS-1$ + Path userM2Home = null; + public void setup() { + try { + Path path = Paths.get(USER_HOME+ + FileSystems.getDefault().getSeparator()+DotEclipse+ + FileSystems.getDefault().getSeparator()+ + "pki.template"); + if (!(Files.exists(path))) { + createTemplate(path); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + public void createTemplate(Path path) { + String editTag = "Edit this File, Save as .pki"; //$NON-NLS-1$ + try { + Files.createFile(path); + Files.write(path, (hashTag + System.lineSeparator()).getBytes(), StandardOpenOption.APPEND); + Files.write(path, (hashTag + System.lineSeparator()).getBytes(), StandardOpenOption.APPEND); + Files.write(path, shortHashTag.getBytes(), StandardOpenOption.APPEND); + Files.write(path, editTag.getBytes(), StandardOpenOption.APPEND); + Files.write(path, (shortHashTag + System.lineSeparator()).getBytes(), StandardOpenOption.APPEND); + Files.write(path, (hashTag + System.lineSeparator()).getBytes(), StandardOpenOption.APPEND); + Files.write(path, (hashTag + System.lineSeparator()).getBytes(), StandardOpenOption.APPEND); + Files.write(path, ((buildBuffer()) + System.lineSeparator()).getBytes(), StandardOpenOption.APPEND); + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + public String buildBuffer() { + StringBuilder b = new StringBuilder(); + b.append("javax.net.ssl.keyStore="); //$NON-NLS-1$ + b.append("[Fully quallified name of your Keystore File]"); //$NON-NLS-1$ + b.append(System.lineSeparator()); + b.append("javax.net.ssl.keyStorePassword="); //$NON-NLS-1$ + b.append("[Eclipse will encrypt this entry]"); //$NON-NLS-1$ + b.append(System.lineSeparator()); + b.append("javax.net.ssl.keyStoreType="); //$NON-NLS-1$ + b.append("[types allowed; PCKS11, PKCS12]"); //$NON-NLS-1$ + b.append(System.lineSeparator()); + b.append("javax.net.ssl.keyStoreProvider="); //$NON-NLS-1$ + b.append("[SunPKCS11, PKCS12]"); //$NON-NLS-1$ + b.append(System.lineSeparator()); + b.append("javax.net.ssl.trustStore="); //$NON-NLS-1$ + b.append("[Fully quallified name of your Truststore File]"); //$NON-NLS-1$ + b.append(System.lineSeparator()); + b.append("javax.net.ssl.trustStorePassword="); //$NON-NLS-1$ + b.append(System.lineSeparator()); + b.append("javax.net.ssl.trustStoreType="); //$NON-NLS-1$ + b.append(System.lineSeparator()); + b.append(hashTag); + b.append(System.lineSeparator()); + return b.toString(); + } + + public static void main(String[] args) { + TemplateForPKIfile.CREATION.setup(); + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.ui.pki/.classpath b/team/bundles/org.eclipse.ui.pki/.classpath new file mode 100644 index 00000000000..c7db9228d9d --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/team/bundles/org.eclipse.ui.pki/.gitignore b/team/bundles/org.eclipse.ui.pki/.gitignore new file mode 100644 index 00000000000..b83d22266ac --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/team/bundles/org.eclipse.ui.pki/.project b/team/bundles/org.eclipse.ui.pki/.project new file mode 100644 index 00000000000..c635487c446 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/.project @@ -0,0 +1,28 @@ + + + org.eclipse.ui.pki + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/team/bundles/org.eclipse.ui.pki/.settings/org.eclipse.core.resources.prefs b/team/bundles/org.eclipse.ui.pki/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..99f26c0203a --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/team/bundles/org.eclipse.ui.pki/.settings/org.eclipse.jdt.core.prefs b/team/bundles/org.eclipse.ui.pki/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..62ef3488cc0 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/team/bundles/org.eclipse.ui.pki/.settings/org.eclipse.pde.core.prefs b/team/bundles/org.eclipse.ui.pki/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000000..f29e940a005 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/team/bundles/org.eclipse.ui.pki/META-INF/MANIFEST.MF b/team/bundles/org.eclipse.ui.pki/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..7d81b9fa09a --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/META-INF/MANIFEST.MF @@ -0,0 +1,25 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: PkiUI +Bundle-SymbolicName: org.eclipse.ui.pki;singleton:=true +Bundle-Version: 1.2.1.qualifier +Export-Package: org.eclipse.ui.pki.pkcs, + org.eclipse.ui.pki.pkiselection, + org.eclipse.ui.pki.preferences, + org.eclipse.ui.pki.util +Bundle-Activator: org.eclipse.ui.pki.AuthenticationPlugin +Bundle-Vendor: Security Team +Automatic-Module-Name: org.eclipse.ui.pki +Import-Package: org.eclipse.core.pki, + org.eclipse.core.pki.auth, + org.eclipse.jface.wizard, + org.osgi.framework;version="1.3.0" +Require-Bundle: org.eclipse.jface, + org.eclipse.equinox.preferences;bundle-version="3.10.200", + org.eclipse.equinox.common;bundle-version="3.18.0", + org.eclipse.osgi;bundle-version="3.18.400", + org.eclipse.ui;bundle-version="3.203.100", + org.eclipse.core.runtime, + org.eclipse.equinox.security;bundle-version="1.3.1000", + org.eclipse.core.pki +Bundle-ActivationPolicy: lazy diff --git a/team/bundles/org.eclipse.ui.pki/build.properties b/team/bundles/org.eclipse.ui.pki/build.properties new file mode 100644 index 00000000000..bbaca78da6a --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/build.properties @@ -0,0 +1,19 @@ +############################################################################### +# Copyright (c) 2023 Security Team 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: +# Security Team - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.properties,\ + plugin.xml diff --git a/team/bundles/org.eclipse.ui.pki/contexts.xml b/team/bundles/org.eclipse.ui.pki/contexts.xml new file mode 100644 index 00000000000..222ed46edf4 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/contexts.xml @@ -0,0 +1,25 @@ + + + + + These are preferences for setting up your PKI + +Certificate Location - The location of your certificate if you choose to provide it. Any CDE actions that may need your certificate acquire it from this location (SVN checkout/sharing) + +Trust Store Location - The location of your trust store. The trust store is a repository of certificates that are explicitly trusted by an application + + + + \ No newline at end of file diff --git a/team/bundles/org.eclipse.ui.pki/plugin.properties b/team/bundles/org.eclipse.ui.pki/plugin.properties new file mode 100644 index 00000000000..5aea8d65aee --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/plugin.properties @@ -0,0 +1,23 @@ +############################################################################### +# Copyright (c) 2000, 2007 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 +# yyyymmdd bug Email and other contact information +# -------- -------- ----------------------------------------------------------- +# 20070201 154100 pmoogk@ca.ibm.com - Peter Moogk, Port internet code from WTP to Eclipse base. +############################################################################### + +# +# Messages in plugin.xml. +# +PLUGIN_NAME=Internet Connection Management UI +PLUGIN_PROVIDER=Eclipse.org + diff --git a/team/bundles/org.eclipse.ui.pki/plugin.xml b/team/bundles/org.eclipse.ui.pki/plugin.xml new file mode 100644 index 00000000000..ac529f0211b --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/plugin.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/AuthenticationPlugin.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/AuthenticationPlugin.java new file mode 100644 index 00000000000..1e58bb3e975 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/AuthenticationPlugin.java @@ -0,0 +1,1232 @@ +/******************************************************************************* + * Copyright (c) 2000, 2012 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: + * Corporation - initial API and implementation + * yyyymmdd bug Email and other contact information + * -------- -------- ----------------------------------------------------------- + * 20231101 00000 joe@schiavone.org PKI implementation + *******************************************************************************/ +package org.eclipse.ui.pki; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.List; +import java.util.Optional; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.security.auth.callback.CallbackHandler; +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.core.pki.FingerprintX509; +import org.eclipse.core.pki.auth.EventConstant; +import org.eclipse.core.pki.auth.PKIState; +import org.eclipse.core.pki.auth.SecurityFileSnapshot; +import org.eclipse.core.pki.pkiselection.PKIProperties; +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.core.runtime.ILog; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.eclipse.jface.preference.IPersistentPreferenceStore; +import org.osgi.framework.BundleContext; +import org.eclipse.ui.pki.dialog.PassphraseDialog; +import org.eclipse.ui.pki.jsse.CdeX509TrustManager; +import org.eclipse.ui.pki.pkcs.VendorImplementation; +import org.eclipse.ui.pki.pkiselection.PKCSSelected; +import org.eclipse.core.pki.exception.UserCanceledException; +import org.eclipse.ui.pki.preferences.AuthenticationPreferences; +import org.eclipse.core.pki.util.KeyStoreFormat; +import org.eclipse.core.pki.util.KeyStoreManager; +import org.eclipse.ui.pki.util.KeyStoreUtil; +import org.eclipse.ui.pki.util.PKIAuthenticator; +import org.eclipse.ui.pki.util.PKISecureStorage; +import org.eclipse.ui.pki.wizard.PKILoginWizard; +import org.eclipse.ui.pki.wizard.TrustStoreLoginWizard; +import org.eclipse.ui.pki.wizard.TrustStoreSecureStorage; + +/** + * The activator class controls the plug-in life cycle + */ +public class AuthenticationPlugin extends AbstractUIPlugin { + + // The plug-in ID + + private KeyStore userKeyStore = null; + private transient String certPassPhrase; + private KeyStore trustStore; + private transient String trustStorePassPhrase; + PKIProperties snapshotProperties = null; + private Provider provider; + + // + // Cert defines + // + private static final int DIGITAL_SIGNATURE = 0; + private static final int KEY_CERT_SIGN = 5; + private static final int CRL_SIGN = 6; + + private static final TrustManager trustManager = new CdeX509TrustManager(); + + // The shared instance + private static AuthenticationPlugin plugin; + + protected static final String DEFAULT_TRUST_STORE = "cacerts"; + protected static final String CONFIGURATION_DIR = "configuration"; + + private static final String DEFAULT_TRUST_STORE_PASSWORD = "changeit"; + private static final String JAVA_SSL_CFG_PATH_KEY = "java.cfg.file"; + private static final String JAVA_SSL_TRUST_STORE_PATH_KEY = "javax.net.ssl.trustStore"; + private static final String JAVA_SSL_TRUST_STORE_TYPE_KEY = "javax.net.ssl.trustStoreType"; + private static final String JAVA_SSL_TRUST_STORE_PASS_KEY = "javax.net.ssl.trustStorePassword"; + private static final String JAVA_SSL_USER_KEY_STORE_PATH_KEY = "javax.net.ssl.keyStore"; + private static final String JAVA_SSL_USER_KEY_STORE_TYPE_KEY = "javax.net.ssl.keyStoreType"; + private static final String JAVA_SSL_USER_KEY_STORE_PASS_KEY = "javax.net.ssl.keyStorePassword"; + private static final String JAVA_SSL_USER_KEY_STORE_PROVIDER_KEY = "javax.net.ssl.keyStoreProvider"; + + /** + * The constructor + */ + public AuthenticationPlugin() {} + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static AuthenticationPlugin getDefault() { + //System.out.println("AuthenticationPlugin ---getDefault plugin"); + if (plugin == null) { + AuthenticationPlugin auth = new AuthenticationPlugin(); + /* + * try { auth.startup(); + * System.out.println("AuthenticationPlugin JUST RAN START UP MANNUALLY"); } + * catch (CoreException e) { // TODO Auto-generated catch block + * e.printStackTrace(); } + */ + } + return plugin; + } + + public static String getPluginId() { + return getDefault().getBundle().getSymbolicName(); + } + + public ILog getLogger() { + + return AuthenticationPlugin.getDefault().getLog(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + + // Has a headless config already been set up + if ((PKIState.CONTROL.isPKCS11on()) || (PKIState.CONTROL.isPKCS12on())) { + LogUtil.logInfo("AuthenticationPluginA Headless system has already setup PKI"); + setCertPassPhrase(System.getProperty("javax.net.ssl.keyStorePassword")); + + snapshotProperties = PKIProperties.getInstance(); + snapshotProperties.load(); + //snapshotProperties.dump(); + + if (PKIState.CONTROL.isPKCS11on()) { + PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS11); + } + if (PKIState.CONTROL.isPKCS12on()) { + + PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS12); + setSystemProperties(); + //AuthenticationPreferences.PKI_CERTIFICATE_LOCATION, + } + PKISecureStorage pkiSecureStorage = new PKISecureStorage(); + pkiSecureStorage.storePKI(this); + + EventProcessor.getInstance().initializeEvent( new PKIController()); + EventProcessor.getInstance().sendEvent(EventConstant.SETUP.getValue() ); + //LogUtil.logInfo("AuthenticationPlugin keystorePKI"+ snapshotProperties.getKeyStore()); + } else { + clearPKI(); + initialize(); + snapshotProperties = PKIProperties.getInstance(); + } + } + + /** + * Tries to get trust store and user certificate information from the system, prompting the user + * if necessary, and then sets javax.net.ssl system properties. + */ + public void setSystemProperties() { + + KeyStore keystore = null; + setTrustStoreSystemProperties(obtainDefaultJKSTrustStore()); + + if ( KeyStoreManager.INSTANCE.isKeyStoreInitialized() ) { + keystore = KeyStoreManager.INSTANCE.getKeyStore(); + this.setCertificatePath(PKIProperties.getInstance().getKeyStore()); + } else { + keystore = obtainUserKeyStore(); + } + + + if (keystore != null) { + setUserKeyStoreSystemProperties(keystore); + } + /* + * NOTE: when user hits cancel keysotre is null... SO DONT set it. + */ + //setUserKeyStoreSystemProperties(obtainUserKeyStore()); + } + + /** + * @return the jks path that is currently set in the system properties or empty string if not in the system property. + */ + public String obtainSystemPropertyJKSPath(){ + String currentJKSPath=""; + try { + currentJKSPath = System.getProperty(JAVA_SSL_TRUST_STORE_PATH_KEY); + if(currentJKSPath == null){ + currentJKSPath =""; + } + } catch (Exception e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + } + return currentJKSPath; + } + + /** + * @return the password currently in the system for the trust store. + */ + public String obtainSystemPropertyJKSPass(){ + String currentJKSPass = System.getProperty(JAVA_SSL_TRUST_STORE_PASS_KEY); + if(currentJKSPass == null){ + currentJKSPass =""; + } + return currentJKSPass; + } + + /** + * @return trust store key store only. + */ + public KeyStore obtainDefaultJKSTrustStore(){ + + String trustStoreDirectory=null; + Optional trustStoreSystemDirectory=null; + Optional trustStoreSystemPassword=null; + try { + trustStoreSystemDirectory = Optional.ofNullable(System.getProperty(JAVA_SSL_TRUST_STORE_PATH_KEY)); + if (trustStoreSystemDirectory.isEmpty() ) { + + trustStoreDirectory=AuthenticationPlugin.getDefault().getPreferenceStore().getString(AuthenticationPreferences.TRUST_STORE_LOCATION); + if ((trustStoreDirectory == null ) || (trustStoreDirectory.isEmpty())) { + trustStoreDirectory=PKIController.PKI_ECLIPSE_DIR.getAbsolutePath() + File.separator + DEFAULT_TRUST_STORE; + } + } else { + trustStoreDirectory = (String) trustStoreSystemDirectory.get().toString(); + } + } catch (Exception e1) { + // TODO Auto-generated catch block + trustStoreDirectory=PKIController.PKI_ECLIPSE_DIR.getAbsolutePath() + File.separator + DEFAULT_TRUST_STORE; + } + + + final String defaultTrustStorePath = trustStoreDirectory; + + trustStoreSystemPassword = Optional.ofNullable(System.getProperty(JAVA_SSL_TRUST_STORE_PASS_KEY)); + if (trustStoreSystemPassword.isEmpty()) { + this.trustStorePassPhrase = DEFAULT_TRUST_STORE_PASSWORD; + } else { + this.trustStorePassPhrase = trustStoreSystemPassword.get().toString(); + } + + //System.out.println("obtainDefaultJKSTrustStore -> " + defaultTrustStorePath + " " + this.trustStorePassPhrase); + + try { + + this.trustStore = KeyStoreUtil.getKeyStore(defaultTrustStorePath, this.trustStorePassPhrase, KeyStoreFormat.JKS); + setTrustStoreSystemProperties(this.trustStore); + AuthenticationPlugin.getDefault().getPreferenceStore().setValue(AuthenticationPreferences.TRUST_STORE_LOCATION, defaultTrustStorePath); + + + } catch (KeyStoreException e) { + System.out.println("The Java key store can not be loaded."); + } catch (NoSuchAlgorithmException e) { + System.out.println("The algorithm used to check the integrity of the jks file cannot be found."); + } catch (CertificateException e) { + System.out.println("The jks file can not be loaded."); + } catch (IOException e) { + System.out.println("There is a problem with the password or problem with the jks file data. Please try a different password."); + } catch (Exception e){ + System.out.println("Unexpected error occurred."); + } + + // Return the result + return this.trustStore; + } + + /** + * Tries to get trust store information from the system, prompting the user + * if necessary, and then sets javax.net.ssl system properties. + * @param keystore This parameter was set here because have to call the obtainJKSTrustStore() in order to create the trust store + * before it can be used. + * @return true if the trust store system properties are set. + */ + public boolean setTrustStoreSystemProperties(KeyStore keystore){ + boolean setTrustStoreProperties = false; + + String trustStoreLocation = getPreferenceStore().getString(AuthenticationPreferences.TRUST_STORE_LOCATION); + if(trustStore != null && trustStore.getType() != null && trustStoreLocation != null && !trustStoreLocation.isEmpty()) { + System.setProperty(JAVA_SSL_TRUST_STORE_PATH_KEY, trustStoreLocation); + System.setProperty(JAVA_SSL_TRUST_STORE_TYPE_KEY, trustStore.getType()); + if(trustStorePassPhrase != null && !trustStorePassPhrase.isEmpty()) { + System.setProperty(JAVA_SSL_TRUST_STORE_PASS_KEY, trustStorePassPhrase); + } else { + System.setProperty(JAVA_SSL_TRUST_STORE_PASS_KEY, DEFAULT_TRUST_STORE_PASSWORD); + } + setTrustStoreProperties = true; + } + + // + // set te HTTPS context this program will use. + // + SSLContext context = null; + try { + context = SSLContext.getDefault(); + context.getInstance("TLS"); + } catch(Exception ctxErr) { + // May not be set yet + } + if (!(context.getProvider().isConfigured()) ) { + setHTTPSContext(); + } + + return setTrustStoreProperties; + } + + /** + * @return the certificate path that is currently set in the system properties or empty string if system property doesn't exist. + */ + public String obtainSystemPropertyPKICertificatePath(){ + + String currentCertificatePath = "" ; + if (PKIState.CONTROL.isPKCS11on()) { + currentCertificatePath = getPreferenceStore().getString(AuthenticationPreferences.PKCS11_CONFIGURE_FILE_LOCATION); + } + if (PKIState.CONTROL.isPKCS12on() ) { + currentCertificatePath = System.getProperty(JAVA_SSL_USER_KEY_STORE_PATH_KEY); + } + + if(currentCertificatePath == null){ + currentCertificatePath =""; + } + return currentCertificatePath; + } + + /** + * @return the pass phrase currently in the system for the pki. + */ + public String obtainSystemPropertyPKICertificatePass(){ + String currentCertificatePass = System.getProperty(JAVA_SSL_USER_KEY_STORE_PASS_KEY); + if(currentCertificatePass == null){ + currentCertificatePass =""; + } + return currentCertificatePass; + } + + /** + * @return user key store + */ + public KeyStore obtainUserKeyStore(){ + KeyStore userKeyStore = null; + try { + + userKeyStore = getUserKeyStore("local"); + if(PKCSSelected.isPkcs12Selected()){ + + AuthenticationPlugin.getDefault().getPreferenceStore().setValue( + AuthenticationPreferences.PKI_CERTIFICATE_LOCATION, obtainSystemPropertyPKICertificatePath()); + } + } catch (UserCanceledException e) { + //Removed initialize() to prevent the system properties to be set + //in the configuration file when the PKI Certificate user interface is canceled. + + } + + return userKeyStore; + } + + + /** + * Tries to get user certificate information from the system, prompting the user + * if necessary, and then sets javax.net.ssl system properties. + * @param userkeystore Must call the obtainUserKeyStore() to create the userKeyStore before setting the properties. + * @return true if the key store system properties are set. + */ + public boolean setUserKeyStoreSystemProperties(KeyStore userkeystore){ + boolean setKeyStoreProperties = false; + String userKeyStoreLocation = null; + Optional keyStorePath = null; + Optional keyStorePassword = null; + //System.out.println("AuthenticationPlugin ----- setUserKeyStoreSystemProperties"); + if ( PKIState.CONTROL.isPKCS11on()) { + System.setProperty(JAVA_SSL_USER_KEY_STORE_TYPE_KEY, "PKCS11"); + System.setProperty(JAVA_SSL_USER_KEY_STORE_PASS_KEY, snapshotProperties.getPasswordAuthentication().getPassword().toString()); + // COMMENTING OUT because this isnt used here. + //userKeyStoreLocation = getPreferenceStore().getString(AuthenticationPreferences.CSPID_CONFIGURE_FILE_LOCATION); + System.setProperty(JAVA_SSL_USER_KEY_STORE_PATH_KEY, "pkcs11" ); + Provider pkcs11Provider = Security.getProvider("SunPKCS11"); + if(pkcs11Provider != null) { + System.setProperty(JAVA_SSL_USER_KEY_STORE_PROVIDER_KEY, pkcs11Provider.getName()); + } + setKeyStoreProperties = true; + } else if ( PKIState.CONTROL.isPKCS12on() ) { + System.setProperty(JAVA_SSL_USER_KEY_STORE_TYPE_KEY, "PKCS12"); + keyStorePath = Optional.ofNullable(System.getProperty(JAVA_SSL_USER_KEY_STORE_PATH_KEY)); + if ( keyStorePath.isEmpty()) { + userKeyStoreLocation = getPreferenceStore().getString(AuthenticationPreferences.PKI_CERTIFICATE_LOCATION); + System.setProperty(JAVA_SSL_USER_KEY_STORE_PATH_KEY, userKeyStoreLocation); + } else { + userKeyStoreLocation = keyStorePath.get().toString(); + + } + keyStorePassword = Optional.ofNullable(System.getProperty(JAVA_SSL_USER_KEY_STORE_PASS_KEY)); + if ( keyStorePassword.isEmpty()) { + System.setProperty(JAVA_SSL_USER_KEY_STORE_PASS_KEY, certPassPhrase); + } else { + certPassPhrase = keyStorePassword.get().toString(); + } + //Used by pkcs12. + if(userKeyStore != null && userKeyStore.getType() != null && certPassPhrase != null && userKeyStoreLocation != null) { + //System.setProperty(JAVA_SSL_USER_KEY_STORE_TYPE_KEY, userKeyStore.getType()); + System.setProperty(JAVA_SSL_USER_KEY_STORE_PASS_KEY, certPassPhrase); + setKeyStoreProperties = true; + } + } + + // + // set the HTTPS context this program will use. + // + //setHTTPSContext(); + SSLContext context = null; + try { + context = SSLContext.getDefault(); + context.getInstance("TLS"); + } catch(Exception ctxErr) { + // May not be set yet + } + if (!(context.getProvider().isConfigured()) ) { + setHTTPSContext(); + } + + return setKeyStoreProperties; + } + + /** + * Checks if the javax.net.ssl system properties are set. + */ + public static boolean isSSLSystemPropertiesSet() { + //System.out.println("AuthenticationPlugin isSSLSystemPropertiesSet PKCS12 PATH:"+AuthenticationPlugin.getDefault().getPreferenceStore().getString(AuthenticationPreferences.PKI_CERTIFICATE_LOCATION)); + String trustPath = System.getProperty(JAVA_SSL_TRUST_STORE_PATH_KEY); + String trustType = System.getProperty(JAVA_SSL_TRUST_STORE_TYPE_KEY); + + String userKeyPath = System.getProperty(JAVA_SSL_USER_KEY_STORE_PATH_KEY); + String userKeyType = System.getProperty(JAVA_SSL_USER_KEY_STORE_TYPE_KEY); + String userKeyPass = System.getProperty(JAVA_SSL_USER_KEY_STORE_PASS_KEY); + + if(isNullEmpty(trustPath) + || isNullEmpty(trustType) + || isNullEmpty(userKeyPath) + || isNullEmpty(userKeyType) + || isNullEmpty(userKeyPass)) { + return false; + } + + return true; + } + + /** + * @return true if javax.net.ssl properties need to be set. + */ + protected static boolean isNeedSSLPropertiesSet() { + boolean flag = false; + + // + // only set them if the user didn't already set the properties somewhere else + // + if(!isSSLSystemPropertiesSet()) { + + flag = true; + + } + + return flag; + } + + /** + * Null safe {@link String#isEmpty()} + * @param property String + */ + private static boolean isNullEmpty(String property) { + return (property == null || property.isEmpty()); + } + + /* + * (non-Javadoc) + * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + + /** + * Returns an image descriptor for the image file at the given + * plug-in relative path + * + * @param path the path + * @return the image descriptor + */ + public ImageDescriptor getImageDescriptor( String path ) { + return imageDescriptorFromPlugin( getPluginId(), path); + } + + /** + * Returns an image descriptor for the image file at the given + * plug-in relative path + * + * @param path the path + * @return the image descriptor + */ + public ImageDescriptor getImageDescriptor( String pluginId, String path ) { + return imageDescriptorFromPlugin( pluginId, path); + } + + + public String getCertificatePath() { + String path = null; + if ( PKIState.CONTROL.isPKCS11on()) { + //System.out.println("AuthenticationPlugin ----getCertificatePath PKCS11"); + System.setProperty(JAVA_SSL_USER_KEY_STORE_TYPE_KEY, "PKCS11"); + path = getPreferenceStore().getString(AuthenticationPreferences.PKCS11_CONFIGURE_FILE_LOCATION); + } else if ( PKIState.CONTROL.isPKCS12on()) { + //System.out.println("AuthenticationPlugin ----getCertificatePath PKCS12"); + System.setProperty(JAVA_SSL_USER_KEY_STORE_TYPE_KEY, "PKCS12"); + path = getPreferenceStore().getString(AuthenticationPreferences.PKI_CERTIFICATE_LOCATION); + } + //System.out.println("AuthenticationPlugin ----getCertificatePath return PATH:"+ path); + return path; + } + + public void setCertificatePath(String path) { + + if ( PKIState.CONTROL.isPKCS11on()) { + //System.out.println("AuthenticationPlugin ----setCertificatePath PKCS11 PATH:"+ path); + System.setProperty(JAVA_SSL_USER_KEY_STORE_TYPE_KEY, "PKCS11"); + //getPreferenceStore().setValue(AuthenticationPreferences.PKCS11_CONFIGURE_FILE_LOCATION, path); + } else if ( PKIState.CONTROL.isPKCS12on()) { + //System.out.println("AuthenticationPlugin ----setCertificatePath PKCS12 PATH:"+ path); + System.setProperty(JAVA_SSL_USER_KEY_STORE_TYPE_KEY, "PKCS12"); + System.clearProperty(JAVA_SSL_USER_KEY_STORE_PROVIDER_KEY); + getPreferenceStore().setValue(AuthenticationPreferences.PKI_CERTIFICATE_LOCATION, path); + } + } + + public String getCertPassPhrase() { + return certPassPhrase; + } + + public void setCertPassPhrase(String passPhrase) { + certPassPhrase = passPhrase; + } + + + public KeyStore getUserKeyStore() throws UserCanceledException { + /* + * TODO: Find all of the CDE calls to getUserKeyStore and create Use case + * to determine the best way to get pkcs11 integration included, see GForge plugin and more + * insid. + */ + return getUserKeyStore("local"); + } + + + public KeyStore getUserKeyStore(String operation ) throws UserCanceledException { + + /* If the pkcs11 has been already enabled by some other application, + * then grab that keystore and go, DO NOT POP UP DIALOG BOX, unless operation is an update.. + * + * @PARAM: operation = { local or update } + * where; + * local = During an eclipse start or restart. + * update = Request to update eclipse pki options + */ + userKeyStore = null; + if (!( operation.equalsIgnoreCase("update".toString()))) { + try { + VendorImplementation vendorPkcs11 = VendorImplementation.getInstance(); + if (vendorPkcs11.isEnabled() ) { + userKeyStore = vendorPkcs11.getKeyStore(); + System.out.println("AuthenticationPlugin - Dynamic vendorPkcs11 enabled."); + PKIState.CONTROL.setPKCS11on(true); + if ( vendorPkcs11.getSelectedX509FingerPrint() == null ) { + /* + * Set fingerprint using the default DS certificate, because this is dynamic vendorPkcs11. + */ + setUserKeyStoreSystemProperties(userKeyStore); + X509Certificate x509 = (X509Certificate) userKeyStore.getCertificate(vendorPkcs11.getAlias()); + vendorPkcs11.setSelectedX509Fingerprint(FingerprintX509.INSTANCE.getFingerPrint(x509, "MD5")); + } + } + + } catch (Exception e) { + PKIState.CONTROL.setPKCS11on(false); + PKIState.CONTROL.setPKCS12on(true); + e.printStackTrace(); + } catch (Throwable e) { + PKIState.CONTROL.setPKCS11on(false); + PKIState.CONTROL.setPKCS12on(true); + e.printStackTrace(); + } + + if (userKeyStore != null ) { + this.setCertificatePath("pkcs11"); + this.setUserKeyStoreSystemProperties(userKeyStore); + this.setProvider(Security.getProvider("SunPKCS11")); + } + } + + if(userKeyStore == null) + { + final List exceptions = new ArrayList(); + final String op = operation; + + Display.getDefault().syncExec(new Runnable() { + + public void run() { + //System.out.println("AuthenticationPlugin getUserKeystore PKCS12 PATH:"+AuthenticationPlugin.getDefault().getPreferenceStore().getString(AuthenticationPreferences.PKI_CERTIFICATE_LOCATION)); + Wizard wizard = new PKILoginWizard(); + wizard.setWindowTitle(op); + WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), wizard); + if(dialog.open() == WizardDialog.CANCEL) { + //System.out.println("AuthenticationPlugin --- PKI LOGIN CANCELED."); + // REMOVED EXCEPTION. WHY are we generating a stack trace for a CANCELLATION??? + //exceptions.add(new UserCanceledException("User login cancelled")); + if ( op.equalsIgnoreCase("Update")) { + userKeyStore=null; + } + + if ((!(PKIState.CONTROL.isPKCS11on())) && (!(PKIState.CONTROL.isPKCS12on())) ) { + //System.out.println("AuthenticationPlugin --- LOGIN CANCELED AND NO PKI IS SELECTED."); + userKeyStore=null; + if ( op.equalsIgnoreCase("Selection")) { + /* + * NOTE: + * Only initialize PKI properties during EarlyStartup when NO Selection is made. + */ + AuthenticationPlugin.getDefault().initialize(); + } + } + //Removed the AuthenticationPlugin.getDefault().initialize() to prevent the system properties to be set + //in the configuration file when the PKI Certificate user interface is canceled. + /* + * TODO: When user presses cancel decide what steps should be taken; + * 1. Does a cancel indicate that NO pki is desired? + * 2. Should all of the SYSTEM properties for PKI be removed from eclipse ws? + * 3. Why are we allowing a stack trace here? + * 4. We CAN detect if ANY varient of PKI was previously selected. Should it be restored? + * 5. Since more stringent oversight is in place, why even allow an eclipse to NOT be pki enabled? + */ + } + } + + }); + + if (exceptions.size() > 0) { + throw exceptions.get(0); + } + } + //SecurityFileSnapshot.INSTANCE.image(); + return userKeyStore; + } + + public void setUserKeyStore(KeyStore keyStore) + { + userKeyStore = keyStore; + } + + /** + * @return the existing user key store. + */ + public KeyStore getExistingUserKeyStore(){ + return userKeyStore; + } + + /** + * @return the existing trustStore. + */ + public KeyStore getExistingTrustStore() { + return trustStore; + } + + + public Provider getProvider() { + return provider; + } + + public void setProvider(Provider provider) { + this.provider = provider; + } + + /** + * This method returns the trust {@link KeyStore} set by the user through the preference page, or + * the default cacert jks trust store. + * @return a valid {@link KeyStore}, or null on error + * @throws IOException + * @throws CertificateException + * @throws NoSuchAlgorithmException + * @throws KeyStoreException + * @throws SecurityException + * @throws NoSuchMethodException + * @throws InvocationTargetException + * @throws IllegalArgumentException + * @throws IllegalAccessException + * @throws InstantiationException + * @throws ClassNotFoundException + */ + @SuppressWarnings("deprecation") + protected KeyPass loadTrustStore() throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + String trustStoreLocation = getPreferenceStore().getString(AuthenticationPreferences.TRUST_STORE_LOCATION); + InputStream in = null; + + try { + + if (trustStoreLocation != null && trustStoreLocation.trim().length() > 0) { + in = new FileInputStream(trustStoreLocation); + in = new BufferedInputStream(in); + //Mark the beginning index position of the buffer. + in.mark(0); + } else { + // + // original reading from bundle + // + //in = getBundle().getEntry(DEFAULT_TRUST_STORE).openStream(); + + // + // try to read the file from the eclipse/configuration directory + // + File ConfigurationFile = new File(Platform.getInstallLocation().getURL().getPath() + File.separator + + AuthenticationPlugin.CONFIGURATION_DIR + File.separator + + AuthenticationPlugin.DEFAULT_TRUST_STORE); + + in = new BufferedInputStream(new FileInputStream(ConfigurationFile)); + + //Mark the beginning index position of the buffer. + in.mark(0); + } + + // try default password + String password = DEFAULT_TRUST_STORE_PASSWORD; + try { + return new KeyPass(KeyStoreUtil.getKeyStore(in, password, KeyStoreFormat.JKS), password); + } catch (Throwable t) { + //Reset the index position to the beginning of the buffer stream. + in.reset(); + } + + // prompt for password + PassphraseDialog dialog = new PassphraseDialog(null, "Enter TrustStore Password"); + if (dialog.open() == Dialog.OK) { + password = dialog.getPassphrase(); + return new KeyPass(KeyStoreUtil.getKeyStore(in, password, KeyStoreFormat.JKS), password); + } + } finally { + try { + in.close(); + } catch (Throwable t) {} + } + + return null; + + } + + + /** + * @return the trust store + * @throws UserCanceledException + */ + public KeyStore getJKSTrustStore() throws UserCanceledException{ + if(trustStore == null) + { + final List exceptions = new ArrayList(); + + Display.getDefault().syncExec(new Runnable() { + + public void run() { + Wizard wizard = new TrustStoreLoginWizard(); + WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), wizard); + + if(dialog.open() == WizardDialog.CANCEL) + exceptions.add(new UserCanceledException("User login cancelled")); + } + + }); + + if (exceptions.size() > 0) { + throw exceptions.get(0); + } + + } + + return trustStore; + } + + + /** + * @return the trustStore, or null on error + */ + public KeyStore getTrustStore() { + if (trustStore == null) { + synchronized(this) { + if (trustStore != null) return trustStore; + try { + KeyPass kp = loadTrustStore(); + trustStore = kp.getKey(); + trustStorePassPhrase = kp.getPass(); + } catch (Throwable t) { + LogUtil.logError("Error while loading trust store", t); + } + } + } + return trustStore; + } + + /** + * @return the trustStorePassPhrase + */ + public String getTrustStorePassPhrase() { + return trustStorePassPhrase; + } + + /** + * @param trustStore the trustStore to set + */ + public void setTrustStore(KeyStore trustStore) { + this.trustStore = trustStore; + } + + /** + * @param trustStorePassPhrase the trustStorePassPhrase to set + */ + public void setTrustStorePassPhrase(String trustStorePassPhrase) { + this.trustStorePassPhrase = trustStorePassPhrase; + } + + + + /** + * @return the trustManager + */ + public static TrustManager getTrustManager() { + return trustManager; + } + + /** + * Returns the user's sid from their pki, or null if pki isn't loaded or other error + * @return the user's sid from their pki, or null if pki isn't loaded or other error + * @throws UserCanceledException + * @throws KeyStoreException + * @throws Exception if user cancels + */ + public String getPkiSid() throws UserCanceledException, KeyStoreException { + KeyStore ks = getUserKeyStore("local"); + if (ks == null) { + return null; + } + Enumeration aliases = ks.aliases(); + while (aliases.hasMoreElements()) { + try { + String alias = aliases.nextElement(); + Certificate cert = ks.getCertificate(alias); + if (cert instanceof X509Certificate) { + X509Certificate pki = (X509Certificate)cert; + String sid = PKIAuthenticator.getSid(pki); + //String affilation = PKIAuthenticator.getAffiliation(pki); + return sid; + } + } catch (Throwable t) {} + } + + return null; + } + + /** + * Returns the user's sid from their pki, or null if pki isn't loaded or other error + * This sid will have the affiliation code associated with it for example a CSE person will + * have "-cse" appended to the end of their sid. + * @return the user's sid from their pki, or null if pki isn't loaded or other error + * @throws UserCanceledException + * @throws KeyStoreException + * @throws Exception if user cancels + */ + public String getAfilliatedPkiSid() throws UserCanceledException, KeyStoreException + { + KeyStore ks = getUserKeyStore("local"); + if (ks == null) + { + return null; + } + + Enumeration aliases = ks.aliases(); + while (aliases.hasMoreElements()) + { + try + { + String alias = aliases.nextElement(); + Certificate cert = ks.getCertificate(alias); + if (cert instanceof X509Certificate) + { + X509Certificate pki = (X509Certificate)cert; + String sid = PKIAuthenticator.getSid(pki); + String affiliation = PKIAuthenticator.getAffiliation(pki); + + if (affiliation.equals("US")) { + return sid + "-US"; + } else { + return sid + "-unknown"; + } + } + } + catch (Throwable t) {} + } + return null; + } + + + public static String getDefaultTrustStorePassword() { + return DEFAULT_TRUST_STORE_PASSWORD; + } + + + class KeyPass { + KeyStore key; + String pass; + /** + * @param key + * @param pass + */ + public KeyPass(KeyStore key, String pass) { + super(); + this.key = key; + this.pass = pass; + } + /** + * @return the key + */ + public KeyStore getKey() { + return key; + } + /** + * @return the pass + */ + public String getPass() { + return pass; + } + /** + * @param key the key to set + */ + public void setKey(KeyStore key) { + this.key = key; + } + /** + * @param pass the pass to set + */ + public void setPass(String pass) { + this.pass = pass; + } + } + + public void initialize() { + try { + //System.out.println("AuthenticationPlugin - initialize"); + + + getPreferenceStore().setValue("JAVA_SSL_USER_KEY_STORE_PATH_KEY", ""); + getPreferenceStore().setValue(AuthenticationPreferences.PKI_CERTIFICATE_LOCATION, ""); + getPreferenceStore().setValue(AuthenticationPreferences.PKCS11_CONFIGURE_FILE_LOCATION, ""); + if ( getPreferenceStore().needsSaving() ) { + /* + * TODO: save the store + */ + //System.out.println(" AuthenticationPlugin -- Please save the store!"); + try { + ((IPersistentPreferenceStore)getPreferenceStore()).save(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + public void clearPKI() { + //System.out.println("AuthenticationPlugin CLEARED PROPERTY PROVIDER TBD"); + //System.clearProperty(JAVA_SSL_USER_KEY_STORE_PROVIDER_KEY); + System.clearProperty(JAVA_SSL_USER_KEY_STORE_PATH_KEY); + System.clearProperty(JAVA_SSL_USER_KEY_STORE_TYPE_KEY); + System.clearProperty(JAVA_SSL_USER_KEY_STORE_PASS_KEY); + /* + * TODO: Decide if we need to CLEAR all the trust store properties too. + * + */ + System.clearProperty(JAVA_SSL_TRUST_STORE_PATH_KEY); + System.clearProperty(JAVA_SSL_TRUST_STORE_TYPE_KEY); + System.clearProperty(JAVA_SSL_TRUST_STORE_PASS_KEY); + } + + /** + * sets the certs on the connection if using the HTTPs protocol + */ + public SSLContext setHTTPSContext() { + SSLContext ctx = null; + if (isSSLSystemPropertiesSet()) { + KeyManagerFactory kmf = null; + TrustManagerFactory tmf = null; + LogUtil.logInfo("AuthenticationPlugin --- setHTTPSContext"); //$NON-NLS-1$ + try { + if ( PKIState.CONTROL.isPKCS11on() ) { + + /* + * SSLContext has already been set for PKCS11: + * DO NOT OVERwrite it! The consequence is that no certificate + * negotiation will occur. + * + */ + ctx = SSLContext.getDefault(); + //System.out.println("AuthenticationPlugin --- setHTTPSContext"); + + } else { + kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + ctx = SSLContext.getInstance("TLS"); + /* + * DEBUG TRUST defaultALG, change from PKIX to SunX509 + */ + try { + //String algo = TrustManagerFactory.getDefaultAlgorithm(); + //System.out.println("AuthenticationPlugin ---- setHTTPSContext ALG:"+algo); + //tmf = TrustManagerFactory.getInstance("SunX509", "SunJSSE"); + tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + tmf.init(trustStore); + kmf.init(userKeyStore, certPassPhrase.toCharArray()); + KeyManager[] keyManagers = kmf.getKeyManagers(); + TrustManager[] trustManagers = tmf.getTrustManagers(); + ctx.init(keyManagers, trustManagers, null); + SSLContext.setDefault(ctx); + HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); + //System.out.println("AuthenticationPlugin HttpsURLConnection CONTEXT set"); + } + + /* + * TESTING TESTING + */ +// System.out.println("AuthenticationPlugin CALLING TEST CODE"); +// testEclipseServer(); +// System.out.println("AuthenticationPlugin COMPLETED TEST CODE"); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return ctx; + } + private void testEclipseServer() { + String url="https://my.test.server/marketplace/oxygen/sites/update.zeroturnaround.com//update-site"; + SSLSocketFactory factory = null; + + try { + System.out.println("AuthenticationPlugin testEclipseServer TESTING CONNECTION"); + URL urlconn = new URL(url); + HttpsURLConnection conn = (HttpsURLConnection) urlconn.openConnection(); + SSLSocketFactory ssl=null; + try { + ssl = SSLContext.getDefault().getSocketFactory(); + + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + conn.setSSLSocketFactory(ssl); + + + System.out.println("AuthenticationPlugin - opendConnection"); + conn.setDoOutput(true); + conn.setUseCaches(false); + int i = conn.getResponseCode(); + if (i == 200) + { + System.out.println("AuthenticationPlugin TEST - 200 STATUS"); + int iContentLen = conn.getContentLength(); + if (iContentLen > 0) + { + InputStreamReader isr = new InputStreamReader(conn.getInputStream()); + char[] response = new char[iContentLen]; + isr.read(response); + isr.close(); + + } + else + { + System.out.println("AuthenticationPlugin TEST - BAD STATUS returned"); + } + } else { + System.out.println("AuthenticationPlugin TEST server returned:"+i); + } + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + private KeyStore.Builder createKeyStoreBuilder() { + /* + * NOTE: This code is used to create a Keystore when there is only a pre-initialized keystore + * already available, as in the case of a pkcs11 enabled application. The Password callback handler + * here allows the PKCS11 keystore to be utilized after it was already initialized + * elsewhere. + */ + KeyStore.Builder builder=null; + + try { + KeyStore.CallbackHandlerProtection cb = new KeyStore.CallbackHandlerProtection( (CallbackHandler) new PasswordCallbackHandler()); + builder = KeyStore.Builder.newInstance("PKCS11", Security.getProvider("SunPKCS11"), cb); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return builder; + } + + /** + * returns true if the array of key usage sent in flags a DigitalSignature + * @param ba + * @return + */ + private static boolean isDigitalSignature(boolean[] ba) { + if ( ba != null) { + return ba[DIGITAL_SIGNATURE] && !ba[KEY_CERT_SIGN] && !ba[CRL_SIGN]; + } else { + return false; + } + } + + /** + * Returns the users email from the certificate or null if it can't find it. + * @return + */ + public String getUserEmail() + { + String userEmail = null; + + if (isSSLSystemPropertiesSet()) { + try { + // + // at this point we have loaded either a PKCS11 or PKCS12 cert + // + Enumeration en = userKeyStore.aliases(); + while (en.hasMoreElements()) { + String alias = en.nextElement(); + //System.out.println(" " + alias); + Certificate cert = userKeyStore.getCertificate(alias); + if (cert.getType().equalsIgnoreCase("X.509")) + { + X509Certificate X509 = (X509Certificate) cert; + + // + // we need to make sure this is a digital certificate instead of a server + // cert or something + // + if (isDigitalSignature(X509.getKeyUsage())) { + Collection> altnames = X509.getSubjectAlternativeNames(); + if (altnames != null) { + for (List item : altnames) { + Integer type = (Integer) item.get(0); + if (type == 1) + try { + userEmail = item.toArray()[1].toString(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + } + + } + + } + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + //System.out.println("Users email is " + userEmail); + return userEmail; + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/EventProcessor.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/EventProcessor.java new file mode 100644 index 00000000000..92172e98bdb --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/EventProcessor.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki; + +import java.util.Map; + +import org.eclipse.osgi.framework.eventmgr.CopyOnWriteIdentityMap; +import org.eclipse.osgi.framework.eventmgr.EventDispatcher; +import org.eclipse.osgi.framework.eventmgr.EventManager; +import org.eclipse.osgi.framework.eventmgr.ListenerQueue; + +public class EventProcessor implements EventDispatcher { + private EventManager eventManager=null; + private ListenerQueue queue = null; + private PKIController localStartup=null; + private static EventProcessor eventProcessor = null; + private boolean isPending=false; + public static EventProcessor getInstance() { + if ( eventProcessor == null ) { + synchronized(EventProcessor.class) { + if ( eventProcessor == null ) { + eventProcessor = new EventProcessor(); + } + } + } + return eventProcessor; + } + private EventProcessor() {} + public void initializeEvent(PKIController startup) { + //System.out.println("EventProcessor, initialize."); + this.localStartup=startup; + eventManager = new EventManager("PKI event"); + Map listeners = new CopyOnWriteIdentityMap(); + listeners.put(startup,null); + queue = new ListenerQueue(eventManager); + } + public void sendEvent(int event) { + //System.out.println("EventProcessor, send event"); + if ( this.localStartup != null ) { + this.dispatchEvent(this.localStartup.eventRunner(event), queue, event, queue ); + } else { + System.out.println("EventProcessor, waited and wated and waited some more.. But alas, nothing."); + isPending=true; + } + } + + public void dispatchEvent(Object eventListener, Object listenerObject, int eventAction, Object eventObject) { + // TODO Auto-generated method stub + ((Runnable) eventListener).run(); + } + + public boolean isEventPending() { + return isPending; + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/PKIController.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/PKIController.java new file mode 100644 index 00000000000..44a710c8b0e --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/PKIController.java @@ -0,0 +1,415 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.preferences.ConfigurationScope; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.osgi.framework.eventmgr.EventManager; +import org.eclipse.osgi.framework.eventmgr.ListenerQueue; +import org.eclipse.osgi.service.datalocation.Location; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IStartup; +import org.eclipse.core.pki.AuthenticationBase; +import org.eclipse.core.pki.auth.EventConstant; +import org.eclipse.core.pki.auth.PKIState; +import org.eclipse.core.pki.auth.PublicKeySecurity; +import org.eclipse.core.pki.pkiselection.PKIProperties; +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.ui.pki.pkcs.VendorImplementation; +import org.eclipse.ui.pki.pkiselection.PKCSSelected; +//import org.eclipse.ui.pki.pkiselection.PKCSpick; +import org.eclipse.core.pki.util.KeyStoreFormat; +import org.eclipse.ui.pki.wizard.TrustStoreSecureStorage; +import org.eclipse.core.pki.exception.UserCanceledException; +import org.eclipse.ui.pki.preferences.AuthenticationPreferences; +import org.eclipse.ui.pki.util.PKISecureStorage; + +public class PKIController implements IStartup { + protected static final String USER_HOME = System.getProperty("user.home"); + public static final File PKI_ECLIPSE_DIR = new File(USER_HOME, ".eclipse_pki"); + public static final String PKI_DIR = "eclipse_pki"; + public static final Path pkiHome = Paths.get(PKI_ECLIPSE_DIR.getAbsolutePath() + File.separator + PKI_DIR); + static boolean isPkcs11Installed = false; + ListenerQueue queue = null; + Properties pkiProperties = null; + + public PKIController() { + } + + @Override + public void earlyStartup() { + // TODO Auto-generated method stub + //System.out.println("PKIController EARLY Startup"); + Startup(); + } + + @SuppressWarnings("static-access") + public void Startup() { + createSigintEclipseDir(); + /* + * Check if .pki file exists. If it doesnt, then create one. + */ + //System.out.println("PKIController Startup"); + + /* + * NOTE: Initialize pki settings so that NO PKI is set on start up. + */ + PKIState.CONTROL.setPKCS11on(false); + PKIState.CONTROL.setPKCS12on(false); + + /* + * PKCS11 will be the default certificate store, so check it first. + */ + + //System.out.println("PKIController Startup"); + + + if (PublicKeySecurity.INSTANCE.isTurnedOn()) { + //System.out.println("PKIController get PKI TYPE"); + PublicKeySecurity.INSTANCE.getPkiPropertyFile("#Gone2Boat@Bay"); + String pkiType = System.getProperty("javax.net.ssl.keyStoreType").trim(); + //System.out.println("PKIController PKI TYPE:["+pkiType+"]"); + if ( pkiType != null) { + if (pkiType.equalsIgnoreCase("PKCS12")) { + //System.out.println("PKIController PKI TYPE FROM FILE:"+System.getProperty("javax.net.ssl.keyStoreType")); + PKIState.CONTROL.setPKCS11on(false); + PKIState.CONTROL.setPKCS12on(true); + PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS12); + + //System.out.println("PKIController PKI PKCS12 PASSWD:["+System.getProperty("javax.net.ssl.keyStorePassword")+"]"); + AuthenticationPlugin.getDefault().setCertPassPhrase(System.getProperty("javax.net.ssl.keyStorePassword")); + + } else { + System.out.println("PKIController PKI TYPE NOT FOUND TO BE EQUAL"); + } + if ("PKCS11".equalsIgnoreCase(System.getProperty("javax.net.ssl.keyStoreType"))) { + if (VendorImplementation.getInstance().isInstalled()) { + PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS11); + PKIState.CONTROL.setPKCS11on(true); + PKIState.CONTROL.setPKCS12on(false); + } else { + // need exception here no PROVIDER + } + } + } + } else { + if ( AuthenticationBase.INSTANCE.isPkcs11Setup() ) { + if (((!(VendorImplementation.getInstance().isInstalled())) || (isPreviousPkiSelection()))) { + PKIState.CONTROL.setPKCS11on(false); + PKIState.CONTROL.setPKCS12on(true); + PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS12); + } else { + PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS11); + } + } + } + + try { + //System.out.println("PKIController Setup preferences"); + IPreferenceStore store = AuthenticationPlugin.getDefault().getPreferenceStore(); + String tsPref = store.getString(AuthenticationPreferences.TRUST_STORE_LOCATION); + + // System.out.println("tspref " + tsPref); + + if (tsPref == null || tsPref.isEmpty()) { + this.installTrustStore(); + } else { + File tsFileLoc = new File(tsPref); + if (!tsFileLoc.exists()) { + // TS location exists in pref store but file not actually in default location - + // can this break for custom locations? + this.installTrustStore(); + } + } + // Load system properties + if (AuthenticationPlugin.isNeedSSLPropertiesSet()) { + //System.out.println("PKIController Setup preferences SEND EVENT"); + EventProcessor.getInstance().initializeEvent(this); + if (EventProcessor.getInstance().isEventPending()) { + EventProcessor.getInstance().sendEvent(EventConstant.SETUP.getValue()); + } + // setupSSLSystemProperties(isPkcs11Installed); + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public boolean isPreviousPkiSelection() { + + PKISecureStorage pkiSecureStorage = new PKISecureStorage(); + return pkiSecureStorage.isPKISaved(); + + } + + public Object eventRunner(int incoming) { + final Integer value = Integer.valueOf(incoming); + return new Runnable() { + public void run() { + //System.out.println("PKIController EVENT runner"); + if (value.equals(EventConstant.DONE.getValue())) { + AuthenticationPlugin.getDefault().setUserKeyStore(VendorImplementation.getInstance().getKeyStore()); + } else if (value.equals(EventConstant.CANCEL.getValue())) { + VendorImplementation.getInstance().off(); + isPkcs11Installed = false; + PKIState.CONTROL.setPKCS11on(false); + //System.clearProperty("javax.net.ssl.keyStoreType"); + //System.clearProperty("javax.net.ssl.keyStoreProvider"); + //System.out.println("PKIController - TURNED OFF ALL PKCS11"); + } else if (value.equals(EventConstant.SETUP.getValue())) { + //System.out.println("PKIController - STARTING SETUP"); + setupSSLSystemProperties(isPkcs11Installed); + } + } + }; + } + + /** + * @see AuthenticationPlugin#setSystemProperties() + */ + void setupSSLSystemProperties(final boolean isPkcs11Installed) { + Display.getDefault().asyncExec(new Runnable() { + final boolean is11on = isPkcs11Installed; + + public void run() { + final String KEYSTORE_SELECTION = "Selection"; + PKISecureStorage pkiSecureStorage = new PKISecureStorage(); + TrustStoreSecureStorage truststoreSecureStorage = new TrustStoreSecureStorage(); + + // if (!(pkiSecureStorage.isPkcs11Enabled())) { + if (!(is11on)) { + // TrustStoreSecureStorage truststoreSecureStorage = new + // TrustStoreSecureStorage(); + + if (pkiSecureStorage.isPKISaved() && truststoreSecureStorage.isJKSSaved()) { + + if (pkiSecureStorage.getPkiType().equalsIgnoreCase("PKCS11")) { + PKIState.CONTROL.setPKCS11on(true); + PKIState.CONTROL.setPKCS12on(false); + } else { + PKIState.CONTROL.setPKCS11on(false); + PKIState.CONTROL.setPKCS12on(true); + } + // First, set the system properties from secure storage then retrieved the paths + // from the system + // properties to set the preference store for later use. + // System.out.println("EarlyStartup ---------------- setupSSLSystemProperties"); + + pkiSecureStorage.loadUpPKI(); + pkiSecureStorage.setPKISystemProperties(); + truststoreSecureStorage.setTrustStoreSystemProperties(); + + String pkiPath = AuthenticationPlugin.getDefault().obtainSystemPropertyPKICertificatePath(); + String jksPath = AuthenticationPlugin.getDefault().obtainSystemPropertyJKSPath(); + + AuthenticationPlugin.getDefault().setCertificatePath(pkiPath); + AuthenticationPlugin.getDefault().setCertPassPhrase(pkiSecureStorage.getCertPassPhrase()); + AuthenticationPlugin.getDefault().setUserKeyStore(pkiSecureStorage.getUserKeyStore()); + + AuthenticationPlugin.getDefault().getPreferenceStore() + .setValue(AuthenticationPreferences.TRUST_STORE_LOCATION, jksPath); + AuthenticationPlugin.getDefault() + .setTrustStorePassPhrase(truststoreSecureStorage.getJksPassPhrase()); + AuthenticationPlugin.getDefault().setTrustStore(truststoreSecureStorage.getTrustStore()); + + } else if (pkiSecureStorage.isPKISaved() && !truststoreSecureStorage.isJKSSaved()) { + AuthenticationPlugin.getDefault().setTrustStoreSystemProperties( + AuthenticationPlugin.getDefault().obtainDefaultJKSTrustStore()); + + // First, set the system properties from secure storage then retrieved the paths + // from the system + // properties to set the preference store for later use. + if (pkiSecureStorage.getPkiType().equals("PKCS11")) { + PKIState.CONTROL.setPKCS11on(true); + PKIState.CONTROL.setPKCS12on(false); + } else { + PKIState.CONTROL.setPKCS11on(false); + PKIState.CONTROL.setPKCS12on(true); + } + pkiSecureStorage.loadUpPKI(); + pkiSecureStorage.setPKISystemProperties(); + + // String pkiPath = + // AuthenticationPlugin.getDefault().obtainSystemPropertyPKICertificatePath(); + // AuthenticationPlugin.getDefault().setCertificatePath(pkiPath); + + AuthenticationPlugin.getDefault().setCertPassPhrase(pkiSecureStorage.getCertPassPhrase()); + AuthenticationPlugin.getDefault().setUserKeyStore(pkiSecureStorage.getUserKeyStore()); + + } else if (!pkiSecureStorage.isPKISaved() && truststoreSecureStorage.isJKSSaved()) { + // First, set the system properties from secure storage then retrieved the paths + // from the system + // properties to set the preference store for later use. + truststoreSecureStorage.setTrustStoreSystemProperties(); + String jksPath = AuthenticationPlugin.getDefault().obtainSystemPropertyJKSPath(); + + AuthenticationPlugin.getDefault().getPreferenceStore() + .setValue(AuthenticationPreferences.TRUST_STORE_LOCATION, jksPath); + AuthenticationPlugin.getDefault() + .setTrustStorePassPhrase(truststoreSecureStorage.getJksPassPhrase()); + AuthenticationPlugin.getDefault().setTrustStore(truststoreSecureStorage.getTrustStore()); + + // Set the pki system properties. + AuthenticationPlugin.getDefault().setUserKeyStoreSystemProperties( + AuthenticationPlugin.getDefault().obtainUserKeyStore()); + + } else { + + AuthenticationPlugin.getDefault().setSystemProperties(); + + String jksPath = AuthenticationPlugin.getDefault().obtainSystemPropertyJKSPath(); + + AuthenticationPlugin.getDefault().getPreferenceStore() + .setValue(AuthenticationPreferences.TRUST_STORE_LOCATION, jksPath); + AuthenticationPlugin.getDefault() + .setTrustStorePassPhrase(truststoreSecureStorage.getJksPassPhrase()); + AuthenticationPlugin.getDefault().setTrustStore(truststoreSecureStorage.getTrustStore()); + + + AuthenticationPlugin.getDefault().getPreferenceStore() + .setValue(AuthenticationPreferences.PKI_CERTIFICATE_LOCATION, + PKIProperties.getInstance().getKeyStore()); + } + } else { + + AuthenticationPlugin.getDefault().obtainDefaultJKSTrustStore(); + try { + AuthenticationPlugin.getDefault().getUserKeyStore(KEYSTORE_SELECTION); + } catch (UserCanceledException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if (VendorImplementation.getInstance().isEnabled()) { + this.dispatchEvent(eventRunner(EventConstant.DONE.getValue()), queue, 0, queue); + } + + } + } + + private void dispatchEvent(Object eventRunner, ListenerQueue queue, + int i, ListenerQueue queue2) { + // TODO Auto-generated method stub + ((Runnable) eventRunner).run(); + } + }); + + } + + private void installTrustStore() { + /* + * TODO: Create an enum of the IC comms and utilize the correct trust + */ + + String filename = AuthenticationPlugin.DEFAULT_TRUST_STORE; + File localTrustStore = new File(PKI_ECLIPSE_DIR, filename); + + // System.out.println("Install Truststore - local -> " + localTrustStore); + + // + // we want to install the new one anyway + // + // if(!localTrustStore.exists()) { + FileChannel fc = null; + ReadableByteChannel rbc = null; + FileOutputStream os = null; + try { + localTrustStore.createNewFile(); + os = new FileOutputStream(localTrustStore); + fc = os.getChannel(); + + // + // open file in eclipses configuration directory + // + File ConfigurationFile = new File(Platform.getInstallLocation().getURL().getPath() + File.separator + + AuthenticationPlugin.CONFIGURATION_DIR + File.separator + + AuthenticationPlugin.DEFAULT_TRUST_STORE); + + InputStream is = new FileInputStream(ConfigurationFile); + + // + // copy the contents of the eclipse/ cacerts file to our .pki directory + // + rbc = Channels.newChannel(is); + ByteBuffer buffer = ByteBuffer.allocate(1024); + buffer.clear(); + while (rbc.read(buffer) != -1) { + buffer.flip(); + fc.write(buffer); + buffer.compact(); + } + + } catch (IOException e) { + LogUtil.logError("Issue writing default trust store to disk.", e); + } finally { + if (fc != null) { + try { + fc.close(); + } catch (Exception e) { + } + } + if (os != null) { + try { + os.close(); + } catch (Exception e) { + } + } + if (rbc != null) { + try { + rbc.close(); + } catch (Exception e) { + } + } + // } + } + AuthenticationPlugin.getDefault().getPreferenceStore().setValue(AuthenticationPreferences.TRUST_STORE_LOCATION, + localTrustStore.getAbsolutePath()); + + } + + private void createSigintEclipseDir() { + Lock fsLock = new ReentrantLock(); + fsLock.lock(); + try { + if (Files.notExists(pkiHome)) { + Files.createDirectories(pkiHome); + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + fsLock.unlock(); + } + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/PasswordCallbackHandler.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/PasswordCallbackHandler.java new file mode 100644 index 00000000000..ce79011325a --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/PasswordCallbackHandler.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki; + +import java.io.IOException; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; + +public class PasswordCallbackHandler implements CallbackHandler { + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + // TODO Auto-generated method stub + + } + +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/buttons/PKCSButtons.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/buttons/PKCSButtons.java new file mode 100644 index 00000000000..95f377a84bf --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/buttons/PKCSButtons.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.buttons; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.pki.AuthenticationPlugin; +import org.eclipse.ui.pki.pkiselection.PKCS11WidgetSelectedActions; +import org.eclipse.ui.pki.pkiselection.PKCS12WidgetSelectedActions; +import org.eclipse.ui.pki.preferences.AuthenticationPreferences; + + +public class PKCSButtons { + + protected Button pkcs12Button; + protected Button pkcs11Button; + + public PKCSButtons(final Composite sectionComposite){ + + final Group buttonGroup = new Group(sectionComposite, SWT.NONE); + buttonGroup.setText("Select PKI Type to Use"); + GridLayout layout = new GridLayout(); + buttonGroup.setLayout(layout); + + //Create layout and controls + Composite subsectionComposite = new Composite(buttonGroup, SWT.NONE); + GridLayout subsectionCompositeLayout = new GridLayout(1, false); + subsectionComposite.setLayout(subsectionCompositeLayout); + subsectionComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + pkcs11Button = new Button(subsectionComposite, SWT.RADIO); + pkcs11Button.setLayoutData(new GridData(SWT.BEGINNING, SWT.BOTTOM, true, true)); + + pkcs11Button.setText("(PKCS11)"); + + pkcs12Button = new Button(subsectionComposite, SWT.RADIO); + pkcs12Button.setLayoutData(new GridData(SWT.BEGINNING, SWT.TOP, true, true)); + pkcs12Button.setText("(PKCS12)"); + } + + public void buttonSelected(final Text certpathtext, final Label pkiLabel, final Button browseButton, final Text passwordText){ + //PKCS11 is always initially selected by default. + if(pkcs11Button.getSelection()){ + pkcs11Actions(certpathtext, pkiLabel, browseButton); + } + + pkcs11Button.addSelectionListener(new SelectionAdapter(){ + @Override + public void widgetSelected(SelectionEvent e) { + + if(pkcs11Button.getSelection()){ + pkcs11Actions(certpathtext, pkiLabel, browseButton); + passwordText.setText(""); + } + } + }); + + pkcs12Button.addSelectionListener(new SelectionAdapter(){ + @Override + public void widgetSelected(SelectionEvent e) { + + if(pkcs12Button.getSelection()){ + PKCS12WidgetSelectedActions.setKeyStoreFormat(); + certpathtext.setText(AuthenticationPlugin.getDefault().getPreferenceStore().getString(AuthenticationPreferences.PKI_CERTIFICATE_LOCATION)); + PKCS12WidgetSelectedActions.userInterfaceDisplay(certpathtext, pkiLabel, null, null, browseButton, true); + passwordText.setText(""); + } + } + }); + } + + void pkcs11Actions(Text certpathtext, Label pkiLabel, Button browseButton){ + PKCS11WidgetSelectedActions.setKeyStoreFormat(); + PKCS11WidgetSelectedActions.userInterfaceDisplay(certpathtext, pkiLabel, true); + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/dialog/PassphraseDialog.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/dialog/PassphraseDialog.java new file mode 100644 index 00000000000..9a138d98e85 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/dialog/PassphraseDialog.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.dialog; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + + +public class PassphraseDialog extends Dialog{ + protected Text passphraseField; + protected String passphrase=null; + protected String message=null; + + public PassphraseDialog(Shell parentShell, String message){ + super(parentShell); + this.message=message; + } + + protected void configureShell(Shell newShell){ + super.configureShell(newShell); + newShell.setText(message); + } + + public void create(){ + super.create(); + passphraseField.setFocus(); + } + + protected Control createDialogArea(Composite parent){ + initializeDialogUnits(parent); + Composite main=new Composite(parent, SWT.NONE); + + GridLayout layout=new GridLayout(); + layout.numColumns=3; + layout.marginHeight=convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); + layout.marginWidth=convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); + layout.verticalSpacing=convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + layout.horizontalSpacing=convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + main.setLayout(layout); + main.setLayoutData(new GridData(GridData.FILL_BOTH)); + + if(message!=null){ + Label messageLabel=new Label(main, SWT.WRAP); + messageLabel.setText(message); + GridData data=new GridData(GridData.FILL_HORIZONTAL); + data.horizontalSpan=3; + messageLabel.setLayoutData(data); + } + + createPassphraseFields(main); + Dialog.applyDialogFont(main); + return main; + } + + protected void createPassphraseFields(Composite parent){ + new Label(parent, SWT.NONE).setText("Password"); + passphraseField=new Text(parent, SWT.BORDER); + GridData data=new GridData(GridData.FILL_HORIZONTAL); + data.widthHint=convertHorizontalDLUsToPixels(IDialogConstants.ENTRY_FIELD_WIDTH); + passphraseField.setLayoutData(data); + passphraseField.setEchoChar('*'); + + new Label(parent, SWT.NONE); + } + + public String getPassphrase(){ + return passphrase; + } + + protected void okPressed(){ + String _passphrase=passphraseField.getText(); + if(_passphrase==null||_passphrase.length()==0){ + return; + } + passphrase=_passphrase; + super.okPressed(); + } + + protected void cancelPressed(){ + passphrase=null; + super.cancelPressed(); + } +} + diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/jsse/CdeX509TrustManager.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/jsse/CdeX509TrustManager.java new file mode 100644 index 00000000000..f3bd914db73 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/jsse/CdeX509TrustManager.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.jsse; + +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.ui.pki.AuthenticationPlugin; + + +/** + * A {@link TrustManager} which uses the user supplied (through preference page) trust store + * or the default 5eyesTrustStore. + */ +public class CdeX509TrustManager implements X509TrustManager { + + //TODO You can enhance MyX509TrustManager to handle dynamic keystore updates. When a checkClientTrusted or checkServerTrusted test fails and does not establish a trusted certificate chain, you can add the required trusted certificate to the keystore. You need to create a new pkixTrustManager from the TrustManagerFactory initialized with the updated keystore. When you establish a new connection (using the previously initialized SSLContext), the newly added certificate will be called to make the trust decisions. + + /* + * The default PKIX X509TrustManager9. We'll delegate + * decisions to it, and fall back to the logic in this class if the + * default X509TrustManager doesn't trust it. + */ + protected X509TrustManager pkixTrustManager = null; + + protected void init() { + + if (pkixTrustManager != null) { + return; + } + + synchronized (this) { + + if (pkixTrustManager != null) { + return; + } + + try { + // create a "default" JSSE X509TrustManager. + + KeyStore ks = AuthenticationPlugin.getDefault().getTrustStore(); + + TrustManagerFactory tmf = + TrustManagerFactory.getInstance("PKIX"); + tmf.init(ks); + + TrustManager tms [] = tmf.getTrustManagers(); + + /* + * Iterate over the returned trustmanagers, look + * for an instance of X509TrustManager. If found, + * use that as our "default" trust manager. + */ + for (int i = 0; i < tms.length; i++) { + if (tms[i] instanceof X509TrustManager) { + pkixTrustManager = (X509TrustManager) tms[i]; + return; + } + } + } catch (NoSuchAlgorithmException e) { + LogUtil.logError("Error while initializing " + CdeX509TrustManager.class.getName(), e); + } catch (KeyStoreException e) { + LogUtil.logError("Error while initializing " + CdeX509TrustManager.class.getName(), e); + } + } + + + + } + + + /* (non-Javadoc) + * @see javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert.X509Certificate[], java.lang.String) + */ + public void checkClientTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + init(); + pkixTrustManager.checkClientTrusted(arg0, arg1); + } + + /* (non-Javadoc) + * @see javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String) + */ + public void checkServerTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + init(); + pkixTrustManager.checkServerTrusted(arg0, arg1); + } + + /* (non-Javadoc) + * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() + */ + public X509Certificate[] getAcceptedIssuers() { + init(); + return pkixTrustManager.getAcceptedIssuers(); + } + +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkcs/EclipsePkiProvider.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkcs/EclipsePkiProvider.java new file mode 100644 index 00000000000..d4857d73184 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkcs/EclipsePkiProvider.java @@ -0,0 +1,12 @@ +package org.eclipse.ui.pki.pkcs; + +import java.util.List; + +import org.eclipse.core.pki.AuthenticationBase; + +public interface EclipsePkiProvider { + public AuthenticationBase security = AuthenticationBase.INSTANCE; + public List getList(); + public String getAlias(); + public void off(); +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkcs/ProviderImpl.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkcs/ProviderImpl.java new file mode 100644 index 00000000000..688648b98ff --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkcs/ProviderImpl.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.pkcs; + +import java.util.List; + +import javax.net.ssl.SSLContext; + + +public class ProviderImpl { + public static SSLPkcs11Provider security = SSLPkcs11Provider.getInstance(); + public static SSLPkcs11Provider getNewInstance() { + security=SSLPkcs11Provider.getInstance(); + return security; + } + @SuppressWarnings("unchecked") + public List getList() { + return (List) security.getList(); + } + public String getAlias() { + return security.getAlias(); + } + @SuppressWarnings("static-access") + public void off() { + security.disable(); + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkcs/SSLPkcs11Provider.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkcs/SSLPkcs11Provider.java new file mode 100644 index 00000000000..a1ba69b5772 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkcs/SSLPkcs11Provider.java @@ -0,0 +1,325 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.pkcs; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.Security; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.List; + +import javax.net.ssl.SSLContext; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.ui.pki.pkiselection.PKCSSelected; +import org.eclipse.core.pki.AuthenticationBase; +import org.eclipse.core.pki.pkiselection.PKIProperties; +import org.eclipse.ui.pki.AuthenticationPlugin; + + +public class SSLPkcs11Provider { + private static final SSLPkcs11Provider iprovider = new SSLPkcs11Provider(); + private static String alias=null; + private static SSLContext sslContext; + private static Object sunPkcs11Instance=null; + private transient static String pin="pin"; + private static List list = new ArrayList(); + private static boolean isPKCS11on=false; + private static boolean isInstalled=false; + private static KeyStore keyStore; + private static KeyStore targetKeyStore; + private static KeyStore trustStore; + private static Provider provider = null; + private static KeyStore.PasswordProtection pp = new KeyStore.PasswordProtection(pin.toCharArray());; + private SSLPkcs11Provider(){} + protected final static int DIGITAL_SIGNATURE=0; + private static final int KEY_ENCIPHERMENT = 2; + protected static PKIProperties auth=PKIProperties.getInstance();; + public boolean isPKCS11Enabled() {return isPKCS11on;} + public boolean isPKCS11Installed() {return isInstalled;} + public void setPKCS11on(boolean isPKCS11on) {SSLPkcs11Provider.isPKCS11on = isPKCS11on;} + public static SSLPkcs11Provider getInstance() { if (!isPKCS11on) getProvider(); return iprovider;} + public static Provider getProvider() { + String tmpAlias=null; + String logMessage="logger message"; + try { + + System.out.println("SSLPkcs11Provider STARTING PROCESSING"); + + /* + * PKCS11 can be dynamic. So if its already been enabled no PiN is needed and + * the Software will let you hook into it dynamically. + */ + char[] tmpPassword=null; + if ( !(pin.equalsIgnoreCase("pin"))) { + // WITH A PIM + tmpPassword=Arrays.copyOf(pp.getPassword(), pp.getPassword().length); + } else { + // WITHOUT A PIN + tmpPassword=Arrays.copyOf(pin.toCharArray(), pin.toCharArray().length ); + } + + /* + * Set up the PKI keystore for PKCS11 + */ + System.out.println("SSLPkcs11Provide init KEYSTORE FIX THIS "); + // @see AUTHENTICATION + targetKeyStore = AuthenticationBase.INSTANCE.initialize(tmpPassword); + + if ( targetKeyStore != null ) { + + try { + /* + * The correct pin must be entered for this to work properly or the pkcs11 manager + * must already be enabled by some other applcation outside of eclipse. + */ + //System.out.println("SSLPkcs11Provide init KEYSTORE with pin:"+pin); + targetKeyStore.load(null, pin.toCharArray()); + + keyStore = KeyStore.getInstance("JKS"); + keyStore.load(null,"".toCharArray()); + Enumeration aliasesEnum = targetKeyStore.aliases(); + list = new ArrayList(); + while (aliasesEnum.hasMoreElements()) { + tmpAlias = (String) aliasesEnum.nextElement(); + try { + X509Certificate certificate = (X509Certificate) targetKeyStore.getCertificate(tmpAlias); + /* + * See if this credential is Digital Signature usage, we only want those, NO KE! + */ + try { + certificate.checkValidity(); + if ( isDigitalSignature(certificate.getKeyUsage()) ) { + PrivateKey privateKey = (PrivateKey) targetKeyStore.getKey(tmpAlias, null); + if ( privateKey != null) { + alias = tmpAlias; + list.add( alias ); + isPKCS11on = true; + isInstalled=true; + auth.setKeyStorePassword( getPin() ); + keyStore.setCertificateEntry(tmpAlias, certificate); + //System.out.println("SSLPkcs11Provider - SunPKCS11 DS ALIAS:"+alias); + IStatus status = new Status (IStatus.OK, AuthenticationPlugin.getPluginId()," SunPKCS11 provider loaded."); + //AuthenticationPlugin.getDefault().getLog().log(status); + if ( pin.equals("pin")) { + System.out.println("SSLPkcs11Provide KEYSTORE PIN CHECK FIX THIS "); + // @see AUTHENTICATION + AuthenticationBase.INSTANCE.setSSLContext(targetKeyStore); + } + } + } else { + if ( !(isKeyEncipherment(certificate.getKeyUsage())) ) { + //System.out.println("SSLPkcs11Provider - NOT KE alias:"+tmpAlias ); + keyStore.setCertificateEntry(tmpAlias, certificate); + } + } + } catch (CertificateExpiredException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + //System.out.println("SSLPkcs11Provider - SunPKCS11 EXPIRED DS ALIAS:"+tmpAlias); + //keyStore.setCertificateEntry(tmpAlias+" EXPIRED", certificate); + } + catch (CertificateNotYetValidException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + //System.out.println("SSLPkcs11Provider - SunPKCS11 INVALID DS ALIAS:"+tmpAlias); + //keyStore.setCertificateEntry(tmpAlias+" INVALID", certificate); + } + } catch (UnrecoverableKeyException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + //sslContext = AuthenticationBase.INSTANCE.setSSLContext(keyStore); + } catch (Exception e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + + /* + * Keystore is not loaded yet, no password provided and we require pin! + */ + keyStore=null; + // + //Pkcs11Provider.setConfigurePath(""); + // + isInstalled=true; + //System.out.println("SSLPkcs11Provider ----------- PRESSED CANCEL when pin was requested.."); + PKCSSelected.setPkcs11Selected(false); + PKCSSelected.setPkcs12Selected(false); + isPKCS11on = false; + } + + } else { + logMessage = "Unable to locate a valid pkcs11 provider, searching for SunPKCS11"; + //AuthenticationPlugin.getDefault().getLog().log(new Status(IStatus.OK, AuthenticationPlugin.getPluginId()+":SSLPkcs11Provider",logMessage)); + System.out.println("SSLPkcs11Provider -------------------------- NO SunPKCS11 provider found."); + } + + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + // TODO Auto-generated catch block + //e.printStackTrace(); + /* + * + * THE USER PRESSED CANCEL when their pin was being requested + * + */ + keyStore=null; + // + //Pkcs11Provider.setConfigurePath(""); + // + isInstalled=true; + System.out.println("SSLPkcs11Provider ----------- PRESSED CANCEL when pin was requested.."); + PKCSSelected.setPkcs11Selected(false); + PKCSSelected.setPkcs12Selected(false); + isPKCS11on = false; + } + return provider; + } + + public String getAlias() { + return this.alias; + } + public List getList() { + return this.list; + } + public static String getPin() { + return pin; + } + public void setPin(String pin) { + this.pin = pin; + pp = new KeyStore.PasswordProtection(pin.toCharArray()); + } + public boolean login() { + Method logout=null; + Class noparams[]={}; + //System.out.println("SSLPkcs11Provider LOGIN"); + if ( provider != null) { + + try { + if ( sunPkcs11Instance != null ) { + logout = sunPkcs11Instance.getClass().getMethod("logout", noparams); + try { + logout.invoke(sunPkcs11Instance); + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } catch (NoSuchMethodException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvocationTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + getProvider(); + return isPKCS11on; + } + public void logoff() { + try { + //System.out.println("SSLPkcs11Provider LOGOFF INVOKATION:"); + //provider.clear(); + isPKCS11on = false; + isInstalled=false; + //System.out.println("SSLPkcs11Provider LOGOFF DONE"); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + public KeyStore getKeyStore() { +// if ( keyStore == null ) { +// System.out.println("SSLPkcs11Provider getting new PROVIDER "); +// getProvider(); +// } + //return keyStore; + return targetKeyStore; + } + public static void disable() { + isPKCS11on=false; + } + + /* + * + * Eclipse software looks for the digitalSignature ONLY, could be multiple in the target keystore + * + * BIT SET is as follow; + * + * 0 = digitalSignature + * 1 = nonRepudiations - (modified in subsequent definitions) + * 2 = keyEncipherment + * 3 = dataEncipherment + * 4 = keyAgreement + * 5 = keyCertSign + * 6 = cRLsign + * 7 = decipherOnly + */ + private static boolean isDigitalSignature(boolean[] ba) { + if ( ba != null) { + + return ba[DIGITAL_SIGNATURE]; + } else { + return false; + } + } + private static boolean isKeyEncipherment(boolean[] ba) { + if ( ba != null) { + + return ba[KEY_ENCIPHERMENT]; + } else { + return false; + } + } + + public SSLContext getSSLContext() { + return sslContext; + } + public static void setSSLContext(SSLContext sslContext) { + SSLPkcs11Provider.sslContext = sslContext; + } + public static void listProviders() { + for ( Provider provider : Security.getProviders() ) { + //System.out.println("BEFORE ADDING ANY Provider NAME:"+ provider.getName() ); + } + } + public static void listProviderAlgs(Provider provider ) { + + Enumeration keys = provider.keys(); + while ( keys.hasMoreElements()) { + //System.out.println( "KEY:"+keys.nextElement()); + } + + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkcs/VendorImplementation.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkcs/VendorImplementation.java new file mode 100644 index 00000000000..8463486ee10 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkcs/VendorImplementation.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.pkcs; + +import java.security.KeyStore; +import java.util.List; + +import javax.net.ssl.SSLContext; + +import org.eclipse.core.pki.AuthenticationBase; + +public class VendorImplementation implements EclipsePkiProvider { + private static final VendorImplementation venderImpl=new VendorImplementation(); + private static VendorImplementation csp=new VendorImplementation(); + + private static boolean isquiet=false; + private static String selectedX509Fingerprint; + + private static final VendorImplementation silentPkcs11=new VendorImplementation(isquiet); + private transient boolean enabled=false; + public static VendorImplementation getInstance(){ return venderImpl;} + public static VendorImplementation getInstance(boolean quiet){ isquiet=quiet;return silentPkcs11;} + + private VendorImplementation() { + try { + + if ( security.isPkcs11Setup()) { + enabled=true; + } + } catch (Exception e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + } + } + private VendorImplementation(boolean quiet) { + //super(quiet); + } + public static void refresh() { + getInstance(); + } + public void enable(boolean changeValue) { + enabled=changeValue; + } + public boolean isEnabled() { + return security.isPkcs11Setup(); + } + public boolean isInstalled() { + return security.isPkcs11Setup(); + } + public KeyStore getKeyStore() { + return security.getKeyStore(); + } + public String getSelectedX509FingerPrint() { + return selectedX509Fingerprint; + } + public void setSelectedX509Fingerprint( String fingerprint ) { + //System.out.println("VendorImplementation--------- setSelectedX509Fingerprint PRINTE:"+fingerprint); + selectedX509Fingerprint=fingerprint; + //System.out.println("VendorImplementation ---FIX THIS------ setSelectedX509Fingerprint PRINT:"+fingerprint); + AuthenticationBase.INSTANCE.setFingerprint(selectedX509Fingerprint); + + } + public SSLContext getSSLContext() { + return security.getSSLContext(); + } + public boolean login( final String pin ) { + security.setPin(pin); + if (security.login()) { + return true; + } + return false; + } + public void logoff() { + security.logoff(); + } + @Override + public List getList() { + // TODO Auto-generated method stub + return AuthenticationBase.INSTANCE.getList(); + } + @Override + public String getAlias() { + // TODO Auto-generated method stub + return null; + } + @Override + public void off() { + // TODO Auto-generated method stub + + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkiselection/PKCS11WidgetSelectedActions.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkiselection/PKCS11WidgetSelectedActions.java new file mode 100644 index 00000000000..98a561643eb --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkiselection/PKCS11WidgetSelectedActions.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.pkiselection; + +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.core.pki.util.KeyStoreFormat; + +public class PKCS11WidgetSelectedActions { + + public static void setKeyStoreFormat(){ + PKCSSelected.setPkcs11Selected(true); + PKCSSelected.setPkcs12Selected(false); + PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS11); + } + + /** + * Causes the PKI Certificate to be visible or not. + * @param password The Text box to enter the path. + * @param passwordlabel The PKI Certificate label. + * @param visibility true to make all 3 fields visible, false to make it not visible. + */ + public static void userInterfaceDisplay(Text password, Label passwordlabel, boolean visibility){ + if(password != null) password.setVisible(visibility); + passwordlabel.setVisible(visibility); + } + +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkiselection/PKCS12WidgetSelectedActions.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkiselection/PKCS12WidgetSelectedActions.java new file mode 100644 index 00000000000..36421b0df99 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkiselection/PKCS12WidgetSelectedActions.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.pkiselection; + +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.core.pki.util.KeyStoreFormat; + +public class PKCS12WidgetSelectedActions { + + public static void setKeyStoreFormat(){ + PKCSSelected.setPkcs12Selected(true); + PKCSSelected.setPkcs11Selected(false); + PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS12); + } + + public static void userInterfaceDisplay(Text certpathtext, Label pkiLabel, + Label passwordlabel, Text passwordtext, Button browseButton, boolean visiblity) { + certpathtext.setVisible(visiblity); + pkiLabel.setVisible(visiblity); + browseButton.setVisible(visiblity); + passwordlabel.setVisible(visiblity); + passwordtext.setVisible(visiblity); + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkiselection/PKCSSelected.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkiselection/PKCSSelected.java new file mode 100644 index 00000000000..2c7dc3ee566 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkiselection/PKCSSelected.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.pkiselection; + +import org.eclipse.core.pki.util.KeyStoreFormat; + +public class PKCSSelected { + + private static boolean pkcs11Selected = false; + private static boolean pkcs12Selected = false; + private static KeyStoreFormat keystoreformat = KeyStoreFormat.PKCS11; + + + public static boolean isPkcs11Selected() { + return pkcs11Selected; + } + public static void setPkcs11Selected(boolean pkcs11Selected) { + PKCSSelected.pkcs12Selected = false; + PKCSSelected.pkcs11Selected = pkcs11Selected; + } + public static boolean isPkcs12Selected() { + return pkcs12Selected; + } + public static void setPkcs12Selected(boolean pkcs12Selected) { + PKCSSelected.pkcs11Selected = false; + PKCSSelected.pkcs12Selected = pkcs12Selected; + } + public static KeyStoreFormat getKeystoreformat() { + return keystoreformat; + } + public static void setKeystoreformat(KeyStoreFormat keystoreformat) { + PKCSSelected.keystoreformat = keystoreformat; + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkiselection/PKCSpick.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkiselection/PKCSpick.java new file mode 100644 index 00000000000..527d227ed4a --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/pkiselection/PKCSpick.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.pkiselection; + +import org.eclipse.core.pki.auth.PKIState; + +public class PKCSpick { + private static final PKCSpick pkcs = new PKCSpick(); + private static boolean isPKCS11on=false; + private static boolean isPKCS12on=false; + private PKCSpick(){} + public static PKCSpick getInstance() {return pkcs;} + public boolean isPKCS11on() {return isPKCS11on;} + public boolean isPKCS12on() {return isPKCS12on;} + public void setPKCS11on(boolean isPKCS11on) { + PKCSpick.isPKCS11on = isPKCS11on; + if ( PKIState.CONTROL.isPKCS11on()) { + PKCSpick.isPKCS11on=true; + } + } + public void setPKCS12on(boolean isPKCS12on) { + PKCSpick.isPKCS12on = isPKCS12on; + if ( PKIState.CONTROL.isPKCS12on()) { + PKCSpick.isPKCS12on=true; + } + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/AuthenticationPreferences.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/AuthenticationPreferences.java new file mode 100644 index 00000000000..f50f71b93e3 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/AuthenticationPreferences.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.preferences; + +public class AuthenticationPreferences { + + private static final String PREFIX = AuthenticationPreferences.class.getPackage().getName(); + + public static final String MANUAL_PKI_SELECTION = PREFIX + "." + "manualPkiSelectionPref"; + + public static final boolean MANUAL_PKI_SELECTION_DEFAULT = true; + + public static final String PKI_SELECTION_TYPE = "pkiType"; + + public static final String SELECTED_PKI_CERTIFICATE = PREFIX + "." + "selectedPkiCertificatePref"; + + public static final String DEFAULT_PKI_CERTIFICATE_DIR = "U:\\private\\certificates"; + + public static final String DONT_SAVE_SELECTED_PKI_PATH = PREFIX + "." + "dontSaveSelectedPkiPref"; + + public static final String DEFAULT_AUTHENTICATION_DISABLED = PREFIX + "." + "defaultAuthenticationDisabledPref"; + + public static final boolean DEFAULT_AUTHENTICATION_DISABLED_DEFAULT = false; + + public static final String SELECTED_DEFAULT_AUTHENTICATABLE = PREFIX + "." + "selectedDefaultAuthenticatablePref"; + + public static final String SELECTED_DEFAULT_AUTHENTICATABLE_DEFAULT = ""; + + public static final String PKI_CERTIFICATE_LOCATION = "pkiCertLocation"; + + public static final String PKCS11_CFG_FILE_LOCATION = "pkcs11CfgFile"; + + public static final String X500_CREDENTIAL = "x500Credential"; + + public static final String TRUST_STORE_LOCATION = "trustStoreLocation"; + + public static final String PKCS11_CONFIGURE_FILE_LOCATION = "pkcs11ConfigureFileLocation"; + + public static final String SECURITY_PROVIDER = "securityProvider"; + + public static final String[] FILTER_NAMES = { "PKCS #12 Files (*.p12)", "All Files (*.*)" }; + + public static final String[] FILTER_EXTS = { "*.p12", "*.*" }; + +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/ChangedPressedFieldEditorStatus.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/ChangedPressedFieldEditorStatus.java new file mode 100644 index 00000000000..7014e2e8ec2 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/ChangedPressedFieldEditorStatus.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.preferences; + +import java.security.KeyStore; + +public class ChangedPressedFieldEditorStatus { + + private static boolean isPKISaveCertificateChecked = false; + private static boolean isJKSSaveTrustStoreChecked = false; + private static boolean isSaveConfigurationLocationFileChecked = false; + private static boolean isChecked = false; + + private static boolean ispkiChangedPressed = false; + private static boolean isjksChangedPressed = false; + + private static KeyStore pkiUserKeyStore = null; + private static KeyStore previousUserKeyStore = null; + private static KeyStore jksTrustStore = null; + + public ChangedPressedFieldEditorStatus() { + // TODO Auto-generated constructor stub + } + + /** + * @return the isPKISaveCertificateChecked + */ + public static boolean isPKISaveCertificateChecked() { + return isPKISaveCertificateChecked; + } + + /** + * @param isPKISaveCertificateChecked the isPKISaveCertificateChecked to set + */ + public static void setPKISaveCertificateChecked( + boolean isPKISaveCertificateChecked) { + ChangedPressedFieldEditorStatus.isPKISaveCertificateChecked = isPKISaveCertificateChecked; + } + + /** + * @return the isJKSSaveTrustStoreChecked + */ + public static boolean isJKSSaveTrustStoreChecked() { + return isJKSSaveTrustStoreChecked; + } + + /** + * @param isJKSSaveTrustStoreChecked the isJKSSaveTrustStoreChecked to set + */ + public static void setJKSSaveTrustStoreChecked( + boolean isJKSSaveTrustStoreChecked) { + ChangedPressedFieldEditorStatus.isJKSSaveTrustStoreChecked = isJKSSaveTrustStoreChecked; + } + + /** + * @return the pkiChangedPressed + */ + public static boolean isPkiChangedPressed() { + return ispkiChangedPressed; + } + + /** + * @param pkiChangedPressed the pkiChangedPressed to set + */ + public static void setPkiChangedPressed(boolean pkiChangedPressed) { + ChangedPressedFieldEditorStatus.ispkiChangedPressed = pkiChangedPressed; + } + + /** + * @return the jksChangedPressed + */ + public static boolean isJksChangedPressed() { + return isjksChangedPressed; + } + + /** + * @param jksChangedPressed the jksChangedPressed to set + */ + public static void setJksChangedPressed(boolean jksChangedPressed) { + ChangedPressedFieldEditorStatus.isjksChangedPressed = jksChangedPressed; + } + + + public static boolean isSaveConfigurationLocationFileChecked() { + return isSaveConfigurationLocationFileChecked; + } + + public static void setSaveConfigurationLocationFileChecked(boolean isSaveConfigurationLocationFileChecked) { + ChangedPressedFieldEditorStatus.isSaveConfigurationLocationFileChecked = isSaveConfigurationLocationFileChecked; + } + + /** + * @return user key store. + */ + public static KeyStore getPkiUserKeyStore() { + return pkiUserKeyStore; + } + + /** + * Sets the user key store. + * @param pkiUserKeyStore + */ + public static void setPkiUserKeyStore(KeyStore pkiUserKeyStore) { + ChangedPressedFieldEditorStatus.previousUserKeyStore = ChangedPressedFieldEditorStatus.pkiUserKeyStore; + ChangedPressedFieldEditorStatus.pkiUserKeyStore = pkiUserKeyStore; + } + public static KeyStore getPreviousUserKeyStore() { + return previousUserKeyStore; + } + + /** + * @return the trust store. + */ + public static KeyStore getJksTrustStore() { + return jksTrustStore; + } + + /** + * Sets the trust store. + * @param jksTrustStore + */ + public static void setJksTrustStore(KeyStore jksTrustStore) { + ChangedPressedFieldEditorStatus.jksTrustStore = jksTrustStore; + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/CheckUpdatedKeystoreValue.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/CheckUpdatedKeystoreValue.java new file mode 100644 index 00000000000..a888af59ba6 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/CheckUpdatedKeystoreValue.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.preferences; + +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.pki.pkcs.VendorImplementation; +import org.eclipse.ui.pki.pkiselection.PKCSpick; +import org.eclipse.ui.pki.preferences.ChangedPressedFieldEditorStatus; +import org.eclipse.core.pki.util.KeyStoreFormat; +import org.eclipse.ui.pki.util.KeyStoreUtil; +import org.eclipse.ui.pki.AuthenticationPlugin; +import org.eclipse.core.pki.exception.UserCanceledException; + + +public class CheckUpdatedKeystoreValue { + + public static boolean isValid(String userInputPath) { + + //System.out.println("CheckUpdatedKeystoreValue ---- isValid "); + //System.out.println("CheckUpdatedKeystoreValue ---- isValid incoming value: "+userInputPath ); + boolean isFound = false; + StringBuilder message = new StringBuilder(); + message.append("Reading credentials:"); + //KeyStore existingUserKeyStore = null; + KeyStore newUserKeyStore = null; + String passwd=null; + String userSuppliedLocation = null; + + try { + if ( userInputPath == null ) { + return false; + } + if ( PKCSpick.getInstance().isPKCS11on()) { + + try { + + /* + * TODO + * NOTE: NEED to add a check here to make sure that the path that was entered is + * valid and that there is a valid CFG file.. + * + */ + System.out.println("CheckUpdatedKeystoreValue ---- ADD a check here to make sure path is good cfg "); + VendorImplementation.refresh(); + newUserKeyStore = VendorImplementation.getInstance().getKeyStore(); + if ( newUserKeyStore != null ) { + + isFound=true; + } + } catch(Exception e) { + System.out.println("CheckUpdatedKeystoreValue ---- isValid bad path exception"); + } + } + + if ( PKCSpick.getInstance().isPKCS12on()) { + //System.out.println("CheckUpdatedKeystoreValue ---- isValid PKCS12 "); + passwd = AuthenticationPlugin.getDefault().getCertPassPhrase(); + if ( (passwd != null ) && (!( passwd.isEmpty() ))) { + userSuppliedLocation = userInputPath; + //System.out.println("CheckUpdatedKeystoreValue ---- isValid PKCS12 passwd:"+passwd+" incoming:"+userInputPath); + //System.out.println("CheckUpdatedKeystoreValue ---- isValid PKCS12 passwd:"+passwd+" LOCATION:"+userSuppliedLocation); + + newUserKeyStore = KeyStoreUtil.getKeyStore(userInputPath, passwd, KeyStoreFormat.PKCS12); + isFound=true; + } else { + //System.out.println("CheckUpdatedKeystoreValue ---- isValid PKCS12 NO PASSWORD WAS FOUND"); + newUserKeyStore = AuthenticationPlugin.getDefault().getUserKeyStore("Update"); + } + } + System.out.println("CheckUpdatedKeystoreValue ---- TBD COMMENTED OUT,, DONT NEED?"); + /* + * if (userSuppliedLocation.isEmpty()) { + * + * throw new IllegalArgumentException(); } + */ + //isFound=true; + + + } catch (KeyStoreException e) { + message.append( "Problem reading your certificate. 1111" ); + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + message.append( "Problem reading your certificate. 1112" ); + e.printStackTrace(); + } catch (CertificateException e) { + message.append( "Problem reading your certificate. 1113" ); + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalArgumentException e) { + message.append( "Problem reading your certificate. Not found in specfified location." ); + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SecurityException e) { + message.append( "Problem reading your certificate. 0000111000 " ); + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + //System.out.println("PKICertLocation : IOEXCEPTION"); + message.append( "Problem reading your certificate. " ); + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (UserCanceledException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + Status status=null; + if (!(isFound)) { + status = new Status(IStatus.ERROR, "plugin0", 0, message.toString(), null); + ErrorDialog.openError(Display.getCurrent().getActiveShell(), "Error Display","Your entry cant be loaded,", status); + } else { + ChangedPressedFieldEditorStatus.setPkiUserKeyStore( newUserKeyStore ); + AuthenticationPlugin.getDefault().setUserKeyStore( newUserKeyStore ); + AuthenticationPlugin.getDefault().setCertificatePath(userSuppliedLocation); + } + return isFound; + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/PKICertLocationFieldEditor.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/PKICertLocationFieldEditor.java new file mode 100644 index 00000000000..d643af2269c --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/PKICertLocationFieldEditor.java @@ -0,0 +1,352 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.preferences; + +import java.io.File; +import java.nio.file.FileSystems; +import java.security.KeyStore; +import java.security.KeyStoreException; + +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.core.pki.pkiselection.PKIProperties; +import org.eclipse.jface.dialogs.DialogPage; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.StringButtonFieldEditor; +import org.eclipse.jface.preference.StringFieldEditor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.pki.pkiselection.PKCSpick; +import org.eclipse.ui.pki.preferences.ChangedPressedFieldEditorStatus; +import org.eclipse.ui.pki.AuthenticationPlugin; +import org.eclipse.core.pki.exception.UserCanceledException; + +/** + * This class can be used in an {@link FieldEditorPreferencePage} to represent an + * pki certificate location.. + * @since 1.3 + * + */ +public class PKICertLocationFieldEditor extends StringButtonFieldEditor { + private String type = null; + String myName=null; + private boolean validInput=true; + private Composite father=null; + boolean inFocus = true; + protected KeyStore updatedKeystore=null; + protected PKIProperties lastPropertyValues=null; + PreferencePage preferencePage=null; + protected final static String FOCUS_LOST="LOST_FOCUS"; + protected final static String FOCUS_GAINED="GAINED_FOCUS"; + private FocusAdapter focusAdapter=null; + private Button changeButton = null; + private static final String UPDATE_PREFERENCE = "Update"; + //private static final String CSPext="java_pkcs11.cfg"; + public PKICertLocationFieldEditor(String name, String labelText, + Composite parent, String pkiType, PreferencePage preferencePage) { + + //System.out.println("PKICertLocationFieldEditor CONSTRUCTOR open "); + this.preferencePage = preferencePage; + init(name, labelText); + myName=name; + type = pkiType; + father=parent; + setErrorMessage(JFaceResources + .getString("DirectoryFieldEditor.errorMessage"));//$NON-NLS-1$ + + setChangeButtonText(JFaceResources.getString("openChange"/*"openBrowse"*/));//$NON-NLS-1$ + //setValidateStrategy(VALIDATE_ON_FOCUS_LOST); + //setValidateStrategy(VALIDATE_ON_KEY_STROKE | VALIDATE_ON_FOCUS_LOST); + //setValidateStrategy(VALIDATE_ON_KEY_STROKE); + //setValidateStrategy(UNLIMITED); + + if ( pkiType.equalsIgnoreCase("PKCS11")) { + setChangeButtonText("Update"); + } + createControl(parent); + //setPropertyChangeListener( listener() ); + getTextControl().addFocusListener( focus(oldValue) ); + lastPropertyValues = PKIProperties.getInstance(); + lastPropertyValues.load(); + + if ( this.getChangeControl(parent) != null ) { + changeButton = this.getChangeControl(parent); + } + } + + + @Override + protected boolean checkState() { + //getPage().getControl().addFocusListener( focus() ); + //System.out.println("PKICertLocationFieldEditor checkState is occring"); + checkValue(); + return validInput; + } + + @Override + public void store() { + //System.out.println("PKICertLocationFieldEditor store values is occring"); + } + + @Override + protected void refreshValidState() { + //System.out.println("PKICertLocationFieldEditor refreshValidState"); + + isValid(); + } + @Override + public boolean isValid() { + + //System.out.println("PKICertLocationFieldEditor isValid check"); + boolean isGood = false; + + try { + if ( inFocus ) { + isGood = checkValue(); + } else { + isGood = true; + super.isValid(); + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + isGood=false; + } + //System.out.println("PKICertLocationFieldEditor isValid check isVALID:"+isGood); + return isGood; + } + + protected boolean checkValue() { + //System.out.println("PKICertLocationFieldEditor in checkValue"); + if ( type.equalsIgnoreCase("pkcs12")) { + return true; + } + /* + * NOTE: Turn off modifiable field and allow "update" button to be enabled. + */ + if ( type.equalsIgnoreCase("pkcs11")) { + return true; + } + + //System.out.println("PKICertLocationFieldEditor --- You should not see this"); + // NOTE: after change above, the rest of code in this method wont run. + String value = getStringValue(); + if ( isPathGood( value ) ) { + validInput=true; + changeButton.setEnabled(true); + if ( isPathConfigGood(value)) { + //System.out.println("PKICertLocationFieldEditor --- turn on apply, but not yest"); + //this.preferencePage.pageChangeListener( myName, "VALIDATE", oldValue, "TURN_ON_APPLY"); + } + } else { + changeButton.setEnabled(false); + validInput=false; + } + + getTextControl(father); + return validInput; + + } +// @Override +// public Text getTextControl(Composite parent) { +// +// Text text= super.getTextControl(parent); +// if ( validInput ) { +// text.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK)); +// System.out.println("PKICertLocationFieldEditor -- Set text color BLACK"); +// } else { +// text.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED)); +// System.out.println("PKICertLocationFieldEditor -- Set text color RED"); +// } +// return text; +// } + + @Override + protected String changePressed(){ + StringBuilder message = new StringBuilder(); + message.append("Reading credentials:"); + String fileName; + KeyStore existingUserKeyStore = null; + KeyStore newUserKeyStore = null; + String path = this.getStringValue(); + try { + + + if ( type.equalsIgnoreCase("PKCS11")) { + + } + if ( (this.getStringValue().equals(oldValue) )) { + //System.out.println("PKICertLocationFieldEditor --- NO CHANGE IN VALUES"); + ChangedPressedFieldEditorStatus.setPkiChangedPressed(false); + ChangedPressedFieldEditorStatus.setJksChangedPressed(false); + } else { + ChangedPressedFieldEditorStatus.setPkiChangedPressed(true); + } + + existingUserKeyStore = AuthenticationPlugin.getDefault().getExistingUserKeyStore(); + ChangedPressedFieldEditorStatus.setPkiUserKeyStore(existingUserKeyStore); + + if(AuthenticationPlugin.getDefault().getExistingUserKeyStore() != null){ + AuthenticationPlugin.getDefault().setUserKeyStore(null); + } + + //System.out.println("PKICertLocationFieldEditor -- changePressed THIS POPS UP THE DISPAY TO CHANGE THE FLAVOR and IT DOES BLOCK"); + /* + * + * NOTE: The following code will pop up an authentication request dialog. IT BLOCKS until either user has pressed cancel button or + * entered the requested security info and successfully pressed finish button. + * + */ + System.out.println("PKICertLocationFieldEditor BEFORE"); + newUserKeyStore = AuthenticationPlugin.getDefault().getUserKeyStore(this.UPDATE_PREFERENCE); + System.out.println("PKICertLocationFieldEditor AFTER"); + /* + * + * NOTE: AFTER blocking, code continues here. + * + */ + if ( newUserKeyStore == null) { + /* + * NOTE: if the keystore is equal NULL, then the user probably pressed cancel. SO restore back to las setting. + */ + System.out.println("PKICertLocationFieldEditor --- NO KEYSORE FOUND"); + preferencePage.exitView = true; + this.preferencePage.pageChangeListener(getPreferenceName(),"VALIDATE", oldValue, "TURN_OFF_APPLY"); + ChangedPressedFieldEditorStatus.setPkiChangedPressed(false); + if ( existingUserKeyStore != null ) { + //System.out.println("PKICertLocationFieldEditor ORIGINAL KEYSTORE TYPE= "+ existingUserKeyStore.getType() ); + AuthenticationPlugin.getDefault().setUserKeyStore(existingUserKeyStore); + if ( "PKCS11".equalsIgnoreCase(existingUserKeyStore.getType()) ) { + PKCSpick.getInstance().setPKCS11on( true ); + PKCSpick.getInstance().setPKCS12on( false ); + lastPropertyValues.setKeyStoreType(existingUserKeyStore.getType()); + lastPropertyValues.restore(); + //AuthenticationPlugin.getDefault().setCertificatePath(Pkcs11Provider.getConfigurePath()); + + + AuthenticationPlugin.getDefault().setCertificatePath("pkcs11"); + + AuthenticationPlugin.getDefault().setUserKeyStoreSystemProperties(existingUserKeyStore); + AuthenticationPlugin.getDefault().setTrustStoreSystemProperties(AuthenticationPlugin.getDefault().obtainDefaultJKSTrustStore()); + } else if ( "PKCS12".equalsIgnoreCase(existingUserKeyStore.getType()) ) { + PKCSpick.getInstance().setPKCS12on( true ); + PKCSpick.getInstance().setPKCS11on( false ); + lastPropertyValues.setKeyStoreType(existingUserKeyStore.getType()); + //debugging + //lastPropertyValues.dump(); + lastPropertyValues.setKeyStoreProvider(existingUserKeyStore.getProvider().getName()); + lastPropertyValues.restore(); + AuthenticationPlugin.getDefault().setCertificatePath(lastPropertyValues.getKeyStore()); + AuthenticationPlugin.getDefault().setUserKeyStoreSystemProperties(existingUserKeyStore); + AuthenticationPlugin.getDefault().setTrustStoreSystemProperties(AuthenticationPlugin.getDefault().obtainDefaultJKSTrustStore()); + } else { + PKCSpick.getInstance().setPKCS12on( false ); + PKCSpick.getInstance().setPKCS11on( false ); + AuthenticationPlugin.getDefault().initialize(); + } + + } else { + //System.out.println("PKICertLocationFieldEditor --- RESET EVERYTHING OH NO VALUES"); + PKCSpick.getInstance().setPKCS12on( false ); + PKCSpick.getInstance().setPKCS11on( false ); + AuthenticationPlugin.getDefault().initialize(); + } + + } else { + //System.out.println("PKICertLocationFieldEditor - NEW KEYSTORE ENTERED"); + ChangedPressedFieldEditorStatus.setPkiChangedPressed(true); + ChangedPressedFieldEditorStatus.setPkiUserKeyStore(newUserKeyStore); + } + //ChangedPressedFieldEditorStatus.setJksChangedPressed(false); + } catch (UserCanceledException e) { + + //} catch (Exception e) { + ChangedPressedFieldEditorStatus.setPkiChangedPressed(false); + ChangedPressedFieldEditorStatus.setPKISaveCertificateChecked(false); + ChangedPressedFieldEditorStatus.setPkiUserKeyStore(null); + + AuthenticationPlugin.getDefault().setUserKeyStore(existingUserKeyStore); + AuthenticationPlugin.getDefault().setCertificatePath(AuthenticationPlugin.getDefault().obtainSystemPropertyPKICertificatePath()); + AuthenticationPlugin.getDefault().setCertPassPhrase(AuthenticationPlugin.getDefault().obtainSystemPropertyPKICertificatePass()); + + System.out.println("PKICertLocationFieldEditor:Unable to set javax.net.ssl properties!"); + } + + fileName = AuthenticationPlugin.getDefault().getCertificatePath(); + + if (( null != fileName ) && (!fileName.isEmpty())) { + fileName = AuthenticationPlugin.getDefault().getCertificatePath(); + if ( PKCSpick.getInstance().isPKCS11on()) { + //System.out.println("PKICertLocationFieldEditor -- EVENT FOR newVALUE:"+fileName+" oldVALUE:"+oldValue+" THIS PREFRENCE:"+getPreferenceName()); + this.preferencePage.pageChangeListener(getPreferenceName(),AuthenticationPreferences.PKCS11_CONFIGURE_FILE_LOCATION, oldValue, fileName); + } else { + this.preferencePage.pageChangeListener(getPreferenceStore(),AuthenticationPreferences.PKI_CERTIFICATE_LOCATION, oldValue, fileName); + } + return fileName; + } else { + this.preferencePage.pageChangeListener(getPreferenceName(),AuthenticationPreferences.PKCS11_CONFIGURE_FILE_LOCATION, oldValue, myName); + if (((this.getStringValue() != null)) && (!this.getStringValue().isEmpty())) { + return this.getStringValue(); + } + } + + return null; + } + + private FocusAdapter focus(final String oldValue) { + focusAdapter = new FocusAdapter() { + public void focusGained(FocusEvent e) { + //System.out.println("PKICertLocationFieldEditor focus gained"); + //getPreferenceStore().firePropertyChangeEvent("FOCUS", oldValue, FOCUS_GAINED); + preferencePage.pageChangeListener(myName, "FOCUS", oldValue, FOCUS_GAINED); + } + public void focusLost(FocusEvent e) { + //System.out.println("PKICertLocationFieldEditor focus LOST "); + inFocus = false; + preferencePage.pageChangeListener(myName,"FOCUS", oldValue, FOCUS_LOST); + //getPreferenceStore().firePropertyChangeEvent("FOCUS", oldValue, FOCUS_LOST); + } + }; + return focusAdapter; + } + private boolean isPathGood( String s ) { + boolean isGood=false; + File f = null; + try { + isGood = new File( s ).exists(); + } catch( Exception e ){} + return isGood; + } + private boolean isPathConfigGood( String s ) { + boolean goodConfig=false; + StringBuilder sb = new StringBuilder(); + try { + sb.append(s); + sb.append(File.separator); + sb.append("java_pkcs11.cfg"); + goodConfig = new File( sb.toString() ).exists(); + } catch( Exception e ){} + + + return goodConfig; + + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/PreferencePage.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/PreferencePage.java new file mode 100644 index 00000000000..abc360887d4 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/PreferencePage.java @@ -0,0 +1,772 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.preferences; + +import java.io.PrintStream; +import java.security.KeyStore; +import java.security.Provider; +import java.security.Security; +import java.util.Optional; + +import org.eclipse.core.pki.AuthenticationBase; +import org.eclipse.core.pki.auth.PKIState; +import org.eclipse.core.pki.pkiselection.PKI; +import org.eclipse.core.pki.pkiselection.PKIProperties; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.FileFieldEditor; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PathEditor; +import org.eclipse.jface.preference.PreferenceStore; +import org.eclipse.jface.preference.StringFieldEditor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.internal.IPreferenceConstants; +import org.eclipse.ui.pki.pkcs.VendorImplementation; +//import org.eclipse.ui.pki.pkiselection.PKCSpick; +import org.eclipse.ui.pki.preferences.ChangedPressedFieldEditorStatus; +import org.eclipse.ui.pki.util.PKISecureStorage; +import org.eclipse.ui.pki.wizard.TrustStoreSecureStorage; +import org.eclipse.ui.preferences.ScopedPreferenceStore; +import org.osgi.service.prefs.BackingStoreException; +import org.eclipse.ui.pki.AuthenticationPlugin; + + +/** + * @since 1.3 + */ +public class PreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { + + private StringFieldEditor pkcs11Certificate; + private StringFieldEditor pkiCertificate; + private StringFieldEditor trustStoreJKS; + private StringFieldEditor securityProvider; + private FileFieldEditor configurationLocationFile; + private PKI previousPKI; + private Composite yourSibling=null; + private String pkiType="NONE"; + private boolean isGoodConfig=false; + public boolean exitView=false; + private Group groups = null; + private String pkcs11Label="Smartcard location Configuration"; + private String pkcs12Label="PKCS12 Certificate Installation location"; + PKISecureStorage pkiSecureStorage = null; +// Display display = Display.getCurrent(); +// Color blue = display.getSystemColor(SWT.COLOR_BLUE); +// Color red = display.getSystemColor(SWT.COLOR_RED); +// Color green = display.getSystemColor(SWT.COLOR_GREEN); +// Color yellow = display.getSystemColor(SWT.COLOR_YELLOW); +// Color black = display.getSystemColor(SWT.COLOR_BLACK); + + public PreferencePage() { + super(FieldEditorPreferencePage.GRID); + noDefaultButton(); + setPreferenceStore(AuthenticationPlugin.getDefault().getPreferenceStore()); + setDescription("PKI Preferences:"); + //printoutStore(); + //listProviders(); + previousPKI = this.previousPKI(); + pkiSecureStorage = new PKISecureStorage(); + } + @Override + public void createControl(Composite parent) { + super.createControl( parent ); + + PlatformUI.getWorkbench().getHelpSystem().setHelp(this.getShell(), + "org.eclipse.pki.preferences"); + } + @Override + protected Control createContents(Composite parent) { + String propertyAddedProvider=null; + // help to debug + //yourParent.getChildren()[0].setBackground(yellow); + + yourSibling = new Composite(parent, SWT.NONE); + + // HELP with debugging... + //yourSibling.setBackground(red); + + yourSibling.setLayoutData( new GridData( GridData.FILL_BOTH ) ); + GridLayout pkiGrid = new GridLayout(); + pkiGrid.marginTop=10; + yourSibling.setLayout( pkiGrid ); + groups = addGroup( yourSibling ); + addFields( groups ); + initialize(); + setEditors(); + checkState(); + + /* + * NOTE: + * When there has been NO pki selection made, then select PKCS11, but ONLY if its been configured by SA's. + * Otherwise, just make the pkcs12 selection available. + */ + + if (PKIState.CONTROL.isPKCS11on()) { + //(VendorImplementation.getInstance().isInstalled() )) { + + //System.out.println("PreferencePage -------- AVAL:"+VendorImplementation.getInstance().isInstalled() ); + //System.out.println("PreferencePage --------- TURNING ON DEFAULT pkcs11 is on"); + setPkcs12InVisible(); + setPkcs11Visible(); + + setVisible(false); + + Optional incomingProvider = Optional.ofNullable(AuthenticationBase.INSTANCE.getPkiProvider()); + if ( incomingProvider.isEmpty() ) { + incomingProvider = Optional.ofNullable(System.getProperty("javax.net.ssl.keyStoreProvider")); + + if (incomingProvider.isEmpty() ) { + propertyAddedProvider="PKCS11"; + } else { + propertyAddedProvider=(String) incomingProvider.get(); + } + securityProvider.setStringValue(propertyAddedProvider); + } else { + securityProvider.setStringValue((String) incomingProvider.get()); + } + System.out.println("PreferencePage --------- preference:"+securityProvider.getStringValue() ); + + Optional cfgDirectoryHolder = Optional.ofNullable(AuthenticationBase.INSTANCE.getCfgDirectory()); + + if ( cfgDirectoryHolder.isEmpty() ) { + configurationLocationFile.setStringValue("Set to your PKCS11 cfg file"); + } else { + configurationLocationFile.setStringValue((String) cfgDirectoryHolder.get()); + } + + System.out.println("PreferencePage --------- set cfgvalue"+configurationLocationFile.getStringValue()); + AuthenticationPlugin.getDefault() + .getPreferenceStore() + .setValue(AuthenticationPreferences.SECURITY_PROVIDER, + securityProvider.getStringValue()); + + AuthenticationPlugin.getDefault() + .getPreferenceStore() + .setValue(AuthenticationPreferences.PKCS11_CFG_FILE_LOCATION, + configurationLocationFile.getStringValue() ); + + } else if (PKIState.CONTROL.isPKCS12on()) { + //System.out.println("PreferencePage --------- pkcs12 is on ----------------"); + setPkcs11InVisible(); + setPkcs12Visible(); + pkiSecureStorage.storePKI(AuthenticationPlugin.getDefault()); + pkiSecureStorage.loadUpPKI(); + + + } else if ((!( PKIState.CONTROL.isPKCS11on() )) && + (!(PKIState.CONTROL.isPKCS12on())) ) { + //(!(VendorImplementation.getInstance().isInstalled() ))) { + //System.out.println("PreferencePage --------- THERE WAS NO DEFAULT pkcs12 is on"); + PKIState.CONTROL.setPKCS12on(true); + setPkcs11InVisible(); + setPkcs12Visible(); + } + + //initialize(); + //setEditors(); + //checkState(); + + yourSibling.layout(); + + parent.redraw(); + return yourSibling; + } + + + private Group addGroup(Composite top) { + Group group = new Group(top, SWT.TOP); + GridData data = new GridData(SWT.TOP, GridData.FILL_HORIZONTAL); + data.horizontalSpan=550; + data.verticalSpan=5; + data.widthHint=650; + data.heightHint = 225; + group.setLayoutData(data); + return group; + } + private void addFields(Group group) { + + configurationLocationFile = new FileFieldEditor(IPreferenceConstants.DEFAULT_EDITORS, + "&PKCS11 config Selection:", true, group ); + + securityProvider = new PKICertLocationFieldEditor(AuthenticationPreferences.SECURITY_PROVIDER, + "Java PKI Security Provider", group, "pkcs11", this); + + pkcs11Certificate = new PKICertLocationFieldEditor("NONE", + "Smartcard repository location", group, "pkcs11", this); + + pkiCertificate = new PKICertLocationFieldEditor(AuthenticationPreferences.PKI_CERTIFICATE_LOCATION, + "Certificate path:", group, "pkcs12", this); + + trustStoreJKS = new TrustStoreLocationFieldEditor(AuthenticationPreferences.TRUST_STORE_LOCATION, + "Trust Store Location:", group); + + configurationLocationFile.setEnabled(true, group); + securityProvider.getTextControl(group).setEnabled(true); + pkcs11Certificate.getTextControl(group).setEnabled(false); + pkiCertificate.getTextControl(group).setEnabled(false); + trustStoreJKS.getTextControl(group).setEnabled(false); + + configurationLocationFile.loadDefault(); + securityProvider.loadDefault(); + pkcs11Certificate.loadDefault(); + pkiCertificate.loadDefault(); + + addField(configurationLocationFile); + addField(securityProvider); + addField(pkcs11Certificate); + addField(pkiCertificate); + + } + + + /** + * Initializes all field editors. + */ + protected void initialize() { + super.initialize(); + + } + protected void setEditors() { + + if (pkiCertificate != null) { + pkiCertificate.setPage(this); + pkiCertificate.setPreferenceStore(AuthenticationPlugin.getDefault().getPreferenceStore()); + pkiCertificate.load(); + } + if (pkcs11Certificate != null) { + pkcs11Certificate.setPage(this); + pkcs11Certificate.setPreferenceStore(AuthenticationPlugin.getDefault().getPreferenceStore()); + pkcs11Certificate.load(); + } + if (trustStoreJKS != null) { + trustStoreJKS.setPage(this); + trustStoreJKS.setPreferenceStore(AuthenticationPlugin.getDefault().getPreferenceStore()); + trustStoreJKS.load(); + } + if (configurationLocationFile != null ) { + configurationLocationFile.setPage(this); + configurationLocationFile.setPreferenceStore(AuthenticationPlugin.getDefault().getPreferenceStore()); + configurationLocationFile.load(); + } + if (securityProvider != null ) { + securityProvider.setPage(this); + securityProvider.setPreferenceStore(AuthenticationPlugin.getDefault().getPreferenceStore()); + securityProvider.load(); + } + } + protected void setPkcs11InVisible() { + + try { + //System.out.println("PreferencePage --------- pkcs12 is on setting PKCS11 INVISIBLE"); + groups.getChildren()[0].setVisible(false); + groups.getChildren()[1].setVisible(false); + groups.getChildren()[2].setVisible(false); + groups.getChildren()[3].setVisible(false); + groups.getChildren()[4].setVisible(false); + groups.getChildren()[5].setVisible(false); + groups.getChildren()[6].setVisible(false); + groups.getChildren()[7].setVisible(false); + groups.getChildren()[8].setVisible(false); + groups.setText(pkcs12Label); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + protected void setPkcs12InVisible() { + + try { + //System.out.println("PreferencePage --------- pkcs11 is on"); + groups.getChildren()[9].setVisible(false); + groups.getChildren()[10].setVisible(false); + groups.getChildren()[11].setVisible(false); + groups.getChildren()[12].setVisible(false); + + groups.setText(pkcs11Label); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + protected void setPkcs11Visible() { + + try { + pkiType="pkcs11"; + groups.setText(pkcs11Label); + + + groups.getChildren()[0].setVisible(true); + groups.getChildren()[1].setVisible(true); + groups.getChildren()[2].setVisible(true); + groups.getChildren()[3].setVisible(true); + groups.getChildren()[4].setVisible(true); + groups.getChildren()[5].setVisible(true); + groups.getChildren()[6].setVisible(true); + groups.getChildren()[7].setVisible(true); + groups.getChildren()[8].setVisible(true); + + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + protected void setPkcs12Visible() { + + try { + pkiType="pkcs12"; + groups.setText(pkcs12Label); + + //groups.getChildren()[7].setVisible(true); + //groups.getChildren()[8].setVisible(true); + groups.getChildren()[9].setVisible(true); + groups.getChildren()[10].setVisible(true); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + public void findGroups() { + Control[] co = groups.getChildren(); + for(Control c : groups.getChildren()) { + + } + for(int i=0; i < co.length; i++) { + if ( co[i] instanceof Label ) { + System.out.println("PreferencePage GROUP:"+ i+" "+co[i].toString()); + } + } + + } + + @Override + protected void performApply() { + //CheckUpdatedKeystoreValue.isValid( pkiCertificate.getStringValue() ); + //super.performApply(); + + //System.out.println("PreferencePage -- APPLY PRESSED FIX the stored values. TYPE:"+pkiType); + try { + if (!(exitView)) { + if ( pkiType.equals("pkcs11") && ChangedPressedFieldEditorStatus.isPkiChangedPressed()) { + //System.out.println("PreferencePage - APPLY PRESSED REQUEST PKCS11 needs to be set"); + if ( pkcs11Certificate.isValid() ) { + PKIState.CONTROL.setPKCS11on(true); + ChangedPressedFieldEditorStatus.setPkiChangedPressed(true); + if ((ChangedPressedFieldEditorStatus.isPkiChangedPressed() ) ) { + if ( CheckUpdatedKeystoreValue.isValid( pkcs11Certificate.getStringValue() )) { + + pkcs11Certificate.setStringValue( "pkcs11" ); + + + //System.out.println("PreferencePage SETTING certificate path for PKCS11 FIX THIS"); + AuthenticationPlugin.getDefault().setCertificatePath("pkcs11"); + + //System.out.println("PreferencePage SECURITYPROVIDER:"+ securityProvider.getStringValue()); + //System.out.println("PreferencePage CFG:"+ configurationLocationFile.getStringValue()); + + + //AuthenticationPlugin.getDefault().getPreferenceStore().setValue(AuthenticationPreferences.SECURITY_PROVIDER, defaultTrustStorePath); + //AuthenticationPlugin.getDefault().getPreferenceStore().setValue(AuthenticationPreferences.PKCS11_CONFIGURE_FILE_LOCATION, defaultTrustStorePath); + + AuthenticationPlugin.getDefault().setUserKeyStore(VendorImplementation.getInstance().getKeyStore()); + AuthenticationPlugin.getDefault().setUserKeyStoreSystemProperties( VendorImplementation.getInstance().getKeyStore() ); + System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11"); + pkcs11Certificate.getTextControl(groups).setEnabled(false); + } + } + } + } + if ( (pkiType.equalsIgnoreCase("pkcs12") && (ChangedPressedFieldEditorStatus.isPkiChangedPressed()))) { + if ( pkiCertificate.isValid() ) { + PKIState.CONTROL.setPKCS12on(true); + if ((ChangedPressedFieldEditorStatus.isPkiChangedPressed() ) ) { + if ( CheckUpdatedKeystoreValue.isValid( pkiCertificate.getStringValue() )) { + AuthenticationPlugin.getDefault().setCertificatePath(pkiCertificate.getStringValue()); + pkiCertificate.getTextControl(groups).setEnabled(false); + } + } + } + } + previousPKI = this.previousPKI(); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Override + protected void performDefaults() { + //System.out.println("PreferencePage --------- perform defaults...----------------------------RE"); + + //getPreferenceStore().removePropertyChangeListener( propertyChangeListener ); +// if ( pkcs11Composite == null) { +// AuthenticationPlugin.getDefault().setUserKeyStore(null); +// super.performDefaults(); +// } + } + + public void init(IWorkbench workbench) { + // TODO Auto-generated method stub + } + + @Override + protected void createFieldEditors() { + // NOT called b/c we override createContents() + } + + /* (non-Javadoc) + * @see org.eclipse.jface.preference.FieldEditorPreferencePage#performOk() + */ + @Override + public boolean performOk() { + boolean isOK=true; + //System.out.println("PreferencePage --------- OK PRESSED REQUEST TBD: FIX the stored values. TYPE:"+pkiType); + + if(ChangedPressedFieldEditorStatus.isJksChangedPressed()){ + //System.out.println("PreferencePage --------- OK PRESSED REQUEST changepresed trust"); + changeJKSTrustStoreSecureStorage(); + //The trust store path, trust store password and key store already set in AuthenticationPlugin when + //the user entered and clicked Finish in the trust store login wizard. + AuthenticationPlugin.getDefault().setTrustStoreSystemProperties(AuthenticationPlugin.getDefault().getExistingTrustStore()); + } + if(ChangedPressedFieldEditorStatus.isSaveConfigurationLocationFileChecked()){ + //System.out.println("PreferencePage --------- OK PRESSED REQUEST changepresed CFG FILE"); + } + + if ((ChangedPressedFieldEditorStatus.isPkiChangedPressed() ) ) { + AuthenticationPlugin.getDefault().setUserKeyStore(ChangedPressedFieldEditorStatus.getPkiUserKeyStore()); + //System.out.println("PreferencePage --------- PROCESSING A PKI CHANGE OK REQUEST"); + if (( PKIState.CONTROL.isPKCS11on()) || ( pkiType.equals("pkcs11") )) { + + //System.out.println("PreferencePage SECURITYPROVIDER:"+ securityProvider.getStringValue()); + //System.out.println("PreferencePage CFG:"+ configurationLocationFile.getStringValue()); + + AuthenticationPlugin.getDefault() + .getPreferenceStore() + .setValue(AuthenticationPreferences.SECURITY_PROVIDER, + securityProvider.getStringValue()); + + AuthenticationPlugin.getDefault() + .getPreferenceStore() + .setValue(AuthenticationPreferences.PKCS11_CFG_FILE_LOCATION, + configurationLocationFile.getStringValue() ); + + /* + * NOTE: + * The USER needs to be able to type in a location. and If its NOT valid, then FAIL this TEST. + */ + isOK = CheckUpdatedKeystoreValue.isValid( pkcs11Certificate.getStringValue() ); + + pkcs11Certificate.setStringValue( "pkcs11" ); + + PKIProperties.getInstance().setKeyStorePassword(AuthenticationPlugin.getDefault().getCertPassPhrase()); + PKIProperties.getInstance().restore(); + } else if (( PKIState.CONTROL.isPKCS12on()) || ( pkiType.equals("pkcs12") )) { + //System.out.println("PreferencePage --------- PROCESSING A CHANGE OK REQUEST FOR PKCS12"); + if ( (pkiCertificate.getStringValue() != null ) || (!pkiCertificate.getStringValue().isEmpty() )){ + isOK = CheckUpdatedKeystoreValue.isValid( pkiCertificate.getStringValue() ); + } else { + // The value was alaready set in authentication plugin so get it from there. + isOK = CheckUpdatedKeystoreValue.isValid( AuthenticationPlugin.getDefault().getCertificatePath() ); + } + } else { + //System.out.println("PreferencePage --------- PROCESSING A CHANGE OK REQUESt NO SELECTION"); + } + + changePKISecureStorage(); + //System.out.println("PreferencePage -----------performOK SETING TRUSTSTORE VALUE BACK to initial value:"+ AuthenticationPlugin.getDefault().obtainSystemPropertyJKSPath()); + //AuthenticationPlugin.getDefault().setTrustStoreSystemProperties(AuthenticationPlugin.getDefault().getExistingTrustStore()); + + //trustStoreJKS.setStringValue(AuthenticationPlugin.getDefault().obtainSystemPropertyJKSPath()); + + //createContents(yourParent); + + //The pki path, pki password and key store already set in AuthenticationPlugin when + //the user entered and clicked Finish in the pki login wizard. + //AuthenticationPlugin.getDefault().setUserKeyStoreSystemProperties(AuthenticationPlugin.getDefault().getExistingUserKeyStore()); + + } else { + //System.out.println("PreferencePage --------- OK PRESSED REQUEST AND DING A RESTORE OF OLD VALUES"); + previousPKI.reSetSystem(); + } + + ChangedPressedFieldEditorStatus.setPKISaveCertificateChecked(false); + ChangedPressedFieldEditorStatus.setJKSSaveTrustStoreChecked(false); + ChangedPressedFieldEditorStatus.setSaveConfigurationLocationFileChecked(false); + ChangedPressedFieldEditorStatus.setPkiChangedPressed(false); + ChangedPressedFieldEditorStatus.setJksChangedPressed(false); + + //System.out.println("PreferencePage -----------performOK DONE VALUE:"+isOK); + if ( isOK ) { + super.performOk(); + } + + //return super.performOk(); + return isOK; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.preference.PreferencePage#performCancel() + */ + @Override + public boolean performCancel() { + + //String jksTrustStorePathInSystemProperties = AuthenticationPlugin.getDefault().obtainSystemPropertyJKSPath(); + String jksTrustStorePathInSystemProperties =""; + + if(ChangedPressedFieldEditorStatus.isPkiChangedPressed()){ + AuthenticationPlugin.getDefault().setUserKeyStore(ChangedPressedFieldEditorStatus.getPreviousUserKeyStore()); + previousPKI.reSetSystem(); + if ( previousPKI.getKeyStoreType().equalsIgnoreCase("PKCS11") ) { + PKIState.CONTROL.setPKCS11on(true); + PKIState.CONTROL.setPKCS12on(false); + AuthenticationPlugin.getDefault().setCertificatePath("pkcs11" ); + pkcs11Certificate.setStringValue("pkcs11"); + } + if ( previousPKI.getKeyStoreType().equalsIgnoreCase("PKCS12") ) { + PKIState.CONTROL.setPKCS12on(true); + PKIState.CONTROL.setPKCS11on(false); + String pkiCertificatePathInSystemProperties = AuthenticationPlugin.getDefault().obtainSystemPropertyPKICertificatePath(); + AuthenticationPlugin.getDefault().setCertificatePath(pkiCertificatePathInSystemProperties); + pkiCertificate.setStringValue(pkiCertificatePathInSystemProperties); + } + PKIProperties.getInstance().load(); + AuthenticationPlugin.getDefault().setCertPassPhrase(AuthenticationPlugin.getDefault().obtainSystemPropertyPKICertificatePass()); + AuthenticationPlugin.getDefault().setTrustStoreSystemProperties(AuthenticationPlugin.getDefault().getTrustStore()); + + if ( previousPKI.isSecureStorage()) { + ChangedPressedFieldEditorStatus.setPKISaveCertificateChecked( true ); + changePKISecureStorage(); + } + + } else { + //System.out.println("PreferencePage -----------performCANCEL THERE WAS NO CHANGE,,,.."); + } + + if(ChangedPressedFieldEditorStatus.isJksChangedPressed()){ + AuthenticationPlugin.getDefault().setTrustStore(ChangedPressedFieldEditorStatus.getJksTrustStore()); + AuthenticationPlugin.getDefault().getPreferenceStore().setValue(AuthenticationPreferences.TRUST_STORE_LOCATION, jksTrustStorePathInSystemProperties); + AuthenticationPlugin.getDefault().setTrustStorePassPhrase(AuthenticationPlugin.getDefault().obtainSystemPropertyJKSPass()); + } + + ChangedPressedFieldEditorStatus.setPkiChangedPressed(false); + ChangedPressedFieldEditorStatus.setJksChangedPressed(false); + + + ChangedPressedFieldEditorStatus.setPKISaveCertificateChecked(false); + ChangedPressedFieldEditorStatus.setJKSSaveTrustStoreChecked(false); + + ChangedPressedFieldEditorStatus.setPkiUserKeyStore(null); + ChangedPressedFieldEditorStatus.setJksTrustStore(null); + + return super.performCancel(); + + } + @Override + public boolean okToLeave() { + //System.out.println("PreferencePage ----------------------------------------ok to leave"); + + //initialize(); + //this.performApply(); + //this.performDefaults(); + + /* + *** dont do this because it causes problems + * this.getShell().setVisible(false); + */ +// return false; + return true; + } +// @Override +// public void setValid( boolean b ) { +// isGoodConfig = b; +// } + + @Override + public boolean isValid() { + //System.out.println("PreferencePage ------ isValid"); + boolean isGood=false; + isGood=isGoodConfig; + if ( PKIState.CONTROL.isPKCS12on()) { + isGood=true; + } + if ( PKIState.CONTROL.isPKCS11on()) { + if ( pkcs11Certificate.isValid() ) { + isGood=true; + } + } + if ((!(PKIState.CONTROL.isPKCS11on())) && + (!(PKIState.CONTROL.isPKCS12on())) ) { + isGood=true; + } + //System.out.println("PreferencePage --------------------------isValid-----------------VALID:"+isGoodConfig); + + /* + * TODO + * Figure out how to see if focus is lost for this preference page. + * Till then the apply and OK buttons need to be ALEWAYS enabled. + */ + //isGood=true; + return isGood; + } + + /** + * Store changed PKI information to secure storage. + */ + private void changePKISecureStorage(){ + + pkiSecureStorage = new PKISecureStorage(); + if(ChangedPressedFieldEditorStatus.isPKISaveCertificateChecked()){ + pkiSecureStorage.storePKI(AuthenticationPlugin.getDefault()); + } else { + pkiSecureStorage.getNode().removeNode(); + } + } + + /** + * Store changed jks trust store to secure storage. + */ + private void changeJKSTrustStoreSecureStorage(){ + AuthenticationPlugin.getDefault().getPreferenceStore().setValue(AuthenticationPreferences.TRUST_STORE_LOCATION, trustStoreJKS.getStringValue() ); + TrustStoreSecureStorage jksTrustStore = new TrustStoreSecureStorage(); + if(ChangedPressedFieldEditorStatus.isJKSSaveTrustStoreChecked()){ + jksTrustStore.storeJKS(AuthenticationPlugin.getDefault()); + } else { + jksTrustStore.getNode().removeNode(); + } + } + public boolean pageChangeListener(Object source, String property, String oldValue, String newValue ) { + boolean pageUpdate=true; + + try { + if ( "FOCUS".equals(property)) { + if ( newValue.equals(PKICertLocationFieldEditor.FOCUS_LOST) ) { + isGoodConfig=true; + exitView=true; + setValid(true); + } + if ( newValue.equals(PKICertLocationFieldEditor.FOCUS_GAINED) ) { + isGoodConfig=false; + exitView=false; + setValid(false); + } + } + if ( "VALIDATE".equals(property)) { + if ( newValue.equals("TURN_ON_APPLY") ) { + //System.out.println("PreferencePage ------ APPLY EVENT TURN ON GOOD CONFIG GOODCONIF:"+isGoodConfig); + if (!( isGoodConfig) ) { + //System.out.println("PreferencePage ------ APPLY EVENT TURN ON GOOD CONFIG"); + isGoodConfig=true; + setValid(true); + setVisible(true); + } + updateApplyButton(); + } + if ( newValue.equals("TURN_OFF_APPLY") ) { + //System.out.println("PreferencePage ------ APPLY EVENT TURN OFF APPLY --- GOOD CONFIG"); + isGoodConfig=false; + setValid(false); + setVisible(true); + } + } + if ( AuthenticationPreferences.PKI_CERTIFICATE_LOCATION.equals(property)) { + if ( newValue != null) { + setPkcs11InVisible(); + setPkcs12Visible(); + pkcs11Certificate.setStringValue((String) ""); + pkiCertificate.setStringValue((String) newValue); + isGoodConfig=true; + setValid(true); + } + } + if ( AuthenticationPreferences.PKCS11_CONFIGURE_FILE_LOCATION.equals(property)) { + if ( newValue != null) { + setPkcs12InVisible(); + setPkcs11Visible(); + pkiCertificate.setStringValue((String) ""); + pkcs11Certificate.setStringValue((String) newValue); + isGoodConfig=true; + setValid(true); + } + } + + } catch( Exception pageProcessorError) { + pageProcessorError.printStackTrace(); + } + + return pageUpdate; + } + + protected PKI previousPKI() { + PKI pki = new PKI(); + PKIProperties current = PKIProperties.getInstance(); + pkiSecureStorage = new PKISecureStorage(); + if (pkiSecureStorage.isPKISaved()) { + pki.setSecureStorage(true); + } + current.load(); + pki.setKeyStore(current.getKeyStore()); + pki.setKeyStorePassword(current.getKeyStorePassword()); + pki.setKeyStoreProvider(current.getKeyStoreProvider()); + pki.setKeyStoreType(current.getKeyStoreType()); + return pki; + } + public static void listProviders() { + for ( Provider provider : Security.getProviders() ) { + System.out.println("PreferencePage -BEFORE ADDING ANY Provider NAME:"+ provider.getName() ); + } + } + + public void printoutStore() { + PrintStream ps = new PrintStream( System.out); + ScopedPreferenceStore store = (ScopedPreferenceStore) AuthenticationPlugin.getDefault().getPreferenceStore(); + IEclipsePreferences[] prefs = store.getPreferenceNodes(true); + for ( IEclipsePreferences node : prefs) { + try { + String[] keys=node.keys(); + for ( String name : keys) { + System.out.println("PreferencePage PREF:"+ name+" VALUE:"+ + node.get(name, null)); + } + } catch (BackingStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + + //String[] names = store.preferenceNames(); + //for ( String name : names) { + // System.out.println("PreferencePage PREF:"+ name+" VALUE:"+ store.getDefaultString(name)); + //} +// PreferenceStore store = (PreferenceStore) this.getPreferenceStore(); +// store.list ( ps ); + + + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/TrustStoreLocationFieldEditor.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/TrustStoreLocationFieldEditor.java new file mode 100644 index 00000000000..d44d6263d92 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/preferences/TrustStoreLocationFieldEditor.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.preferences; + +import java.security.KeyStore; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.StringButtonFieldEditor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.pki.preferences.ChangedPressedFieldEditorStatus; +import org.eclipse.ui.pki.AuthenticationPlugin; +import org.eclipse.core.pki.exception.UserCanceledException; + +/** + * This class can be used in an {@link FieldEditorPreferencePage} to represent a trust store + * location. Validation is performed as the user enters a new value. + * @since 1.3 + * + */ +public class TrustStoreLocationFieldEditor extends StringButtonFieldEditor { + + public TrustStoreLocationFieldEditor(String name, String labelText, + Composite parent) { + init(name, labelText); + setEmptyStringAllowed(false); + setErrorMessage(JFaceResources + .getString("DirectoryFieldEditor.errorMessage"));//$NON-NLS-1$ + setChangeButtonText(JFaceResources.getString("openChange"/*"openBrowse"*/));//$NON-NLS-1$ + setValidateStrategy(VALIDATE_ON_FOCUS_LOST); + createControl(parent); + } + + + @Override + protected String changePressed(){ + ChangedPressedFieldEditorStatus.setJksChangedPressed(true); + String fileName; + KeyStore existingJKSTrustStore = null; + try{ + + existingJKSTrustStore = AuthenticationPlugin.getDefault().getExistingTrustStore(); + + ChangedPressedFieldEditorStatus.setJksTrustStore(existingJKSTrustStore); + + if(AuthenticationPlugin.getDefault().getExistingTrustStore() != null){ + AuthenticationPlugin.getDefault().setTrustStore(null); + } + + AuthenticationPlugin.getDefault().getJKSTrustStore(); + + } catch (UserCanceledException e) { + + ChangedPressedFieldEditorStatus.setJksChangedPressed(false); + ChangedPressedFieldEditorStatus.setJKSSaveTrustStoreChecked(false); + ChangedPressedFieldEditorStatus.setJksTrustStore(null); + + AuthenticationPlugin.getDefault().setTrustStore(existingJKSTrustStore); + AuthenticationPlugin.getDefault().getPreferenceStore().setValue( + AuthenticationPreferences.TRUST_STORE_LOCATION, AuthenticationPlugin.getDefault().obtainSystemPropertyJKSPath()); + AuthenticationPlugin.getDefault().setTrustStorePassPhrase(AuthenticationPlugin.getDefault().obtainSystemPropertyJKSPass()); + + //System.out.println("Unable to set javax.net.ssl properties!"); + } + + fileName = AuthenticationPlugin.getDefault().getPreferenceStore().getString(AuthenticationPreferences.TRUST_STORE_LOCATION); + + if ( null != fileName ) { + return fileName; + } + + return null; + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/KeyStoreUtil.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/KeyStoreUtil.java new file mode 100644 index 00000000000..87ab5ee5cf4 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/KeyStoreUtil.java @@ -0,0 +1,264 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.util; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Hashtable; + +import javax.security.auth.login.FailedLoginException; + +import org.eclipse.core.pki.util.KeyStoreFormat; + +//import sun.security.pkcs11.wrapper.PKCS11Exception; + +public class KeyStoreUtil { + + + /** + * Returns a KeyStore object loaded from provided file location and decrypted with given password + * @param fileLocation + * @param password + * @param format "JKS", "PKCS12" + * @return + * @throws KeyStoreException + * @throws IOException + * @throws CertificateException + * @throws NoSuchAlgorithmException + * @throws SecurityException + * @throws NoSuchMethodException + * @throws InvocationTargetException + * @throws IllegalArgumentException + * @throws IllegalAccessException + * @throws InstantiationException + * @throws ClassNotFoundException + */ + protected static boolean isKeyStoreInitialized=false; + protected final static int DIGITAL_SIGNATURE=0; + protected static KeyStore keystore=null; + public static KeyStore getKeyStore(String fileLocation, String password, KeyStoreFormat format) + throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { + InputStream in = null; + try { + + //if selection is pkcs11 then pkcs11 provider. + //Put code here instead of in pkcs11 widget action so that an error thrown can be + //displayed on the user interface. + /* + * IF we are pkcs11, this method SHOULD NEVER be called. + */ +// if (KeyStoreFormat.PKCS11.getValue().equals(format.getValue())){ +// Pkcs11Provider provider = new Pkcs11Provider(); +// provider.setSecurityProvider(fileLocation); +// } + + in = new FileInputStream(fileLocation); + in = new BufferedInputStream(in); + return getKeyStore(in, password, format); + } finally { + try { + in.close(); + } catch (Throwable t) {} + } + } + + /** + * Returns a KeyStore object loaded from provided {@link InputStream} and decrypted with given password + * @param in + * @param password + * @param format "JKS", "PKCS12", "PKCS11" + * @return + * @throws KeyStoreException + * @throws NoSuchAlgorithmException + * @throws CertificateException + * @throws IOException + */ + public static KeyStore getKeyStore(InputStream in, String password, KeyStoreFormat format) + throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { + + keystore = KeyStore.getInstance(format.getValue()); + char pwd[] = null; + if(password != null) + pwd = password.toCharArray(); + + keystore.load(in, pwd); + return keystore; + + } + public static KeyStore getKeyStore(KeyStoreFormat format) + throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, NoSuchProviderException { + + String pin=""; + KeyStore.PasswordProtection pp = new KeyStore.PasswordProtection(pin.toCharArray()); + keystore = KeyStore.getInstance("pkcs11", "SunPKCS11" ); + try { + keystore.load(null, pp.getPassword()); + isKeyStoreInitialized=true; + } catch (IOException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + //System.out.println("KeyStoreUtil ------ The user elected to press cancel, KEYSOTRE is NOT initialized."); + keystore=null; + } + return keystore; + } + public static KeyStore getKeyStore() { return keystore; } + public static Hashtable getCertificates(KeyStore keyStore) { + + Hashtable table = new Hashtable(); + PrivateKey privateKey=null; + + try { + if ( isKeyStoreInitialized ) { + Enumeration aliasesEnum = keyStore.aliases(); + while (aliasesEnum.hasMoreElements()) + { + String alias = (String) aliasesEnum.nextElement(); + X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); + try { + if ( isDigitalSignature(certificate.getKeyUsage()) ) { + privateKey = (PrivateKey) keyStore.getKey(alias, null); + if ( privateKey != null) { + table.put(certificate, privateKey); + } + } + } catch (UnrecoverableKeyException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return table; + + } + public static ArrayListgetAliases(KeyStore keyStore) { + + ArrayListaliasList = new ArrayList(); + PrivateKey privateKey=null; + try { + Enumeration aliasesEnum = keyStore.aliases(); + while (aliasesEnum.hasMoreElements()) + { + String alias = (String) aliasesEnum.nextElement(); + X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); + try { + if ( isDigitalSignature(certificate.getKeyUsage()) ) { +// privateKey = (PrivateKey) keyStore.getKey(alias, null); +// if ( privateKey != null) { +// aliasList.add(alias); +// } + aliasList.add(alias); + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + //System.out.println("END OF WHILE STATUEM"); + } + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return aliasList; + + } + private static boolean isDigitalSignature(boolean[] ba) { + if ( ba != null) { + return ba[DIGITAL_SIGNATURE]; + } else { + return false; + } + } + + public static boolean checkUserKeystorePass(String certPath, String password, String certType) + { + StringBuilder message = new StringBuilder(); + message.append( "Problem reading your certificate. \n\r \n\r" ); + + try { + + KeyStore keyStore = getKeyStore(certPath, password, KeyStoreFormat.valueOf(certType) ); + getAliases( keyStore); + return true; + } + + catch (KeyStoreException e) { + message.append( "The selected file does not appear " ); + message.append( "to be a valid PKCS file. Please " ); + message.append( "select a different file and/or " ); + message.append( "check the logs for more information." ); + System.err.printf("%s\n", message.toString()); + } + + catch (NoSuchAlgorithmException e) { + message.append( "An unexpected error '" ); + message.append( e.getClass().getName() ); + message.append( "' occurred: " ); + message.append( e.getMessage() ); + message.append( " Please select a different file and/or " ); + message.append( "check the logs for more information." ); + System.err.printf("%s\n", message.toString()); + } + + catch (CertificateException e) { + message.append( "Either your password was incorrect or the " ); + message.append( "the selected file is corrupt. Please try " ); + message.append( "a different password or PKCS file." ); + System.err.printf("%s CertificateException: %s\n", message.toString(), e.getMessage()); + } + + catch (IOException e) { + if ( e.getCause().toString().contains("FailedLoginException")) { + message.append( "\tYou entered an incorrect password. \n\r" ); + message.append( "\tPlease check your password and re-enter it. \n\r \n\r" ); + System.err.printf("%s IOException: %s\n", message.toString(), e.getMessage()); + } else { + + message.append( "Either your password was incorrect or the " ); + message.append( "selected file is corrupt. Please try " ); + message.append( "a different password or PKCS file." ); + System.err.printf("%s IOException: %s\n", message.toString(), e.getMessage()); + } + } + + //System.out.println("KeyStoreUtil ----------checkUserKeystorePass NEEDS TO RETURN FALSE and its NOT"); + return false; + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/PKIAuthenticator.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/PKIAuthenticator.java new file mode 100644 index 00000000000..6591cefd8a7 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/PKIAuthenticator.java @@ -0,0 +1,255 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.util; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.security.Key; +import java.security.KeyPair; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.security.Security; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.pki.exception.InvalidPkcs12StreamException; +import org.eclipse.core.pki.exception.NonDigitalSignatureCertificateException; +import org.eclipse.core.pki.exception.WrongPasswordException; + + +/** + * The PKIAuthenticator is a Singleton class used to load and store a user's + * Certificate information. It currently supports the PKCS12 format for user + * keystores. + * + * @version 1.0 + * @since 1.0 + */ +public class PKIAuthenticator extends java.net.Authenticator { + private final static PKIAuthenticator INSTANCE = new PKIAuthenticator(); + + private String DN = null; + private String sid = null; + private String userPassword = null; + private String keystoreFilename = null; + + private X509Certificate certificate = null; + private X509Certificate[] certChain = null; + private KeyStore keystore = null; + private KeyPair keypair = null; + + private PKIAuthenticator() { + java.net.Authenticator.setDefault( INSTANCE ); + } + + /** + * Returns a unique instance of the PKIAuthenticator class. + * + * @return PKIAuthenticator + */ + public synchronized static PKIAuthenticator getInstance() { + return INSTANCE; + } + + /** + * Gets the subject DN of the user certificate. + * + * @return DN + * @uml.property name="dN" + */ + public String getDN() { + return DN; + } + + /** + * Gets the sid embedded in the subject DN of the user certificate. + * + * @return sid + * @uml.property name="sid" + */ + public String getSid() { + return sid; + } + + /** + * Gets the password needed to decrypt the PKCS#12 file. + * + * @return password + */ + public String getPassword() { + return userPassword; + } + + /** + * Gets the name of the PKCS#12 file. + * + * @return filename + * @uml.property name="keystoreFilename" + */ + public String getKeystoreFilename() { + return keystoreFilename; + } + + /** + * Gets the digital signature public key certificate for the user. + * + * @return certificate + */ + public X509Certificate getDSCertificate() { + return certificate; + } + + /** + * Gets the chain of certificates in the PKCS#12 file. The chain begins with + * the user's digital signature certificate. + * + * @return certificate chain (as a defensive copy) + */ + public X509Certificate[] getCertificateChain() { + if ( certChain == null ) + return null; + + X509Certificate[] cc = new X509Certificate[ certChain.length ]; + System.arraycopy( certChain, 0, cc, 0, certChain.length ); + return cc; + } + + /** + * Gets the contents of the PKCS#12 file as a KeyStore. + * + * @return keystore + * @uml.property name="keystore" + */ + public KeyStore getKeystore() { + return keystore; + } + + /** + * Gets the user's public and private keys. + * + * @return key pair + * @uml.property name="keypair" + */ + public KeyPair getKeypair() { + return keypair; + } + + /** + * Gets the user's private key. + * + * @return private key + */ + public PrivateKey getPrivateKey() { + return keypair.getPrivate(); + } + + /** + * Gets the user's public key. + * + * @return public key + */ + public PublicKey getPublicKey() { + return keypair.getPublic(); + } + + /** + * Returns true if the specified certificate is a digital signature + * certificate . + * + * @param certificate The Certificate to be tested for usage. + * @return True if the certificate is a digital signature certificate, + * false otherwise. + */ + private boolean isDigitalSignatureCertificate( X509Certificate certificate) { + return (certificate.getKeyUsage()[0]); + } + + /** + * Extracts and returns the user's SID from the DN of the the specified + * certificate. The DN looks like this: + * CN=Doe John Keith jkdoe,OU=D009,OU=POW,OU=DDD,O=Gubm,C=CA + * This algorithm was adapted from this perl regex: + * my ($affil, $sid) = ($client_dn =~ /C=(\w\w).*?CN=.*?\(?(\S+?)\)?$/); + * + * @param certificate The Certificate containing the user's SID. + * @return The user's SID. + */ + public static String getSid( X509Certificate certificate ) { + String distinguishedName = certificate.getSubjectX500Principal().getName(); + //System.out.println("distingushed name " + distinguishedName); + String[] attributes = distinguishedName.split( "," ); + + // + // pattern to pull out sid from "Doe John Keith jkdoe" The sid may have parens + // around it which means it's second party. + // + Pattern filenamePat = Pattern.compile(".*?\\(?(\\S+?)\\)?$", Pattern.CASE_INSENSITIVE); + + for ( int i = 0; i < attributes.length; i++ ) + { + String[] attribute = attributes[ i ].split( "=" ); + if ( attribute[ 0 ].equalsIgnoreCase( "CN" ) ) + { + //System.out.println(attribute[1]); + Matcher m = filenamePat.matcher(attribute[1]); + if (m.matches()); + { + //System.out.println("Found it " + m.group(1)); + return m.group(1); + } + } + } + return null; + } + + + /** + * Extracts and returns the user's affiliation from the DN of the the specified + * certificate. The DN looks like this: + * CN=Doe John Keith jkdoe,OU=D004,OU=POW,OU=DDD,O=Gubm,C=CA + * This algorithm was adapted from this perl regex: + * my ($affil, $sid) = ($client_dn =~ /C=(\w\w).*?CN=.*?\(?(\S+?)\)?$/); + * + * @param certificate The Certificate containing the user's SID. + * @return The user's affiliation US, UK, etc + */ + public static String getAffiliation( X509Certificate certificate ) { + String distinguishedName = certificate.getSubjectX500Principal().getName(); + //System.out.println("distingushed name " + distinguishedName); + String[] attributes = distinguishedName.split( "," ); + + for ( int i = 0; i < attributes.length; i++ ) + { + String[] attribute = attributes[ i ].split( "=" ); + + if ( attribute[ 0 ].equalsIgnoreCase( "C" ) ) + { + //System.out.println("Country code is " + attribute[1]); + return attribute[1]; + } + } + return null; + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/PKISecureStorage.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/PKISecureStorage.java new file mode 100644 index 00000000000..a39645db3fe --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/PKISecureStorage.java @@ -0,0 +1,306 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.util; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; + +import org.eclipse.core.pki.auth.PKIState; +import org.eclipse.core.pki.pkiselection.PKIProperties; +import org.eclipse.core.pki.util.ExpiredCertCheck; +import org.eclipse.core.pki.util.KeyStoreManager; +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.equinox.security.storage.ISecurePreferences; +import org.eclipse.equinox.security.storage.SecurePreferencesFactory; +import org.eclipse.equinox.security.storage.StorageException; +import org.eclipse.ui.pki.AuthenticationPlugin; +import org.eclipse.ui.pki.pkcs.VendorImplementation; +import org.eclipse.ui.pki.pkiselection.PKCSSelected; +import org.eclipse.ui.pki.pkiselection.PKCSpick; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +/** + * + * + */ +public class PKISecureStorage extends AbstractUIPlugin { + + private ISecurePreferences securePreference = null; + private ISecurePreferences node = null; + + private transient String certPassPhrase; + private String certificateLocation; + protected PKIProperties auth=PKIProperties.getInstance(); + private static final String JAVA_SSL_USER_KEY_STORE_PATH_KEY = "javax.net.ssl.keyStore"; + private static final String JAVA_SSL_USER_KEY_STORE_TYPE_KEY = "javax.net.ssl.keyStoreType"; + private static final String JAVA_SSL_USER_KEY_STORE_PASS_KEY = "javax.net.ssl.keyStorePassword"; + + protected final String PKI_LOCATION = "pki_location"; + protected final String PKCS11_LOCATION = "pkcs11_location"; + protected final String PKCS12_LOCATION = "pkcs12_location"; + protected final String PKI_TYPE = "pki_type"; + protected final String PKI_STATUS = "pki_status"; + protected final String PKI_PIN = "pki_pin"; + protected final String PKI_PASSPHRASE = "pki_passphrase"; + protected final String PKI_SAVED = "pki_saved"; + protected final String PKI_PROVIDER = "pki_provider"; + protected final String PKI_USER_STORE_NODE = "org.eclipse.pki.util/userKeyStore"; + protected final String SVNSaveAuthorizationInfo = "Save Authorization Info"; + + public PKISecureStorage(){ + this.securePreference = SecurePreferencesFactory.getDefault(); + this.node = securePreference.node(PKI_USER_STORE_NODE); + } + + /** + * Stores the pki information in secure storage. + * @param authenticationInfo the authentication plugin containing the information input by user. + */ + public void storePKI(AuthenticationPlugin authenticationInfo){ + try { + + String userKeyStoreLocation = authenticationInfo.getCertificatePath().trim(); + String passPhrase = authenticationInfo.getCertPassPhrase().trim(); + //System.out.println("PKISexcureStorage - LOCATION:"+userKeyStoreLocation+" PASSwd:"+passPhrase); + if ( PKIState.CONTROL.isPKCS11on() ) { + node.remove(PKCS12_LOCATION); + node.remove(PKI_PASSPHRASE); + node.put(PKI_TYPE, "PKCS11", false); + + userKeyStoreLocation = "pkcs11"; + node.put(PKCS11_LOCATION, userKeyStoreLocation, false); + node.put(PKI_PIN, passPhrase, true); + } + if ( PKIState.CONTROL.isPKCS12on() ) { + String status = ExpiredCertCheck.INSTANCE.getDate(userKeyStoreLocation, passPhrase.toCharArray()); + node.remove(PKCS11_LOCATION); + node.remove(PKI_PIN); + node.put(PKI_TYPE, "PKCS12", false); + node.put(PKI_STATUS, status, false); + node.put(PKCS12_LOCATION, userKeyStoreLocation, false); + node.put(PKI_PASSPHRASE, passPhrase, true); + } + node.put(PKI_SAVED, "true", false); + try { + node.flush(); + } catch (IOException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } + } catch (StorageException e) { + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } + } + + /** + * The secure storage node containing the information. + * @return the secure storage node. + */ + public ISecurePreferences getNode(){ + return node; + } + + /** + * Test if pki is saved in secure storage. + * @return true if saved or false if not saved. + */ + public boolean isPKISaved(){ + boolean saved = false; + try { + if("true".equals(node.get(PKI_SAVED, "false"))){ + saved = true; + } + } catch (StorageException e) { + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } + return saved; + } + public String getPkiType() { + String type = null; + try { + type = node.get(PKI_TYPE, "none"); + } catch (StorageException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return type; + } + + /** + * Creates the user key store from secure storage. + * @return the user key store from secure storage. + */ + public KeyStore getUserKeyStore(){ + String certLocation = null; + KeyStore keyStore = null; + String pkiType=null; + + try { + if ( !(node.get(PKI_TYPE, "none").equals("none"))) { + pkiType = node.get(PKI_TYPE, "none"); + } else { + /* + * TODO: make backwards compatible, default to pkcs12, because pkiType came to the game late. + */ + pkiType = "PKCS12"; + } + + if (( PKIState.CONTROL.isPKCS11on()) && (( pkiType.equals("PKCS11")))) { + VendorImplementation vendorImplementation = VendorImplementation.getInstance(true); + if ( vendorImplementation.isInstalled() ) { + vendorImplementation.login(node.get(PKI_PIN, "none")); + keyStore = VendorImplementation.getInstance().getKeyStore(); + AuthenticationPlugin.getDefault().setUserKeyStoreSystemProperties(keyStore); + auth.load(); + } else { + //System.out.println("PKISecureStorage -- PKCS11 NOT enabled"); + } + } else if (( PKIState.CONTROL.isPKCS12on() ) && (( pkiType.equals("PKCS12")))) { + certLocation = node.get(PKCS12_LOCATION, "none"); + if (certLocation.equals("none") ) { + certLocation = node.get(PKI_LOCATION, "none"); + } + try { + /* + * NOTE: The following code will pop up a prompt for secure storage password on UNIX only, but NOT windoz. + * 1. Should we be requesting password on windows too? + * 2. Perhaps, after getting password ONCE, then subsequently just load and go. + * 3. There is a catch block below that logs when the cancel button is pressed on the password dialog. + */ + certPassPhrase = node.get(PKI_PASSPHRASE, "none"); + certificateLocation = certLocation; + + try { + keyStore = KeyStoreManager.INSTANCE.getKeyStore(certLocation, certPassPhrase, PKCSSelected.getKeystoreformat()); /*KeyStoreFormat.PKCS12*/ + //keyStore = KeyStoreUtil.getKeyStore(certLocation, certPassPhrase, PKCSSelected.getKeystoreformat()); /*KeyStoreFormat.PKCS12*/ + + //keyStore = KeyStoreManager(); + //System.out.println("PKISecureStorage - GetUserkeystore setup done"); + //} catch (KeyStoreException e){ + // LogUtil.logError(SVNSaveAuthorizationInfo, e); + //} catch (NoSuchAlgorithmException e){ + // LogUtil.logError(SVNSaveAuthorizationInfo, e); + //} catch (CertificateException e){ + // LogUtil.logError(SVNSaveAuthorizationInfo, e); + //} catch (IOException e){ + // LogUtil.logError(SVNSaveAuthorizationInfo, e); + } catch (IllegalArgumentException e) { + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } catch (SecurityException e) { + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } + } catch (Exception e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + //System.out.println("PKISecureStorage - I PRESSED CANCEL When prompted for SS password...."); + + IStatus status = new Status (IStatus.OK, AuthenticationPlugin.getPluginId()," Canceled Secure Storage Loading..."); + AuthenticationPlugin.getDefault().getLog().log(status); + } + } + } catch (Exception e) { + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } + return keyStore; + } + public void loadUpPKI( ) { + //System.out.println("PKISecureStorage - loaduppki...."); + try { + if ( PKIState.CONTROL.isPKCS11on() ) { + this.certificateLocation=node.get(PKCS11_LOCATION, "none"); + this.certPassPhrase = node.get(PKI_PIN, "none"); + if ( this.certificateLocation.equalsIgnoreCase("none")) { + this.certificateLocation = "pkcs11"; + } + } + if ( PKIState.CONTROL.isPKCS12on() ) { + this.certificateLocation=node.get(PKCS12_LOCATION, "none"); + if ( this.certificateLocation.equals("none") ) { + this.certificateLocation=node.get(PKI_LOCATION, "none"); + } + // NOTE: Is it still "none" ???? then set it to something. + if ( this.certificateLocation.equalsIgnoreCase("none")) { + /* + * NOTE: If you change it to anything other than "none" make sure you also start checking for that + * value ALL the code that uses th elocation. FYI; Best choice is "none"... + */ + } + } + AuthenticationPlugin.getDefault().setCertificatePath( this.certificateLocation ); + AuthenticationPlugin.getDefault().setCertPassPhrase(getCertPassPhrase()); + AuthenticationPlugin.getDefault().setUserKeyStore(this.getUserKeyStore()); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Sets the system properties for the PKI only. Does not set the user key store in AuthenticationPlugin. + */ + public void setPKISystemProperties(){ + KeyStore userKeyStore = getUserKeyStore(); + String userKeyStoreLocation = certificateLocation; + //System.out.println("PKISecureStorage - setpkisystemproperties.... DONT OVERWRITE"); + if ( PKIState.CONTROL.isPKCS11on() ) { + if( (certPassPhrase != null) && (userKeyStoreLocation != null) && + (!certificateLocation.equals("none")) && (!certPassPhrase.equals("none"))) { + System.setProperty(JAVA_SSL_USER_KEY_STORE_PATH_KEY, "pkcs11"); + System.setProperty(JAVA_SSL_USER_KEY_STORE_PASS_KEY, certPassPhrase); + AuthenticationPlugin.getDefault().setCertificatePath( userKeyStoreLocation ); + } + } else if ( PKIState.CONTROL.isPKCS12on() ) { + if(userKeyStore != null && userKeyStore.getType() != null && certPassPhrase != null && userKeyStoreLocation != null + && !certificateLocation.equals("none") && !certPassPhrase.equals("none")) { + + System.setProperty(JAVA_SSL_USER_KEY_STORE_PATH_KEY, userKeyStoreLocation); + System.setProperty(JAVA_SSL_USER_KEY_STORE_TYPE_KEY, userKeyStore.getType()); + System.setProperty(JAVA_SSL_USER_KEY_STORE_PASS_KEY, certPassPhrase); + AuthenticationPlugin.getDefault().setCertificatePath( userKeyStoreLocation ); + } + } + } + + /** + * @return the certificate password + */ + public String getCertPassPhrase() { + try { + certPassPhrase = node.get(PKI_PASSPHRASE, "none"); + } catch (StorageException e) { + //LoggedOperation.reportError(SVNSaveAuthorizationInfo, e); + IStatus status = new Status (IStatus.OK, AuthenticationPlugin.getPluginId()," Canceled Secure Storage Load.."); + AuthenticationPlugin.getDefault().getLog().log(status); + } + return certPassPhrase; + } + public boolean isPkcs11Enabled() { + if (!(VendorImplementation.getInstance().isInstalled()) ){ + return false; + } else { + return true; + } + + } + private void clear() { + node.clear(); + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/Pkcs11Provider.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/Pkcs11Provider.java new file mode 100644 index 00000000000..59a35da7144 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/Pkcs11Provider.java @@ -0,0 +1,215 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.util; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.security.KeyStoreException; +import java.security.Provider; +import java.security.Security; +import java.util.Properties; + +import org.eclipse.ui.pki.preferences.AuthenticationPreferences; +import org.eclipse.ui.pki.AuthenticationPlugin; + +public class Pkcs11Provider { + + private final static String JAVA_EXT_DIR = "java.ext.dirs"; + private static Class pkcs11Class = null; + private static String configurePath = null; + + + public Pkcs11Provider(){} + public static void listProviders() { + for ( Provider provider : Security.getProviders() ) { + //System.out.println("BEFORE ADDING ANY Provider NAME:"+ provider.getName() ); + } + } + @Deprecated + public static boolean addProvider() { + boolean isProvider = false; + try { + /* + * TODO: Make the single sign on work here. + */ + Provider provider = Security.getProvider(System.getProperty("javax.net.ssl.keyStoreProvider")); + //listProviders(); + if ( provider != null ) { + //System.out.println("Pkcs11Provider --------- pkcs11 IS INSTALLED and MANAGER IS configured........................"); + + AuthenticationPlugin.getDefault().getPreferenceStore().setValue(AuthenticationPreferences.PKI_SELECTION_TYPE, "pkcs11"); + } + ClassLoader pkcs11 = new SpecialClassLoader(System.getProperty(JAVA_EXT_DIR).split(":")[0]); + //Class pkcs11Class = null; + pkcs11Class = pkcs11.loadClass("sun.security.pkcs11.SunPKCS11"); + //Provider pkcs11Provider = new SunPKCS11(this.getOsInstalledPath().toString()); + StringBuilder installedPkcs11 = new StringBuilder(); + try { + /* + * NOTE: + * The configure path for pkcs11 may be altered, assuming its installed somewhere, + * This is done in the eclipse preference section. Otherwise, the INSTALLATION + * is done via admin and is OS specific and not a user configured property. + */ + if ( getConfigurePath() != null) { + installedPkcs11 = new StringBuilder(); + installedPkcs11.append(getConfigurePath()); + } else { + installedPkcs11 = getOsInstalledPath(); + } + + if (!( installedPkcs11.toString().isEmpty())) { + String cfg = configPath( installedPkcs11.toString() ); + Provider pkcs11Provider = (Provider)(pkcs11Class.getConstructor(java.lang.String.class).newInstance(cfg)); + Security.addProvider(pkcs11Provider); + isProvider=true; + AuthenticationPlugin.getDefault().getPreferenceStore().setValue(AuthenticationPreferences.PKI_SELECTION_TYPE, "pkcs11"); + //System.out.println("Pkcs11Provider ---- LOADED the provider from:"+cfg); + setConfigurePath(cfg); + } + + } catch (InstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvocationTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchMethodException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } catch (ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return isProvider; + } + + public void setSecurityProvider(String filePath) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, KeyStoreException{ + String configName = filePath; + ClassLoader pkcs11 = new SpecialClassLoader(System.getProperty(JAVA_EXT_DIR).split(":")[0]); + Class pkcs11Class = null; + Provider pkcs11Provider = null; + pkcs11Class = pkcs11.loadClass("sun.security.pkcs11.SunPKCS11"); + pkcs11Provider = (Provider)(pkcs11Class.getConstructor(java.lang.String.class).newInstance(configName)); + + if(pkcs11Provider == null){ + throw new NullPointerException("PKCS11 PROVIDER IS NULL."); + } + + Security.addProvider(pkcs11Provider); + } + + public static String configPath(String specifiedLocation) { + StringBuilder location = new StringBuilder(); + if (( specifiedLocation != null) && (!(specifiedLocation.equalsIgnoreCase("NONE"))) && (!(specifiedLocation.equalsIgnoreCase("pkcs11")))) { + location.append(specifiedLocation); + } else { + location = getOsInstalledPath(); + } + if ((location.length() != 0) && (!(location.toString().endsWith("java_pkcs11.cfg")))){ + location.append(File.separator); + location.append("java_pkcs11.cfg"); + } + + if(!getPkcsCfg(location.toString())){ + location = new StringBuilder(); + } + + return location.toString(); + } + @Deprecated + public static StringBuilder getOsInstalledPath() { + + //String path=null; + StringBuilder pkcs11Path = new StringBuilder(); + Properties p = System.getProperties(); + + try { + if (p.getProperty("os.name").equals("Linux")) { + /* + * The OS is Linux so process according to LINUX rules. + */ + pkcs11Path.append("/opt/pkcs11"); + if ( !(getPkcsCfg(pkcs11Path.toString() ))) { + pkcs11Path = new StringBuilder(); + pkcs11Path.append(p.getProperty("user.home")); + pkcs11Path.append(File.separator); + pkcs11Path.append("pkcs11"); + + if (!(getPkcsCfg(pkcs11Path.toString()))) { + pkcs11Path = new StringBuilder(); + } + } + } + if (p.getProperty("os.name").contains("Windows")) { + pkcs11Path.append("C:"); + pkcs11Path.append(File.separator); + pkcs11Path.append("Windows"); + pkcs11Path.append(File.separator); + pkcs11Path.append("SysWOW64"); + pkcs11Path.append(File.separator); + pkcs11Path.append("pkcs11"); + + if (!(getPkcsCfg( pkcs11Path.toString() ))) { + pkcs11Path = new StringBuilder(); + pkcs11Path.append("C:"); + pkcs11Path.append(File.separator); + pkcs11Path.append("Progra~2"); + pkcs11Path.append(File.separator); + pkcs11Path.append("pkcs11"); + if (!(getPkcsCfg(pkcs11Path.toString()))) { + pkcs11Path = new StringBuilder(); + } + } + + } if (pkcs11Path.length() == 0 ) { + //To Do + //System.out.println("Pkcs11Provider ---- NO PKCS11 IS INSTALLED"); + throw new KeyStoreException("You have specified an invalid location, Is pkcs11 installed?"); + } + } catch (Exception e) { + // TODO: handle exception + } + return pkcs11Path; + } + + private static boolean getPkcsCfg(String incoming) { + File file = new File(incoming); + return file.exists(); + } + @Deprecated + public static String getConfigurePath() { + return configurePath; + } + @Deprecated + public static void setConfigurePath(String configurePath) { + //System.out.println("Pkcs11Provider: setConfigurePath" ); + Pkcs11Provider.configurePath = configurePath; + } + public Class getProviderClass() { + return pkcs11Class; + + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/PkiView.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/PkiView.java new file mode 100644 index 00000000000..6a33bec4d50 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/PkiView.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.util; + + + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.pki.util.ExpiredX509CertificateData; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.part.ViewPart; + +public class PkiView extends ViewPart { + + private Composite view; + private Label alias; + private Label certLocation; + private Label expirationDate; + private Label distinguishedName; + private Label seperator; + public PkiView() { + super(); + } + public void init(ArrayList expiredCerts) { + ExpiredX509CertificateData data=null; + for(Object d : expiredCerts.toArray()) { + + data = (ExpiredX509CertificateData) d; + certLocation.setText("Certificate File Location:"+data.getCertLocation()); + //seperator.setText(null); + alias.setText("Alias:"+data.getAlias()); + expirationDate.setText("EXPIRATION DATE:"+data.getExpirationDate()); + distinguishedName.setText("DN:"+data.getDistinguishedName()); + alias.setFocus(); + view.pack(); + + } + //System.out.println("ExpiredCertCheck PKIVIEW:"+data.getExpirationDate()); + + } + @Override + public void createPartControl(Composite parent) { + // TODO Auto-generated method stub + + view = parent; + RowLayout layout = new RowLayout(); + //Label separator = new Label(parent, SWT.SEPARATOR | SWT.SHADOW_OUT | SWT.HORIZONTAL); + layout.type = SWT.VERTICAL; + view.setLayout( layout); + + certLocation = new Label(view, 0); + // Create a Label is Horizontal Separator + //Label hSeparator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); + + //seperator = new Label(parent, SWT.SEPARATOR | SWT.SHADOW_OUT | SWT.HORIZONTAL); + alias = new Label(view, 0); + + expirationDate = new Label(view, 0); + distinguishedName = new Label(view, 0); + + + view.layout(true); + } + + @Override + public void setFocus() { + // TODO Auto-generated method stub + certLocation.setFocus(); + alias.setFocus(); + } + +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/SSLHelper.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/SSLHelper.java new file mode 100644 index 00000000000..409325f65fa --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/SSLHelper.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.util; + +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; + +import org.eclipse.core.pki.util.LogUtil; + +/** + * This class can be used to create an SSLSocketFactory with provided keystore and trustore. + * You might use this class in the following way: + * + * KeyStore keystore = KeyStoreUtil.getKeyStore("/path/to/cert/bob.p12", "password", KeyStoreFormat.PKCS12) + * KeyStore truststore = KeyStoreUtil.getKeyStore("/path/to/trustcert/trust.jks", null, KeyStoreFormat.JKS) + * SSLSocketFactory sslSocketFactory = getSSLSocketFactory(getKeyManagers(keystore, "password", getTrustManagers(truststore)) + * + */ +public abstract class SSLHelper { + + public final static String X509_ALGORITHM = "SunX509"; + public final static String SSL_PROTOCOL = "SSL"; + + + public static SSLSocketFactory getSSLSocketFactory(KeyManager[] keyManagers, TrustManager[] trustManagers) { + return getSSLContext(keyManagers, trustManagers).getSocketFactory(); + } + + private static SSLContext getSSLContext(KeyManager[] keyManagers, TrustManager[] trustManagers) { + SSLContext sslContext = null; + try { + sslContext = SSLContext.getInstance(SSL_PROTOCOL); + + + sslContext.init(keyManagers, trustManagers, null); + return sslContext; + } catch (KeyManagementException e) { + LogUtil.logError(e.getMessage(), e); + } catch (NoSuchAlgorithmException e) { + LogUtil.logError(e.getMessage(), e); + } + return null; + } + + public static TrustManager[] getTrustManagers(KeyStore trustStore) { + + TrustManagerFactory trustManagerFactory; + try { + + trustManagerFactory = TrustManagerFactory.getInstance( X509_ALGORITHM ); + trustManagerFactory.init( trustStore ); + return trustManagerFactory.getTrustManagers(); + + } catch (NoSuchAlgorithmException e) { + LogUtil.logError(e.getMessage(), e); + } catch (KeyStoreException e) { + LogUtil.logError(e.getMessage(), e); + } + + return null; + } + + public static KeyManager[] getKeyManagers(KeyStore keyStore, char[] password) { + try { + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(X509_ALGORITHM); + keyManagerFactory.init(keyStore, password); + return keyManagerFactory.getKeyManagers(); + } catch (Exception e) { + LogUtil.logError(e.getMessage(), e); + } + return null; + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/SpecialClassLoader.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/SpecialClassLoader.java new file mode 100644 index 00000000000..a89a8af0b4b --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/util/SpecialClassLoader.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.util; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class SpecialClassLoader extends ClassLoader { + + private String findThisClassAt = null; + + public SpecialClassLoader(String classlocation){ + findThisClassAt = classlocation; + } + + protected Class findClass(String name) throws ClassNotFoundException{ + try{ + byte[] classBytes = null; + classBytes = loadClassbytes(name); + Class cl = defineClass(name, classBytes, 0, classBytes.length); + if (cl == null) throw new ClassNotFoundException(name); + return cl; + } catch (IOException e){ + throw new ClassNotFoundException(name); + } + } + + private byte[] loadClassbytes(String name) throws IOException { + + return Files.readAllBytes(Paths.get(findThisClassAt)); + } + + public String getFindThisClassAtLocation() { + return findThisClassAt; + } + +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/CertificateSelectionPage.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/CertificateSelectionPage.java new file mode 100644 index 00000000000..bc0fc0f4b84 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/CertificateSelectionPage.java @@ -0,0 +1,1259 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.wizard; + +import java.io.File; +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Iterator; + +import org.eclipse.core.pki.FingerprintX509; +import org.eclipse.core.pki.auth.PKIState; +import org.eclipse.core.pki.pkiselection.PKI; +import org.eclipse.core.pki.pkiselection.PKIProperties; +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +//import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.ProgressBar; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.pki.buttons.PKCSButtons; +import org.eclipse.ui.pki.pkcs.VendorImplementation; +import org.eclipse.ui.pki.pkiselection.PKCSSelected; +//import org.eclipse.ui.pki.pkiselection.PKCSpick; +import org.eclipse.ui.pki.preferences.ChangedPressedFieldEditorStatus; +import org.eclipse.core.pki.util.KeyStoreFormat; +import org.eclipse.ui.pki.util.KeyStoreUtil; +import org.eclipse.ui.pki.util.PKISecureStorage; +import org.eclipse.ui.pki.AuthenticationPlugin; +import org.eclipse.ui.pki.preferences.AuthenticationPreferences; + + + + +public class CertificateSelectionPage extends WizardPage { + + private final static String NAME = "Default Authentication - Certificate Selection Page"; + private final static String DESCRIPTION = "Choose your method of authentication, PKCS11 or PKCS12"; +//SWM: 20200305 private final static String TITLE = "PKI Authentication"; + private final static String TITLE = "PKI Certificate Selection"; + private final static String EMPTY_STRING = ""; + private final static String[] INITIAL_SLOT = {"There has been no certificate selected from store, please select your DS slot."} ; + private final static String OPENING_INSTRUCTIONS = + "This application authenticates users using their X509 corporate-issued " + + "PKI certificates and certificate passwords. For more information " + + "about PKI certificates, type \"go pki\" in your web browser, " + + "or to find out about the PKCS11 software product type \"pkcs11\" in your web browser."; + private final static String PKCS12_SELECTION_INSTRUCTIONS = + "Please select the PKI Digital Signature certificate provided to " + + "you by the Public Key Infrastructure Group. This X509 " + + "certificate will originally include a \"D\" or \"DS\" in its " + + "name and is normally located in " + + AuthenticationPreferences.DEFAULT_PKI_CERTIFICATE_DIR + "."; + private final static String PKCS11_SELECTION_INSTRUCTIONS = + "Select the credential you would like to use during this session. "; + PKISecureStorage pkiSecureStorage = null; + protected PKIProperties lastPropertyValues=null; + protected static String[] slots=null; + protected static int certificateIndex=0; + protected static String selectedAlias=null; + private Text certPathText = null; + private Button pkcs12selectCert = null; + private Button checkPasswordButton = null; + private Button checkPinButton = null; + private Text passwordText = null; + private Label passwordLabel; + private Text pinText = null; + private ProgressBar progressBar = null; + private Label pkcs12certificateLabel = null; + private boolean finishOK=false; + private boolean validPasswd=false; + private Label pkcs11PasswordLabel = null; + private Composite buttonGroup = null; + public Button pkcs11Button = null; + + + private Label pkcs12PasswordLabel = null; + + public Button pkcs12Button = null; + public Button fakeButton = null; + private Text pkcs12PasswordTextBox = null; + + private boolean isSaveCertificateChecked = false; + private boolean isButtonSelected = false; + + protected Button saveCertificateCheckBox; + + protected PKCSButtons pkcsbuttons = null; + + protected Combo combo = null; + + public CertificateSelectionPage() { + super( NAME ); + setTitle( TITLE ); + setDescription( DESCRIPTION ); + try { + lastPropertyValues = PKIProperties.getInstance(); + lastPropertyValues.setLastPkiValue(setLastInstance( lastPropertyValues )); + pkiSecureStorage = new PKISecureStorage(); + if ((!(PKIState.CONTROL.isPKCS11on())) && ((!(PKIState.CONTROL.isPKCS12on())))) { + PKCSSelected.setPkcs11Selected(false); + PKCSSelected.setPkcs12Selected(false); + + } + if ( PKIState.CONTROL.isPKCS11on()) { + + AuthenticationPlugin.getDefault().getPreferenceStore().setValue( + AuthenticationPreferences.PKI_SELECTION_TYPE, "PKCS11"); + slots = selectFromPkcs11Store(); + PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS11); + PKCSSelected.setPkcs11Selected(true); + isButtonSelected=true; + + } else { + if ( PKIState.CONTROL.isPKCS12on()) { + PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS12); + AuthenticationPlugin.getDefault().getPreferenceStore().setValue( + AuthenticationPreferences.PKI_SELECTION_TYPE, "PKCS12"); + PKCSSelected.setPkcs12Selected(true); + isButtonSelected=true; + + } else { + isButtonSelected=false; + } + + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + //MessageDialog.openConfirm(Display.getCurrent().getActiveShell(), "OK", "HERE IS WHERE WE LOAD PKCS11."); + } + + + private Composite addCertificateDetailsSection( final Composite parent ) { + + //This composite is used for the remaining methods. + //final Composite sectionComposite = new Composite( parent, SWT.NONE ); + final Composite sectionComposite = new Composite( parent, SWT.NO_RADIO_GROUP ); + sectionComposite.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true ) ); + GridLayout sectionCompositeLayout = new GridLayout( 2, false ); + sectionCompositeLayout.verticalSpacing = 1; + sectionComposite.setLayout( sectionCompositeLayout ); + + //This composite is used for the addPKITypeButtons + //final Composite sectionComposite1 = new Composite( parent, SWT.NONE ); + final Composite sectionComposite1 = new Composite( parent, SWT.NO_RADIO_GROUP ); + sectionComposite1.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true ) ); + GridLayout sectionCompositeLayout1 = new GridLayout( 1, false ); + sectionCompositeLayout1.verticalSpacing = 1; + sectionComposite1.setLayout( sectionCompositeLayout1 ); + + addButtonGroup(parent); + + //Add pkcs12 section + addPKCS12Section(sectionComposite1); + + // Add pkcs11 section + addPKCS11Section(sectionComposite); + + //Add pkcs11 and pkcs12 widget selection. + addPKCSWidgetSelection(); + + if (PKIState.CONTROL.isPKCS12on()) { + //this.pkcs12Button.setSelection(true); + this.pkcs12Button.setFocus(); + pkcs12Actions(); + } else { + if (PKIState.CONTROL.isPKCS11on() ) { + this.pkcs11Button.setSelection(true); + //Not sure if add this setFocus() to cspid. + //this.pkcs11Button.setFocus(); + pkcs11Actions(); + } else { + // else NO buttons are selected! Make everything GREY! + this.deSelectAll(); + + pkcs11Button.setSelection(false); + pkcs12Button.setSelection(false); + fakeButton.setSelection(true); + } + } + + return sectionComposite; + } + + private void addPKCSWidgetSelection() { + + pkcs11Button.addSelectionListener(new SelectionAdapter(){ + @Override + public void widgetSelected(SelectionEvent e) { + /* + * TODO: + * Figure out why WINDOZ does not set radio buttons correctly. + * The FAKE button allows the real button to be de-selected at STARTUP only, then + * the buttons work correclty. + */ + if ( fakeButton.getSelection() ) { + //System.out.println("CertificateSelectionPage - FAKE BUTTON IS SELECTED"); + //pkcs11Button.setSelection(false); + fakeButton.setSelection(false);; + + //return; + } + /**************************************************************************************/ + Event event = new Event(); + //System.out.println("CertificateSelectionPage - 11-BUTTON:"+pkcs11Button.getSelection()); + //System.out.println("CertificateSelectionPage - 11-BUTTON INCOMING:"+e.toString()); + if ((pkcs11Button.getSelection()) && ((e.doit==true)) ) { + if ( VendorImplementation.getInstance().isInstalled() ) { + CertificateSelectionPage.this.setMessage("Please enter your PKCS11 PiN.", WizardPage.INFORMATION); + pinText.setEnabled(true); + passwordLabel.setEnabled(true); + checkPinButton.setEnabled(true); + pkcs11PasswordLabel.setEnabled(false); + combo.setText(""); + combo.setEnabled(false); + deSelectPkcs12(); + if ( VendorImplementation.getInstance().isEnabled() ) { + slots = selectFromPkcs11Store(); + if ( passwordText != null ) { + passwordText.setText(""); + } + } else { + //System.out.println("CertificateSelectionPage -- pkcs11 is NOT enabled"); + //AuthenticationPlugin.getDefault().getLog().log(new Status(IStatus.OK, AuthenticationPlugin.getPluginId()+":CertificateSelectionPage","PKCS11 CHECK")); + try { + if ( VendorImplementation.getInstance().isInstalled() ) { + //AuthenticationPlugin.getDefault().getLog().log(new Status(IStatus.OK, AuthenticationPlugin.getPluginId()+":CertificateSelectionPage","PKCS11 IS ALIVE")); + } else { + // Disable the PKCS11 button, becuase its not configured on this machine. + event = new Event(); + event.doit = false; + event.stateMask = 80000; + pkcs11Button.notifyListeners(SWT.Selection, event); + } + } catch (Exception e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + isPageComplete(); + } + // + // if we get here someone selected PKCS11 on a machine that does not have PKCS11 installed. + // + } else { + //System.out.println("CertificateSelectionPage ---------------FALSE----------------- PKCS11 IS TURNED OFF"); + pkcs11Button.setSelection(false); + pkcs12Button.setSelection(true); + VendorImplementation.getInstance().off(); + PKIState.CONTROL.setPKCS11on(false); + } + //isPageComplete(); + } else { + + System.out.println("CertificateSelectionPage ---------CLEAR------FALSE----------------- PKCS11 IS TURNED OFF"); + pkcs11Button.setSelection(false); + pkcs12Button.setSelection(false); + VendorImplementation.getInstance().off(); + deSelectAll(); + System.clearProperty("javax.net.ssl.keyStoreType"); + System.clearProperty("javax.net.ssl.keyStoreProvider"); + PKIState.CONTROL.setPKCS11on(false); + } + + if ( isPageComplete() ) { + //System.out.println("CertificateSelectionPage --------------------- PKCS11 FINISH BUTTON IS GOOD"); + } + } + }); + + pkcs12Button.addSelectionListener(new SelectionAdapter(){ + @Override + public void widgetSelected(SelectionEvent e) { + //System.out.println("CertificateSelectionPage - 12-BUTTON:"+pkcs12Button.getSelection()); + //System.out.println("CertificateSelectionPage - 12-BUTTON INCOMING:"+e.toString()); + if ((pkcs12Button.getSelection()) && ((e.doit==true))) { + //System.out.println("CertificateSelectionPage --------------------- PKCS12 IS TURNED ON"); + PKIState.CONTROL.setPKCS12on(true); + pkcs12Actions(); + deSelectPkcs11(); + + setPageComplete(false); + CertificateSelectionPage.this.setMessage("Please enter your valid PKCS12 password and P12 file location.", WizardPage.INFORMATION); + } else { + // UN-select selected stuff... + //System.out.println("CertificateSelectionPage --------------------- PKCS12 IS TURNED OFF"); + PKIState.CONTROL.setPKCS12on(false); + PKCSSelected.setPkcs12Selected(false); + deSelectAll(); + isButtonSelected=true; + } + + if ( isPageComplete() ) { + //System.out.println("CertificateSelectionPage --------------------- PKCS12 FINISH BUTTON IS GOOD"); + } else { + //System.out.println("CertificateSelectionPage --------------------- PKCS12 FINISH BUTTON IS FALSE"); + } + } + }); + //System.out.println("CertificateSelectionPage - addPKCSWidgetSelection MAKING BURTTONS AVAILABLE"); + //isButtonSelected=true; + } + private void deSelectAll() { + this.deSelectPkcs11(); + this.deSelectPkcs12(); + setPageComplete(isPageComplete()); + getWizard().canFinish(); + //System.out.println("CertificateSelectionPage ----deSelectALL probably need to grey off finish bitton too"); + } + private void deSelectPkcs11() { + this.pkcs11Button.setSelection(false); + this.checkPinButton.setEnabled(false); + this.pinText.setEnabled(false); + this.passwordLabel.setEnabled(false); + this.pkcs11PasswordLabel.setEnabled(false); + this.combo.setEnabled(false); + PKIState.CONTROL.setPKCS11on(false); + } + private void deSelectPkcs12() { + this.pkcs12Button.setSelection(false); + this.pkcs12certificateLabel.setEnabled(false); + this.certPathText.setEnabled(false); + this.pkcs12PasswordLabel.setEnabled(false); + this.pkcs12PasswordTextBox.setEnabled(false); + //this.saveCertificateCheckBox.setEnabled(false); + this.pkcs12selectCert.setEnabled(false); + this.checkPasswordButton.setEnabled(false); + //this.passwordText.setText(""); + if ( this.passwordText != null) { + this.passwordText.setText(""); + } + } + + void pkcs11Actions(){ + + // TURN OFF ALL PKCS12 + this.pkcs12certificateLabel.setEnabled(false); + this.certPathText.setEnabled(false); + this.pkcs12PasswordLabel.setEnabled(false); + this.pkcs12PasswordTextBox.setEnabled(false); + //this.saveCertificateCheckBox.setEnabled(false); + this.pkcs12selectCert.setEnabled(false); + this.pkcs12Button.setSelection(false); + this.checkPasswordButton.setEnabled(false); + + + //TURN ON ALL PKCS11 + this.checkPinButton.setEnabled(true); + this.passwordLabel.setEnabled(true); + this.pinText.setEnabled(true); + this.pkcs11Button.setSelection(true); + PKCSSelected.setPkcs11Selected(true); + + + } + + private void pkcs12Actions(){ + + //TURN OFF PKCS11 + this.checkPinButton.setEnabled(false); + this.pinText.setEnabled(false); + this.passwordLabel.setEnabled(false); + this.pkcs11PasswordLabel.setEnabled(false); + this.pinText.setText(""); + //this.pkcs11PasswordTextBox.setEnabled(false); + this.pkcs11Button.setSelection(false); + this.combo.setEnabled(false); + this.checkPasswordButton.setEnabled(false); + + //Enable PKCS12 + this.passwordText = this.pkcs12PasswordTextBox; + this.pkcs12certificateLabel.setEnabled(true); + this.certPathText.setEnabled(true); + //this.saveCertificateCheckBox.setEnabled(true); + this.pkcs12PasswordLabel.setEnabled(true); + this.pkcs12PasswordTextBox.setEnabled(true); + this.pkcs12selectCert.setEnabled(true); + PKCSSelected.setPkcs12Selected(true); + +//SWM: 20200312 - Added the next 2 lines to fix Win 10 lost focus problem + this.pkcs12Button.setSelection(true); + this.pkcs12Button.forceFocus(); + + //this.pkcs12Button.setSelection(true); + //PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS12); + //this.pkcs12Button.forceFocus(); + //this.pkcs11PasswordTextBox.setText(""); + if ( pkiSecureStorage.isPKISaved() ) { + //System.out.println("CertificateSelectionPage --- pkcs12 IS IN SECURE STORAGE"); + pkiSecureStorage.loadUpPKI(); + pkiSecureStorage.setPKISystemProperties(); + this.certPathText.setText( AuthenticationPlugin.getDefault().getCertificatePath() ); + } else { + //System.out.println("CertificateSelectionPage --- pkcs12 IS NOT IN SECURE STORAGE"); + } + } + + + private void addPKCS12Section(Composite sectionComposite1) { + Group group = new Group(sectionComposite1, SWT.NONE); + group.setLayout(new GridLayout()); + group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); +//SWM: 20200306 group.setText("PKCS12 (deprecating)"); + group.setText("PKCS12 (.p12)"); + + //Create layout and controls + //Composite pkcs12ButtonComposite = new Composite(group, SWT.NONE); + Composite pkcs12ButtonComposite = new Composite(group, SWT.NO_RADIO_GROUP); + GridLayout pkcs12ButtonCompositeLayout = new GridLayout(1, false); + pkcs12ButtonComposite.setLayout(pkcs12ButtonCompositeLayout); + pkcs12ButtonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + + int widthHint = computeWidthHint( this.getContainer().getShell() ); + GridData labelGridData = new GridData( GridData.FILL_BOTH ); + Label selectionInstructionsLabel = new Label( pkcs12ButtonComposite, SWT.WRAP ); + labelGridData = new GridData( GridData.FILL_BOTH ); + labelGridData.widthHint = widthHint; + selectionInstructionsLabel.setLayoutData( labelGridData ); + selectionInstructionsLabel.setText( PKCS12_SELECTION_INSTRUCTIONS ); + + this.pkcs12Button = new Button(pkcs12ButtonComposite, SWT.RADIO); + this.pkcs12Button.setLayoutData(new GridData(SWT.BEGINNING, SWT.TOP, true, true)); + this.pkcs12Button.setText("PKCS12"); + + // Create layout and controls for manually selecting certs + Composite subsectionComposite = new Composite( group, SWT.NONE ); + GridLayout subsectionCompositeLayout = new GridLayout( 3, false ); + subsectionComposite.setLayout( subsectionCompositeLayout ); + subsectionComposite.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true ) ); + + // Create label for selecting the certificate + this.pkcs12certificateLabel = new Label( subsectionComposite, SWT.RIGHT ); + this.pkcs12certificateLabel.setText( "PKI Certificate Location: " ); + + this.certPathText = new Text( subsectionComposite, SWT.LEFT | SWT.BORDER ); + this.certPathText.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true ) ); + + this.pkcs12selectCert = new Button( subsectionComposite, SWT.PUSH ); + this.pkcs12selectCert.setText( "Browse..." ); + + BrowseButtonListener listener = new BrowseButtonListener(); + pkcs12selectCert.addSelectionListener( listener ); + + //Create layout and controls + Composite pkcs12PasswordComposite = new Composite(group, SWT.NONE); + GridLayout pkcs12PasswordLayout = new GridLayout(3, false); + //pkcs12PasswordLayout.horizontalSpacing = 10; + //pkcs12PasswordLayout.verticalSpacing = 10; + pkcs12PasswordComposite.setLayout(pkcs12PasswordLayout); + pkcs12PasswordComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + // Create controls for specifying the password + this.pkcs12PasswordLabel = new Label( pkcs12PasswordComposite, SWT.RIGHT ); + this.pkcs12PasswordLabel.setText( "PKI Certificate Password: " ); + + this.pkcs12PasswordTextBox = new Text( pkcs12PasswordComposite, SWT.LEFT | SWT.PASSWORD | SWT.BORDER ); + this.pkcs12PasswordTextBox.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true ) ); + + this.checkPasswordButton = new Button(pkcs12PasswordComposite, SWT.RIGHT); + this.checkPasswordButton.setText("Validate"); + this.checkPasswordButton.addSelectionListener(new SelectionListener(){ + + public void widgetSelected(SelectionEvent e) { + // TODO Auto-generated method stub + //System.out.println("CertificateSelectionPage -- bitton selected"); + CertificateSelectionPage.this.setErrorMessage( "CHECKING PASSWORD AND KEYSTORE"); + if ( checkPasswordAndKeystore( certPathText.getText().trim(), passwordText.getText() ) ) { + + if (!(PKCS12CheckValid.INSTANCE.isExpired(getUserKeyStore(), passwordText.getText().toCharArray()))) { + + CertificateSelectionPage.this.setErrorMessage(null); + CertificateSelectionPage.this.setMessage("Password matches your Keystore, PRESS the Finish button to continue.", WizardPage.INFORMATION); + finishOK=true; + setPageComplete(true); + pkcs12selectCert.setEnabled(false); + certPathText.setEnabled(false); + pkcs12PasswordTextBox.setEnabled(false); + checkPasswordButton.setEnabled(false); + passwordText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK)); + } else { + CertificateSelectionPage.this.setErrorMessage( "The keystore has expired certificate."); + passwordText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED)); + } + } else { + CertificateSelectionPage.this.setErrorMessage( "The Password does NOT match your keystore."); + passwordText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED)); + } + isPageComplete(); + } + + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + //System.out.println("CertificateSelectionPage -- button default selected"); + } + + }); + + final Composite sectionComposite2 = new Composite( group, SWT.NONE ); + sectionComposite2.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true ) ); + GridLayout sectionCompositeLayout2 = new GridLayout( 1, false ); + sectionCompositeLayout2.verticalSpacing = 1; + sectionComposite2.setLayout( sectionCompositeLayout2 ); + + //addSaveCertificateCheckbox(sectionComposite2); + + + ModifyListener modifyListener = new ModifyListener() { + public void modifyText( ModifyEvent e ) { + CertificateSelectionPage.this.setErrorMessage( null ); + //CertificateSelectionPage.this.getContainer().updateButtons(); + //System.out.println("CertificateSelectionPage --- modifyText PASSWD LISTENER!"); + + try { + if ( (!(passwordText.getText().isEmpty()) )) { + CertificateSelectionPage.this.setMessage("Please enter your valid PKCS12 password and P12 file location.", WizardPage.INFORMATION); + validPasswd=true; + //setPageComplete(true); + checkPasswordButton.setEnabled(true); + passwordText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK)); + if (finishOK ) { + // RESET the finish button back to + getWizard().canFinish(); + setPageComplete(false); + finishOK=false; + passwordText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED)); + CertificateSelectionPage.this.setErrorMessage( "Altered Password does NOT match your keystore."); + } + } + isPageComplete(); + CertificateSelectionPage.this.getContainer().updateButtons(); + } catch (Exception e1) { + // TODO Auto-generated catch block + //e1.printStackTrace(); + } + } + }; + pkcs12PasswordTextBox.addModifyListener( modifyListener ); + if (PKIState.CONTROL.isPKCS12on()) { + this.pkcs12Button.setSelection(true); + //PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS12); + this.pkcs12Button.forceFocus(); + pkiSecureStorage = new PKISecureStorage(); + + if ( pkiSecureStorage.isPKISaved() ) { + + pkiSecureStorage.loadUpPKI(); + pkiSecureStorage.setPKISystemProperties(); + this.certPathText.setText( AuthenticationPlugin.getDefault().getCertificatePath() ); + + this.certPathText.setText(AuthenticationPlugin.getDefault().getPreferenceStore().getString(AuthenticationPreferences.PKI_CERTIFICATE_LOCATION)); + } else { + this.certPathText.setText( AuthenticationPlugin.getDefault().getCertificatePath() ); + } + + } +// else { +// System.out.println("CertificateSelectionPage --- pkcs12 CERTPATHTEXT: WRONG VALUE IS GETTING STORED INTO pkcs12 PREF---- FIX THIS"); +// System.out.println("CertificateSelectionPage --- pkcs12 CERTPATHTEXT:"+AuthenticationPlugin.getDefault().getPreferenceStore().getString(AuthenticationPreferences.PKI_CERTIFICATE_LOCATION)); +// this.certPathText.setText(AuthenticationPlugin.getDefault().getPreferenceStore().getString(AuthenticationPreferences.PKI_CERTIFICATE_LOCATION)); +// } + } + + + private void addPKCS11Section(Composite sectionComposite) { + Group group = new Group(sectionComposite, SWT.NONE); + group.setLayout(new GridLayout()); + group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + group.setText("PKCS11 (pki)"); + + //Create layout and controls + //Composite pkcs11ButtonComposite = new Composite(group, SWT.NONE); + Composite pkcs11ButtonComposite = new Composite(group, SWT.NO_RADIO_GROUP); + + GridLayout pkcs11ButtonCompositeLayout = new GridLayout(1, false); + pkcs11ButtonComposite.setLayout(pkcs11ButtonCompositeLayout); + pkcs11ButtonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + int widthHint = computeWidthHint( this.getContainer().getShell() ); + GridData labelGridData = new GridData( GridData.FILL_BOTH ); + Label selectionInstructionsLabel1 = new Label( pkcs11ButtonComposite, SWT.WRAP ); + labelGridData = new GridData( GridData.FILL_BOTH ); + labelGridData.widthHint = widthHint; + selectionInstructionsLabel1.setLayoutData( labelGridData ); + selectionInstructionsLabel1.setText( PKCS11_SELECTION_INSTRUCTIONS ); + + + this.pkcs11Button = new Button(pkcs11ButtonComposite, SWT.RADIO); + //this.pkcs11Button = new Button(buttonGroup, SWT.RADIO); + fakeButton = new Button(pkcs11ButtonComposite, SWT.RADIO); + fakeButton.setSelection(true); + fakeButton.setVisible(false); + + + this.pkcs11Button.setLayoutData(new GridData(SWT.BEGINNING, SWT.BOTTOM, true, true)); + this.pkcs11Button.setText("PKCS11"); + + //this.pkcs11Button.forceFocus(); + + addPasswordSubsection( pkcs11ButtonComposite ); + + this.pkcs11PasswordLabel = new Label( pkcs11ButtonComposite, SWT.RIGHT ); + this.pkcs11PasswordLabel.setText( "Pkcs11 Selection list: " ); + + this.combo = new Combo(pkcs11ButtonComposite, SWT.READ_ONLY); + this.combo.setItems(INITIAL_SLOT); + this.combo.select(0); + ModifyListener modifyListener = new ModifyListener() { + public void modifyText( ModifyEvent e ) { + //System.out.println("CertificateSelectionPage ----addPKCS11Section Modify Event"+e.getSource().toString()); + //System.out.println("CertificateSelectionPage ----addPKCS11Section SLOT"+combo.getSelectionIndex()); + CertificateSelectionPage.this.setErrorMessage( null ); + CertificateSelectionPage.this.getContainer().updateButtons(); + selectedAlias = combo.getText(); + } + }; + combo.addModifyListener( modifyListener ); + + combo.addSelectionListener(new SelectionAdapter() { + public void widgetSelected( SelectionEvent event) { + + //System.out.println("CertificateSelectionPage --MY SELECTION"+combo.getText()); + selectedAlias = combo.getText(); + certificateIndex = combo.getSelectionIndex(); + } + }); + if ( PKIState.CONTROL.isPKCS11on()) { + if ( pkiSecureStorage.isPKISaved() ) { + pkiSecureStorage.loadUpPKI(); + } + //System.out.println("CertificateSelectionPage ----addPKCS11Section SELECTING PKCS11 BUTTON"); + if ( this.loadPkcs11Slots() ) { + this.pkcs11Button.setEnabled(true); + this.pkcs11Button.forceFocus(); + } + pkcs11Actions(); + this.pkcs11PasswordLabel.setEnabled(false); + this.combo.setText(""); + this.slots=null; + this.combo.setEnabled(false); + isPageComplete(); + } + else { + pkcs12Actions(); + } + } + private Composite addButtonGroup(Composite parent) { + /* + * TBD: + * @TODO CREATE a radio group without grouping buttons together. + */ + buttonGroup = new Composite(parent, SWT.NO_RADIO_GROUP); + + return buttonGroup; + } + + + private void addPKITypeButtons(final Composite sectionComposite) { + pkcsbuttons = new PKCSButtons(sectionComposite); + + pkcsbuttons.buttonSelected(certPathText, pkcs12certificateLabel, pkcs12selectCert, passwordText); + } + + + private void addSaveCertificateCheckbox(final Composite sectionComposite) { + + //Create layout and controls + Composite subsectionComposite = new Composite(sectionComposite, SWT.NONE); + + GridLayout subsectionCompositeLayout = new GridLayout(2, false); + subsectionComposite.setLayout(subsectionCompositeLayout); + subsectionComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true )); + + + saveCertificateCheckBox = new Button(subsectionComposite, SWT.CHECK); + saveCertificateCheckBox.setText("Save your selection into Eclipse Secure Store? "); + saveCertificateCheckBox.addSelectionListener(new SelectionListener(){ + + public void widgetSelected(SelectionEvent e) { + isSaveCertificateChecked = saveCertificateCheckBox.getSelection(); + ChangedPressedFieldEditorStatus.setPKISaveCertificateChecked(isSaveCertificateChecked); + } + + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + + } + + }); + } + + private void addFileSelectSubsection( final Composite sectionComposite ) { + // Create label for selecting the certificate + pkcs12certificateLabel = new Label( sectionComposite, SWT.RIGHT ); + pkcs12certificateLabel.setText( "PKI Certificate or Pkcs11 Location: " ); + + // Create layout and controls for manually selecting certs + Composite subsectionComposite = new Composite( sectionComposite, SWT.NONE ); + GridLayout subsectionCompositeLayout = new GridLayout( 2, false ); + subsectionComposite.setLayout( subsectionCompositeLayout ); + subsectionComposite.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true ) ); + + certPathText = new Text( subsectionComposite, SWT.LEFT | SWT.BORDER ); + certPathText.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true ) ); + AuthenticationPlugin plugin = AuthenticationPlugin.getDefault(); + String preferencesKey = AuthenticationPreferences.PKI_CERTIFICATE_LOCATION; + IPreferenceStore preferenceStore = plugin.getPreferenceStore(); + String certificatePath = preferenceStore.getString( preferencesKey ); + if ( null != certificatePath ) { + certPathText.setText( certificatePath ); + } + + pkcs12selectCert = new Button( subsectionComposite, SWT.PUSH ); + pkcs12selectCert.setText( "Browse..." ); + BrowseButtonListener listener = new BrowseButtonListener(); + pkcs12selectCert.addSelectionListener( listener ); + + } + + private Composite addInstructionsSection( final Composite parent ) { + // Create composite for the section + Composite sectionComposite = new Composite( parent, SWT.NONE ); + GridLayout subsectionCompositeLayout = new GridLayout(); + //subsectionCompositeLayout.horizontalSpacing = 10; + //subsectionCompositeLayout.verticalSpacing = 10; + sectionComposite.setLayout( subsectionCompositeLayout ); + sectionComposite.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true ) ); + + // Calculate initial width + int widthHint = computeWidthHint( this.getContainer().getShell() ); + + // Create labels for each set of instructions + Label openingInstructionsLabel = new Label( sectionComposite, SWT.WRAP ); + GridData labelGridData = new GridData( GridData.FILL_BOTH ); + labelGridData.widthHint = widthHint; + openingInstructionsLabel.setLayoutData( labelGridData ); + openingInstructionsLabel.setText( OPENING_INSTRUCTIONS ); + + return sectionComposite; + } + + + + private void addPasswordSubsection( final Composite sectionComposite ) { + // Create controls for specifying the password + + + // Create layout and controls for manually selecting certs + Composite subsectionComposite = new Composite( sectionComposite, SWT.NONE ); + GridLayout subsectionCompositeLayout = new GridLayout( 3, false ); + //subsectionCompositeLayout.horizontalSpacing = 1; + //subsectionCompositeLayout.verticalSpacing = 1; + + subsectionComposite.setLayout( subsectionCompositeLayout ); + subsectionComposite.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true ) ); + passwordLabel = new Label( subsectionComposite, SWT.LEFT ); + passwordLabel.setText( "Enter your PiN: " ); + pinText = new Text( subsectionComposite, SWT.LEFT | SWT.PASSWORD | SWT.BORDER ); + pinText.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true ) ); + + ModifyListener modifyListener = new ModifyListener() { + public void modifyText( ModifyEvent e ) { + //System.out.println("CertificateSelectionPage - PKCS11 entering text"); + if (( checkPinButton != null ) && (PKIState.CONTROL.isPKCS11on())) { + checkPinButton.setEnabled(true); + } + CertificateSelectionPage.this.setErrorMessage( null ); + CertificateSelectionPage.this.getContainer().updateButtons(); + } + }; + pinText.addModifyListener( modifyListener ); + if ( this.combo == null) { + //this.slots=null; + } + this.checkPinButton = new Button(subsectionComposite, SWT.RIGHT); + this.checkPinButton.setText("Log in"); + this.checkPinButton.addSelectionListener(new SelectionListener(){ + public void widgetSelected(SelectionEvent e) { + // TODO Auto-generated method stub + //System.out.println("CertificateSelectionPage -- bitton selected"); + CertificateSelectionPage.this.setErrorMessage( "CHECKING PiN AND KEYSTORE"); + + if (!(pinText.getText().isEmpty())) { + if ( VendorImplementation.getInstance().login(pinText.getText().trim() ) ) { + CertificateSelectionPage.this.setErrorMessage(null); + CertificateSelectionPage.this.setMessage("Password matches your Keystore, PRESS the Finish button to continue.", WizardPage.INFORMATION); + finishOK=true; + setPageComplete(true); + PKIState.CONTROL.setPKCS11on(true); + slots = selectFromPkcs11Store(); + combo.setEnabled(true); + pkcs11PasswordLabel.setEnabled(true); + loadPkcs11Slots(); + pkcs11Actions(); + PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS11); + PKIState.CONTROL.setPKCS12on(false); + pinText.setEnabled(false); + pinText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK)); + AuthenticationPlugin.getDefault().setCertPassPhrase(pinText.getText().trim()); + checkPinButton.setEnabled(false); + } else { + CertificateSelectionPage.this.setErrorMessage( "The Pin does NOT match your keystore."); + pinText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED)); + pkcs11PasswordLabel.setEnabled(false); + combo.setText(""); + combo.setEnabled(false); + slots=null; + loadPkcs11Slots(); + if ( pinText.getText().trim().isEmpty()) { + pinText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK)); + } + finishOK=false; + } + } else { + CertificateSelectionPage.this.setErrorMessage( "The Pin does NOT match your keystore."); + } + isPageComplete(); + } + + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + //System.out.println("CertificateSelectionPage -- button default selected"); + } + + }); + + } + + private void addProgressBarSection( final Composite parent ) { + // Create progress bar + Composite spacer = new Composite( parent, SWT.NONE ); + spacer.setLayoutData( new GridData( GridData.FILL_BOTH ) ); + spacer.setLayout( new GridLayout() ); + progressBar = new ProgressBar( parent, SWT.HORIZONTAL | SWT.INDETERMINATE ); + progressBar.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) ); + progressBar.setVisible( false ); + } + + private int computeWidthHint( Shell shell ) { + double ratio = .50d; + double boundsWidth = ( double ) shell.getBounds().width; + int widthHint = ( int ) ( boundsWidth * ratio ); + if ( widthHint < 400 ) { + widthHint = 400; + } + + return widthHint; + } + + public void createControl( final Composite parent ) { + // Create a main composite for the page + //final Composite main = new Composite( parent, SWT.NONE ); + //final Composite main = new Composite( parent, SWT.BORDER ); + final Composite main = new Composite( parent, SWT.BORDER | SWT.NO_RADIO_GROUP ); + main.setSize(500, 100); + main.pack(true); + main.setLayoutData( new GridData( GridData.FILL_BOTH ) ); + main.setLayout( new GridLayout() ); + + // Add section for instructions + addInstructionsSection( main ); + + // Add section for certificate details, including file and password + addCertificateDetailsSection( main ); + + // Add section for password + addProgressBarSection( main ); + + addSaveCertificateCheckbox(main); + // set focus on password entry if cert path already set + //for PKCS12 + + if (certPathText != null && certPathText.getText() != null && + !"".equals(certPathText.getText().trim()) && + passwordText != null) { + passwordText.setFocus(); + } + //for PKCS11 +// if (PKCSSelected.isPkcs11Selected()){ +// passwordText.setFocus(); +// } +// + PlatformUI.getWorkbench().getHelpSystem().setHelp(this.getShell(), + "org.eclipse.pki.wizard"); + + + main.getSize(); + main.pack(true); + + // Finishing touches + this.setPageComplete( true ); + this.setControl( main ); + } + + @Override + public Control getControl() { + return super.getControl(); + } + + protected KeyStore getUserKeyStore() { + String certPath = null; + String password = null; + KeyStore keyStore = null; + try { + + try { + certPath = certPathText.getText(); + password = passwordText.getText(); + } catch (Exception e) {} + + + if (password != null ) { + System.setProperty("javax.net.ssl.keyStorePassword", password); + } else { + System.setProperty("javax.net.ssl.keyStorePassword", "*******"); + } + if (( certPath != null ) && (PKIState.CONTROL.isPKCS12on() ) ) { + System.setProperty("javax.net.ssl.keyStore", certPath ); + } + if (( certPath != null ) && (PKIState.CONTROL.isPKCS11on() ) ) { + System.setProperty("javax.net.ssl.keyStore", "pkcs11" ); + } + + keyStore = KeyStoreUtil.getKeyStore(); + if ( keyStore == null ) { + keyStore = KeyStoreUtil.getKeyStore(certPath, password, PKCSSelected.getKeystoreformat()/*KeyStoreFormat.PKCS12*/); + } + + + } catch ( Throwable exception ) { + + + if ( null != exception ) { + StringBuilder message = new StringBuilder(); + message.append( "Problem reading your certificate. " ); + if(exception instanceof KeyStoreException){ + message.append("The Java Key Store can not be loaded"); + } else if(exception instanceof NoSuchAlgorithmException){ + message.append("The algorithm used to check the integrity of the pki file cannot be found."); + } else if(exception instanceof CertificateException){ + message.append("The pki file can not be loaded."); + } else if(exception instanceof IOException){ + message.append( "Either your password was incorrect or the " ); + message.append( "the selected file is corrupt. Please try " ); + message.append( "a different password or PKCS file." ); + } else { + message.append( "An unexpected error '" ); + message.append( exception.getClass().getName() ); + message.append( "' occurred: " ); + message.append( exception.getMessage() ); + message.append( " Please select a different file and/or " ); + message.append( "check the logs for more information." ); + } + this.setErrorMessage( message.toString() ); + + } + } + // Return the result + return keyStore; + + } + + public String getCertificatePath() + { + return certPathText.getText(); + } + + public void setCertificatePath(String path){ + this.certPathText.setText(path);; + } + + public String getCertPassPhrase() + { + return passwordText.getText(); + } + + public boolean isSaveCertificateChecked() { + return isSaveCertificateChecked; + } + public void setSaveCertificateChecked( boolean b ) { + isSaveCertificateChecked=b; + ChangedPressedFieldEditorStatus.setPKISaveCertificateChecked(isSaveCertificateChecked); + } + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.WizardPage#isPageComplete() + */ + @Override + public boolean isPageComplete() { + boolean isComplete=false; + + //System.out.println("CertificateSelectionPage is PAGE COMPLETE?"); + try { + // Get path + String certPath = null; + if ( null != certPathText ) { + certPath = certPathText.getText().trim(); + } + + if ( PKIState.CONTROL.isPKCS12on()) { + //System.out.println("CertificateSelectionPage is PAGE COMPLETE? PKCS12"); + System.clearProperty("javax.net.ssl.keyStoreType"); + if ( (!(certPath.isEmpty())) && (!(passwordText.getText().isEmpty() ))) { + //System.out.println("CertificateSelectionPage YES PAGE IS COMPLETE? PKCS12"); + if ( finishOK ) { + PKCSSelected.setKeystoreformat(KeyStoreFormat.PKCS12); + isComplete=true; + } + } + } + if (( PKIState.CONTROL.isPKCS11on()) && (pkcs11Button.getSelection()) && + (!(pinText.getText().isEmpty()) &&(finishOK))) { + //System.out.println("CertificateSelectionPage -------------------- is PAGE COMPLETE? PKCS11"); + //System.out.println("CertificateSelectionPage -------------------- PiN PKCS11:"+ pinText.getText()); + isComplete=true; + } + if ((!(PKIState.CONTROL.isPKCS11on())) && ((!(PKIState.CONTROL.isPKCS12on())))) { + //System.out.println("CertificateSelectionPage --------- NOTHING PICKED"); + } + } catch (Exception e) { + /* + * This method may be called before page is displayed, so make sure its NOT complete.. + */ + // TODO Auto-generated catch block + //e.printStackTrace(); + isComplete=false; + } + return isComplete; + } + protected void exitOnCompletion() { + this.getShell().setVisible(false); + } + + protected boolean finishButton() { + //this.getWizard().getContainer().getButton(IDialogConstants.FINISH_ID); + //System.out.println("CertificateSelectionPage PRESSED FINISH BUTTON "+finishOK); + return finishOK; + } + public boolean isFinished() { + return finishOK; + } + + @SuppressWarnings("static-access") + protected boolean performFinish() { + boolean isDone=false; + String fingerprint=null; + //System.out.println("CertificateSelectionPage PAGE COMPLETE FINISH BUTTON "); + + try { + AuthenticationPlugin plugin = AuthenticationPlugin.getDefault(); + if ( PKIState.CONTROL.isPKCS12on()) { + isDone=true; + String path = certPathText.getText().trim(); + if ( !path.equals( "" ) ) { + plugin.setCertificatePath( path ); + lastPropertyValues.load(); + } + } + if ( PKIState.CONTROL.isPKCS11on() ) { + isDone=true; + plugin.setCertificatePath( "pkcs11" ); + + plugin.setCertPassPhrase(VendorImplementation.security.getPin()); + System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11"); + lastPropertyValues.load(); + KeyStore store = VendorImplementation.getInstance().getKeyStore(); + if ( store == null ) { + System.out.println("CertificateSelectionPage performFinish() CANT FIND KEYSTORE"); + } + + X509Certificate x509 = (X509Certificate) VendorImplementation.getInstance().getKeyStore().getCertificate(selectedAlias); + if ( x509 != null) { + //System.out.println("CertificateSelectionPage performFinish() CERTIFICATE ALIAS:"+ x509.getSubjectDN()); + fingerprint=FingerprintX509.INSTANCE.getFingerPrint(x509, "SHA-256"); + VendorImplementation.getInstance().setSelectedX509Fingerprint(fingerprint); + } + } + if (!( plugin.isSSLSystemPropertiesSet() )) { + AuthenticationPlugin.getDefault().obtainDefaultJKSTrustStore(); + } + + if(!ChangedPressedFieldEditorStatus.isPkiChangedPressed()){ + PKISecureStorage pkiStorage = new PKISecureStorage(); + if(isSaveCertificateChecked()){ + pkiStorage.storePKI(AuthenticationPlugin.getDefault()); + } else { + pkiStorage.getNode().removeNode(); + } + } + } catch ( Throwable t) { + LogUtil.logError(t.getMessage(), t); + } + //System.out.println("CertificateSelectionPage ------------------performFinish DONE STATUS:"+isDone); + return isDone; + } + boolean checkPasswordAndKeystore( String path, String password ) { + boolean isOK = false; + + try { + if ( KeyStoreUtil.checkUserKeystorePass( path, password, "PKCS12" )) { + isOK=true; + //System.out.println("CertificateSelectionPage KeyStoreUtil SUCCESSFULLY VERIFIED cert path and password"); + } else { + //System.out.println("CertificateSelectionPage KeyStoreUtil SAYS ITS INVALID"); + } + } catch (Exception e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + isOK=false; + } + + return isOK; + } + private boolean isPKCS12Expired(char[] c) { + boolean isOK=false; + + PKCS12CheckValid.INSTANCE.isExpired(getUserKeyStore(), c); + return isOK; + } + private PKI setLastInstance( PKIProperties lastPki ) { + PKI pki = null; + + try { + pki = new PKI(); + pki.setKeyStorePassword(lastPki.getKeyStorePassword()); + pki.setKeyStoreProvider(lastPki.getKeyStoreProvider()); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return pki; + } + private void restoreLastPKI() { + + } + private class BrowseButtonListener extends SelectionAdapter { + @Override + public void widgetSelected( SelectionEvent e ) { + Shell shell = pkcs12selectCert.getShell(); + FileDialog dialog = new FileDialog( shell, SWT.SINGLE ); + String fileName = certPathText.getText(); + if ( ( null != fileName ) && + ( !fileName.trim().equals( "" ) ) ) { + File path = new File( fileName ); + if ( path.exists() ) { + if ( path.isDirectory() ) { + dialog.setFilterPath( path.getAbsolutePath() ); + } else { + dialog.setFileName( path.getAbsolutePath() ); + } + } + } + String[] filterNames = AuthenticationPreferences.FILTER_NAMES; + String[] filterExts = AuthenticationPreferences.FILTER_EXTS; + dialog.setFilterNames( filterNames ); + dialog.setFilterExtensions( filterExts ); + fileName = dialog.open(); + if ( null != fileName ) { + certPathText.setText( fileName ); + CertificateSelectionPage.this.getContainer().updateButtons(); + } + } + } + protected boolean loadPkcs11Slots() { + boolean isAnySlots=false; + try { + System.out.println("CertificateSelectionPage -- loadPkcs11Slots load slots"); + if ( slots != null ) { + if ( slots.length < 1 ) { + slots = new String[1]; + slots[0] = "Eclipse didnt find any x509 digital signatures. Did you enter your PIN? Please check your CAC."; + } + } else { + slots = new String[1]; + slots[0] = "Eclipse didnt find any x509 digital signatures. Did you enter your PIN? Please check your CAC."; + } + combo.setItems(slots); + combo.select(0); + isAnySlots=true; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return isAnySlots; + } + + protected String[] selectFromPkcs11Store() { + ArrayList list = new ArrayList(); + String items[] = null; + items = new String[1]; + try { + System.out.println("CertificateSelectionPage -- --selectFromPkcs11Store"); + if ( VendorImplementation.getInstance().isInstalled()) { + System.out.println("CertificateSelectionPage -- --selectFromPkcs11Store installed"); + list = new ArrayList(VendorImplementation.getInstance().getList()); + LogUtil.logInfo("CertificateSelectionPage - selectFromPkcs11Store list from cac:"+list.size()); + Iteratorit = list.iterator(); + int i=0; + if ( list.isEmpty() ) { + items = new String[1]; + items[0] = "Eclipse didnt find any x509 digital signatures. Did you enter your PIN? Please check your CAC."; + } else { + items = new String[list.size()]; + while ( it.hasNext() ) { + items[i] = it.next(); + i++; + } + } + System.out.println("CertificateSelectionPage -- --selectFromPkcs11Store installed DONE"); + } else { + // SET SELECTION TO PKCS12 here, because there is no PKCS11 installed + System.out.println("CertificateSelectionPage ----NOT able to load a PROVIDER"); + } + } catch(Exception e) { + e.printStackTrace(); + } + return items; + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/PKCS12CheckValid.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/PKCS12CheckValid.java new file mode 100644 index 00000000000..b477029be65 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/PKCS12CheckValid.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.wizard; + +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509Certificate; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Enumeration; + + + +public enum PKCS12CheckValid { + INSTANCE; + String expirationDate = null; + public boolean isExpired( KeyStore keyStore, char[] c) { + boolean isExpired=false; + + try { + Enumeration aliasesEnum = keyStore.aliases(); + while (aliasesEnum.hasMoreElements()) { + String alias = (String) aliasesEnum.nextElement(); + //System.out.println("ALIAS:"+ alias); + X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); + Date goodUntil = certificate.getNotAfter(); + DateFormat sdf = SimpleDateFormat.getDateInstance(); + expirationDate = sdf.format(goodUntil); + //System.out.println("EXPIRATION:"+ expirationDate); + + try { + certificate.checkValidity(); + } catch (CertificateExpiredException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + isExpired=true; + + } catch (CertificateNotYetValidException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return isExpired; + //return false; + + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/PKILoginWizard.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/PKILoginWizard.java new file mode 100644 index 00000000000..61111acbe06 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/PKILoginWizard.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.wizard; + + +import java.security.KeyStore; + +import org.eclipse.core.pki.auth.EventConstant; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Event; +import org.eclipse.ui.pki.EventProcessor; +import org.eclipse.ui.pki.pkcs.VendorImplementation; +import org.eclipse.ui.pki.pkiselection.PKCSSelected; +import org.eclipse.ui.pki.pkiselection.PKCSpick; +import org.eclipse.ui.pki.AuthenticationPlugin; + +import org.eclipse.core.pki.auth.PublicKeySecurity; + + +public class PKILoginWizard extends Wizard { + + protected int PAGE_WIDTH = 550; + protected int PAGE_HEIGHT = 100; + private CertificateSelectionPage certSelectionPage; + private String operation=null; + private String lastPkiPick=null;; + + public PKILoginWizard() { + super(); + this.setWindowTitle( "PKI Certificate Selection" ); + this.setHelpAvailable( false ); + this.setNeedsProgressMonitor( true ); + /* + * NOTE: + * Grab up the current selection, if any. + * This will enable the software to restore to last + * selection if a cancel is pressed. + */ + if (PKCSpick.getInstance().isPKCS12on() ) { + this.lastPkiPick = "pkcs12"; + } else if (PKCSpick.getInstance().isPKCS11on() ) { + this.lastPkiPick = "pkcs11"; + } else { + this.lastPkiPick = "NONE"; + } + } + @Override + public void setWindowTitle( String s ) { + StringBuilder sb = new StringBuilder(); + this.operation = s; + sb.append( "PKI Certificate "); + sb.append( this.operation ); + super.setWindowTitle( sb.toString() ); + } + + @Override + public void addPages() { + certSelectionPage = new CertificateSelectionPage(); + this.addPage( certSelectionPage ); + } + + + @Override + public boolean canFinish() { + boolean finishState = false; + //System.out.println("PKILoginWizard --- canFinish"); + if ((certSelectionPage != null) && + (certSelectionPage.isPageComplete() ) ) { + finishState=true; + } + + return finishState; + } + @Override + public boolean performCancel() { + certSelectionPage.setSaveCertificateChecked(false); + + if ( this.operation.equals("Selection")) { + EventProcessor.getInstance().sendEvent(EventConstant.CANCEL.getValue() ); + } else { + Event event = new Event(); + event.doit = true; + event.stateMask = 80000; + if ( this.lastPkiPick.equals("pkcs11") ) { + certSelectionPage.pkcs11Button.setSelection(true); + certSelectionPage.pkcs11Button.notifyListeners(SWT.Selection, event); + } else if ( this.lastPkiPick.equals("pkcs12") ) { + certSelectionPage.pkcs12Button.setSelection(true); + certSelectionPage.pkcs12Button.notifyListeners(SWT.Selection, event); + } + } + certSelectionPage.lastPropertyValues.restore(); + return true; + } + @Override + public boolean performFinish() { + String certificatePath = null; + KeyStore userKeyStore = certSelectionPage.getUserKeyStore(); + //System.out.println("PKILoginWizard -- FINISH"); + + try { + if(PKCSSelected.isPkcs11Selected()) { + //certSelectionPage.setCertificatePath(Pkcs11Provider.configPath("NONE")); + System.setProperty("javax.net.ssl.keyStore", "PKCS11"); + System.setProperty("javax.net.ssl.keyStoreType", "PKCS11"); + PKCSpick.getInstance().setPKCS11on(true); + PKCSpick.getInstance().setPKCS12on(false); + userKeyStore = VendorImplementation.getInstance().getKeyStore(); + certificatePath = "pkcs11"; + + } + if(PKCSSelected.isPkcs12Selected()) { + PKCSpick.getInstance().setPKCS11on(false); + PKCSpick.getInstance().setPKCS12on(true); + //System.setProperty("javax.net.ssl.keyStoreType", "PKCS12"); + certificatePath = certSelectionPage.getCertificatePath(); + } + + if ( null != userKeyStore ) { + + AuthenticationPlugin.getDefault().setUserKeyStore(userKeyStore); + if(PKCSSelected.isPkcs11Selected()) { + //certSelectionPage.setCertificatePath(Pkcs11Provider.configPath("NONE")); + } else { + if ( certificatePath != null ) { + AuthenticationPlugin.getDefault().setCertificatePath( certificatePath ); + + AuthenticationPlugin.getDefault().setCertPassPhrase( + certSelectionPage.getCertPassPhrase()); + } + } + + + //if the Change button is not pressed in the Preference window, then automatically save to + //secure storage. If it is pressed, then wait until OK or Apply button is clicked in the + //Preference window. + + // MOVED pkiSecure Storage call to CertificateSelectionPage so that the path could be saved first. + + // Tell the page to finish its own business + certSelectionPage.performFinish(); + PublicKeySecurity.INSTANCE.setupPKIfile(); + return true; + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return false; + } +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/TrustStoreLoginWizard.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/TrustStoreLoginWizard.java new file mode 100644 index 00000000000..9c38d5eb097 --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/TrustStoreLoginWizard.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.wizard; + +import java.security.KeyStore; +import org.eclipse.jface.wizard.Wizard; + +import org.eclipse.ui.pki.AuthenticationPlugin; +import org.eclipse.ui.pki.preferences.AuthenticationPreferences; +import org.eclipse.ui.pki.preferences.ChangedPressedFieldEditorStatus; +import org.eclipse.ui.pki.wizard.TrustStoreSecureStorage; + +public class TrustStoreLoginWizard extends Wizard { + + private TrustStoreSelectionPage truststorePage; + + public TrustStoreLoginWizard() { + super(); + this.setWindowTitle("Trust Store Selection"); + this.setHelpAvailable(false); + this.setNeedsProgressMonitor(true); + } + + @Override + public boolean performFinish() { + /* + * check if changes made and to store new info into secure storage or not and to remove secure storage if not. + */ + KeyStore truststorekeystore = truststorePage.getTrustStore(); + + if ( null != truststorekeystore ) { + + //Set trust store to user entered values. + AuthenticationPlugin.getDefault().setTrustStore(truststorekeystore); + AuthenticationPlugin.getDefault().setTrustStorePassPhrase(truststorePage.getPasswordText()); + AuthenticationPlugin.getDefault().getPreferenceStore().setValue(AuthenticationPreferences.TRUST_STORE_LOCATION, + truststorePage.getTruststoreJKSPath()); + + TrustStoreSecureStorage truststoreSecureStorage = new TrustStoreSecureStorage(); + + //if the Change button is not pressed in the Preference window, then automatically save to + //secure storage. If it is pressed, then wait until OK or Apply button is clicked in the + //Preference window. + if(!ChangedPressedFieldEditorStatus.isJksChangedPressed()){ + if(truststorePage.isPasswordSaveChecked()){ + truststoreSecureStorage.storeJKS(AuthenticationPlugin.getDefault()); + } else { + truststoreSecureStorage.getNode().removeNode(); + } + } + + // Tell the page to finish its own business + truststorePage.performFinish(); + + return true; + } + return false; + } + + @Override + public void addPages() { + truststorePage = new TrustStoreSelectionPage(); + this.addPage(truststorePage); + } + + @Override + public boolean canFinish() { + if(truststorePage != null && + truststorePage.isPageComplete()) + return true; + + return false; + } + +} diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/TrustStoreSecureStorage.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/TrustStoreSecureStorage.java new file mode 100644 index 00000000000..8d8fb5b4e2f --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/TrustStoreSecureStorage.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.wizard; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; + +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.equinox.security.storage.ISecurePreferences; +import org.eclipse.equinox.security.storage.SecurePreferencesFactory; +import org.eclipse.equinox.security.storage.StorageException; +import org.eclipse.ui.pki.AuthenticationPlugin; +import org.eclipse.ui.pki.pkiselection.PKCSpick; +import org.eclipse.core.pki.util.KeyStoreFormat; +import org.eclipse.ui.pki.util.KeyStoreUtil; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.eclipse.ui.pki.preferences.AuthenticationPreferences; + +public class TrustStoreSecureStorage extends AbstractUIPlugin { + + private ISecurePreferences securePreference = null; + private ISecurePreferences node = null; + + private String jksLocation; + private transient String jksPassPhrase; + + private static final String JAVA_SSL_TRUST_STORE_PATH_KEY = "javax.net.ssl.trustStore"; + private static final String JAVA_SSL_TRUST_STORE_TYPE_KEY = "javax.net.ssl.trustStoreType"; + private static final String JAVA_SSL_TRUST_STORE_PASS_KEY = "javax.net.ssl.trustStorePassword"; + private static final String TRUST_STORE_SECURE_STORAGE_NODE = "org.eclipse.pki.util/secureTrustJKSStore"; + private static final String SVNSaveAuthorizationInfo = "Save Authorization Info"; + + private final String JKS_LOCATION = "jks_location"; + private final String JKS_PASSPHRASE = "jks_passphrase"; + private final String JKS_SAVED = "jks_saved"; + + + public TrustStoreSecureStorage() { + this.securePreference = SecurePreferencesFactory.getDefault(); + this.node = securePreference.node(TRUST_STORE_SECURE_STORAGE_NODE); + } + + /** + * Stores the trust store information in secure storage. + * @param authenticationInfo the authentication plugin containing the user input. + */ + public void storeJKS(AuthenticationPlugin authenticationInfo){ + try { + String truststoreLocation = authenticationInfo.getPreferenceStore().getString(AuthenticationPreferences.TRUST_STORE_LOCATION); + node.put(JKS_LOCATION, truststoreLocation, false); + String passPhrase = authenticationInfo.getTrustStorePassPhrase().trim(); + node.put(JKS_PASSPHRASE, passPhrase, true); + node.put(JKS_SAVED, "true", false); + } catch (StorageException e) { + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } + } + + /** + * Test if the trust store is saved in secure storage. + * @return true if saved or false if not saved. + */ + public boolean isJKSSaved(){ + boolean saved = false; + try { + if("true".equals(node.get(JKS_SAVED, "false"))){ + saved = true; + } + } catch (StorageException e) { + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } + return saved; + } + + /** + * Creates the trust store from secure storage + * @return the trust store. + */ + public KeyStore getTrustStore(){ + KeyStore keyStore = null; + try { + jksLocation = node.get(JKS_LOCATION, "none"); + jksPassPhrase = node.get(JKS_PASSPHRASE, "none"); + if (jksLocation == null || jksLocation.isEmpty() ) { + jksLocation=AuthenticationPlugin.getDefault().getPreferenceStore().getString(AuthenticationPreferences.TRUST_STORE_LOCATION); + } + if ( PKCSpick.getInstance().isPKCS12on() ) { + keyStore = KeyStoreUtil.getKeyStore(jksLocation, jksPassPhrase, KeyStoreFormat.JKS); + } + } catch (StorageException e) { + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } catch (KeyStoreException e){ + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } catch (NoSuchAlgorithmException e){ + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } catch (CertificateException e){ + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } catch (IOException e){ + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } catch (IllegalArgumentException e) { + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } catch (SecurityException e) { + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } + return keyStore; + } + + /** + * Clears the saved trust store in secure storage. + * @return true if clear was successful, else false if not cleared. + */ + public boolean clearSavedTrustStore(){ + boolean cleared = false; + node.clear(); + try { + if("none".equals(node.get(JKS_LOCATION, "none")) && + "none".equals(node.get(JKS_PASSPHRASE, "none"))){ + cleared = true; + } + } catch (StorageException e) { + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } + return cleared; + } + + + /** + * Sets the trust store system properties only. Does not set the trust store key in AuthenticationPlugin. + */ + public void setTrustStoreSystemProperties(){ + KeyStore trustStore = getTrustStore(); + String trustStoreLocation = jksLocation; + if(trustStore != null && trustStore.getType() != null && trustStoreLocation != null && !trustStoreLocation.isEmpty()) { + System.setProperty(JAVA_SSL_TRUST_STORE_PATH_KEY, trustStoreLocation); + System.setProperty(JAVA_SSL_TRUST_STORE_TYPE_KEY, trustStore.getType()); + if(jksPassPhrase != null && !jksPassPhrase.isEmpty()) { + System.setProperty(JAVA_SSL_TRUST_STORE_PASS_KEY, jksPassPhrase); + } else { + System.setProperty(JAVA_SSL_TRUST_STORE_PASS_KEY, AuthenticationPlugin.getDefaultTrustStorePassword()); + } + } + } + + /** + * The node in secure storage containing the trust store information. + * @return the trust store secure storage node. + */ + public ISecurePreferences getNode() { + return node; + } + + /** + * @return the jks trust store password. + */ + public String getJksPassPhrase() { + try { + jksPassPhrase = node.get(JKS_PASSPHRASE, "none"); + } catch (StorageException e) { + LogUtil.logError(SVNSaveAuthorizationInfo, e); + } + return jksPassPhrase; + } +} \ No newline at end of file diff --git a/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/TrustStoreSelectionPage.java b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/TrustStoreSelectionPage.java new file mode 100644 index 00000000000..d9c2e64008d --- /dev/null +++ b/team/bundles/org.eclipse.ui.pki/src/org/eclipse/ui/pki/wizard/TrustStoreSelectionPage.java @@ -0,0 +1,411 @@ +/******************************************************************************* + * Copyright (c) 2023 Eclipse Platform, Security Group 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: + * Eclipse Platform - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.pki.wizard; + +import java.io.File; +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; + +import org.eclipse.core.pki.util.LogUtil; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.pki.preferences.ChangedPressedFieldEditorStatus; +import org.eclipse.core.pki.util.KeyStoreFormat; +import org.eclipse.ui.pki.util.KeyStoreUtil; +import org.eclipse.ui.pki.AuthenticationPlugin; +import org.eclipse.ui.pki.PKIController; +import org.eclipse.ui.pki.preferences.AuthenticationPreferences; + +public class TrustStoreSelectionPage extends WizardPage { + + private final static String PAGENAME = "Default Authentication - Trust Store Selection Page"; + private final static String TITLE = "Trust Store Authentication"; + private final static String DESCRIPTION = "Select Trust Store"; + private final static String EMPTY_STRING = ""; + private final static String OPENING_INSTRUCTIONS = + "This application allows users to select the Java keystore file. " + + "If the default trust store in your home directory is used, the default password will automatically appear in the password field."; + private final static String SELECTION_INSTRUCTIONS = + "Please select the Java keystore by clicking on the Browse... button. If using a different " + + "trust store (jks file), delete the default password and enter the password for the new trust store."; + + private Text truststorePathText = null; + private Button selecttruststore = null; + private Text passwordText = null; + private String truststoreJKSPath = null; + + private boolean isPasswordSaveChecked = false; + + protected Button passwordSavedCheckbox; + + + + public TrustStoreSelectionPage() { + super(PAGENAME); + setTitle(TITLE); + setDescription(DESCRIPTION); + } + + public void createControl(Composite parent) { + // Create a main composite for the page + final Composite main = new Composite( parent, SWT.NONE ); + main.setLayoutData( new GridData( GridData.FILL_BOTH ) ); + main.setLayout( new GridLayout() ); + + // Add section for instructions + addInstructionsSection( main ); + + // Add section for trust store details, including file and password + addTrustStoreDetailSection(main); + + + // set focus on password entry if trust store path already set + if (truststorePathText != null && truststorePathText.getText() != null && + !"".equals(truststorePathText.getText().trim()) && + passwordText != null) { + passwordText.setFocus(); + } + + // Finishing touches + this.setPageComplete( true ); + this.setControl( main ); + + } + + private Composite addInstructionsSection(final Composite parent) { + // Create composite for the section + Composite sectionComposite = new Composite( parent, SWT.NONE ); + GridLayout subsectionCompositeLayout = new GridLayout(); + subsectionCompositeLayout.horizontalSpacing = 10; + subsectionCompositeLayout.verticalSpacing = 10; + sectionComposite.setLayout( subsectionCompositeLayout ); + sectionComposite.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) ); + + // Calculate initial width + int widthHint = computeWidthHint( this.getContainer().getShell() ); + + // Create labels for each set of instructions + Label openingInstructionsLabel = new Label( sectionComposite, SWT.WRAP ); + GridData labelGridData = new GridData( GridData.FILL_BOTH ); + labelGridData.widthHint = widthHint; + openingInstructionsLabel.setLayoutData( labelGridData ); + openingInstructionsLabel.setText( OPENING_INSTRUCTIONS ); + + Label selectionInstructionsLabel = new Label( sectionComposite, SWT.WRAP ); + labelGridData = new GridData( GridData.FILL_BOTH ); + labelGridData.widthHint = widthHint; + selectionInstructionsLabel.setLayoutData( labelGridData ); + selectionInstructionsLabel.setText( SELECTION_INSTRUCTIONS ); + + return sectionComposite; + + } + + private int computeWidthHint( Shell shell ) { + double ratio = .50d; + double boundsWidth = ( double ) shell.getBounds().width; + int widthHint = ( int ) ( boundsWidth * ratio ); + if ( widthHint < 400 ) { + widthHint = 400; + } + + return widthHint; + } + + private Composite addTrustStoreDetailSection(final Composite parent){ + final Composite sectionComposite = new Composite( parent, SWT.NONE ); + sectionComposite.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) ); + GridLayout sectionCompositeLayout = new GridLayout( 2, false ); + sectionCompositeLayout.verticalSpacing = 1; + sectionComposite.setLayout( sectionCompositeLayout ); + + //Add section for the trust store selection + addTrustStoreSelection(sectionComposite); + + // Add section for password + addPasswordSubsection( sectionComposite ); + + //Add section for saving certificate checkbox + addSavePasswordCheckbox(sectionComposite); + + return sectionComposite; + } + + + private void addSavePasswordCheckbox(Composite sectionComposite) { + //Create label for saving the certificate + Label saveCertificateLabel = new Label(sectionComposite, SWT.RIGHT); + saveCertificateLabel.setText("Save Trust Store Information: "); + + //Create layout and controls + Composite subsectionComposite = new Composite(sectionComposite, SWT.NONE); + GridLayout subsectionCompositeLayout = new GridLayout(2, false); + subsectionComposite.setLayout(subsectionCompositeLayout); + subsectionComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + passwordSavedCheckbox = new Button(subsectionComposite, SWT.CHECK); + passwordSavedCheckbox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); + + passwordSavedCheckbox.addSelectionListener(new SelectionListener(){ + + public void widgetSelected(SelectionEvent e) { + isPasswordSaveChecked = passwordSavedCheckbox.getSelection(); + ChangedPressedFieldEditorStatus.setJKSSaveTrustStoreChecked(isPasswordSaveChecked); + } + + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + + } + + }); + + } + + private void addPasswordSubsection(Composite sectionComposite) { + // Create controls for specifying the password + Label passwordLabel = new Label( sectionComposite, SWT.RIGHT ); + passwordLabel.setText( "Trust Store Password: " ); + + // Create layout and controls for manually selecting certs + Composite subsectionComposite = new Composite( sectionComposite, SWT.NONE ); + GridLayout subsectionCompositeLayout = new GridLayout( 2, false ); + subsectionCompositeLayout.horizontalSpacing = 10; + subsectionCompositeLayout.verticalSpacing = 10; + subsectionComposite.setLayout( subsectionCompositeLayout ); + subsectionComposite.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) ); + + passwordText = new Text( subsectionComposite, SWT.LEFT | SWT.PASSWORD | SWT.BORDER ); + passwordText.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) ); + if(isUsingDefaultTrustStore(truststorePathText.getText().trim())){ + passwordText.setText(AuthenticationPlugin.getDefaultTrustStorePassword()); + } + + ModifyListener modifyListener = new ModifyListener() { + public void modifyText( ModifyEvent e ) { + TrustStoreSelectionPage.this.setErrorMessage( null ); + TrustStoreSelectionPage.this.getContainer().updateButtons(); + } + }; + passwordText.addModifyListener( modifyListener ); + Composite spacer = new Composite( subsectionComposite, SWT.NONE ); + spacer.setLayoutData( new GridData( GridData.FILL_BOTH ) ); + spacer.setLayout( new GridLayout() ); + + } + + private void addTrustStoreSelection(final Composite sectionComposite) { + // Create label for selecting the trust store + Label certificateLabel = new Label( sectionComposite, SWT.RIGHT ); + certificateLabel.setText( "Trust Store Location: " ); + + // Create layout and controls for manually selecting trust store + Composite subsectionComposite = new Composite( sectionComposite, SWT.NONE ); + GridLayout subsectionCompositeLayout = new GridLayout( 2, false ); + subsectionComposite.setLayout( subsectionCompositeLayout ); + subsectionComposite.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) ); + + truststorePathText = new Text( subsectionComposite, SWT.LEFT | SWT.BORDER ); + truststorePathText.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) ); + AuthenticationPlugin plugin = AuthenticationPlugin.getDefault(); + String preferencesKey = AuthenticationPreferences.TRUST_STORE_LOCATION; + IPreferenceStore preferenceStore = plugin.getPreferenceStore(); + String truststorePath = preferenceStore.getString( preferencesKey ); + if ( null != truststorePath ) { + truststorePathText.setText( truststorePath ); + } + + selecttruststore = new Button( subsectionComposite, SWT.PUSH ); + selecttruststore.setText( "Browse..." ); + BrowseButtonListener listener = new BrowseButtonListener(); + selecttruststore.addSelectionListener( listener ); + } + + private boolean isUsingDefaultTrustStore(String trustStorePath){ + boolean usingDefaultTrustStore = false; + + final String defaultTrustStorePath = new File(PKIController.PKI_ECLIPSE_DIR, "cacerts").getPath(); + + if(trustStorePath.equals(defaultTrustStorePath)){ + usingDefaultTrustStore = true; + } + + return usingDefaultTrustStore; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.WizardPage#isPageComplete() + */ + @Override + public boolean isPageComplete() { + + // Get path + String truststorePath = null; + if ( null != truststorePathText ) { + truststorePath = truststorePathText.getText().trim(); + } + + // Test path + if ( null != truststorePath && !truststorePath.equals(EMPTY_STRING)) + return true; + + return false; + } + + + protected void performFinish() { + try { + // Persist the selected path, if specified + if ( ( null != truststorePathText ) && + ( null != truststorePathText.getText() ) ) { + String path = truststorePathText.getText().trim(); + truststoreJKSPath = path; + if ( !path.equals( "" ) ) { + AuthenticationPlugin plugin = AuthenticationPlugin.getDefault(); + String key = AuthenticationPreferences.TRUST_STORE_LOCATION; + IPreferenceStore preferenceStore = + plugin.getPreferenceStore(); + preferenceStore.setValue( key, path ); + } + } + + } catch ( Throwable t ) { + LogUtil.logError(t.getMessage(), t); + } + } + + + protected KeyStore getTrustStore(){ + String errormsg = null; + KeyStore keyStore = null; + String truststorePath = truststorePathText.getText(); + truststoreJKSPath = truststorePath; + String password = passwordText.getText(); + + try { + keyStore = KeyStoreUtil.getKeyStore(truststorePath, password, KeyStoreFormat.JKS); + } catch (KeyStoreException e) { + errormsg = "The Java key store can not be loaded."; + } catch (NoSuchAlgorithmException e) { + errormsg = "The algorithm used to check the integrity of the jks file cannot be found."; + } catch (CertificateException e) { + errormsg = "The jks file can not be loaded."; + } catch (IOException e) { + errormsg = "There is a problem with the password or problem with the jks file data. Please try a different password:"+password; + } catch (Exception e){ + errormsg = "Unexpected error occurred."; + } + + if(errormsg != null){ + this.setErrorMessage(errormsg); + keyStore = null; + } + + // Return the result + return keyStore; + } + + + + public Text getTruststorePathText() { + return truststorePathText; + } + + + + public Button getSelecttruststore() { + return selecttruststore; + } + + + + public boolean isPasswordSaveChecked() { + return isPasswordSaveChecked; + } + + public void setPasswordSaved(boolean isPasswordSaved) { + this.isPasswordSaveChecked = isPasswordSaved; + } + + @Override + public Control getControl() { + return super.getControl(); + } + + + + public String getTruststoreJKSPath() { + return truststoreJKSPath; + } + + + + public String getPasswordText() { + return passwordText.getText(); + } + + + + private class BrowseButtonListener extends SelectionAdapter { + @Override + public void widgetSelected( SelectionEvent e ) { + Shell shell = selecttruststore.getShell(); + FileDialog dialog = new FileDialog( shell, SWT.SINGLE ); + String fileName = truststorePathText.getText(); + if ( ( null != fileName ) && + ( !fileName.trim().equals( "" ) ) ) { + File path = new File( fileName ); + if ( path.exists() ) { + if ( path.isDirectory() ) { + dialog.setFilterPath( path.getAbsolutePath() ); + } else { + dialog.setFileName( path.getAbsolutePath() ); + } + } + } + String[] filterNames = {"*"}; + String[] filterExts = {"*.jks"}; + dialog.setFilterNames( filterNames ); + dialog.setFilterExtensions( filterExts ); + fileName = dialog.open(); + if ( null != fileName ) { + truststorePathText.setText( fileName ); + if(isUsingDefaultTrustStore(truststorePathText.getText().trim())){ + passwordText.setText(AuthenticationPlugin.getDefaultTrustStorePassword()); + } else { + passwordText.setText(""); + } + TrustStoreSelectionPage.this.getContainer().updateButtons(); + } + } + } +} \ No newline at end of file diff --git a/team/tests/org.eclipse.core.tests.pki/.classpath b/team/tests/org.eclipse.core.tests.pki/.classpath new file mode 100644 index 00000000000..ea7738861a0 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/.classpath @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/team/tests/org.eclipse.core.tests.pki/.project b/team/tests/org.eclipse.core.tests.pki/.project new file mode 100644 index 00000000000..bb53ef76671 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/.project @@ -0,0 +1,28 @@ + + + org.eclipse.core.tests.net + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/team/tests/org.eclipse.core.tests.pki/META-INF/MANIFEST.MF b/team/tests/org.eclipse.core.tests.pki/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..4f822e635c7 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/META-INF/MANIFEST.MF @@ -0,0 +1,23 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: PKI Tests Plug-in +Bundle-SymbolicName: org.eclipse.core.tests.pki;singleton:=true +Bundle-Version: 1.0.300 +Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.29.0,4.0.0)", + org.eclipse.core.pki, + org.mockito.mockito-core, + org.junit;bundle-version="4.13.2", + org.osgi.annotation.bundle;bundle-version="2.0.0" +Import-Package: org.assertj.core.api, + org.bouncycastle.util.test;version="[1.77.0,2.0.0]", + org.eclipse.core.tests.pki, + org.junit.jupiter.api, + org.junit.platform.suite.api, + org.osgi.framework +Bundle-Activator: org.eclipse.core.tests.pki.Activator +Bundle-ClassPath: ., + tests/org.eclipse.core.tests.pki/ +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Export-Package: org.eclipse.core.tests.pki +Bundle-Vendor: Delmarva Security +Automatic-Module-Name: org.eclipse.core.tests.pki diff --git a/team/tests/org.eclipse.core.tests.pki/about.html b/team/tests/org.eclipse.core.tests.pki/about.html new file mode 100644 index 00000000000..164f781a8fd --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/about.html @@ -0,0 +1,36 @@ + + + + +About + + +

About This Content

+ +

November 30, 2017

+

License

+ +

+ The Eclipse Foundation makes available all content in this plug-in + ("Content"). Unless otherwise indicated below, the Content + is provided to you under the terms and conditions of the Eclipse + Public License Version 2.0 ("EPL"). A copy of the EPL is + available at http://www.eclipse.org/legal/epl-2.0. + For purposes of the EPL, "Program" will mean the Content. +

+ +

+ If you did not receive this Content directly from the Eclipse + Foundation, the Content is being redistributed by another party + ("Redistributor") and different terms and conditions may + apply to your use of any object code in the Content. Check the + Redistributor's license that was provided with the Content. If no such + license exists, contact the Redistributor. Unless otherwise indicated + below, the terms and conditions of the EPL still apply to any source + code in the Content and such source code may be obtained at http://www.eclipse.org. +

+ + + \ No newline at end of file diff --git a/team/tests/org.eclipse.core.tests.pki/build.properties b/team/tests/org.eclipse.core.tests.pki/build.properties new file mode 100644 index 00000000000..d50a081ee21 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/build.properties @@ -0,0 +1,25 @@ +############################################################################### +# Copyright (c) 2005, 2007 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 +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.properties,\ + plugin.xml,\ + about.html,\ + . +src.includes = META-INF/, \ + about.html +jre.compilation.profile = JavaSE-17 +javacErrors.. = -assertIdentifier,-enumIdentifier diff --git a/team/tests/org.eclipse.core.tests.pki/nope.xml.ORIG b/team/tests/org.eclipse.core.tests.pki/nope.xml.ORIG new file mode 100644 index 00000000000..d6ebc88c814 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/nope.xml.ORIG @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/team/tests/org.eclipse.core.tests.pki/plugin.properties b/team/tests/org.eclipse.core.tests.pki/plugin.properties new file mode 100644 index 00000000000..ff07e8370b3 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/plugin.properties @@ -0,0 +1,18 @@ +############################################################################### +# Copyright (c) 2000, 2006 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 +############################################################################### +# +# Resource strings for PKI Tests plugin.xml file +# +pluginName= PKI Tests +providerName= Eclipse.org diff --git a/team/tests/org.eclipse.core.tests.pki/plugin.xml b/team/tests/org.eclipse.core.tests.pki/plugin.xml new file mode 100644 index 00000000000..6af97466599 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/plugin.xml @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/Activator.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/Activator.java new file mode 100644 index 00000000000..1bc35e2ab97 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/Activator.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2007 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.core.tests.pki; + + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +/** + * The activator class controls the plug-in life cycle + */ + +public class Activator implements BundleActivator { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.core.tests.pki"; + + // The shared instance + private static Activator plugin; + + private static BundleContext context; + + public static BundleContext getContext() { + return context; + } + + /** + * The constructor + */ + public Activator() { + } + + @Override + public void start(BundleContext context) throws Exception { + //super.start(context); + Activator.context = context; + new MainTest(); + } + + @Override + public void stop(BundleContext context) throws Exception { + + } + public static Activator getDefault() { + return plugin; + } + +} diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/MainTest.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/MainTest.java new file mode 100644 index 00000000000..654b326f6d4 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/MainTest.java @@ -0,0 +1,70 @@ +package org.eclipse.core.tests.pki; + +/******************************************************************************* + * Copyright (c) 2024 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 + *******************************************************************************/ +//import org.eclipse.core.pki.PKISetup; +import java.util.Properties; + + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doNothing; +import static org.mockito.ArgumentMatchers.isA; + +import org.junit.Before; +import org.junit.Test; + + +import org.eclipse.core.pki.auth.SecurityFileSnapshot; +import org.eclipse.core.pki.pkiselection.PkiPasswordGrabberWidget; +import org.eclipse.core.pki.pkiselection.PKI; +import org.eclipse.core.pki.auth.PKIState; + + +public class MainTest { + Properties properties = new Properties(); + String testName = "PKItestSubscriber"; + + SecurityFileSnapshot securityFileSnapshotMock = null; + PkiPasswordGrabberWidget pkiPasswordGrabberWidgetMock = null; + PKI pkiMock = null; + + PKIState pkiStateMock = null; + + public MainTest() { + System.out.println("Constructor MainTest"); + } + + @Before + public void Initialize() throws Exception { + + securityFileSnapshotMock = mock(SecurityFileSnapshot.class); + pkiPasswordGrabberWidgetMock = mock(PkiPasswordGrabberWidget.class); + + pkiMock = mock(PKI.class); + pkiStateMock = mock(PKIState.class); + + } + @Test + public void testSecurityFileSnapshot() { + when(securityFileSnapshotMock.image()).thenReturn(true); + when(securityFileSnapshotMock.createPKI()).thenReturn(true); + when(securityFileSnapshotMock.load(isA(String.class), isA(String.class))).thenReturn(properties); + doNothing().when(securityFileSnapshotMock).restoreProperties(); + } + @Test + public void testPkiPasswordGrabberWidget() { + when(pkiPasswordGrabberWidgetMock.getInput()).thenReturn("testPassword"); + } +} diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/SecurityOpRequestTest.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/SecurityOpRequestTest.java new file mode 100644 index 00000000000..f2dcd733f44 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/SecurityOpRequestTest.java @@ -0,0 +1,55 @@ +package org.eclipse.core.tests.pki; + +/******************************************************************************* + * Copyright (c) 2024 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 + *******************************************************************************/ +//import org.eclipse.core.pki.PKISetup; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +//import static org.assertj.swing.edt.FailOnThreadViolationRepaintManager; +//import static org.assertj.swing.fixture.JPanelFixture; +//import static org.assertj.swing.testing.AssertJSwingTestCaseTemplate; + + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doNothing; + +import org.junit.Before; + +import org.junit.Test; + +import org.eclipse.core.pki.pkiselection.SecurityOpRequest; + +public class SecurityOpRequestTest { + SecurityOpRequest securityOpRequestMock = null; + + + public SecurityOpRequestTest() {} + + @Before + public void Initialize() throws Exception { + //MockitoAnnotations.initMocks(this); + securityOpRequestMock = mock(SecurityOpRequest.class); + } + + @Test + public void testSecurityOp() { + when(securityOpRequestMock.getConnected()).thenReturn(true); + doNothing().when(securityOpRequestMock).setConnected(false); + boolean testResult = securityOpRequestMock.getConnected(); + assertTrue(testResult); + securityOpRequestMock.setConnected(true); + } +} diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/ContextObserverTest.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/ContextObserverTest.java new file mode 100644 index 00000000000..09681ee3c0d --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/ContextObserverTest.java @@ -0,0 +1,21 @@ +package org.eclipse.core.tests.pki.auth; + +import org.junit.jupiter.api.Test; +import static org.mockito.Mockito.mock; +//import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doNothing; +import static org.mockito.ArgumentMatchers.isA; + +import org.eclipse.core.pki.auth.ContextObservable; + +public class ContextObserverTest { + + ContextObservable contextObservableMock = mock(ContextObservable.class); + public ContextObserverTest() {} + + @Test + void testOnChange() { + doNothing().when(contextObservableMock).onchange(isA(String.class)); + } + +} diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/EventConstantTest.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/EventConstantTest.java new file mode 100644 index 00000000000..d5e7b598906 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/EventConstantTest.java @@ -0,0 +1,75 @@ +package org.eclipse.core.tests.pki.auth; + + + +import java.util.Random; + +import org.mockito.Mock; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.eclipse.core.pki.auth.EventConstant; + +import org.junit.Before; +import org.junit.Test; + +public class EventConstantTest { + + @Mock + EventConstant eventConstantMock = null; + public EventConstantTest() {} + int DONE=0; + int CANCEL=2; + int SETUP = Integer.valueOf(10).intValue(); + + @Before + public void Initialize() throws Exception { + //MockitoAnnotations.initMocks(this); + eventConstantMock = mock(EventConstant.class); + } + @Test + public void testEventConstantSetup() { + + //Random rand = new Random(); + //int ordinal = rand.nextInt(EventConstant.values().length); + + int returnValue = EventConstant.SETUP.getValue(); + assertEquals(SETUP, returnValue); + + //try ( MockedStatic eventConstantMock = mockStatic(EventConstant.class)) { + // eventConstantMock.when(() -> { EventConstant.SETUP.getValue(); }) + // .mock.isOk().thenReturn(ordinal); + //} + + } + @Test + public void testEventConstantDone() { + Random rand = new Random(); + int ordinal = rand.nextInt(EventConstant.values().length); + when(eventConstantMock.getValue()).thenReturn(ordinal); + try { + int returnValue = EventConstant.DONE.getValue(); + assertEquals(DONE, returnValue); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testEventConstantClose() { + Random rand = new Random(); + int ordinal = rand.nextInt(EventConstant.values().length); + when(eventConstantMock.getValue()).thenReturn(ordinal); + try { + int returnValue = EventConstant.CANCEL.getValue(); + assertEquals(CANCEL, returnValue); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + +} diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/IncomingSystemPropertyTest.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/IncomingSystemPropertyTest.java new file mode 100644 index 00000000000..e1412d0e2f2 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/IncomingSystemPropertyTest.java @@ -0,0 +1,67 @@ +package org.eclipse.core.tests.pki.auth; + +import static org.junit.jupiter.api.Assertions.*; + + +import org.eclipse.core.pki.auth.IncomingSystemProperty; + +import org.mockito.Mock; + +import static org.mockito.Mockito.mock; +import org.junit.Before; +import org.junit.Test; + +public class IncomingSystemPropertyTest { + + @Mock + IncomingSystemProperty incomingSystemPropertyMock = null; + public IncomingSystemPropertyTest() {} + + @Before + public void Initialize() throws Exception { + //MockitoAnnotations.initMocks(this); + incomingSystemPropertyMock = mock(IncomingSystemProperty.class); + } + + @Test + public void testCheckType() { + try { + boolean result = incomingSystemPropertyMock.checkType(); + assertFalse(result); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + @Test + public void testCheckKeyStore() { + try { + boolean result = incomingSystemPropertyMock.checkKeyStore("PiN"); + assertFalse(result); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + @Test + public void testCheckTrustStoreType() { + try { + boolean result = incomingSystemPropertyMock.checkTrustStoreType(); + assertFalse(result); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + @Test + public void testCheckTrustStore() { + try { + boolean result = incomingSystemPropertyMock.checkTrustStore(); + assertFalse(result); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + +} diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/KeystoreSetupTest.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/KeystoreSetupTest.java new file mode 100644 index 00000000000..3ec5019e918 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/KeystoreSetupTest.java @@ -0,0 +1,37 @@ +package org.eclipse.core.tests.pki.auth; + + +import org.eclipse.core.pki.auth.KeystoreSetup; + +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockedStatic; + +import static org.mockito.Mockito.mock; + +import org.junit.Before; +import org.junit.Test; + + +public class KeystoreSetupTest { + + + @Mock + KeystoreSetup keyStoreSetupMock = null; + public KeystoreSetupTest() {} + + @Before + public void Initialize() throws Exception { + //MockitoAnnotations.initMocks(this); + keyStoreSetupMock = mock(KeystoreSetup.class); + } + @Test + public void testgetInstance() { + KeystoreSetup keystoreMock = Mockito.spy(KeystoreSetup.getInstance()); + + try (MockedStatic keyStoreSetupMock = Mockito.mockStatic(KeystoreSetup.class)) { + keyStoreSetupMock.when(() -> { KeystoreSetup.getInstance(); }) + .thenReturn(keystoreMock); + } + } +} diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PKISetupTest.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PKISetupTest.java new file mode 100644 index 00000000000..980d530d5cf --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PKISetupTest.java @@ -0,0 +1,110 @@ +package org.eclipse.core.tests.pki.auth; + +/******************************************************************************* + * Copyright (c) 2024 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 + *******************************************************************************/ +//import org.eclipse.core.pki.PKISetup; + +import javax.net.ssl.SSLContext; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.mockito.Mock; +import org.mockito.Mockito; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doNothing; +import static org.mockito.ArgumentMatchers.isA; +import org.mockito.MockedStatic; + +import org.junit.Before; +import org.junit.Test; +import org.osgi.framework.BundleContext; + +import org.eclipse.core.pki.auth.PKISetup; + + +public class PKISetupTest { + + PKISetup pkiSetupMock = null; + + @Mock + private SSLContext context; + + @Mock + private BundleContext bundleContext; + + public PKISetupTest() {} + + @Before + public void Initialize() throws Exception { + //MockitoAnnotations.initMocks(this); + pkiSetupMock = mock(PKISetup.class); + //context = SSLContext.getDefault(); + } + + @Test + public void testStart() { + //doNothing().when(pkiSetupMock).start(bundleContext).thenThrows(new Exception()); + try { + doNothing().when(pkiSetupMock).start(bundleContext); + } catch (Exception e) { + // TODO Auto-generated catch block + assertThrows(Exception.class, () -> pkiSetupMock.start(bundleContext)); + } + } + @Test + public void testStop() { + //doNothing().when(pkiSetupMock).start(bundleContext).thenThrows(new Exception()); + try { + doNothing().when(pkiSetupMock).stop(bundleContext); + } catch (Exception e) { + // TODO Auto-generated catch block + assertThrows(Exception.class, () -> pkiSetupMock.stop(bundleContext)); + } + } + @Test + public void testlog() { + doNothing().when(pkiSetupMock).log(isA(String.class)); + } + @Test + public void testStartup() { + doNothing().when(pkiSetupMock).Startup(); + } + @Test + public void testgetInstance() { + PKISetup pki = Mockito.spy(PKISetup.getInstance()); + + try (MockedStatic pkiSetupMock = Mockito.mockStatic(PKISetup.class)) { + pkiSetupMock.when(() -> { PKISetup.getInstance(); }) + .thenReturn(pki); + } + } + @Test + public void testgetSSLContext() { + + when(pkiSetupMock.getSSLContext()).thenReturn(context); + //when(pkiSetupMock.getSSLContext()).thenThrow(new NoSuchAlgorithmException("no no no!")); + /* + * try (MockedStatic pkiSetupMock = + * Mockito.mockStatic(PKISetup.class)) { pkiSetupMock.when(() -> { + * PKISetup.getSSLContext(); }) .thenReturn(SSLContext.class); } + */ + + } + @Test + public void testsetSSLContext() { + doNothing().when(pkiSetupMock).setSSLContext(context); + } +} diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PKIStateTest.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PKIStateTest.java new file mode 100644 index 00000000000..1d03ca85709 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PKIStateTest.java @@ -0,0 +1,55 @@ +package org.eclipse.core.tests.pki.auth; + + +import static org.junit.jupiter.api.Assertions.assertTrue; + + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doNothing; + +import org.junit.Before; +import org.junit.Test; + +import org.eclipse.core.pki.auth.PKIState; + +/******************************************************************************* + * Copyright (c) 2025 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 + *******************************************************************************/ + +public class PKIStateTest { + PKIState pkiStateMock = null; + public PKIStateTest() {} + + @Before + public void Initialize() throws Exception { + //MockitoAnnotations.initMocks(this); + pkiStateMock = mock(PKIState.class); + } + @Test + public void testSetPKCS11on() { + when(pkiStateMock.isPKCS11on()).thenReturn(true); + doNothing().when(pkiStateMock).setPKCS11on(false); + boolean testResult = pkiStateMock.isPKCS11on(); + assertTrue(testResult); + pkiStateMock.setPKCS11on(true); + } + @Test + public void testSetPKCS12on() { + when(pkiStateMock.isPKCS12on()).thenReturn(true); + doNothing().when(pkiStateMock).setPKCS12on(false); + boolean testResult = pkiStateMock.isPKCS12on(); + assertTrue(testResult); + pkiStateMock.setPKCS12on(true); + } +} diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PKITestSubscriber.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PKITestSubscriber.java new file mode 100644 index 00000000000..03bfff524fb --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PKITestSubscriber.java @@ -0,0 +1,56 @@ +package org.eclipse.core.tests.pki.auth; +/******************************************************************************* + * Copyright (c) 2024 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 + *******************************************************************************/ + +import java.util.concurrent.Flow.Subscriber; +import java.util.concurrent.Flow.Subscription; + +import org.eclipse.core.pki.pkiselection.SecurityOpRequest; + +public class PKITestSubscriber implements Subscriber { + private Subscription subscription; + private String name; + //private SSLContext sslContext; + + public PKITestSubscriber() {} + public PKITestSubscriber(String name) { + this.name = name; + } + public void setName(String s) { + this.name=s; + } + public String getName() { + return this.name; + } + public void onSubscribe(Subscription subscription) { + // TODO Auto-generated method stub + this.subscription = subscription; + } + public void onNext(Object item) { + // TODO Auto-generated method stub + if ( subscription == null) { + SecurityOpRequest.INSTANCE.setConnected(false); + subscription.cancel(); + } + SecurityOpRequest.INSTANCE.setConnected(true); + } + + public void onError(Throwable throwable) { + // TODO Auto-generated method stub + } + + public void onComplete() { + // TODO Auto-generated method stub + } +} diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/ProxiesTest.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/ProxiesTest.java new file mode 100644 index 00000000000..dd5a8597f78 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/ProxiesTest.java @@ -0,0 +1,95 @@ +package org.eclipse.core.tests.pki.auth; + +/******************************************************************************* + * Copyright (c) 2024 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 + *******************************************************************************/ +//import org.eclipse.core.pki.PKISetup; + +import java.util.Optional; +import java.net.URI; +import org.mockito.Mockito; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.any; +import org.mockito.MockedStatic; +import org.junit.Before; +import org.junit.Test; +import org.eclipse.core.pki.auth.Proxies; + +public class ProxiesTest { + String user="user"; + Proxies proxiesMock = null; + Optionaloptional = Optional.of("TESTING"); + + public ProxiesTest() {} + + @Before + public void Initialize() throws Exception { + proxiesMock = mock(Proxies.class); + } + @Test + public void testProxiesUserDomain() { + try (MockedStatic proxiesMock = Mockito.mockStatic(Proxies.class)) { + proxiesMock.when(() -> { Proxies.getUserDomain(any(String.class )); }) + .thenReturn(Optional.empty()); + } + } + @Test + public void testProxiesWorkstation() { + try (MockedStatic proxiesMock = Mockito.mockStatic(Proxies.class)) { + proxiesMock.when(() -> { Proxies.getWorkstation(); }) + .thenReturn(Optional.empty()); + } + } + @Test + public void testProxiesUserName() { + try (MockedStatic proxiesMock = Mockito.mockStatic(Proxies.class)) { + proxiesMock.when(() -> { Proxies.getUserName(any(String.class )); }) + .thenReturn(Optional.empty()); + } + } + @Test + public void testProxiesProxyHost() { + try (MockedStatic proxiesMock = Mockito.mockStatic(Proxies.class)) { + proxiesMock.when(() -> { Proxies.getProxyHost(any(URI.class )); }) + .thenReturn(Optional.empty()); + } + } + @Test + public void testProxiesProxyAuthentication() { + + } + + /* + * @Test public void testProxiesProxyData() { Proxies + * proxy=Proxies.getProxyData(any(URI.class )); Object spy = Mockito.spy(proxy); + * try (MockedStatic proxiesMock = Mockito.mockStatic(Proxies.class)) + * { proxiesMock.when(() -> { spy.getProxyData(any(URI.class )); }) + * .thenReturn(Optional.empty()); } } + */ + @Test + public void testProxiesProxyUser() { + try (MockedStatic proxiesMock = Mockito.mockStatic(Proxies.class)) { + proxiesMock.when(() -> { Proxies.getProxyUser(any(URI.class )); }) + .thenReturn(Optional.empty()); + } + } + @Test + public void testProxiesProxyPassword() { + try (MockedStatic proxiesMock = Mockito.mockStatic(Proxies.class)) { + proxiesMock.when(() -> { Proxies.getProxyPassword(any(URI.class )); }) + .thenReturn(Optional.empty()); + } + } + +} diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PublicKeySecurityTest.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PublicKeySecurityTest.java new file mode 100644 index 00000000000..fb14f01e346 --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PublicKeySecurityTest.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2025 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.core.tests.pki.auth; + + +import java.util.Properties; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import org.junit.Before; +import org.junit.Test; + +import org.eclipse.core.pki.auth.PublicKeySecurity; + +public class PublicKeySecurityTest { + PublicKeySecurity publicKeySecurityMock = null; + Properties properties = new Properties(); + String PiN = "12345679"; + public PublicKeySecurityTest() {} + + + @Before + public void Initialize() throws Exception { + publicKeySecurityMock = mock(PublicKeySecurity.class); + } + + @Test + public void testGetpkiPropertyFile() { + when(publicKeySecurityMock.getPkiPropertyFile(PiN)).thenReturn(properties); + } + +} diff --git a/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PublishPasswordUpdateTest.java b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PublishPasswordUpdateTest.java new file mode 100644 index 00000000000..ea883e34c9b --- /dev/null +++ b/team/tests/org.eclipse.core.tests.pki/src/org/eclipse/core/tests/pki/auth/PublishPasswordUpdateTest.java @@ -0,0 +1,59 @@ +package org.eclipse.core.tests.pki.auth; + +/******************************************************************************* + * Copyright (c) 2024 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 + *******************************************************************************/ +//import org.eclipse.core.pki.PKISetup; +import java.util.Properties; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doNothing; +import static org.mockito.ArgumentMatchers.isA; +import org.junit.Before; +import org.junit.Test; +import org.eclipse.core.pki.auth.PublishPasswordUpdate; + +public class PublishPasswordUpdateTest { + Properties properties = new Properties(); + Object o = new Object(); + String testName = "PKItestSubscriber"; + PKITestSubscriber subscriber = null; + PublishPasswordUpdate publishPasswordUpdateMock = null; + + + public PublishPasswordUpdateTest() {} + + @Before + public void Initialize() throws Exception { + subscriber = new PKITestSubscriber(testName); + publishPasswordUpdateMock = mock(PublishPasswordUpdate.class); + } + + @Test + public void testRun() { + assertEquals(this.testName, subscriber.getName(), "The name should be set correctly."); + assertNotEquals("footest", subscriber.getName(), "The name should be set correctly."); + } + + @Test + public void testPublishPasswordUpdate() { + doNothing().when(publishPasswordUpdateMock).subscribe(subscriber); + when(publishPasswordUpdateMock.getSubscriberCount()).thenReturn(1); + doNothing().when(publishPasswordUpdateMock).publishMessage(isA(String.class)); + doNothing().when(publishPasswordUpdateMock).close(); + } +} diff --git a/team/tests/pom.xml b/team/tests/pom.xml index 9dac7430f1b..2f02e3e0b8d 100644 --- a/team/tests/pom.xml +++ b/team/tests/pom.xml @@ -27,5 +27,6 @@ org.eclipse.core.tests.net org.eclipse.jsch.tests org.eclipse.team.tests.core + org.eclipse.core.tests.pki