8129988: JSSE should create a single instance of the cacerts KeyStore
Reviewed-by: mullan
This commit is contained in:
parent
ad76f31ded
commit
e546b078a6
@ -935,12 +935,20 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static TrustManager[] getTrustManagers() throws Exception {
|
private static TrustManager[] getTrustManagers() throws Exception {
|
||||||
KeyStore ks =
|
|
||||||
TrustManagerFactoryImpl.getCacertsKeyStore("defaultctx");
|
|
||||||
|
|
||||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
|
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
|
||||||
TrustManagerFactory.getDefaultAlgorithm());
|
TrustManagerFactory.getDefaultAlgorithm());
|
||||||
tmf.init(ks);
|
if ("SunJSSE".equals(tmf.getProvider().getName())) {
|
||||||
|
// The implementation will load the default KeyStore
|
||||||
|
// automatically. Cached trust materials may be used
|
||||||
|
// for performance improvement.
|
||||||
|
tmf.init((KeyStore)null);
|
||||||
|
} else {
|
||||||
|
// Use the explicitly specified KeyStore for third party's
|
||||||
|
// TrustManagerFactory implementation.
|
||||||
|
KeyStore ks = TrustStoreManager.getTrustedKeyStore();
|
||||||
|
tmf.init(ks);
|
||||||
|
}
|
||||||
|
|
||||||
return tmf.getTrustManagers();
|
return tmf.getTrustManagers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ import java.security.cert.*;
|
|||||||
import javax.net.ssl.*;
|
import javax.net.ssl.*;
|
||||||
|
|
||||||
import sun.security.validator.Validator;
|
import sun.security.validator.Validator;
|
||||||
|
import sun.security.validator.TrustStoreUtil;
|
||||||
|
|
||||||
abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
|
abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
|
|||||||
protected void engineInit(KeyStore ks) throws KeyStoreException {
|
protected void engineInit(KeyStore ks) throws KeyStoreException {
|
||||||
if (ks == null) {
|
if (ks == null) {
|
||||||
try {
|
try {
|
||||||
ks = getCacertsKeyStore("trustmanager");
|
trustManager = getInstance(TrustStoreManager.getTrustedCerts());
|
||||||
} catch (SecurityException se) {
|
} catch (SecurityException se) {
|
||||||
// eat security exceptions but report other throwables
|
// eat security exceptions but report other throwables
|
||||||
if (debug != null && Debug.isOn("trustmanager")) {
|
if (debug != null && Debug.isOn("trustmanager")) {
|
||||||
@ -72,14 +73,17 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
|
|||||||
"SunX509: skip default keystore: " + e);
|
"SunX509: skip default keystore: " + e);
|
||||||
}
|
}
|
||||||
throw new KeyStoreException(
|
throw new KeyStoreException(
|
||||||
"problem accessing trust store" + e);
|
"problem accessing trust store", e);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
trustManager = getInstance(TrustStoreUtil.getTrustedCerts(ks));
|
||||||
}
|
}
|
||||||
trustManager = getInstance(ks);
|
|
||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract X509TrustManager getInstance(KeyStore ks) throws KeyStoreException;
|
abstract X509TrustManager getInstance(
|
||||||
|
Collection<X509Certificate> trustedCerts);
|
||||||
|
|
||||||
abstract X509TrustManager getInstance(ManagerFactoryParameters spec)
|
abstract X509TrustManager getInstance(ManagerFactoryParameters spec)
|
||||||
throws InvalidAlgorithmParameterException;
|
throws InvalidAlgorithmParameterException;
|
||||||
@ -126,126 +130,14 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the keystore with the configured CA certificates.
|
|
||||||
*/
|
|
||||||
static KeyStore getCacertsKeyStore(String dbgname) throws Exception
|
|
||||||
{
|
|
||||||
String storeFileName = null;
|
|
||||||
File storeFile = null;
|
|
||||||
FileInputStream fis = null;
|
|
||||||
String defaultTrustStoreType;
|
|
||||||
String defaultTrustStoreProvider;
|
|
||||||
final HashMap<String,String> props = new HashMap<>();
|
|
||||||
final String sep = File.separator;
|
|
||||||
KeyStore ks = null;
|
|
||||||
|
|
||||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
|
|
||||||
@Override
|
|
||||||
public Void run() throws Exception {
|
|
||||||
props.put("trustStore", System.getProperty(
|
|
||||||
"javax.net.ssl.trustStore"));
|
|
||||||
props.put("javaHome", System.getProperty(
|
|
||||||
"java.home"));
|
|
||||||
props.put("trustStoreType", System.getProperty(
|
|
||||||
"javax.net.ssl.trustStoreType",
|
|
||||||
KeyStore.getDefaultType()));
|
|
||||||
props.put("trustStoreProvider", System.getProperty(
|
|
||||||
"javax.net.ssl.trustStoreProvider", ""));
|
|
||||||
props.put("trustStorePasswd", System.getProperty(
|
|
||||||
"javax.net.ssl.trustStorePassword", ""));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try:
|
|
||||||
* javax.net.ssl.trustStore (if this variable exists, stop)
|
|
||||||
* jssecacerts
|
|
||||||
* cacerts
|
|
||||||
*
|
|
||||||
* If none exists, we use an empty keystore.
|
|
||||||
*/
|
|
||||||
|
|
||||||
try {
|
|
||||||
storeFileName = props.get("trustStore");
|
|
||||||
if (!"NONE".equals(storeFileName)) {
|
|
||||||
if (storeFileName != null) {
|
|
||||||
storeFile = new File(storeFileName);
|
|
||||||
fis = getFileInputStream(storeFile);
|
|
||||||
} else {
|
|
||||||
String javaHome = props.get("javaHome");
|
|
||||||
storeFile = new File(javaHome + sep + "lib" + sep
|
|
||||||
+ "security" + sep +
|
|
||||||
"jssecacerts");
|
|
||||||
if ((fis = getFileInputStream(storeFile)) == null) {
|
|
||||||
storeFile = new File(javaHome + sep + "lib" + sep
|
|
||||||
+ "security" + sep +
|
|
||||||
"cacerts");
|
|
||||||
fis = getFileInputStream(storeFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fis != null) {
|
|
||||||
storeFileName = storeFile.getPath();
|
|
||||||
} else {
|
|
||||||
storeFileName = "No File Available, using empty keystore.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultTrustStoreType = props.get("trustStoreType");
|
|
||||||
defaultTrustStoreProvider = props.get("trustStoreProvider");
|
|
||||||
if (debug != null && Debug.isOn(dbgname)) {
|
|
||||||
System.out.println("trustStore is: " + storeFileName);
|
|
||||||
System.out.println("trustStore type is : " +
|
|
||||||
defaultTrustStoreType);
|
|
||||||
System.out.println("trustStore provider is : " +
|
|
||||||
defaultTrustStoreProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to initialize trust store.
|
|
||||||
*/
|
|
||||||
if (defaultTrustStoreType.length() != 0) {
|
|
||||||
if (debug != null && Debug.isOn(dbgname)) {
|
|
||||||
System.out.println("init truststore");
|
|
||||||
}
|
|
||||||
if (defaultTrustStoreProvider.length() == 0) {
|
|
||||||
ks = KeyStore.getInstance(defaultTrustStoreType);
|
|
||||||
} else {
|
|
||||||
ks = KeyStore.getInstance(defaultTrustStoreType,
|
|
||||||
defaultTrustStoreProvider);
|
|
||||||
}
|
|
||||||
char[] passwd = null;
|
|
||||||
String defaultTrustStorePassword =
|
|
||||||
props.get("trustStorePasswd");
|
|
||||||
if (defaultTrustStorePassword.length() != 0)
|
|
||||||
passwd = defaultTrustStorePassword.toCharArray();
|
|
||||||
|
|
||||||
// if trustStore is NONE, fis will be null
|
|
||||||
ks.load(fis, passwd);
|
|
||||||
|
|
||||||
// Zero out the temporary password storage
|
|
||||||
if (passwd != null) {
|
|
||||||
for (int i = 0; i < passwd.length; i++) {
|
|
||||||
passwd[i] = (char)0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (fis != null) {
|
|
||||||
fis.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class SimpleFactory extends TrustManagerFactoryImpl {
|
public static final class SimpleFactory extends TrustManagerFactoryImpl {
|
||||||
@Override
|
@Override
|
||||||
X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
|
X509TrustManager getInstance(
|
||||||
return new X509TrustManagerImpl(Validator.TYPE_SIMPLE, ks);
|
Collection<X509Certificate> trustedCerts) {
|
||||||
|
return new X509TrustManagerImpl(
|
||||||
|
Validator.TYPE_SIMPLE, trustedCerts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
X509TrustManager getInstance(ManagerFactoryParameters spec)
|
X509TrustManager getInstance(ManagerFactoryParameters spec)
|
||||||
throws InvalidAlgorithmParameterException {
|
throws InvalidAlgorithmParameterException {
|
||||||
@ -253,13 +145,15 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
|
|||||||
("SunX509 TrustManagerFactory does not use "
|
("SunX509 TrustManagerFactory does not use "
|
||||||
+ "ManagerFactoryParameters");
|
+ "ManagerFactoryParameters");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class PKIXFactory extends TrustManagerFactoryImpl {
|
public static final class PKIXFactory extends TrustManagerFactoryImpl {
|
||||||
@Override
|
@Override
|
||||||
X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
|
X509TrustManager getInstance(
|
||||||
return new X509TrustManagerImpl(Validator.TYPE_PKIX, ks);
|
Collection<X509Certificate> trustedCerts) {
|
||||||
|
return new X509TrustManagerImpl(Validator.TYPE_PKIX, trustedCerts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
X509TrustManager getInstance(ManagerFactoryParameters spec)
|
X509TrustManager getInstance(ManagerFactoryParameters spec)
|
||||||
throws InvalidAlgorithmParameterException {
|
throws InvalidAlgorithmParameterException {
|
||||||
|
@ -0,0 +1,395 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sun.security.ssl;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.cert.*;
|
||||||
|
import java.security.cert.Certificate;
|
||||||
|
|
||||||
|
import sun.security.action.*;
|
||||||
|
import sun.security.validator.TrustStoreUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of static utility methods to manage the default trusted KeyStores
|
||||||
|
* effectively.
|
||||||
|
*/
|
||||||
|
final class TrustStoreManager {
|
||||||
|
private static final Debug debug = Debug.getInstance("ssl");
|
||||||
|
|
||||||
|
// A singleton service to manage the default trusted KeyStores effectively.
|
||||||
|
private static final TrustAnchorManager tam = new TrustAnchorManager();
|
||||||
|
|
||||||
|
// Restrict instantiation of this class.
|
||||||
|
private TrustStoreManager() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an unmodifiable set of all trusted X509Certificates contained
|
||||||
|
* in the default trusted KeyStore.
|
||||||
|
*/
|
||||||
|
public static Set<X509Certificate> getTrustedCerts() throws Exception {
|
||||||
|
return tam.getTrustedCerts(TrustStoreDescriptor.createInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an instance of the default trusted KeyStore.
|
||||||
|
*/
|
||||||
|
public static KeyStore getTrustedKeyStore() throws Exception {
|
||||||
|
return tam.getKeyStore(TrustStoreDescriptor.createInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A descriptor of the default trusted KeyStore.
|
||||||
|
*
|
||||||
|
* The preference of the default trusted KeyStore is:
|
||||||
|
* javax.net.ssl.trustStore
|
||||||
|
* jssecacerts
|
||||||
|
* cacerts
|
||||||
|
*/
|
||||||
|
private static final class TrustStoreDescriptor {
|
||||||
|
private static final String fileSep = File.separator;
|
||||||
|
private static final String defaultStorePath =
|
||||||
|
GetPropertyAction.privilegedGetProperty("java.home") +
|
||||||
|
fileSep + "lib" + fileSep + "security";
|
||||||
|
private static final String defaultStore =
|
||||||
|
defaultStorePath + fileSep + "cacerts";
|
||||||
|
private static final String jsseDefaultStore =
|
||||||
|
defaultStorePath + fileSep + "jssecacerts";
|
||||||
|
|
||||||
|
// the trust store name
|
||||||
|
private final String storeName;
|
||||||
|
|
||||||
|
// the trust store type, JKS/PKCS12
|
||||||
|
private final String storeType;
|
||||||
|
|
||||||
|
// the provider of the trust store
|
||||||
|
private final String storeProvider;
|
||||||
|
|
||||||
|
// the password used for the trust store
|
||||||
|
private final String storePassword;
|
||||||
|
|
||||||
|
// the File object of the trust store
|
||||||
|
private final File storeFile;
|
||||||
|
|
||||||
|
// the last modified time of the store
|
||||||
|
private final long lastModified;
|
||||||
|
|
||||||
|
private TrustStoreDescriptor(String storeName, String storeType,
|
||||||
|
String storeProvider, String storePassword,
|
||||||
|
File storeFile, long lastModified) {
|
||||||
|
this.storeName = storeName;
|
||||||
|
this.storeType = storeType;
|
||||||
|
this.storeProvider = storeProvider;
|
||||||
|
this.storePassword = storePassword;
|
||||||
|
this.storeFile = storeFile;
|
||||||
|
this.lastModified = lastModified;
|
||||||
|
|
||||||
|
if (debug != null && Debug.isOn("trustmanager")) {
|
||||||
|
System.out.println(
|
||||||
|
"trustStore is: " + storeName + "\n" +
|
||||||
|
"trustStore type is: " + storeType + "\n" +
|
||||||
|
"trustStore provider is: " + storeProvider + "\n" +
|
||||||
|
"the last modified time is: " + (new Date(lastModified)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of TrustStoreDescriptor for the default
|
||||||
|
* trusted KeyStore.
|
||||||
|
*/
|
||||||
|
static TrustStoreDescriptor createInstance() {
|
||||||
|
return AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TrustStoreDescriptor run() {
|
||||||
|
// Get the system properties for trust store.
|
||||||
|
String storePropName = System.getProperty(
|
||||||
|
"javax.net.ssl.trustStore", jsseDefaultStore);
|
||||||
|
String storePropType = System.getProperty(
|
||||||
|
"javax.net.ssl.trustStoreType",
|
||||||
|
KeyStore.getDefaultType());
|
||||||
|
String storePropProvider = System.getProperty(
|
||||||
|
"javax.net.ssl.trustStoreProvider", "");
|
||||||
|
String storePropPassword = System.getProperty(
|
||||||
|
"javax.net.ssl.trustStorePassword", "");
|
||||||
|
|
||||||
|
String temporaryName = "";
|
||||||
|
File temporaryFile = null;
|
||||||
|
long temporaryTime = 0L;
|
||||||
|
if (!"NONE".equals(storePropName)) {
|
||||||
|
String[] fileNames =
|
||||||
|
new String[] {storePropName, defaultStore};
|
||||||
|
for (String fileName : fileNames) {
|
||||||
|
File f = new File(fileName);
|
||||||
|
if (f.isFile() && f.canRead()) {
|
||||||
|
temporaryName = fileName;;
|
||||||
|
temporaryFile = f;
|
||||||
|
temporaryTime = f.lastModified();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not break, the file is inaccessible.
|
||||||
|
if (debug != null &&
|
||||||
|
Debug.isOn("trustmanager")) {
|
||||||
|
System.out.println(
|
||||||
|
"Inaccessible trust store: " +
|
||||||
|
storePropName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
temporaryName = storePropName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TrustStoreDescriptor(
|
||||||
|
temporaryName, storePropType, storePropProvider,
|
||||||
|
storePropPassword, temporaryFile, temporaryTime);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof TrustStoreDescriptor) {
|
||||||
|
TrustStoreDescriptor that = (TrustStoreDescriptor)obj;
|
||||||
|
return ((this.lastModified == that.lastModified) &&
|
||||||
|
Objects.equals(this.storeName, that.storeName) &&
|
||||||
|
Objects.equals(this.storeType, that.storeType) &&
|
||||||
|
Objects.equals(this.storeProvider, that.storeProvider));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Please be careful if computing security-sensitive attributes'
|
||||||
|
// hash code. For example the storePassword should not be computed.
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = 17;
|
||||||
|
|
||||||
|
if (storeName != null && !storeName.isEmpty()) {
|
||||||
|
result = 31 * result + storeName.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storeType != null && !storeType.isEmpty()) {
|
||||||
|
result = 31 * result + storeType.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storeProvider != null && !storeProvider.isEmpty()) {
|
||||||
|
result = 31 * result + storeProvider.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storeFile != null) {
|
||||||
|
result = 31 * result + storeFile.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastModified != 0L) {
|
||||||
|
result = (int)(31 * result + lastModified);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The trust anchors manager used to expedite the performance.
|
||||||
|
*
|
||||||
|
* This class can be used to provide singleton services to access default
|
||||||
|
* trust KeyStore more effectively.
|
||||||
|
*/
|
||||||
|
private static final class TrustAnchorManager {
|
||||||
|
// Last trust store descriptor.
|
||||||
|
private TrustStoreDescriptor descriptor;
|
||||||
|
|
||||||
|
// The key store used for the trust anchors.
|
||||||
|
//
|
||||||
|
// Use weak reference so that the heavy loaded KeyStore object can
|
||||||
|
// be atomically cleared, and reloaded if needed.
|
||||||
|
private WeakReference<KeyStore> ksRef;
|
||||||
|
|
||||||
|
// The trusted X.509 certificates in the key store.
|
||||||
|
//
|
||||||
|
// Use weak reference so that the heavy loaded certificates collection
|
||||||
|
// objects can be atomically cleared, and reloaded if needed.
|
||||||
|
private WeakReference<Set<X509Certificate>> csRef;
|
||||||
|
|
||||||
|
private TrustAnchorManager() {
|
||||||
|
this.descriptor = null;
|
||||||
|
this.ksRef = new WeakReference<>(null);
|
||||||
|
this.csRef = new WeakReference<>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default trusted KeyStore with the specified descriptor.
|
||||||
|
*
|
||||||
|
* @return null if the underlying KeyStore is not available.
|
||||||
|
*/
|
||||||
|
synchronized KeyStore getKeyStore(
|
||||||
|
TrustStoreDescriptor descriptor) throws Exception {
|
||||||
|
|
||||||
|
TrustStoreDescriptor temporaryDesc = this.descriptor;
|
||||||
|
KeyStore ks = ksRef.get();
|
||||||
|
if ((ks != null) && descriptor.equals(temporaryDesc)) {
|
||||||
|
return ks;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload a new key store.
|
||||||
|
if ((debug != null) && Debug.isOn("trustmanager")) {
|
||||||
|
System.out.println("Reload the trust store");
|
||||||
|
}
|
||||||
|
|
||||||
|
ks = loadKeyStore(descriptor);
|
||||||
|
this.descriptor = descriptor;
|
||||||
|
this.ksRef = new WeakReference<>(ks);
|
||||||
|
|
||||||
|
return ks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get trusted certificates in the default trusted KeyStore with
|
||||||
|
* the specified descriptor.
|
||||||
|
*
|
||||||
|
* @return empty collection if the underlying KeyStore is not available.
|
||||||
|
*/
|
||||||
|
synchronized Set<X509Certificate> getTrustedCerts(
|
||||||
|
TrustStoreDescriptor descriptor) throws Exception {
|
||||||
|
|
||||||
|
KeyStore ks = null;
|
||||||
|
TrustStoreDescriptor temporaryDesc = this.descriptor;
|
||||||
|
Set<X509Certificate> certs = csRef.get();
|
||||||
|
if (certs != null) {
|
||||||
|
if (descriptor.equals(temporaryDesc)) {
|
||||||
|
return certs;
|
||||||
|
} else {
|
||||||
|
// Use the new descriptor.
|
||||||
|
this.descriptor = descriptor;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Try to use the cached store at first.
|
||||||
|
if (descriptor.equals(temporaryDesc)) {
|
||||||
|
ks = ksRef.get();
|
||||||
|
} else {
|
||||||
|
// Use the new descriptor.
|
||||||
|
this.descriptor = descriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload the trust store if needed.
|
||||||
|
if (ks == null) {
|
||||||
|
if ((debug != null) && Debug.isOn("trustmanager")) {
|
||||||
|
System.out.println("Reload the trust store");
|
||||||
|
}
|
||||||
|
ks = loadKeyStore(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload trust certs from the key store.
|
||||||
|
if ((debug != null) && Debug.isOn("trustmanager")) {
|
||||||
|
System.out.println("Reload trust certs");
|
||||||
|
}
|
||||||
|
|
||||||
|
certs = loadTrustedCerts(ks);
|
||||||
|
if ((debug != null) && Debug.isOn("trustmanager")) {
|
||||||
|
System.out.println("Reloaded " + certs.size() + " trust certs");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that as ks is a local variable, it is not
|
||||||
|
// necessary to add it to the ksRef weak reference.
|
||||||
|
this.csRef = new WeakReference<>(certs);
|
||||||
|
|
||||||
|
return certs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the the KeyStore as described in the specified descriptor.
|
||||||
|
*/
|
||||||
|
private static KeyStore loadKeyStore(
|
||||||
|
TrustStoreDescriptor descriptor) throws Exception {
|
||||||
|
if (!"NONE".equals(descriptor.storeName) &&
|
||||||
|
descriptor.storeFile == null) {
|
||||||
|
|
||||||
|
// No file available, no KeyStore available.
|
||||||
|
if (debug != null && Debug.isOn("trustmanager")) {
|
||||||
|
System.out.println("No available key store");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyStore ks;
|
||||||
|
if (descriptor.storeProvider.isEmpty()) {
|
||||||
|
ks = KeyStore.getInstance(descriptor.storeType);
|
||||||
|
} else {
|
||||||
|
ks = KeyStore.getInstance(
|
||||||
|
descriptor.storeType, descriptor.storeProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
char[] password = null;
|
||||||
|
if (!descriptor.storePassword.isEmpty()) {
|
||||||
|
password = descriptor.storePassword.toCharArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!"NONE".equals(descriptor.storeName)) {
|
||||||
|
try (FileInputStream fis = AccessController.doPrivileged(
|
||||||
|
new OpenFileInputStreamAction(descriptor.storeFile))) {
|
||||||
|
ks.load(fis, password);
|
||||||
|
} catch (FileNotFoundException fnfe) {
|
||||||
|
// No file available, no KeyStore available.
|
||||||
|
if (debug != null && Debug.isOn("trustmanager")) {
|
||||||
|
System.out.println(
|
||||||
|
"Not available key store: " + descriptor.storeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ks.load(null, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load trusted certificates from the specified KeyStore.
|
||||||
|
*/
|
||||||
|
private static Set<X509Certificate> loadTrustedCerts(KeyStore ks) {
|
||||||
|
if (ks == null) {
|
||||||
|
return Collections.<X509Certificate>emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
return TrustStoreUtil.getTrustedCerts(ks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -68,16 +68,21 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
|
|||||||
|
|
||||||
private static final Debug debug = Debug.getInstance("ssl");
|
private static final Debug debug = Debug.getInstance("ssl");
|
||||||
|
|
||||||
X509TrustManagerImpl(String validatorType, KeyStore ks)
|
X509TrustManagerImpl(String validatorType,
|
||||||
throws KeyStoreException {
|
Collection<X509Certificate> trustedCerts) {
|
||||||
|
|
||||||
this.validatorType = validatorType;
|
this.validatorType = validatorType;
|
||||||
this.pkixParams = null;
|
this.pkixParams = null;
|
||||||
if (ks == null) {
|
|
||||||
|
if (trustedCerts == null) {
|
||||||
trustedCerts = Collections.<X509Certificate>emptySet();
|
trustedCerts = Collections.<X509Certificate>emptySet();
|
||||||
} else {
|
|
||||||
trustedCerts = KeyStores.getTrustedCerts(ks);
|
|
||||||
}
|
}
|
||||||
showTrustedCerts();
|
|
||||||
|
this.trustedCerts = trustedCerts;
|
||||||
|
|
||||||
|
if (debug != null && Debug.isOn("trustmanager")) {
|
||||||
|
showTrustedCerts();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
X509TrustManagerImpl(String validatorType, PKIXBuilderParameters params) {
|
X509TrustManagerImpl(String validatorType, PKIXBuilderParameters params) {
|
||||||
@ -90,7 +95,10 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
|
|||||||
Validator v = getValidator(Validator.VAR_TLS_SERVER);
|
Validator v = getValidator(Validator.VAR_TLS_SERVER);
|
||||||
trustedCerts = v.getTrustedCertificates();
|
trustedCerts = v.getTrustedCertificates();
|
||||||
serverValidator = v;
|
serverValidator = v;
|
||||||
showTrustedCerts();
|
|
||||||
|
if (debug != null && Debug.isOn("trustmanager")) {
|
||||||
|
showTrustedCerts();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -305,22 +313,20 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showTrustedCerts() {
|
private void showTrustedCerts() {
|
||||||
if (debug != null && Debug.isOn("trustmanager")) {
|
for (X509Certificate cert : trustedCerts) {
|
||||||
for (X509Certificate cert : trustedCerts) {
|
System.out.println("adding as trusted cert:");
|
||||||
System.out.println("adding as trusted cert:");
|
System.out.println(" Subject: "
|
||||||
System.out.println(" Subject: "
|
+ cert.getSubjectX500Principal());
|
||||||
+ cert.getSubjectX500Principal());
|
System.out.println(" Issuer: "
|
||||||
System.out.println(" Issuer: "
|
+ cert.getIssuerX500Principal());
|
||||||
+ cert.getIssuerX500Principal());
|
System.out.println(" Algorithm: "
|
||||||
System.out.println(" Algorithm: "
|
+ cert.getPublicKey().getAlgorithm()
|
||||||
+ cert.getPublicKey().getAlgorithm()
|
+ "; Serial number: 0x"
|
||||||
+ "; Serial number: 0x"
|
+ cert.getSerialNumber().toString(16));
|
||||||
+ cert.getSerialNumber().toString(16));
|
System.out.println(" Valid from "
|
||||||
System.out.println(" Valid from "
|
+ cert.getNotBefore() + " until "
|
||||||
+ cert.getNotBefore() + " until "
|
+ cert.getNotAfter());
|
||||||
+ cert.getNotAfter());
|
System.out.println();
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,76 +25,33 @@
|
|||||||
|
|
||||||
package sun.security.validator;
|
package sun.security.validator;
|
||||||
|
|
||||||
import java.io.*;
|
import java.util.Set;
|
||||||
import java.util.*;
|
import java.util.HashSet;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
import java.security.*;
|
import java.security.KeyStore;
|
||||||
import java.security.cert.*;
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
|
|
||||||
import sun.security.action.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection of static utility methods related to KeyStores.
|
* Collection of static utility methods related to trust anchor KeyStores.
|
||||||
*
|
*
|
||||||
* @author Andreas Sterbenz
|
* @author Andreas Sterbenz
|
||||||
*/
|
*/
|
||||||
public class KeyStores {
|
public final class TrustStoreUtil {
|
||||||
|
|
||||||
private KeyStores() {
|
private TrustStoreUtil() {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// in the future, all accesses to the system cacerts keystore should
|
|
||||||
// go through this class. but not right now.
|
|
||||||
/*
|
|
||||||
private static final String javaHome =
|
|
||||||
(String)AccessController.doPrivileged(new GetPropertyAction("java.home"));
|
|
||||||
|
|
||||||
private static final char SEP = File.separatorChar;
|
|
||||||
|
|
||||||
private static KeyStore caCerts;
|
|
||||||
|
|
||||||
private static KeyStore getKeyStore(String type, String name,
|
|
||||||
char[] password) throws IOException {
|
|
||||||
if (type == null) {
|
|
||||||
type = "JKS";
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
KeyStore ks = KeyStore.getInstance(type);
|
|
||||||
FileInputStream in = (FileInputStream)AccessController.doPrivileged
|
|
||||||
(new OpenFileInputStreamAction(name));
|
|
||||||
ks.load(in, password);
|
|
||||||
return ks;
|
|
||||||
} catch (GeneralSecurityException e) {
|
|
||||||
// XXX
|
|
||||||
throw new IOException();
|
|
||||||
} catch (PrivilegedActionException e) {
|
|
||||||
throw (IOException)e.getCause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a KeyStore with the contents of the lib/security/cacerts file.
|
* Return an unmodifiable Set with all trusted X509Certificates contained
|
||||||
* The file is only opened once per JVM invocation and the contents
|
* in the specified KeyStore.
|
||||||
* cached subsequently.
|
|
||||||
*
|
|
||||||
public static synchronized KeyStore getCaCerts() throws IOException {
|
|
||||||
if (caCerts != null) {
|
|
||||||
return caCerts;
|
|
||||||
}
|
|
||||||
String name = javaHome + SEP + "lib" + SEP + "security" + SEP + "cacerts";
|
|
||||||
caCerts = getKeyStore(null, name, null);
|
|
||||||
return caCerts;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a Set with all trusted X509Certificates contained in
|
|
||||||
* this KeyStore.
|
|
||||||
*/
|
*/
|
||||||
public static Set<X509Certificate> getTrustedCerts(KeyStore ks) {
|
public static Set<X509Certificate> getTrustedCerts(KeyStore ks) {
|
||||||
Set<X509Certificate> set = new HashSet<X509Certificate>();
|
Set<X509Certificate> set = new HashSet<>();
|
||||||
try {
|
try {
|
||||||
for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
|
for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
|
||||||
String alias = e.nextElement();
|
String alias = e.nextElement();
|
||||||
@ -113,8 +70,10 @@ public class KeyStores {
|
|||||||
}
|
}
|
||||||
} catch (KeyStoreException e) {
|
} catch (KeyStoreException e) {
|
||||||
// ignore
|
// ignore
|
||||||
|
//
|
||||||
|
// This should be rare, but better to log this in the future.
|
||||||
}
|
}
|
||||||
return set;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return Collections.unmodifiableSet(set);
|
||||||
|
}
|
||||||
}
|
}
|
@ -166,7 +166,7 @@ public abstract class Validator {
|
|||||||
*/
|
*/
|
||||||
public static Validator getInstance(String type, String variant,
|
public static Validator getInstance(String type, String variant,
|
||||||
KeyStore ks) {
|
KeyStore ks) {
|
||||||
return getInstance(type, variant, KeyStores.getTrustedCerts(ks));
|
return getInstance(type, variant, TrustStoreUtil.getTrustedCerts(ks));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -21,18 +21,21 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// SunJSSE does not support dynamic system properties, no way to re-use
|
||||||
|
// system properties in samevm/agentvm mode.
|
||||||
|
//
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 4919147
|
* @bug 4919147
|
||||||
* @summary Support for token-based KeyStores
|
* @summary Support for token-based KeyStores
|
||||||
* @run main/othervm BadTSProvider
|
* @run main/othervm BadTSProvider
|
||||||
*
|
|
||||||
* SunJSSE does not support dynamic system properties, no way to re-use
|
|
||||||
* system properties in samevm/agentvm mode.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
|
import java.security.*;
|
||||||
import javax.net.ssl.*;
|
import javax.net.ssl.*;
|
||||||
|
|
||||||
public class BadTSProvider {
|
public class BadTSProvider {
|
||||||
@ -179,13 +182,19 @@ public class BadTSProvider {
|
|||||||
// XXX this test must be updated if the exception message changes
|
// XXX this test must be updated if the exception message changes
|
||||||
|
|
||||||
Throwable cause = se.getCause();
|
Throwable cause = se.getCause();
|
||||||
if (cause instanceof java.security.NoSuchAlgorithmException == false) {
|
if (!(cause instanceof NoSuchAlgorithmException)) {
|
||||||
se.printStackTrace();
|
se.printStackTrace();
|
||||||
throw new Exception("Unexpected exception" + se);
|
throw new Exception("Unexpected exception" + se);
|
||||||
}
|
}
|
||||||
|
|
||||||
cause = cause.getCause();
|
cause = cause.getCause();
|
||||||
if (cause instanceof java.security.NoSuchProviderException == false) {
|
if (!(cause instanceof KeyStoreException)) {
|
||||||
|
se.printStackTrace();
|
||||||
|
throw new Exception("Unexpected exception" + se);
|
||||||
|
}
|
||||||
|
|
||||||
|
cause = cause.getCause();
|
||||||
|
if (!(cause instanceof NoSuchProviderException)) {
|
||||||
se.printStackTrace();
|
se.printStackTrace();
|
||||||
throw new Exception("Unexpected exception" + se);
|
throw new Exception("Unexpected exception" + se);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -45,7 +45,7 @@ import java.util.Collection;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import sun.security.validator.KeyStores;
|
import sun.security.validator.TrustStoreUtil;
|
||||||
import sun.security.validator.Validator;
|
import sun.security.validator.Validator;
|
||||||
|
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ public class EndEntityExtensionCheck {
|
|||||||
|
|
||||||
Validator v = Validator.getInstance(Validator.TYPE_SIMPLE,
|
Validator v = Validator.getInstance(Validator.TYPE_SIMPLE,
|
||||||
Validator.VAR_TLS_CLIENT,
|
Validator.VAR_TLS_CLIENT,
|
||||||
KeyStores.getTrustedCerts(ks));
|
TrustStoreUtil.getTrustedCerts(ks));
|
||||||
try {
|
try {
|
||||||
v.validate(chain);
|
v.validate(chain);
|
||||||
throw new Exception("Chain should not have validated " +
|
throw new Exception("Chain should not have validated " +
|
||||||
|
Loading…
x
Reference in New Issue
Block a user