1 /*
   2  * Copyright (c) 2015, 2016 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 /*
  25  * @test
  26  * @bug 8038089
  27  * @summary TLS optional support for Kerberos cipher suites needs to be re-examined
  28  * @library ../../../../java/security/testlibrary/
  29  * @run main/othervm SSLwithPerms
  30  */
  31 import java.io.*;
  32 import javax.net.ssl.*;
  33 import javax.security.auth.AuthPermission;
  34 import javax.security.auth.kerberos.ServicePermission;
  35 import java.net.SocketPermission;
  36 import java.nio.ByteBuffer;
  37 import java.nio.file.Files;
  38 import java.nio.file.Paths;
  39 import java.security.Principal;
  40 import java.security.Security;
  41 import java.security.SecurityPermission;
  42 import java.util.Collections;
  43 import java.util.Date;
  44 import java.util.List;
  45 import java.util.ArrayList;
  46 import java.util.Locale;
  47 import java.util.PropertyPermission;
  48 
  49 import sun.security.jgss.GSSUtil;
  50 
  51 public class SSLwithPerms {
  52 
  53     static String KRB5_CONF = "krb5.conf";
  54     static String JAAS_CONF = "jaas.conf";
  55     static String REALM = "REALM";
  56     static String KTAB = "ktab";
  57     static String HOST = "host." + REALM.toLowerCase(Locale.US);
  58     static String SERVER = "host/" + HOST;
  59     static String USER = "user";
  60     static char[] PASS = "password".toCharArray();
  61 
  62     public static void main(String[] args) throws Exception {
  63 
  64         Security.setProperty("jdk.tls.disabledAlgorithms", "");
  65         if (args.length == 0) {
  66             KDC kdc = KDC.create(REALM, HOST, 0, true);
  67 
  68             kdc.addPrincipal(USER, PASS);
  69             kdc.addPrincipalRandKey("krbtgt/" + REALM);
  70             kdc.addPrincipalRandKey(SERVER);
  71             KDC.saveConfig(KRB5_CONF, kdc);
  72             kdc.writeKtab(KTAB);
  73 
  74             File f = new File(JAAS_CONF);
  75             FileOutputStream fos = new FileOutputStream(f);
  76             fos.write((
  77                     "ssl {\n" +
  78                             "    com.sun.security.auth.module.Krb5LoginModule required\n" +
  79                             "    principal=\"" + SERVER + "\"\n" +
  80                             "    useKeyTab=true\n" +
  81                             "    keyTab=" + KTAB + "\n" +
  82                             "    isInitiator=false\n" +
  83                             "    storeKey=true;\n};\n"
  84             ).getBytes());
  85             fos.close();
  86 
  87             String hostsFileName = System.getProperty("test.src", ".") + "/TestHosts";
  88 
  89             Proc pc = Proc.create("SSLwithPerms")
  90                     .args("client")
  91                     .inheritIO()
  92                     .prop("java.security.manager", "")
  93                     .prop("java.security.krb5.conf", KRB5_CONF)
  94                     .prop("jdk.net.hosts.file", hostsFileName)
  95                     .prop("javax.net.ssl", "handshake")
  96                     .prop("sun.security.krb5.debug", "true")
  97                     .perm(new SecurityPermission("setProperty.jdk.tls.disabledAlgorithms"))
  98                     .perm(new PropertyPermission("sun.security.krb5.principal", "read"))
  99                     .perm(new FilePermission("port", "read"))
 100                     .perm(new FilePermission(hostsFileName, "read"))
 101                     .perm(new FilePermission(KTAB, "read"))
 102                     .perm(new AuthPermission("modifyPrincipals"))
 103                     .perm(new AuthPermission("modifyPrivateCredentials"))
 104                     .perm(new AuthPermission("doAs"))
 105                     .perm(new SocketPermission("127.0.0.1", "connect"))
 106                     .perm(new ServicePermission("host/host.realm@REALM", "initiate"))
 107                     .start();
 108 
 109             Proc ps = Proc.create("SSLwithPerms")
 110                     .args("server")
 111                     .inheritIO()
 112                     .prop("java.security.manager", "")
 113                     .prop("java.security.krb5.conf", KRB5_CONF)
 114                     .prop("java.security.auth.login.config", JAAS_CONF)
 115                     .prop("jdk.net.hosts.file", hostsFileName)
 116                     .prop("javax.net.ssl", "handshake")
 117                     .prop("sun.security.krb5.debug", "true")
 118                     .perm(new SecurityPermission("setProperty.jdk.tls.disabledAlgorithms"))
 119                     .perm(new AuthPermission("createLoginContext.ssl"))
 120                     .perm(new AuthPermission("doAs"))
 121                     .perm(new FilePermission(hostsFileName, "read"))
 122                     .perm(new FilePermission("port", "write"))
 123                     .perm(new SocketPermission("127.0.0.1", "accept"))
 124                     .perm(new ServicePermission("host/host.realm@REALM", "accept"))
 125                     .start();
 126 
 127             if (pc.waitFor() != 0) {
 128                 throw new Exception();
 129             }
 130             if (ps.waitFor() != 0) {
 131                 throw new Exception();
 132             }
 133         } else if (args[0].equals("client")) {
 134             Context c;
 135             c = Context.fromUserPass(USER, PASS, false);
 136             c.doAs(new JsseClientAction(), null);
 137         } else if (args[0].equals("server")) {
 138             final Context s = Context.fromJAAS("ssl");
 139             s.doAs(new JsseServerAction(), null);
 140         }
 141     }
 142 
 143     private static class JsseClientAction implements Action {
 144         public byte[] run(Context s, byte[] input) throws Exception {
 145             SSLSocketFactory sslsf =
 146                 (SSLSocketFactory) SSLSocketFactory.getDefault();
 147             while (!Files.exists(Paths.get("port"))) {
 148                 Thread.sleep(100);
 149             }
 150             int port = ByteBuffer.allocate(4)
 151                     .put(Files.readAllBytes(Paths.get("port"))).getInt(0);
 152             System.out.println("Connecting " + SERVER + ":" + port);
 153             SSLSocket sslSocket = (SSLSocket) sslsf.createSocket(HOST, port);
 154 
 155             // Enable only a KRB5 cipher suite.
 156             String enabledSuites[] = {"TLS_KRB5_WITH_RC4_128_SHA"};
 157             sslSocket.setEnabledCipherSuites(enabledSuites);
 158 
 159             SSLParameters params = sslSocket.getSSLParameters();
 160             params.setServerNames(Collections.singletonList(new SNIHostName(HOST)));
 161             sslSocket.setSSLParameters(params);
 162 
 163             BufferedReader in = new BufferedReader(new InputStreamReader(
 164                 sslSocket.getInputStream()));
 165             BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
 166                 sslSocket.getOutputStream()));
 167 
 168             String outStr = "Hello There!\n";
 169             out.write(outStr);
 170             out.flush();
 171             System.out.print("Sending " + outStr);
 172 
 173             String inStr = in.readLine();
 174             System.out.println("Received " + inStr);
 175 
 176             String cipherSuiteChosen = sslSocket.getSession().getCipherSuite();
 177             System.out.println("Cipher suite in use: " + cipherSuiteChosen);
 178             Principal self = sslSocket.getSession().getLocalPrincipal();
 179             System.out.println("I am: " + self.toString());
 180             Principal peer = sslSocket.getSession().getPeerPrincipal();
 181             System.out.println("Server is: " + peer.toString());
 182 
 183             sslSocket.close();
 184             return null;
 185         }
 186     }
 187 
 188     private static class JsseServerAction implements Action {
 189         public byte[] run(Context s, byte[] input) throws Exception {
 190             SSLServerSocketFactory sslssf =
 191                 (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
 192             SSLServerSocket sslServerSocket =
 193                 (SSLServerSocket) sslssf.createServerSocket(0); // any port
 194             int port = sslServerSocket.getLocalPort();
 195             System.out.println("Listening on " + port);
 196 
 197             String enabledSuites[] = {"TLS_KRB5_WITH_RC4_128_SHA"};
 198             sslServerSocket.setEnabledCipherSuites(enabledSuites);
 199 
 200             Files.write(Paths.get("port"), ByteBuffer.allocate(4).putInt(port).array());
 201             System.out.println("Waiting for incoming connection...");
 202 
 203             SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
 204 
 205             System.out.println("Got connection from client "
 206                 + sslSocket.getInetAddress());
 207 
 208             BufferedReader in = new BufferedReader(new InputStreamReader(
 209                 sslSocket.getInputStream()));
 210             BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
 211                 sslSocket.getOutputStream()));
 212 
 213             String inStr = in.readLine();
 214             System.out.println("Received " + inStr);
 215 
 216             String outStr = inStr + " " + new Date().toString() + "\n";
 217             out.write(outStr);
 218             System.out.println("Sending " + outStr);
 219             out.flush();
 220 
 221             String cipherSuiteChosen =
 222                 sslSocket.getSession().getCipherSuite();
 223             System.out.println("Cipher suite in use: " + cipherSuiteChosen);
 224             Principal self = sslSocket.getSession().getLocalPrincipal();
 225             System.out.println("I am: " + self.toString());
 226             Principal peer = sslSocket.getSession().getPeerPrincipal();
 227             System.out.println("Client is: " + peer.toString());
 228 
 229             sslSocket.close();
 230             return null;
 231         }
 232     }
 233 }