test/jdk/sun/security/krb5/auto/UnboundSSLUtils.java
changeset 50768 68fa3d4026ea
parent 50767 356eaea05bf0
child 50769 1bf8f9840705
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
     1 /*
       
     2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 import java.io.BufferedInputStream;
       
    25 import java.io.BufferedOutputStream;
       
    26 import java.io.File;
       
    27 import java.io.IOException;
       
    28 import java.security.NoSuchAlgorithmException;
       
    29 import java.security.PrivilegedActionException;
       
    30 import java.security.PrivilegedExceptionAction;
       
    31 import java.util.ArrayList;
       
    32 import java.util.Arrays;
       
    33 import java.util.List;
       
    34 import java.util.Map;
       
    35 import javax.net.ssl.SNIHostName;
       
    36 import javax.net.ssl.SNIMatcher;
       
    37 import javax.net.ssl.SNIServerName;
       
    38 import javax.net.ssl.SSLContext;
       
    39 import javax.net.ssl.SSLParameters;
       
    40 import javax.net.ssl.SSLServerSocket;
       
    41 import javax.net.ssl.SSLServerSocketFactory;
       
    42 import javax.net.ssl.SSLSocket;
       
    43 import javax.net.ssl.SSLSocketFactory;
       
    44 import javax.security.auth.Subject;
       
    45 import javax.security.auth.login.LoginContext;
       
    46 import javax.security.auth.login.LoginException;
       
    47 
       
    48 /*
       
    49  * Helper class for unbound krb5 tests.
       
    50  */
       
    51 class UnboundSSLUtils {
       
    52 
       
    53     static final String KTAB_FILENAME = "krb5.keytab.data";
       
    54     static final String HOST = "localhost";
       
    55     static final String REALM = "TEST.REALM";
       
    56     static final String KRBTGT_PRINCIPAL = "krbtgt/" + REALM;
       
    57     static final String TEST_SRC = System.getProperty("test.src", ".");
       
    58     static final String TLS_KRB5_FILTER = "TLS_KRB5";
       
    59     static final String USER = "USER";
       
    60     static final String USER_PASSWORD = "password";
       
    61     static final String FS = System.getProperty("file.separator");
       
    62     static final String SNI_PATTERN = ".*";
       
    63     static final String USER_PRINCIPAL = USER + "@" + REALM;
       
    64     static final String KRB5_CONF_FILENAME = "krb5.conf";
       
    65     static final int DELAY = 1000;
       
    66 
       
    67    static String[] filterStringArray(String[] src, String filter) {
       
    68         return Arrays.stream(src).filter((item) -> item.startsWith(filter))
       
    69                 .toArray(size -> new String[size]);
       
    70     }
       
    71 
       
    72     /*
       
    73      * The method does JAAS login,
       
    74      * and runs an SSL server in the JAAS context.
       
    75      */
       
    76     static void startServerWithJaas(final SSLEchoServer server,
       
    77             String config) throws LoginException, PrivilegedActionException {
       
    78         LoginContext context = new LoginContext(config);
       
    79         context.login();
       
    80         System.out.println("Server: successful authentication");
       
    81         Subject.doAs(context.getSubject(),
       
    82                 (PrivilegedExceptionAction<Object>) () -> {
       
    83             SSLEchoServer.startServer(server);
       
    84             return null;
       
    85         });
       
    86     }
       
    87 
       
    88 }
       
    89 
       
    90 class SSLClient {
       
    91 
       
    92     private final static byte[][] arrays = {
       
    93         new byte[] {-1, 0, 2},
       
    94         new byte[] {}
       
    95     };
       
    96 
       
    97     private final SSLSocket socket;
       
    98 
       
    99     private SSLClient(SSLSocket socket) {
       
   100         this.socket = socket;
       
   101     }
       
   102 
       
   103     void connect() throws IOException {
       
   104         System.out.println("Client: connect to server");
       
   105         try (BufferedInputStream bis = new BufferedInputStream(
       
   106                         socket.getInputStream());
       
   107                 BufferedOutputStream bos = new BufferedOutputStream(
       
   108                         socket.getOutputStream())) {
       
   109 
       
   110             for (byte[] bytes : arrays) {
       
   111                 System.out.println("Client: send byte array: "
       
   112                         + Arrays.toString(bytes));
       
   113 
       
   114                 bos.write(bytes);
       
   115                 bos.flush();
       
   116 
       
   117                 byte[] recieved = new byte[bytes.length];
       
   118                 int read = bis.read(recieved, 0, bytes.length);
       
   119                 if (read < 0) {
       
   120                     throw new IOException("Client: couldn't read a response");
       
   121                 }
       
   122 
       
   123                 System.out.println("Client: recieved byte array: "
       
   124                         + Arrays.toString(recieved));
       
   125 
       
   126                 if (!Arrays.equals(bytes, recieved)) {
       
   127                     throw new IOException("Client: sent byte array "
       
   128                                 + "is not equal with recieved byte array");
       
   129                 }
       
   130             }
       
   131             socket.getSession().invalidate();
       
   132         } finally {
       
   133             if (!socket.isClosed()) {
       
   134                 socket.close();
       
   135             }
       
   136         }
       
   137     }
       
   138 
       
   139     static SSLClient init(String host, int port, String cipherSuiteFilter,
       
   140             String sniHostName) throws NoSuchAlgorithmException, IOException {
       
   141         SSLContext sslContext = SSLContext.getDefault();
       
   142         SSLSocketFactory ssf = (SSLSocketFactory) sslContext.getSocketFactory();
       
   143         SSLSocket socket = (SSLSocket) ssf.createSocket(host, port);
       
   144         SSLParameters params = new SSLParameters();
       
   145 
       
   146         if (cipherSuiteFilter != null) {
       
   147             String[] cipherSuites = UnboundSSLUtils.filterStringArray(
       
   148                     ssf.getSupportedCipherSuites(), cipherSuiteFilter);
       
   149             System.out.println("Client: enabled cipher suites: "
       
   150                     + Arrays.toString(cipherSuites));
       
   151             params.setCipherSuites(cipherSuites);
       
   152         }
       
   153 
       
   154         if (sniHostName != null) {
       
   155             System.out.println("Client: set SNI hostname: " + sniHostName);
       
   156             SNIHostName serverName = new SNIHostName(sniHostName);
       
   157             List<SNIServerName> serverNames = new ArrayList<>();
       
   158             serverNames.add(serverName);
       
   159             params.setServerNames(serverNames);
       
   160         }
       
   161 
       
   162         socket.setSSLParameters(params);
       
   163 
       
   164         return new SSLClient(socket);
       
   165     }
       
   166 
       
   167 }
       
   168 
       
   169 class SSLEchoServer implements Runnable, AutoCloseable {
       
   170 
       
   171     private final SSLServerSocket ssocket;
       
   172     private volatile boolean stopped = false;
       
   173     private volatile boolean ready = false;
       
   174 
       
   175     /*
       
   176      * Starts the server in a separate thread.
       
   177      */
       
   178     static void startServer(SSLEchoServer server) {
       
   179         Thread serverThread = new Thread(server, "SSL echo server thread");
       
   180         serverThread.setDaemon(true);
       
   181         serverThread.start();
       
   182     }
       
   183 
       
   184     private SSLEchoServer(SSLServerSocket ssocket) {
       
   185         this.ssocket = ssocket;
       
   186     }
       
   187 
       
   188     /*
       
   189      * Main server loop.
       
   190      */
       
   191     @Override
       
   192     public void run() {
       
   193         System.out.println("Server: started");
       
   194         while (!stopped) {
       
   195             ready = true;
       
   196             try (SSLSocket socket = (SSLSocket) ssocket.accept()) {
       
   197                 System.out.println("Server: client connection accepted");
       
   198                 try (
       
   199                     BufferedInputStream bis = new BufferedInputStream(
       
   200                             socket.getInputStream());
       
   201                     BufferedOutputStream bos = new BufferedOutputStream(
       
   202                             socket.getOutputStream())
       
   203                 ) {
       
   204                     byte[] buffer = new byte[1024];
       
   205                     int read;
       
   206                     while ((read = bis.read(buffer)) > 0) {
       
   207                         bos.write(buffer, 0, read);
       
   208                         System.out.println("Server: recieved " + read
       
   209                                 + " bytes: "
       
   210                                 + Arrays.toString(Arrays.copyOf(buffer, read)));
       
   211                         bos.flush();
       
   212                     }
       
   213                 }
       
   214             } catch (IOException e) {
       
   215                 if (stopped) {
       
   216                     // stopped == true means that stop() method was called,
       
   217                     // so just ignore the exception, and finish the loop
       
   218                     break;
       
   219                 }
       
   220                 System.out.println("Server: couldn't accept client connection: "
       
   221                         + e);
       
   222             }
       
   223         }
       
   224         System.out.println("Server: finished");
       
   225     }
       
   226 
       
   227     boolean isReady() {
       
   228         return ready;
       
   229     }
       
   230 
       
   231     void stop() {
       
   232         stopped = true;
       
   233         ready = false;
       
   234 
       
   235         // close the server socket to interupt accept() method
       
   236         try {
       
   237             if (!ssocket.isClosed()) {
       
   238                 ssocket.close();
       
   239             }
       
   240         } catch (IOException e) {
       
   241             throw new RuntimeException("Unexpected exception: " + e);
       
   242         }
       
   243     }
       
   244 
       
   245     @Override
       
   246     public void close() {
       
   247         stop();
       
   248     }
       
   249 
       
   250     int getPort() {
       
   251         return ssocket.getLocalPort();
       
   252     }
       
   253 
       
   254     /*
       
   255      * Creates server instance.
       
   256      *
       
   257      * @param cipherSuiteFilter Filter for enabled cipher suites
       
   258      * @param sniMatcherPattern Pattern for SNI server hame
       
   259      */
       
   260     static SSLEchoServer init(String cipherSuiteFilter,
       
   261             String sniPattern) throws NoSuchAlgorithmException, IOException {
       
   262         SSLContext context = SSLContext.getDefault();
       
   263         SSLServerSocketFactory ssf =
       
   264                 (SSLServerSocketFactory) context.getServerSocketFactory();
       
   265         SSLServerSocket ssocket =
       
   266                 (SSLServerSocket) ssf.createServerSocket(0);
       
   267 
       
   268         // specify enabled cipher suites
       
   269         if (cipherSuiteFilter != null) {
       
   270             String[] ciphersuites = UnboundSSLUtils.filterStringArray(
       
   271                     ssf.getSupportedCipherSuites(), cipherSuiteFilter);
       
   272             System.out.println("Server: enabled cipher suites: "
       
   273                     + Arrays.toString(ciphersuites));
       
   274             ssocket.setEnabledCipherSuites(ciphersuites);
       
   275         }
       
   276 
       
   277         // specify SNI matcher pattern
       
   278         if (sniPattern != null) {
       
   279             System.out.println("Server: set SNI matcher: " + sniPattern);
       
   280             SNIMatcher matcher = SNIHostName.createSNIMatcher(sniPattern);
       
   281             List<SNIMatcher> matchers = new ArrayList<>();
       
   282             matchers.add(matcher);
       
   283             SSLParameters params = ssocket.getSSLParameters();
       
   284             params.setSNIMatchers(matchers);
       
   285             ssocket.setSSLParameters(params);
       
   286         }
       
   287 
       
   288         return new SSLEchoServer(ssocket);
       
   289     }
       
   290 
       
   291 }
       
   292