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 }