OpenJDK / jdk / hs
changeset 30038:632939157af2
8075007: Additional tests for krb5-related cipher suites with unbound server
Reviewed-by: weijun
author | asmotrak |
---|---|
date | Mon, 27 Apr 2015 21:02:40 +0800 |
parents | 3e785fad2c3b |
children | 7f5a75df6e5f 13ab4bf3c34a |
files | jdk/test/sun/security/krb5/auto/KDC.java jdk/test/sun/security/krb5/auto/UnboundSSL.java jdk/test/sun/security/krb5/auto/UnboundSSLMultipleKeys.java jdk/test/sun/security/krb5/auto/UnboundSSLPrincipalProperty.java jdk/test/sun/security/krb5/auto/UnboundSSLUtils.java jdk/test/sun/security/krb5/auto/unbound.ssl.jaas.conf jdk/test/sun/security/krb5/auto/unbound.ssl.policy |
diffstat | 7 files changed, 803 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/test/sun/security/krb5/auto/KDC.java Fri Apr 24 20:51:41 2015 +0400 +++ b/jdk/test/sun/security/krb5/auto/KDC.java Mon Apr 27 21:02:40 2015 +0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2015, 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 @@ -149,6 +149,9 @@ private List<String> conf = new ArrayList<>(); private Thread thread1, thread2, thread3; + private volatile boolean udpConsumerReady = false; + private volatile boolean tcpConsumerReady = false; + private volatile boolean dispatcherReady = false; DatagramSocket u1 = null; ServerSocket t1 = null; @@ -1228,6 +1231,7 @@ // The UDP consumer thread1 = new Thread() { public void run() { + udpConsumerReady = true; while (true) { try { byte[] inbuf = new byte[8192]; @@ -1248,6 +1252,7 @@ // The TCP consumer thread2 = new Thread() { public void run() { + tcpConsumerReady = true; while (true) { try { Socket socket = tcp.accept(); @@ -1270,6 +1275,7 @@ // The dispatcher thread3 = new Thread() { public void run() { + dispatcherReady = true; while (true) { try { q.take().send(); @@ -1280,6 +1286,19 @@ }; thread3.setDaemon(true); thread3.start(); + + // wait for the KDC is ready + try { + while (!isReady()) { + Thread.sleep(100); + } + } catch(InterruptedException e) { + throw new IOException(e); + } + } + + boolean isReady() { + return udpConsumerReady && tcpConsumerReady && dispatcherReady; } public void terminate() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/UnboundSSL.java Mon Apr 27 21:02:40 2015 +0800 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2015, 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. + */ + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivilegedActionException; +import java.util.HashMap; +import java.util.Map; +import javax.security.auth.login.LoginException; + +/* + * @test + * @bug 8025123 + * @summary Checks if an unbound server can handle connections + * only for allowed service principals + * @run main/othervm/policy=unbound.ssl.policy UnboundSSL + * unbound.ssl.jaas.conf server_star + * @run main/othervm/policy=unbound.ssl.policy UnboundSSL + * unbound.ssl.jaas.conf server_multiple_principals + */ +public class UnboundSSL { + + public static void main(String[] args) throws IOException, + NoSuchAlgorithmException,LoginException, PrivilegedActionException, + InterruptedException { + UnboundSSL test = new UnboundSSL(); + test.start(args[0], args[1]); + } + + private void start(String jaacConfigFile, String serverJaasConfig) + throws IOException, NoSuchAlgorithmException,LoginException, + PrivilegedActionException, InterruptedException { + + // define principals + String service1host = "service1." + UnboundSSLUtils.HOST; + String service2host = "service2." + UnboundSSLUtils.HOST; + String service3host = "service3." + UnboundSSLUtils.HOST; + String service1Principal = "host/" + service1host + "@" + + UnboundSSLUtils.REALM; + String service2Principal = "host/" + service2host + "@" + + UnboundSSLUtils.REALM; + String service3Principal = "host/" + service3host + "@" + + UnboundSSLUtils.REALM; + + Map<String, String> principals = new HashMap<>(); + principals.put(UnboundSSLUtils.USER_PRINCIPAL, + UnboundSSLUtils.USER_PASSWORD); + principals.put(UnboundSSLUtils.KRBTGT_PRINCIPAL, null); + principals.put(service1Principal, null); + principals.put(service2Principal, null); + principals.put(service3Principal, null); + + System.setProperty("java.security.krb5.conf", + UnboundSSLUtils.KRB5_CONF_FILENAME); + + // start a local KDC instance + UnboundSSLUtils.startKDC(UnboundSSLUtils.REALM, principals, + UnboundSSLUtils.KTAB_FILENAME, UnboundSSLUtils.KtabMode.APPEND); + + System.setProperty("java.security.auth.login.config", + UnboundSSLUtils.TEST_SRC + UnboundSSLUtils.FS + jaacConfigFile); + System.setProperty("javax.security.auth.useSubjectCredsOnly", "false"); + + try (final SSLEchoServer server = SSLEchoServer.init( + UnboundSSLUtils.TLS_KRB5_FILTER, UnboundSSLUtils.SNI_PATTERN)) { + + // start a server instance + UnboundSSLUtils.startServerWithJaas(server, serverJaasConfig); + + // wait for the server is ready + while (!server.isReady()) { + Thread.sleep(UnboundSSLUtils.DELAY); + } + + int port = server.getPort(); + + // run clients + + // the server should have a permission to handle a request + // with this service principal (there should be an appropriate + // javax.security.auth.kerberos.ServicePermission in policy file) + System.out.println("Connect: SNI hostname = " + service1host + + ", successful connection is expected"); + SSLClient.init(UnboundSSLUtils.HOST, port, + UnboundSSLUtils.TLS_KRB5_FILTER, service1host).connect(); + + // the server should NOT have a permission to handle a request + // with this service principal (there should be an appropriate + // javax.security.auth.kerberos.ServicePermission in policy file) + // handshake failures is expected + System.out.println("Connect: SNI hostname = " + service2host + + ", connection failure is expected"); + try { + SSLClient.init(UnboundSSLUtils.HOST, port, + UnboundSSLUtils.TLS_KRB5_FILTER, service2host) + .connect(); + throw new RuntimeException("Test failed: " + + "expected IOException not thrown"); + } catch (IOException e) { + System.out.println("Expected exception: " + e); + } + + // the server should have a permission to handle a request + // with this service principal (there should be an appropriate + // javax.security.auth.kerberos.ServicePermission in policy file) + System.out.println("Connect: SNI hostname = " + service3host + + ", successful connection is expected"); + SSLClient.init(UnboundSSLUtils.HOST, port, + UnboundSSLUtils.TLS_KRB5_FILTER, service3host).connect(); + } + + System.out.println("Test passed"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/UnboundSSLMultipleKeys.java Mon Apr 27 21:02:40 2015 +0800 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, 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. + */ + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivilegedActionException; +import java.util.HashMap; +import java.util.Map; +import javax.security.auth.login.LoginException; + +/* + * @test + * @bug 8025123 + * @summary Checks if an unbound server pick up a correct key from keytab + * @run main/othervm UnboundSSLMultipleKeys + * unbound.ssl.jaas.conf server_star + * @run main/othervm UnboundSSLMultipleKeys + * unbound.ssl.jaas.conf server_multiple_principals + */ +public class UnboundSSLMultipleKeys { + + public static void main(String[] args) + throws IOException, NoSuchAlgorithmException, LoginException, + PrivilegedActionException, InterruptedException { + UnboundSSLMultipleKeys test = new UnboundSSLMultipleKeys(); + test.start(args[0], args[1]); + } + + private void start(String jaacConfigFile, String serverJaasConfig) + throws IOException, NoSuchAlgorithmException, LoginException, + PrivilegedActionException, InterruptedException { + + // define service principals + String service1host = "service1." + UnboundSSLUtils.HOST; + String service2host = "service2." + UnboundSSLUtils.HOST; + String service3host = "service3." + UnboundSSLUtils.HOST; + String service1Principal = "host/" + service1host + "@" + + UnboundSSLUtils.REALM; + String service2Principal = "host/" + service2host + "@" + + UnboundSSLUtils.REALM; + String service3Principal = "host/" + service3host + "@" + + UnboundSSLUtils.REALM; + + Map<String, String> principals = new HashMap<>(); + principals.put(UnboundSSLUtils.USER_PRINCIPAL, + UnboundSSLUtils.USER_PASSWORD); + principals.put(UnboundSSLUtils.KRBTGT_PRINCIPAL, "pass"); + principals.put(service1Principal, "pass0"); + principals.put(service1Principal, "pass1"); + principals.put(service1Principal, "pass2"); + principals.put(service2Principal, "pass"); + principals.put(service3Principal, "pass"); + + System.setProperty("java.security.krb5.conf", + UnboundSSLUtils.KRB5_CONF_FILENAME); + + /* + * Start a local KDC instance + * + * Keytab file contains 3 keys (with different KVNO) for service1 + * principal, but password for only one key is the same with the record + * for service1 principal in KDC. + */ + UnboundSSLUtils.startKDC(UnboundSSLUtils.REALM, principals, + UnboundSSLUtils.KTAB_FILENAME, UnboundSSLUtils.KtabMode.APPEND); + + System.setProperty("java.security.auth.login.config", + UnboundSSLUtils.TEST_SRC + UnboundSSLUtils.FS + jaacConfigFile); + System.setProperty("javax.security.auth.useSubjectCredsOnly", "false"); + + // start an SSL server instance + try (SSLEchoServer server = SSLEchoServer.init( + UnboundSSLUtils.TLS_KRB5_FILTER, UnboundSSLUtils.SNI_PATTERN)) { + + UnboundSSLUtils.startServerWithJaas(server, serverJaasConfig); + + // wait for the server is ready + while (!server.isReady()) { + Thread.sleep(UnboundSSLUtils.DELAY); + } + + // run a client + System.out.println("Successful connection is expected"); + SSLClient.init(UnboundSSLUtils.HOST, server.getPort(), + UnboundSSLUtils.TLS_KRB5_FILTER, service1host).connect(); + } + + System.out.println("Test passed"); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/UnboundSSLPrincipalProperty.java Mon Apr 27 21:02:40 2015 +0800 @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015, 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. + */ + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivilegedActionException; +import java.util.HashMap; +import java.util.Map; +import javax.security.auth.login.LoginException; + +/* + * @test + * @bug 8025123 + * @summary Checks if an unbound server uses a service principal + * from sun.security.krb5.principal system property if specified + * @run main/othervm UnboundSSLPrincipalProperty + * unbound.ssl.jaas.conf server_star + * @run main/othervm UnboundSSLPrincipalProperty + * unbound.ssl.jaas.conf server_multiple_principals + */ +public class UnboundSSLPrincipalProperty { + + public static void main(String[] args) throws IOException, + NoSuchAlgorithmException,LoginException, PrivilegedActionException, + InterruptedException { + UnboundSSLPrincipalProperty test = new UnboundSSLPrincipalProperty(); + test.start(args[0], args[1]); + } + + public void start(String jaacConfigFile, String serverJaasConfig) + throws IOException, NoSuchAlgorithmException,LoginException, + PrivilegedActionException, InterruptedException { + + // define principals + String service1host = "service1." + UnboundSSLUtils.HOST; + String service3host = "service3." + UnboundSSLUtils.HOST; + String service1Principal = "host/" + service1host + "@" + + UnboundSSLUtils.REALM; + String service3Principal = "host/" + service3host + + "@" + UnboundSSLUtils.REALM; + + Map<String, String> principals = new HashMap<>(); + principals.put(UnboundSSLUtils.USER_PRINCIPAL, + UnboundSSLUtils.USER_PASSWORD); + principals.put(UnboundSSLUtils.KRBTGT_PRINCIPAL, null); + principals.put(service1Principal, null); + principals.put(service3Principal, null); + + System.setProperty("java.security.krb5.conf", + UnboundSSLUtils.KRB5_CONF_FILENAME); + + // start a local KDC instance + UnboundSSLUtils.startKDC(UnboundSSLUtils.REALM, principals, + UnboundSSLUtils.KTAB_FILENAME, UnboundSSLUtils.KtabMode.APPEND); + + System.setProperty("java.security.auth.login.config", + UnboundSSLUtils.TEST_SRC + UnboundSSLUtils.FS + jaacConfigFile); + System.setProperty("javax.security.auth.useSubjectCredsOnly", "false"); + + // start an SSL server instance + try (final SSLEchoServer server = SSLEchoServer.init( + UnboundSSLUtils.TLS_KRB5_FILTER, UnboundSSLUtils.SNI_PATTERN)) { + + // specify a service principal for the server + System.setProperty("sun.security.krb5.principal", + service3Principal); + + UnboundSSLUtils.startServerWithJaas(server, serverJaasConfig); + + // wait for the server is ready + while (!server.isReady()) { + Thread.sleep(UnboundSSLUtils.DELAY); + } + + int port = server.getPort(); + + // connetion failure is expected + // since service3 principal was specified to use by the server + System.out.println("Connect: SNI hostname = " + service1host + + ", connection failure is expected"); + try { + SSLClient.init(UnboundSSLUtils.HOST, port, + UnboundSSLUtils.TLS_KRB5_FILTER, service1host) + .connect(); + throw new RuntimeException("Test failed: " + + "expected IOException not thrown"); + } catch (IOException e) { + System.out.println("Expected exception: " + e); + } + + System.out.println("Connect: SNI hostname = " + service3host + + ", successful connection is expected"); + SSLClient.init(UnboundSSLUtils.HOST, port, + UnboundSSLUtils.TLS_KRB5_FILTER, service3host).connect(); + } + + System.out.println("Test passed"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/UnboundSSLUtils.java Mon Apr 27 21:02:40 2015 +0800 @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2015, 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. + */ + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import javax.net.ssl.SNIHostName; +import javax.net.ssl.SNIMatcher; +import javax.net.ssl.SNIServerName; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.security.auth.Subject; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; + +/* + * Helper class for unbound krb5 tests. + */ +class UnboundSSLUtils { + + static enum KtabMode { APPEND, EXISTING }; + + static final String KTAB_FILENAME = "krb5.keytab.data"; + static final String HOST = "localhost"; + static final String REALM = "TEST.REALM"; + static final String KRBTGT_PRINCIPAL = "krbtgt/" + REALM; + static final String TEST_SRC = System.getProperty("test.src", "."); + static final String TLS_KRB5_FILTER = "TLS_KRB5"; + static final String USER = "USER"; + static final String USER_PASSWORD = "password"; + static final String FS = System.getProperty("file.separator"); + static final String SNI_PATTERN = ".*"; + static final String USER_PRINCIPAL = USER + "@" + REALM; + static final String KRB5_CONF_FILENAME = "krb5.conf"; + static final int DELAY = 1000; + + static String[] filterStringArray(String[] src, String filter) { + return Arrays.stream(src).filter((item) -> item.startsWith(filter)) + .toArray(size -> new String[size]); + } + + /* + * The method does JAAS login, + * and runs an SSL server in the JAAS context. + */ + static void startServerWithJaas(final SSLEchoServer server, + String config) throws LoginException, PrivilegedActionException { + LoginContext context = new LoginContext(config); + context.login(); + System.out.println("Server: successful authentication"); + Subject.doAs(context.getSubject(), + (PrivilegedExceptionAction<Object>) () -> { + SSLEchoServer.startServer(server); + return null; + }); + } + + /* + * Start a KDC server: + * - create a KDC instance + * - create Kerberos principals + * - save Kerberos configuration + * - save keys to keytab file + * - no pre-auth required + */ + static void startKDC(String realm, Map<String, String> principals, + String ktab, KtabMode mode) { + try { + KDC kdc = KDC.create(realm, HOST, 0, true); + kdc.setOption(KDC.Option.PREAUTH_REQUIRED, Boolean.FALSE); + if (principals != null) { + for (Map.Entry<String, String> entry : principals.entrySet()) { + String name = entry.getKey(); + String password = entry.getValue(); + if (password == null || password.isEmpty()) { + System.out.println("KDC: add a principal '" + name + + "' with a random password"); + kdc.addPrincipalRandKey(name); + } else { + System.out.println("KDC: add a principal '" + name + + "' with '" + password + "' password"); + kdc.addPrincipal(name, password.toCharArray()); + } + } + } + + KDC.saveConfig(KRB5_CONF_FILENAME, kdc); + + if (ktab != null) { + File ktabFile = new File(ktab); + if (mode == KtabMode.APPEND) { + if (ktabFile.exists()) { + System.out.println("KDC: append keys to an exising " + + "keytab file " + ktab); + kdc.appendKtab(ktab); + } else { + System.out.println("KDC: create a new keytab file " + + ktab); + kdc.writeKtab(ktab); + } + } else if (mode == KtabMode.EXISTING) { + System.out.println("KDC: use an existing keytab file " + + ktab); + } else { + throw new RuntimeException("KDC: unsupported keytab mode: " + + mode); + } + } + + System.out.println("KDC: started on " + HOST + ":" + kdc.getPort() + + " with '" + realm + "' realm"); + } catch (Exception e) { + throw new RuntimeException("KDC: unexpected exception", e); + } + } + +} + +class SSLClient { + + private final static byte[][] arrays = { + new byte[] {-1, 0, 2}, + new byte[] {} + }; + + private final SSLSocket socket; + + private SSLClient(SSLSocket socket) { + this.socket = socket; + } + + void connect() throws IOException { + System.out.println("Client: connect to server"); + try (BufferedInputStream bis = new BufferedInputStream( + socket.getInputStream()); + BufferedOutputStream bos = new BufferedOutputStream( + socket.getOutputStream())) { + + for (byte[] bytes : arrays) { + System.out.println("Client: send byte array: " + + Arrays.toString(bytes)); + + bos.write(bytes); + bos.flush(); + + byte[] recieved = new byte[bytes.length]; + int read = bis.read(recieved, 0, bytes.length); + if (read < 0) { + throw new IOException("Client: couldn't read a response"); + } + + System.out.println("Client: recieved byte array: " + + Arrays.toString(recieved)); + + if (!Arrays.equals(bytes, recieved)) { + throw new IOException("Client: sent byte array " + + "is not equal with recieved byte array"); + } + } + socket.getSession().invalidate(); + } finally { + if (!socket.isClosed()) { + socket.close(); + } + } + } + + static SSLClient init(String host, int port, String cipherSuiteFilter, + String sniHostName) throws NoSuchAlgorithmException, IOException { + SSLContext sslContext = SSLContext.getDefault(); + SSLSocketFactory ssf = (SSLSocketFactory) sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) ssf.createSocket(host, port); + SSLParameters params = new SSLParameters(); + + if (cipherSuiteFilter != null) { + String[] cipherSuites = UnboundSSLUtils.filterStringArray( + ssf.getSupportedCipherSuites(), cipherSuiteFilter); + System.out.println("Client: enabled cipher suites: " + + Arrays.toString(cipherSuites)); + params.setCipherSuites(cipherSuites); + } + + if (sniHostName != null) { + System.out.println("Client: set SNI hostname: " + sniHostName); + SNIHostName serverName = new SNIHostName(sniHostName); + List<SNIServerName> serverNames = new ArrayList<>(); + serverNames.add(serverName); + params.setServerNames(serverNames); + } + + socket.setSSLParameters(params); + + return new SSLClient(socket); + } + +} + +class SSLEchoServer implements Runnable, AutoCloseable { + + private final SSLServerSocket ssocket; + private volatile boolean stopped = false; + private volatile boolean ready = false; + + /* + * Starts the server in a separate thread. + */ + static void startServer(SSLEchoServer server) { + Thread serverThread = new Thread(server, "SSL echo server thread"); + serverThread.setDaemon(true); + serverThread.start(); + } + + private SSLEchoServer(SSLServerSocket ssocket) { + this.ssocket = ssocket; + } + + /* + * Main server loop. + */ + @Override + public void run() { + System.out.println("Server: started"); + while (!stopped) { + ready = true; + try (SSLSocket socket = (SSLSocket) ssocket.accept()) { + System.out.println("Server: client connection accepted"); + try ( + BufferedInputStream bis = new BufferedInputStream( + socket.getInputStream()); + BufferedOutputStream bos = new BufferedOutputStream( + socket.getOutputStream()) + ) { + byte[] buffer = new byte[1024]; + int read; + while ((read = bis.read(buffer)) > 0) { + bos.write(buffer, 0, read); + System.out.println("Server: recieved " + read + + " bytes: " + + Arrays.toString(Arrays.copyOf(buffer, read))); + bos.flush(); + } + } + } catch (IOException e) { + if (stopped) { + // stopped == true means that stop() method was called, + // so just ignore the exception, and finish the loop + break; + } + System.out.println("Server: couldn't accept client connection: " + + e); + } + } + System.out.println("Server: finished"); + } + + boolean isReady() { + return ready; + } + + void stop() { + stopped = true; + ready = false; + + // close the server socket to interupt accept() method + try { + if (!ssocket.isClosed()) { + ssocket.close(); + } + } catch (IOException e) { + throw new RuntimeException("Unexpected exception: " + e); + } + } + + @Override + public void close() { + stop(); + } + + int getPort() { + return ssocket.getLocalPort(); + } + + /* + * Creates server instance. + * + * @param cipherSuiteFilter Filter for enabled cipher suites + * @param sniMatcherPattern Pattern for SNI server hame + */ + static SSLEchoServer init(String cipherSuiteFilter, + String sniPattern) throws NoSuchAlgorithmException, IOException { + SSLContext context = SSLContext.getDefault(); + SSLServerSocketFactory ssf = + (SSLServerSocketFactory) context.getServerSocketFactory(); + SSLServerSocket ssocket = + (SSLServerSocket) ssf.createServerSocket(0); + + // specify enabled cipher suites + if (cipherSuiteFilter != null) { + String[] ciphersuites = UnboundSSLUtils.filterStringArray( + ssf.getSupportedCipherSuites(), cipherSuiteFilter); + System.out.println("Server: enabled cipher suites: " + + Arrays.toString(ciphersuites)); + ssocket.setEnabledCipherSuites(ciphersuites); + } + + // specify SNI matcher pattern + if (sniPattern != null) { + System.out.println("Server: set SNI matcher: " + sniPattern); + SNIMatcher matcher = SNIHostName.createSNIMatcher(sniPattern); + List<SNIMatcher> matchers = new ArrayList<>(); + matchers.add(matcher); + SSLParameters params = ssocket.getSSLParameters(); + params.setSNIMatchers(matchers); + ssocket.setSSLParameters(params); + } + + return new SSLEchoServer(ssocket); + } + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/unbound.ssl.jaas.conf Mon Apr 27 21:02:40 2015 +0800 @@ -0,0 +1,40 @@ +com.sun.net.ssl.client { + com.sun.security.auth.module.Krb5LoginModule required + principal="USER@TEST.REALM" + doNotPrompt=true + useKeyTab=true + keyTab="krb5.keytab.data"; +}; + +server_star { + com.sun.security.auth.module.Krb5LoginModule required + principal="*" + isInitiator=false + useKeyTab=true + keyTab="krb5.keytab.data" + storeKey=true; +}; + +server_multiple_principals { + com.sun.security.auth.module.Krb5LoginModule required + principal="host/service1.localhost@TEST.REALM" + isInitiator=false + useKeyTab=true + keyTab="krb5.keytab.data" + storeKey=true; + + com.sun.security.auth.module.Krb5LoginModule required + principal="host/service2.localhost@TEST.REALM" + isInitiator=false + useKeyTab=true + keyTab="krb5.keytab.data" + storeKey=true; + + com.sun.security.auth.module.Krb5LoginModule required + principal="host/service3.localhost@TEST.REALM" + isInitiator=false + useKeyTab=true + keyTab="krb5.keytab.data" + storeKey=true; +}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/unbound.ssl.policy Mon Apr 27 21:02:40 2015 +0800 @@ -0,0 +1,26 @@ +grant { + permission java.util.PropertyPermission "*", "read,write"; + permission java.net.SocketPermission "*:*", "listen,resolve,accept,connect"; + permission java.io.FilePermission "*", "read,write,delete"; + permission java.lang.RuntimePermission "accessDeclaredMembers"; + permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; + permission java.lang.RuntimePermission "accessClassInPackage.*"; + permission javax.security.auth.AuthPermission "doAs"; + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission + "createLoginContext.server_star"; + permission javax.security.auth.AuthPermission + "createLoginContext.server_multiple_principals"; + permission javax.security.auth.AuthPermission "modifyPrincipals"; + permission javax.security.auth.PrivateCredentialPermission "javax.security.auth.kerberos.KeyTab java.security.Principal \"krb5.keytab.data\"", "read"; + + // clients have a permission to use all service principals + permission javax.security.auth.kerberos.ServicePermission "*", "initiate"; + + // server has a service permission + // to accept only service1 and service3 principals + permission javax.security.auth.kerberos.ServicePermission + "host/service1.localhost@TEST.REALM", "accept"; + permission javax.security.auth.kerberos.ServicePermission + "host/service3.localhost@TEST.REALM", "accept"; +};