You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by ff...@apache.org on 2017/06/13 08:36:54 UTC

cxf git commit: [CXF-7401]CXF http-jetty fails to get private key if the jks keystore file contains multiple private keys with different password

Repository: cxf
Updated Branches:
  refs/heads/master 20663ce50 -> e877d3098


[CXF-7401]CXF http-jetty fails to get private key if the jks keystore file contains multiple private keys with different password


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/e877d309
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/e877d309
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/e877d309

Branch: refs/heads/master
Commit: e877d30982ae970738495160090a8e948f33c199
Parents: 20663ce
Author: Freeman Fang <fr...@gmail.com>
Authored: Tue Jun 13 16:36:37 2017 +0800
Committer: Freeman Fang <fr...@gmail.com>
Committed: Tue Jun 13 16:36:37 2017 +0800

----------------------------------------------------------------------
 .../jsse/MultiKeyPasswordKeyManager.java        |  83 +++++++++++++++++++
 .../jsse/TLSClientParametersConfig.java         |  10 ++-
 .../jsse/TLSParameterJaxBUtils.java             |  36 ++++++++
 .../jsse/TLSServerParametersConfig.java         |  10 ++-
 .../cxf/systest/https/conduit/jaxws-server.xml  |   8 +-
 .../src/test/resources/keys/MultipleKeys.jks    | Bin 0 -> 4391 bytes
 6 files changed, 139 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/e877d309/core/src/main/java/org/apache/cxf/configuration/jsse/MultiKeyPasswordKeyManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/cxf/configuration/jsse/MultiKeyPasswordKeyManager.java b/core/src/main/java/org/apache/cxf/configuration/jsse/MultiKeyPasswordKeyManager.java
