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