package sun.security.util;
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;
public class KeyStoreDelegator extends KeyStoreSpi {
private static final String KEYSTORE_TYPE_COMPAT = "keystore.type.compat";
private static final Debug debug = Debug.getInstance("keystore");
private String primaryType;
private String secondaryType;
private Class<? extends KeyStoreSpi> primaryKeyStore;
private Class<? extends KeyStoreSpi> secondaryKeyStore;
private String type;
private KeyStoreSpi keystore;
private boolean compatModeEnabled = true;
public KeyStoreDelegator(
String primaryType,
Class<? extends KeyStoreSpi> primaryKeyStore,
String secondaryType,
Class<? extends KeyStoreSpi> secondaryKeyStore) {
compatModeEnabled = "true".equalsIgnoreCase(
AccessController.doPrivileged((PrivilegedAction<String>) () ->
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) {
try {
@SuppressWarnings("deprecation")
KeyStoreSpi tmp = primaryKeyStore.newInstance();
keystore = tmp;
} catch (InstantiationException | IllegalAccessException e) {
}
type = primaryType;
if (debug != 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 {
@SuppressWarnings("deprecation")
KeyStoreSpi tmp = primaryKeyStore.newInstance();
keystore = tmp;
type = primaryType;
keystore.engineLoad(bufferedStream, password);
} catch (Exception e) {
if (e instanceof IOException &&
e.getCause() instanceof UnrecoverableKeyException) {
throw (IOException)e;
}
try {
if (!compatModeEnabled) {
throw e;
}
@SuppressWarnings("deprecation")
KeyStoreSpi tmp= secondaryKeyStore.newInstance();
keystore = tmp;
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) {
} 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");
}
}
}
@Override
public boolean engineProbe(InputStream stream) throws IOException {
boolean result = false;
try {
@SuppressWarnings("deprecation")
KeyStoreSpi tmp = primaryKeyStore.newInstance();
keystore = tmp;
type = primaryType;
result = keystore.engineProbe(stream);
} catch (Exception e) {
throw new IOException(e);
} finally {
if (result == false) {
type = null;
keystore = null;
}
}
return result;
}
}