new file mode 100644
index 0000000..c6dcbc9
--- /dev/null
+++ b/core/src/main/java/org/apache/cxf/configuration/jsse/MultiKeyPasswordKeyManager.java
@@ -0,0 +1,83 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.configuration.jsse;
+
+import java.net.Socket;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.X509KeyManager;
+
+public class MultiKeyPasswordKeyManager implements X509KeyManager {
+    private final KeyStore mKeyStore;
+    private final String mKeyAlias;
+    private final String mKeyPassword;
+
+    public MultiKeyPasswordKeyManager(KeyStore keystore, String keyAlias, String keyPassword) {
+        mKeyStore = keystore;
+        mKeyAlias = keyAlias;
+        mKeyPassword = keyPassword;
+    }
+
+    public String[] getClientAliases(String keyType, Principal[] issuers) {
+        return new String[] {
+            mKeyAlias
+        };
+    }
+
+    public String[] getServerAliases(String keyType, Principal[] issuers) {
+        return new String[] {
+            mKeyAlias
+        };
+    }
+    public X509Certificate[] getCertificateChain(String alias) {
+        Certificate[] chain = null;
+        try {
+            chain = mKeyStore.getCertificateChain(alias);
+        } catch (KeyStoreException kse) {
+            throw new RuntimeException(kse);
+        }
+        final X509Certificate[] certChain = new X509Certificate[chain.length];
+        for (int i = 0; i < chain.length; i++) {
+            certChain[i] = (X509Certificate)chain[i];
+        }
+        return certChain;
+    }
+
+    public PrivateKey getPrivateKey(String alias) {
+        try {
+            return (PrivateKey)mKeyStore.getKey(alias, mKeyPassword.toCharArray());
+        } catch (GeneralSecurityException gse) {
+            throw new RuntimeException(gse);
+        }
+    }
+
+    public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
+        return mKeyAlias;
+    }
+
+    public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
+        return mKeyAlias;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/e877d309/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParametersConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParametersConfig.java b/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParametersConfig.java
index 3d9f89c..7ca29da 100644
--- a/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParametersConfig.java
+++ b/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParametersConfig.java
@@ -108,8 +108,14 @@ public final class TLSClientParametersConfig {
                         params.getSecureRandomParameters()));
         }
         if (params.isSetKeyManagers() && !usingDefaults) {
-            ret.setKeyManagers(
-                TLSParameterJaxBUtils.getKeyManagers(params.getKeyManagers()));
+            if (!params.isSetCertAlias()) {
+                ret.setKeyManagers(
+                                    TLSParameterJaxBUtils.getKeyManagers(params.getKeyManagers()));
+            } else {
+                ret.setKeyManagers(
+                                    TLSParameterJaxBUtils.getKeyManagers(params.getKeyManagers(), 
+                                                                         params.getCertAlias()));
+            }
         }
         if (params.isSetTrustManagers() && !usingDefaults) {
             ret.setTrustManagers(

http://git-wip-us.apache.org/repos/asf/cxf/blob/e877d309/core/src/main/java/org/apache/cxf/configuration/jsse/TLSParameterJaxBUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/cxf/configuration/jsse/TLSParameterJaxBUtils.java b/core/src/main/java/org/apache/cxf/configuration/jsse/TLSParameterJaxBUtils.java
index b2e5ce0..88f60ba 100644
--- a/core/src/main/java/org/apache/cxf/configuration/jsse/TLSParameterJaxBUtils.java
+++ b/core/src/main/java/org/apache/cxf/configuration/jsse/TLSParameterJaxBUtils.java
@@ -297,6 +297,42 @@ public final class TLSParameterJaxBUtils {
 
         return fac.getKeyManagers();
     }
+    
+    /**
+     * This method converts the JAXB KeyManagersType into a list of
+     * JSSE KeyManagers.
+     */
+    public static KeyManager[] getKeyManagers(KeyManagersType kmc, String alias)
+        throws GeneralSecurityException,
+               IOException {
+
+        KeyStore keyStore = getKeyStore(kmc.getKeyStore(), false);
+
+        String alg = kmc.isSetFactoryAlgorithm()
+                     ? kmc.getFactoryAlgorithm()
+                     : KeyManagerFactory.getDefaultAlgorithm();
+
+        char[] keyPass = getKeyPassword(kmc);
+
+        KeyManagerFactory fac =
+                     kmc.isSetProvider()
+                     ? KeyManagerFactory.getInstance(alg, kmc.getProvider())
+                     : KeyManagerFactory.getInstance(alg);
+                     
+        try {             
+            fac.init(keyStore, keyPass);
+
+            return fac.getKeyManagers();
+        } catch (java.security.UnrecoverableKeyException uke) {
+            //jsse has the restriction that different key in keystore
+            //cannot has different password, use MultiKeyPasswordKeyManager
+            //as fallback when this happen
+            MultiKeyPasswordKeyManager manager
+                = new MultiKeyPasswordKeyManager(keyStore, alias,
+                                             new String(keyPass));
+            return new KeyManager[]{manager};
+        }
+    }
 
     private static char[] getKeyPassword(KeyManagersType kmc) {
         char[] keyPass = kmc.isSetKeyPassword()

http://git-wip-us.apache.org/repos/asf/cxf/blob/e877d309/core/src/main/java/org/apache/cxf/configuration/jsse/TLSServerParametersConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/cxf/configuration/jsse/TLSServerParametersConfig.java b/core/src/main/java/org/apache/cxf/configuration/jsse/TLSServerParametersConfig.java
index cdf35fd..29f9d82 100644
--- a/core/src/main/java/org/apache/cxf/configuration/jsse/TLSServerParametersConfig.java
+++ b/core/src/main/java/org/apache/cxf/configuration/jsse/TLSServerParametersConfig.java
@@ -72,8 +72,14 @@ public class TLSServerParametersConfig
             this.setClientAuthentication(params.getClientAuthentication());
         }
         if (params.isSetKeyManagers()) {
-            this.setKeyManagers(
-                TLSParameterJaxBUtils.getKeyManagers(params.getKeyManagers()));
+            if (!params.isSetCertAlias()) {
+                this.setKeyManagers(
+                                    TLSParameterJaxBUtils.getKeyManagers(params.getKeyManagers()));
+            } else {
+                this.setKeyManagers(
+                                    TLSParameterJaxBUtils.getKeyManagers(params.getKeyManagers(), 
+                                                                         params.getCertAlias()));
+            }
         }
         if (params.isSetTrustManagers()) {
             this.setTrustManagers(

http://git-wip-us.apache.org/repos/asf/cxf/blob/e877d309/systests/transports/src/test/resources/org/apache/cxf/systest/https/conduit/jaxws-server.xml
----------------------------------------------------------------------
diff --git a/systests/transports/src/test/resources/org/apache/cxf/systest/https/conduit/jaxws-server.xml b/systests/transports/src/test/resources/org/apache/cxf/systest/https/conduit/jaxws-server.xml
index b59a010..ae51b7d 100644
--- a/systests/transports/src/test/resources/org/apache/cxf/systest/https/conduit/jaxws-server.xml
+++ b/systests/transports/src/test/resources/org/apache/cxf/systest/https/conduit/jaxws-server.xml
@@ -49,8 +49,8 @@ under the License.
     <httpj:engine-factory id="port-9002-tls-config">
         <httpj:engine port="${testutil.ports.BusServer.2}">
             <httpj:tlsServerParameters>
-                <sec:keyManagers keyPassword="password">
-                    <sec:keyStore type="JKS" password="password" resource="keys/Bethal.jks"/>
+                <sec:keyManagers keyPassword="changit">
+                    <sec:keyStore type="JKS" password="password" resource="keys/MultipleKeys.jks"/>
                 </sec:keyManagers>
                 <sec:trustManagers>
                     <sec:keyStore type="JKS" password="password" resource="keys/Truststore.jks"/>
@@ -65,8 +65,8 @@ under the License.
     <!-- -->
     <http:conduit name="{http://apache.org/hello_world/services}HttpsPort.http-conduit">
         <http:tlsClientParameters disableCNCheck="true">
-            <sec:keyManagers keyPassword="password">
-                <sec:keyStore type="JKS" password="password" resource="keys/Morpit.jks"/>
+            <sec:keyManagers keyPassword="anotherchangit">
+                <sec:keyStore type="JKS" password="password" resource="keys/MultipleKeys.jks"/>
             </sec:keyManagers>
             <sec:trustManagers>
                 <sec:keyStore type="JKS" password="password" resource="keys/Truststore.jks"/>

http://git-wip-us.apache.org/repos/asf/cxf/blob/e877d309/testutils/src/test/resources/keys/MultipleKeys.jks
----------------------------------------------------------------------
diff --git a/testutils/src/test/resources/keys/MultipleKeys.jks b/testutils/src/test/resources/keys/MultipleKeys.jks
new file mode 100644
index 0000000..9e6c477
Binary files /dev/null and b/testutils/src/test/resources/keys/MultipleKeys.jks differ