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

Reply via email to