Skip to content

Commit

Permalink
Correctly handle PKCS#11 tokens for system keystore (elastic#33460)
Browse files Browse the repository at this point in the history
* Correctly handle NONE keyword for system keystore

As defined in the PKCS#11 reference guide
https://docs.oracle.com/javase/8/docs/technotes/guides/security/p11guide.html
PKCS#11 tokens can be used as the JSSE keystore and truststore and
the way to indicate this is to set `javax.net.ssl.keyStore` and
`javax.net.ssl.trustStore` to `NONE` (case sensitive).

This commits ensures that we honor this convention and do not
attempt to load the keystore or truststore if the system property is
set to NONE.

* Handle password protected system truststore

When a PKCS#11 token is used as the system truststore, we need to
pass a password when loading it, even if only for reading
certificate entries. This commit ensures that if
`javax.net.ssl.trustStoreType` is set to `PKCS#11` (as it would
when a PKCS#11 token is in use) the password specified in
`javax.net.ssl.trustStorePassword` is passed when attempting to
load the truststore.

Relates elastic#33459
  • Loading branch information
jkakavas committed Sep 10, 2018
1 parent 95100e0 commit 77aeeda
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
import java.io.IOException;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -34,7 +38,7 @@ private DefaultJDKTrustConfig() {
@Override
X509ExtendedTrustManager createTrustManager(@Nullable Environment environment) {
try {
return CertParsingUtils.trustManager(null, TrustManagerFactory.getDefaultAlgorithm());
return CertParsingUtils.trustManager(getSystemTrustStore(), TrustManagerFactory.getDefaultAlgorithm());
} catch (Exception e) {
throw new ElasticsearchException("failed to initialize a TrustManagerFactory", e);
}
Expand Down Expand Up @@ -81,4 +85,20 @@ static TrustConfig merge(TrustConfig trustConfig) {
return new CombiningTrustConfig(Arrays.asList(INSTANCE, trustConfig));
}
}

/**
* When a PKCS#11 token is used as the system default keystore/truststore, we need to pass the keystore
* password when loading, even for reading certificates only ( as opposed to i.e. JKS keystores where
* we only need to pass the password for reading Private Key entries ).
*
* @return the KeyStore used as truststore for PKCS#11 initialized with the password, null otherwise
*/
private KeyStore getSystemTrustStore() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
if (System.getProperty("javax.net.ssl.trustStoreType", "").equalsIgnoreCase("PKCS11")) {
KeyStore keyStore = KeyStore.getInstance("PKCS11");
keyStore.load(null, System.getProperty("javax.net.ssl.trustStorePassword", "").toCharArray());
return keyStore;
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ private static KeyConfig createKeyConfig(Settings settings, SSLConfiguration glo
if (global != null) {
return global.keyConfig();
}
if (System.getProperty("javax.net.ssl.keyStore") != null) {
if (System.getProperty("javax.net.ssl.keyStore") != null && System.getProperty("javax.net.ssl.keyStore").equals("NONE") == false) {
// TODO: we should not support loading a keystore from sysprops...
try (SecureString keystorePassword = new SecureString(System.getProperty("javax.net.ssl.keyStorePassword", ""))) {
return new StoreKeyConfig(System.getProperty("javax.net.ssl.keyStore"), KeyStore.getDefaultType(), keystorePassword,
Expand Down Expand Up @@ -233,7 +233,8 @@ private static TrustConfig createCertChainTrustConfig(Settings settings, KeyConf
String trustStoreAlgorithm = SETTINGS_PARSER.truststoreAlgorithm.get(settings);
String trustStoreType = getKeyStoreType(SETTINGS_PARSER.truststoreType, settings, trustStorePath);
return new StoreTrustConfig(trustStorePath, trustStoreType, trustStorePassword, trustStoreAlgorithm);
} else if (global == null && System.getProperty("javax.net.ssl.trustStore") != null) {
} else if (global == null && System.getProperty("javax.net.ssl.trustStore") != null
&& System.getProperty("javax.net.ssl.trustStore").equals("NONE") == false) {
try (SecureString truststorePassword = new SecureString(System.getProperty("javax.net.ssl.trustStorePassword", ""))) {
return new StoreTrustConfig(System.getProperty("javax.net.ssl.trustStore"), KeyStore.getDefaultType(), truststorePassword,
System.getProperty("ssl.TrustManagerFactory.algorithm", TrustManagerFactory.getDefaultAlgorithm()));
Expand Down

0 comments on commit 77aeeda

Please sign in to comment.