You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by jf...@apache.org on 2015/11/08 19:03:27 UTC
svn commit: r1713277 - in /tomcat/trunk/java/org/apache/tomcat/util/net:
SSLHostConfigCertificate.java openssl/CipherSuiteConverter.java
openssl/OpenSSLContext.java openssl/OpenSSLKeyManager.java
Author: jfclere
Date: Sun Nov 8 18:03:26 2015
New Revision: 1713277
URL: http://svn.apache.org/viewvc?rev=1713277&view=rev
Log:
Allow to use java keystore with the openssl engine.
Modified:
tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java
tomcat/trunk/java/org/apache/tomcat/util/net/openssl/CipherSuiteConverter.java
tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLKeyManager.java
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java?rev=1713277&r1=1713276&r2=1713277&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java Sun Nov 8 18:03:26 2015
@@ -28,7 +28,7 @@ public class SSLHostConfigCertificate {
public static final Type DEFAULT_TYPE = Type.UNDEFINED;
static final String DEFAULT_KEYSTORE_PROVIDER =
- System.getProperty("javax.net.ssl.keyStoreProvider");
+ System.getProperty("javax.net.ssl.keyStoreProvider", "SunX509");
static final String DEFAULT_KEYSTORE_TYPE =
System.getProperty("javax.net.ssl.keyStoreType", "JKS");
@@ -43,7 +43,7 @@ public class SSLHostConfigCertificate {
private String certificateKeyPassword = null;
// JSSE
- private String certificateKeyAlias;
+ private String certificateKeyAlias = "tomcat";
private String certificateKeystorePassword = "changeit";
private String certificateKeystoreFile = System.getProperty("user.home")+"/.keystore";
private String certificateKeystoreProvider = DEFAULT_KEYSTORE_PROVIDER;
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/openssl/CipherSuiteConverter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/openssl/CipherSuiteConverter.java?rev=1713277&r1=1713276&r2=1713277&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/openssl/CipherSuiteConverter.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/openssl/CipherSuiteConverter.java Sun Nov 8 18:03:26 2015
@@ -182,9 +182,11 @@ public final class CipherSuiteConverter
p2j.put("TLS", "TLS_" + javaCipherSuiteSuffix);
o2j.put(openSslCipherSuite, p2j);
+ /* TODO the log looks broken...
if (logger.isDebugEnabled()) {
logger.debug(sm.getString("converter.mapping", javaCipherSuite, openSslCipherSuite));
}
+ */
return openSslCipherSuite;
}
@@ -313,10 +315,12 @@ public final class CipherSuiteConverter
j2o.putIfAbsent(javaCipherSuiteTls, openSslCipherSuite);
j2o.putIfAbsent(javaCipherSuiteSsl, openSslCipherSuite);
+ /* TODO the log looks broken...
if (logger.isDebugEnabled()) {
logger.debug(sm.getString("converter.mapping", javaCipherSuiteTls, openSslCipherSuite));
logger.debug(sm.getString("converter.mapping", javaCipherSuiteSsl, openSslCipherSuite));
}
+ */
return p2j;
}
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java?rev=1713277&r1=1713276&r2=1713277&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java Sun Nov 8 18:03:26 2015
@@ -17,17 +17,28 @@
package org.apache.tomcat.util.net.openssl;
import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
+import java.util.Base64;
import java.util.List;
+import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
@@ -38,12 +49,14 @@ import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;
import org.apache.juli.logging.Log;
@@ -52,6 +65,7 @@ import org.apache.tomcat.jni.Certificate
import org.apache.tomcat.jni.Pool;
import org.apache.tomcat.jni.SSL;
import org.apache.tomcat.jni.SSLContext;
+import org.apache.tomcat.util.file.ConfigFileLoader;
import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.Constants;
import org.apache.tomcat.util.net.SSLHostConfig;
@@ -99,6 +113,10 @@ public class OpenSSLContext implements o
private static final AtomicIntegerFieldUpdater<OpenSSLContext> DESTROY_UPDATER
= AtomicIntegerFieldUpdater.newUpdater(OpenSSLContext.class, "aprPoolDestroyed");
static final CertificateFactory X509_CERT_FACTORY;
+
+ private static final String BEGIN_KEY = "-----BEGIN RSA PRIVATE KEY-----\n";
+
+ private static final Object END_KEY = "\n-----END RSA PRIVATE KEY-----";
private boolean initialized = false;
static {
@@ -118,7 +136,7 @@ public class OpenSSLContext implements o
try {
if (SSLHostConfig.adjustRelativePath(certificate.getCertificateFile()) == null) {
// This is required
- throw new Exception(netSm.getString("endpoint.apr.noSslCertFile"));
+ // throw new Exception(netSm.getString("endpoint.apr.noSslCertFile"));
}
// SSL protocol
@@ -311,20 +329,36 @@ public class OpenSSLContext implements o
}
SSLContext.setCipherSuite(ctx, ciphers);
// Load Server key and certificate
- SSLContext.setCertificate(ctx,
- SSLHostConfig.adjustRelativePath(certificate.getCertificateFile()),
- SSLHostConfig.adjustRelativePath(certificate.getCertificateKeyFile()),
- certificate.getCertificateKeyPassword(), SSL.SSL_AIDX_RSA);
- // Support Client Certificates
- SSLContext.setCACertificate(ctx,
- SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificateFile()),
- SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificatePath()));
- // Set revocation
- SSLContext.setCARevocation(ctx,
- SSLHostConfig.adjustRelativePath(
- sslHostConfig.getCertificateRevocationListFile()),
- SSLHostConfig.adjustRelativePath(
- sslHostConfig.getCertificateRevocationListPath()));
+ if (certificate.getCertificateFile() != null) {
+
+ SSLContext.setCertificate(ctx,
+ SSLHostConfig.adjustRelativePath(certificate.getCertificateFile()),
+ SSLHostConfig.adjustRelativePath(certificate.getCertificateKeyFile()),
+ certificate.getCertificateKeyPassword(), SSL.SSL_AIDX_RSA);
+
+ // Support Client Certificates
+
+ SSLContext.setCACertificate(ctx,
+ SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificateFile()),
+ SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificatePath()));
+ // Set revocation
+ SSLContext.setCARevocation(ctx,
+ SSLHostConfig.adjustRelativePath(
+ sslHostConfig.getCertificateRevocationListFile()),
+ SSLHostConfig.adjustRelativePath(
+ sslHostConfig.getCertificateRevocationListPath()));
+ } else {
+ /* Try use keystore */
+ X509KeyManager keyManager = getJSSEKeyManager(sslHostConfig);
+ String alias = getJSSEAlias(sslHostConfig, keyManager);
+ X509Certificate certificate = keyManager.getCertificateChain(alias)[0];
+ PrivateKey key = keyManager.getPrivateKey(alias);
+ StringBuilder sb = new StringBuilder(BEGIN_KEY);
+ sb.append(Base64.getMimeEncoder(64, new byte[] {'\n'}).encodeToString(key.getEncoded()));
+ sb.append(END_KEY);
+ SSLContext.setCertificateRaw(ctx, certificate.getEncoded(), sb.toString().getBytes(StandardCharsets.US_ASCII), SSL.SSL_AIDX_RSA);
+
+ }
// Client certificate verification
int value = 0;
switch (sslHostConfig.getCertificateVerification()) {
@@ -378,6 +412,50 @@ public class OpenSSLContext implements o
}
}
+ String getJSSEAlias(SSLHostConfig sslHostConfig, X509KeyManager keyManager) {
+ String alias = null;
+ // TODO make sure we get the right one...
+ if (certificate.getCertificateKeyAlias() != null)
+ alias = certificate.getCertificateKeyAlias();
+ return alias;
+ }
+ /**
+ * get the JSSE key manager for the keystore
+ * @throws KeyStoreException
+ * @throws NoSuchAlgorithmException
+ * @throws UnrecoverableKeyException
+ * @throws IOException
+ * @throws CertificateException
+ *
+ */
+ static X509KeyManager getJSSEKeyManager(SSLHostConfig sslHostConfig) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, CertificateException, IOException {
+ String keystoretype = null;
+ String keystoreprovider = null;
+ String keystorefile = null;
+ String password = null;
+ // TODO make sure we get the right one...
+ for (SSLHostConfigCertificate certificate : sslHostConfig.getCertificates(true)) {
+ if (certificate.getCertificateKeystoreFile() != null)
+ keystorefile = certificate.getCertificateKeystoreFile();
+ if (certificate.getCertificateKeystorePassword() != null)
+ password = certificate.getCertificateKeystorePassword();
+ if (certificate.getCertificateKeystoreType() != null)
+ keystoretype = certificate.getCertificateKeystoreType();
+ if (certificate.getCertificateKeystoreProvider() != null)
+ keystoreprovider = certificate.getCertificateKeystoreProvider();
+ }
+ KeyStore ks = KeyStore.getInstance(keystoretype);
+ InputStream stream = ConfigFileLoader.getInputStream(keystorefile);
+ ks.load(stream, password.toCharArray());
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(keystoreprovider);
+ kmf.init(ks, password.toCharArray());
+ KeyManager[] kms = kmf.getKeyManagers();
+ if (kms == null) {
+ return null;
+ }
+ return (X509KeyManager) kms[0];
+ }
+
static OpenSSLKeyManager chooseKeyManager(KeyManager[] managers) throws Exception {
for (KeyManager manager : managers) {
if (manager instanceof OpenSSLKeyManager) {
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLKeyManager.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLKeyManager.java?rev=1713277&r1=1713276&r2=1713277&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLKeyManager.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLKeyManager.java Sun Nov 8 18:03:26 2015
@@ -36,10 +36,10 @@ public class OpenSSLKeyManager implement
OpenSSLKeyManager(String certChainFile, String keyFile) {
if (certChainFile == null) {
- throw new IllegalArgumentException(sm.getString("keyManager.nullCertificateChain"));
+ return;
}
if (keyFile == null) {
- throw new IllegalArgumentException(sm.getString("keyManager.nullPrivateKey"));
+ return;
}
this.certificateChain = new File(certChainFile);
this.privateKey = new File(keyFile);
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org