Author: markt
Date: Thu Feb 21 20:59:10 2019
New Revision: 1854097
URL: http://svn.apache.org/viewvc?rev=1854097&view=rev
Log:
More alignment of JSSE and OpenSSL (and a little code reduction)
Modified:
tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java
tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java
tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java?rev=1854097&r1=1854096&r2=1854097&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java Thu Feb 21
20:59:10 2019
@@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.security.DomainLoadStoreParameter;
+import java.security.Key;
import java.security.KeyStore;
import java.security.cert.CRL;
import java.security.cert.CRLException;
@@ -42,18 +43,24 @@ import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
import javax.net.ssl.CertPathTrustManagerParameters;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509KeyManager;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.file.ConfigFileLoader;
import org.apache.tomcat.util.net.SSLHostConfig.CertificateVerification;
+import org.apache.tomcat.util.net.jsse.JSSEKeyManager;
+import org.apache.tomcat.util.net.jsse.PEMFile;
import org.apache.tomcat.util.res.StringManager;
/**
@@ -250,6 +257,120 @@ public abstract class SSLUtilBase implem
}
+ @Override
+ public KeyManager[] getKeyManagers() throws Exception {
+ String keyAlias = certificate.getCertificateKeyAlias();
+ String algorithm = sslHostConfig.getKeyManagerAlgorithm();
+ String keyPass = certificate.getCertificateKeyPassword();
+ // This has to be here as it can't be moved to SSLHostConfig since the
+ // defaults vary between JSSE and OpenSSL.
+ if (keyPass == null) {
+ keyPass = certificate.getCertificateKeystorePassword();
+ }
+
+ KeyStore ks = certificate.getCertificateKeystore();
+ KeyStore ksUsed = ks;
+
+ /*
+ * Use an in memory key store where possible.
+ * For PEM format keys and certificates, it allows them to be imported
+ * into the expected format.
+ * For Java key stores with PKCS8 encoded keys (e.g. JKS files), it
+ * enables Tomcat to handle the case where multiple keys exist in the
+ * key store, each with a different password. The KeyManagerFactory
+ * can't handle that so using an in memory key store with just the
+ * required key works around that.
+ * Other keys stores (hardware, MS, etc.) will be used as is.
+ */
+
+ char[] keyPassArray = keyPass.toCharArray();
+
+ if (ks == null) {
+ if (certificate.getCertificateFile() == null) {
+ throw new IOException(sm.getString("jsse.noCertFile"));
+ }
+
+ PEMFile privateKeyFile = new PEMFile(
+ certificate.getCertificateKeyFile() != null ?
certificate.getCertificateKeyFile() : certificate.getCertificateFile(),
+ keyPass);
+ PEMFile certificateFile = new
PEMFile(certificate.getCertificateFile());
+
+ Collection<Certificate> chain = new ArrayList<>();
+ chain.addAll(certificateFile.getCertificates());
+ if (certificate.getCertificateChainFile() != null) {
+ PEMFile certificateChainFile = new
PEMFile(certificate.getCertificateChainFile());
+ chain.addAll(certificateChainFile.getCertificates());
+ }
+
+ if (keyAlias == null) {
+ keyAlias = "tomcat";
+ }
+
+ // Switch to in-memory key store
+ ksUsed = KeyStore.getInstance("JKS");
+ ksUsed.load(null, null);
+ ksUsed.setKeyEntry(keyAlias, privateKeyFile.getPrivateKey(),
keyPass.toCharArray(),
+ chain.toArray(new Certificate[chain.size()]));
+ } else {
+ if (keyAlias != null && !ks.isKeyEntry(keyAlias)) {
+ throw new IOException(sm.getString("jsse.alias_no_key_entry",
keyAlias));
+ } else if (keyAlias == null) {
+ Enumeration<String> aliases = ks.aliases();
+ if (!aliases.hasMoreElements()) {
+ throw new IOException(sm.getString("jsse.noKeys"));
+ }
+ while (aliases.hasMoreElements() && keyAlias == null) {
+ keyAlias = aliases.nextElement();
+ if (!ks.isKeyEntry(keyAlias)) {
+ keyAlias = null;
+ }
+ }
+ if (keyAlias == null) {
+ throw new
IOException(sm.getString("jsse.alias_no_key_entry", (Object) null));
+ }
+ }
+
+ Key k = ks.getKey(keyAlias, keyPassArray);
+ if (k != null &&
!"DKS".equalsIgnoreCase(certificate.getCertificateKeystoreType()) &&
+ "PKCS#8".equalsIgnoreCase(k.getFormat())) {
+ // Switch to in-memory key store
+ String provider = certificate.getCertificateKeystoreProvider();
+ if (provider == null) {
+ ksUsed =
KeyStore.getInstance(certificate.getCertificateKeystoreType());
+ } else {
+ ksUsed =
KeyStore.getInstance(certificate.getCertificateKeystoreType(),
+ provider);
+ }
+ ksUsed.load(null, null);
+ ksUsed.setKeyEntry(keyAlias, k, keyPassArray,
ks.getCertificateChain(keyAlias));
+ }
+ // Non-PKCS#8 key stores will use the original key store
+ }
+
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
+ kmf.init(ksUsed, keyPassArray);
+
+ KeyManager[] kms = kmf.getKeyManagers();
+
+ // Only need to filter keys by alias if there are key managers to
filter
+ // and the original key store was used. The in memory key stores only
+ // have a single key so don't need filtering
+ if (kms != null && ksUsed == ks) {
+ String alias = keyAlias;
+ // JKS keystores always convert the alias name to lower case
+ if ("JKS".equals(certificate.getCertificateKeystoreType())) {
+ alias = alias.toLowerCase(Locale.ENGLISH);
+ }
+ for(int i = 0; i < kms.length; i++) {
+ kms[i] = new JSSEKeyManager((X509KeyManager)kms[i], alias);
+ }
+ }
+
+ return kms;
+ }
+
+
@Override
public String[] getEnabledProtocols() {
return enabledProtocols;
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java?rev=1854097&r1=1854096&r2=1854097&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java Thu Feb 21
20:59:10 2019
@@ -16,25 +16,14 @@
*/
package org.apache.tomcat.util.net.jsse;
-import java.io.IOException;
-import java.security.Key;
import java.security.KeyManagementException;
-import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
-import java.security.cert.Certificate;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
-import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.X509KeyManager;
-
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.compat.JreVendor;
@@ -162,118 +151,4 @@ public class JSSEUtil extends SSLUtilBas
throws NoSuchAlgorithmException {
return new JSSESSLContext(sslHostConfig.getSslProtocol());
}
-
-
- @Override
- public KeyManager[] getKeyManagers() throws Exception {
- String keyAlias = certificate.getCertificateKeyAlias();
- String algorithm = sslHostConfig.getKeyManagerAlgorithm();
- String keyPass = certificate.getCertificateKeyPassword();
- // This has to be here as it can't be moved to SSLHostConfig since the
- // defaults vary between JSSE and OpenSSL.
- if (keyPass == null) {
- keyPass = certificate.getCertificateKeystorePassword();
- }
-
- KeyStore ks = certificate.getCertificateKeystore();
- KeyStore ksUsed = ks;
-
- /*
- * Use an in memory key store where possible.
- * For PEM format keys and certificates, it allows them to be imported
- * into the expected format.
- * For Java key stores with PKCS8 encoded keys (e.g. JKS files), it
- * enables Tomcat to handle the case where multiple keys exist in the
- * key store, each with a different password. The KeyManagerFactory
- * can't handle that so using an in memory key store with just the
- * required key works around that.
- * Other keys stores (hardware, MS, etc.) will be used as is.
- */
-
- char[] keyPassArray = keyPass.toCharArray();
-
- if (ks == null) {
- if (certificate.getCertificateFile() == null) {
- throw new IOException(sm.getString("jsse.noCertFile"));
- }
-
- PEMFile privateKeyFile = new PEMFile(
- certificate.getCertificateKeyFile() != null ?
certificate.getCertificateKeyFile() : certificate.getCertificateFile(),
- keyPass);
- PEMFile certificateFile = new
PEMFile(certificate.getCertificateFile());
-
- Collection<Certificate> chain = new ArrayList<>();
- chain.addAll(certificateFile.getCertificates());
- if (certificate.getCertificateChainFile() != null) {
- PEMFile certificateChainFile = new
PEMFile(certificate.getCertificateChainFile());
- chain.addAll(certificateChainFile.getCertificates());
- }
-
- if (keyAlias == null) {
- keyAlias = "tomcat";
- }
-
- // Switch to in-memory key store
- ksUsed = KeyStore.getInstance("JKS");
- ksUsed.load(null, null);
- ksUsed.setKeyEntry(keyAlias, privateKeyFile.getPrivateKey(),
keyPass.toCharArray(),
- chain.toArray(new Certificate[chain.size()]));
- } else {
- if (keyAlias != null && !ks.isKeyEntry(keyAlias)) {
- throw new IOException(sm.getString("jsse.alias_no_key_entry",
keyAlias));
- } else if (keyAlias == null) {
- Enumeration<String> aliases = ks.aliases();
- if (!aliases.hasMoreElements()) {
- throw new IOException(sm.getString("jsse.noKeys"));
- }
- while (aliases.hasMoreElements() && keyAlias == null) {
- keyAlias = aliases.nextElement();
- if (!ks.isKeyEntry(keyAlias)) {
- keyAlias = null;
- }
- }
- if (keyAlias == null) {
- throw new
IOException(sm.getString("jsse.alias_no_key_entry", (Object) null));
- }
- }
-
- Key k = ks.getKey(keyAlias, keyPassArray);
- if (k != null &&
!"DKS".equalsIgnoreCase(certificate.getCertificateKeystoreType()) &&
- "PKCS#8".equalsIgnoreCase(k.getFormat())) {
- // Switch to in-memory key store
- String provider = certificate.getCertificateKeystoreProvider();
- if (provider == null) {
- ksUsed =
KeyStore.getInstance(certificate.getCertificateKeystoreType());
- } else {
- ksUsed =
KeyStore.getInstance(certificate.getCertificateKeystoreType(),
- provider);
- }
- ksUsed.load(null, null);
- ksUsed.setKeyEntry(keyAlias, k, keyPassArray,
ks.getCertificateChain(keyAlias));
- }
- // Non-PKCS#8 key stores will use the original key store
- }
-
-
- KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
- kmf.init(ksUsed, keyPassArray);
-
- KeyManager[] kms = kmf.getKeyManagers();
-
- // Only need to filter keys by alias if there are key managers to
filter
- // and the original key store was used. The in memory key stores only
- // have a single key so don't need filtering
- if (kms != null && ksUsed == ks) {
- String alias = keyAlias;
- // JKS keystores always convert the alias name to lower case
- if ("JKS".equals(certificate.getCertificateKeystoreType())) {
- alias = alias.toLowerCase(Locale.ENGLISH);
- }
- for(int i = 0; i < kms.length; i++) {
- kms[i] = new JSSEKeyManager((X509KeyManager)kms[i], alias);
- }
- }
-
- return kms;
- }
}
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java?rev=1854097&r1=1854096&r2=1854097&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java Thu
Feb 21 20:59:10 2019
@@ -19,33 +19,19 @@ package org.apache.tomcat.util.net.opens
import java.util.List;
import java.util.Set;
-import javax.net.ssl.KeyManager;
-
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.jni.SSL;
import org.apache.tomcat.util.net.SSLContext;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.SSLUtilBase;
-import org.apache.tomcat.util.net.jsse.JSSEUtil;
public class OpenSSLUtil extends SSLUtilBase {
private static final Log log = LogFactory.getLog(OpenSSLUtil.class);
- private final JSSEUtil jsseUtil;
-
public OpenSSLUtil(SSLHostConfigCertificate certificate) {
super(certificate);
-
- if (certificate.getCertificateFile() == null) {
- // Using JSSE configuration for keystore and truststore
- // Missing protocols not a concern so don't warn on skip
- jsseUtil = new JSSEUtil(certificate, false);
- } else {
- // Use OpenSSL configuration for certificates
- jsseUtil = null;
- }
}
@@ -84,14 +70,4 @@ public class OpenSSLUtil extends SSLUtil
public SSLContext createSSLContextInternal(List<String>
negotiableProtocols) throws Exception {
return new OpenSSLContext(certificate, negotiableProtocols);
}
-
-
- @Override
- public KeyManager[] getKeyManagers() throws Exception {
- if (jsseUtil != null) {
- return jsseUtil.getKeyManagers();
- } else {
- return null;
- }
- }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]