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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org