|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.provider; |
|
|
|
import java.io.*; |
|
import java.security.*; |
|
import java.security.cert.Certificate; |
|
import java.security.cert.CertificateFactory; |
|
import java.security.cert.CertificateException; |
|
import java.util.*; |
|
|
|
import sun.security.util.Debug; |
|
|
|
/** |
|
* This class delegates to a primary or secondary keystore implementation. |
|
* |
|
* @since 1.8 |
|
*/ |
|
|
|
class KeyStoreDelegator extends KeyStoreSpi { |
|
|
|
private static final String KEYSTORE_TYPE_COMPAT = "keystore.type.compat"; |
|
private static final Debug debug = Debug.getInstance("keystore"); |
|
|
|
private final String primaryType; |
|
private final String secondaryType; |
|
private final Class<? extends KeyStoreSpi> primaryKeyStore; |
|
|
|
private final Class<? extends KeyStoreSpi> secondaryKeyStore; |
|
// the secondary keystore's class |
|
private String type; |
|
private KeyStoreSpi keystore; |
|
private boolean compatModeEnabled = true; |
|
|
|
public KeyStoreDelegator( |
|
String primaryType, |
|
Class<? extends KeyStoreSpi> primaryKeyStore, |
|
String secondaryType, |
|
Class<? extends KeyStoreSpi> secondaryKeyStore) { |
|
|
|
// Check whether compatibility mode has been disabled |
|
|
|
compatModeEnabled = "true".equalsIgnoreCase( |
|
AccessController.doPrivileged( |
|
new PrivilegedAction<String>() { |
|
public String run() { |
|
return Security.getProperty(KEYSTORE_TYPE_COMPAT); |
|
} |
|
} |
|
)); |
|
|
|
if (compatModeEnabled) { |
|
this.primaryType = primaryType; |
|
this.secondaryType = secondaryType; |
|
this.primaryKeyStore = primaryKeyStore; |
|
this.secondaryKeyStore = secondaryKeyStore; |
|
} else { |
|
this.primaryType = primaryType; |
|
this.secondaryType = null; |
|
this.primaryKeyStore = primaryKeyStore; |
|
this.secondaryKeyStore = null; |
|
|
|
if (debug != null) { |
|
debug.println("WARNING: compatibility mode disabled for " + |
|
primaryType + " and " + secondaryType + " keystore types"); |
|
} |
|
} |
|
} |
|
|
|
@Override |
|
public Key engineGetKey(String alias, char[] password) |
|
throws NoSuchAlgorithmException, UnrecoverableKeyException { |
|
return keystore.engineGetKey(alias, password); |
|
} |
|
|
|
@Override |
|
public Certificate[] engineGetCertificateChain(String alias) { |
|
return keystore.engineGetCertificateChain(alias); |
|
} |
|
|
|
@Override |
|
public Certificate engineGetCertificate(String alias) { |
|
return keystore.engineGetCertificate(alias); |
|
} |
|
|
|
@Override |
|
public Date engineGetCreationDate(String alias) { |
|
return keystore.engineGetCreationDate(alias); |
|
} |
|
|
|
@Override |
|
public void engineSetKeyEntry(String alias, Key key, char[] password, |
|
Certificate[] chain) throws KeyStoreException { |
|
keystore.engineSetKeyEntry(alias, key, password, chain); |
|
} |
|
|
|
@Override |
|
public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) |
|
throws KeyStoreException { |
|
keystore.engineSetKeyEntry(alias, key, chain); |
|
} |
|
|
|
@Override |
|
public void engineSetCertificateEntry(String alias, Certificate cert) |
|
throws KeyStoreException { |
|
keystore.engineSetCertificateEntry(alias, cert); |
|
} |
|
|
|
@Override |
|
public void engineDeleteEntry(String alias) throws KeyStoreException { |
|
keystore.engineDeleteEntry(alias); |
|
} |
|
|
|
@Override |
|
public Enumeration<String> engineAliases() { |
|
return keystore.engineAliases(); |
|
} |
|
|
|
@Override |
|
public boolean engineContainsAlias(String alias) { |
|
return keystore.engineContainsAlias(alias); |
|
} |
|
|
|
@Override |
|
public int engineSize() { |
|
return keystore.engineSize(); |
|
} |
|
|
|
@Override |
|
public boolean engineIsKeyEntry(String alias) { |
|
return keystore.engineIsKeyEntry(alias); |
|
} |
|
|
|
@Override |
|
public boolean engineIsCertificateEntry(String alias) { |
|
return keystore.engineIsCertificateEntry(alias); |
|
} |
|
|
|
@Override |
|
public String engineGetCertificateAlias(Certificate cert) { |
|
return keystore.engineGetCertificateAlias(cert); |
|
} |
|
|
|
@Override |
|
public KeyStore.Entry engineGetEntry(String alias, |
|
KeyStore.ProtectionParameter protParam) |
|
throws KeyStoreException, NoSuchAlgorithmException, |
|
UnrecoverableEntryException { |
|
return keystore.engineGetEntry(alias, protParam); |
|
} |
|
|
|
@Override |
|
public void engineSetEntry(String alias, KeyStore.Entry entry, |
|
KeyStore.ProtectionParameter protParam) |
|
throws KeyStoreException { |
|
keystore.engineSetEntry(alias, entry, protParam); |
|
} |
|
|
|
@Override |
|
public boolean engineEntryInstanceOf(String alias, |
|
Class<? extends KeyStore.Entry> entryClass) { |
|
return keystore.engineEntryInstanceOf(alias, entryClass); |
|
} |
|
|
|
@Override |
|
public void engineStore(OutputStream stream, char[] password) |
|
throws IOException, NoSuchAlgorithmException, CertificateException { |
|
|
|
if (debug != null) { |
|
debug.println("Storing keystore in " + type + " format"); |
|
} |
|
keystore.engineStore(stream, password); |
|
} |
|
|
|
@Override |
|
public void engineLoad(InputStream stream, char[] password) |
|
throws IOException, NoSuchAlgorithmException, CertificateException { |
|
|
|
|
|
if (stream == null || !compatModeEnabled) { |
|
try { |
|
keystore = primaryKeyStore.newInstance(); |
|
|
|
} catch (InstantiationException | IllegalAccessException e) { |
|
// can safely ignore |
|
} |
|
type = primaryType; |
|
|
|
if (debug != null && stream == null) { |
|
debug.println("Creating a new keystore in " + type + " format"); |
|
} |
|
keystore.engineLoad(stream, password); |
|
|
|
} else { |
|
|
|
InputStream bufferedStream = new BufferedInputStream(stream); |
|
bufferedStream.mark(Integer.MAX_VALUE); |
|
try { |
|
keystore = primaryKeyStore.newInstance(); |
|
type = primaryType; |
|
keystore.engineLoad(bufferedStream, password); |
|
|
|
} catch (Exception e) { |
|
|
|
|
|
if (e instanceof IOException && |
|
e.getCause() instanceof UnrecoverableKeyException) { |
|
throw (IOException)e; |
|
} |
|
|
|
try { |
|
keystore = secondaryKeyStore.newInstance(); |
|
type = secondaryType; |
|
bufferedStream.reset(); |
|
keystore.engineLoad(bufferedStream, password); |
|
|
|
if (debug != null) { |
|
debug.println("WARNING: switching from " + |
|
primaryType + " to " + secondaryType + |
|
" keystore file format has altered the " + |
|
"keystore security level"); |
|
} |
|
|
|
} catch (InstantiationException | |
|
IllegalAccessException e2) { |
|
// can safely ignore |
|
|
|
} catch (IOException | |
|
NoSuchAlgorithmException | |
|
CertificateException e3) { |
|
|
|
|
|
if (e3 instanceof IOException && |
|
e3.getCause() instanceof |
|
UnrecoverableKeyException) { |
|
throw (IOException)e3; |
|
} |
|
|
|
if (e instanceof IOException) { |
|
throw (IOException)e; |
|
} else if (e instanceof CertificateException) { |
|
throw (CertificateException)e; |
|
} else if (e instanceof NoSuchAlgorithmException) { |
|
throw (NoSuchAlgorithmException)e; |
|
} |
|
} |
|
} |
|
|
|
if (debug != null) { |
|
debug.println("Loaded a keystore in " + type + " format"); |
|
} |
|
} |
|
} |
|
} |