| /* | |
| * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| // | |
| // SunJSSE does not support dynamic system properties, no way to re-use | |
| // system properties in samevm/agentvm mode. | |
| // | |
| import javax.net.ssl.KeyManager; | |
| import javax.net.ssl.KeyManagerFactory; | |
| import javax.net.ssl.KeyManagerFactorySpi; | |
| import javax.net.ssl.ManagerFactoryParameters; | |
| import javax.net.ssl.SSLServerSocket; | |
| import javax.net.ssl.X509KeyManager; | |
| import java.net.Socket; | |
| import java.security.InvalidAlgorithmParameterException; | |
| import java.security.KeyStore; | |
| import java.security.KeyStoreException; | |
| import java.security.NoSuchAlgorithmException; | |
| import java.security.Principal; | |
| import java.security.PrivateKey; | |
| import java.security.Provider; | |
| import java.security.Security; | |
| import java.security.UnrecoverableKeyException; | |
| import java.security.cert.X509Certificate; | |
| import java.util.Arrays; | |
| /* | |
| * @test | |
| * @bug 8262186 | |
| * @summary Callback semantics of the method X509KeyManager.chooseClientAlias(...) | |
| * @library /javax/net/ssl/templates | |
| * @modules java.base/sun.security.ssl:+open | |
| * java.base/javax.net.ssl:+open | |
| * @run main/othervm MultipleChooseAlias PKIX | |
| * @run main/othervm MultipleChooseAlias SunX509 | |
| */ | |
| public class MultipleChooseAlias extends SSLSocketTemplate { | |
| static volatile int numOfCalls = 0; | |
| static String kmfAlgorithm = null; | |
| @Override | |
| protected void configureServerSocket(SSLServerSocket socket) { | |
| socket.setNeedClientAuth(true); | |
| } | |
| @Override | |
| protected ContextParameters getClientContextParameters() { | |
| return new ContextParameters("TLS", "PKIX", "Mine"); | |
| } | |
| public static void main(String[] args) throws Exception { | |
| kmfAlgorithm = args[0]; | |
| Security.addProvider(new MyProvider()); | |
| try { | |
| new MultipleChooseAlias().run(); | |
| } catch (Exception e) { | |
| // expected | |
| } | |
| if (numOfCalls != 1) { | |
| throw new RuntimeException("Too many times " + numOfCalls); | |
| } | |
| } | |
| static class MyProvider extends Provider { | |
| public MyProvider() { | |
| super("Mine", "1", "many many things"); | |
| put("KeyManagerFactory.Mine", "MultipleChooseAlias$MyKMF"); | |
| } | |
| } | |
| // This KeyManagerFactory impl returns key managers | |
| // wrapped in MyKM | |
| public static class MyKMF extends KeyManagerFactorySpi { | |
| KeyManagerFactory fac; | |
| public MyKMF() { | |
| try { | |
| fac = KeyManagerFactory.getInstance(kmfAlgorithm); | |
| } catch (Exception e) { | |
| throw new AssertionError(e); | |
| } | |
| } | |
| @Override | |
| protected void engineInit(KeyStore ks, char[] password) | |
| throws KeyStoreException, NoSuchAlgorithmException, | |
| UnrecoverableKeyException { | |
| fac.init(ks, password); | |
| } | |
| @Override | |
| protected void engineInit(ManagerFactoryParameters spec) | |
| throws InvalidAlgorithmParameterException { | |
| fac.init(spec); | |
| } | |
| @Override | |
| protected KeyManager[] engineGetKeyManagers() { | |
| KeyManager[] result = fac.getKeyManagers(); | |
| for (int i = 0; i < result.length; i++) { | |
| result[i] = new MyKM((X509KeyManager)result[i]); | |
| } | |
| return result; | |
| } | |
| } | |
| // This KeyManager remembers how many times chooseClientAlias is called. | |
| static class MyKM implements X509KeyManager { | |
| X509KeyManager km; | |
| MyKM(X509KeyManager km) { | |
| this.km = km; | |
| } | |
| public String[] getClientAliases(String keyType, Principal[] issuers) { | |
| return km.getClientAliases(keyType, issuers); | |
| } | |
| public String chooseClientAlias(String[] keyType, Principal[] issuers, | |
| Socket socket) { | |
| System.out.println("chooseClientAlias called on " | |
| + Arrays.toString(keyType)); | |
| numOfCalls++; | |
| return null; // so it will try all key types and finally fails | |
| } | |
| public String[] getServerAliases(String keyType, Principal[] issuers) { | |
| return getServerAliases(keyType, issuers); | |
| } | |
| public String chooseServerAlias(String keyType, Principal[] issuers, | |
| Socket socket) { | |
| return km.chooseServerAlias(keyType, issuers, socket); | |
| } | |
| public X509Certificate[] getCertificateChain(String alias) { | |
| return km.getCertificateChain(alias); | |
| } | |
| public PrivateKey getPrivateKey(String alias) { | |
| return km.getPrivateKey(alias); | |
| } | |
| } | |
| } |