OpenJDK / portola / portola
changeset 20499:4aa3d51ec41b
8025123: SNI support in Kerberos cipher suites
Reviewed-by: weijun, xuelei
Contributed-by: Artem Smotrakov <artem.smotrakov@oracle.com>
author | xuelei |
---|---|
date | Tue, 01 Oct 2013 20:25:44 -0700 |
parents | 6b1da6741f95 |
children | 44c2cb8a99bb |
files | jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java jdk/src/share/classes/sun/security/ssl/Handshaker.java jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java jdk/test/sun/security/krb5/auto/SSL.java |
diffstat | 5 files changed, 112 insertions(+), 48 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java Fri Sep 27 13:32:32 2013 -0400 +++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java Tue Oct 01 20:25:44 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -92,6 +92,8 @@ private List<SNIServerName> requestedServerNames = Collections.<SNIServerName>emptyList(); + private boolean serverNamesAccepted = false; + /* * Constructors */ @@ -567,7 +569,9 @@ // check extensions for (HelloExtension ext : mesg.extensions.list()) { ExtensionType type = ext.type; - if ((type != ExtensionType.EXT_ELLIPTIC_CURVES) + if (type == ExtensionType.EXT_SERVER_NAME) { + serverNamesAccepted = true; + } else if ((type != ExtensionType.EXT_ELLIPTIC_CURVES) && (type != ExtensionType.EXT_EC_POINT_FORMATS) && (type != ExtensionType.EXT_SERVER_NAME) && (type != ExtensionType.EXT_RENEGOTIATION_INFO)) { @@ -864,15 +868,47 @@ break; case K_KRB5: case K_KRB5_EXPORT: - String hostname = getHostSE(); - if (hostname == null) { - throw new IOException("Hostname is required" + - " to use Kerberos cipher suites"); + String sniHostname = null; + for (SNIServerName serverName : requestedServerNames) { + if (serverName instanceof SNIHostName) { + sniHostname = ((SNIHostName) serverName).getAsciiName(); + break; + } } - KerberosClientKeyExchange kerberosMsg = - new KerberosClientKeyExchange( - hostname, isLoopbackSE(), getAccSE(), protocolVersion, - sslContext.getSecureRandom()); + + KerberosClientKeyExchange kerberosMsg = null; + if (sniHostname != null) { + // use first requested SNI hostname + try { + kerberosMsg = new KerberosClientKeyExchange( + sniHostname, getAccSE(), protocolVersion, + sslContext.getSecureRandom()); + } catch(IOException e) { + if (serverNamesAccepted) { + // server accepted requested SNI hostname, + // so it must be used + throw e; + } + // fallback to using hostname + if (debug != null && Debug.isOn("handshake")) { + System.out.println( + "Warning, cannot use Server Name Indication: " + + e.getMessage()); + } + } + } + + if (kerberosMsg == null) { + String hostname = getHostSE(); + if (hostname == null) { + throw new IOException("Hostname is required" + + " to use Kerberos cipher suites"); + } + kerberosMsg = new KerberosClientKeyExchange( + hostname, getAccSE(), protocolVersion, + sslContext.getSecureRandom()); + } + // Record the principals involved in exchange session.setPeerPrincipal(kerberosMsg.getPeerPrincipal()); session.setLocalPrincipal(kerberosMsg.getLocalPrincipal());
--- a/jdk/src/share/classes/sun/security/ssl/Handshaker.java Fri Sep 27 13:32:32 2013 -0400 +++ b/jdk/src/share/classes/sun/security/ssl/Handshaker.java Tue Oct 01 20:25:44 2013 -0700 @@ -335,14 +335,6 @@ } } - boolean isLoopbackSE() { - if (conn != null) { - return conn.getInetAddress().isLoopbackAddress(); - } else { - return false; - } - } - int getPortSE() { if (conn != null) { return conn.getPort();
--- a/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java Fri Sep 27 13:32:32 2013 -0400 +++ b/jdk/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java Tue Oct 01 20:25:44 2013 -0700 @@ -77,12 +77,12 @@ // please won't check the value of impl variable } - public KerberosClientKeyExchange(String serverName, boolean isLoopback, + public KerberosClientKeyExchange(String serverName, AccessControlContext acc, ProtocolVersion protocolVersion, SecureRandom rand) throws IOException { if (impl != null) { - init(serverName, isLoopback, acc, protocolVersion, rand); + init(serverName, acc, protocolVersion, rand); } else { throw new IllegalStateException("Kerberos is unavailable"); } @@ -120,12 +120,12 @@ impl.print(p); } - public void init(String serverName, boolean isLoopback, + public void init(String serverName, AccessControlContext acc, ProtocolVersion protocolVersion, SecureRandom rand) throws IOException { if (impl != null) { - impl.init(serverName, isLoopback, acc, protocolVersion, rand); + impl.init(serverName, acc, protocolVersion, rand); } }
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Fri Sep 27 13:32:32 2013 -0400 +++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Tue Oct 01 20:25:44 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -105,12 +105,12 @@ * secret */ @Override - public void init(String serverName, boolean isLoopback, + public void init(String serverName, AccessControlContext acc, ProtocolVersion protocolVersion, SecureRandom rand) throws IOException { // Get service ticket - KerberosTicket ticket = getServiceTicket(serverName, isLoopback, acc); + KerberosTicket ticket = getServiceTicket(serverName, acc); encodedTicket = ticket.getEncoded(); // Record the Kerberos principals @@ -292,25 +292,33 @@ } // Similar to sun.security.jgss.krb5.Krb5InitCredenetial/Krb5Context - private static KerberosTicket getServiceTicket(String srvName, - boolean isLoopback, final AccessControlContext acc) throws IOException { + private static KerberosTicket getServiceTicket(String serverName, + final AccessControlContext acc) throws IOException { - // get the local hostname if srvName is loopback address - String serverName = srvName; - if (isLoopback) { + if ("localhost".equals(serverName) || + "localhost.localdomain".equals(serverName)) { + + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Get the local hostname"); + } String localHost = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<String>() { public String run() { - String hostname; try { - hostname = InetAddress.getLocalHost().getHostName(); + return InetAddress.getLocalHost().getHostName(); } catch (java.net.UnknownHostException e) { - hostname = "localhost"; + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Warning," + + " cannot get the local hostname: " + + e.getMessage()); + } + return null; } - return hostname; } }); - serverName = localHost; + if (localHost != null) { + serverName = localHost; + } } // Resolve serverName (possibly in IP addr form) to Kerberos principal
--- a/jdk/test/sun/security/krb5/auto/SSL.java Fri Sep 27 13:32:32 2013 -0400 +++ b/jdk/test/sun/security/krb5/auto/SSL.java Tue Oct 01 20:25:44 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2013, 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 @@ -23,11 +23,12 @@ /* * @test - * @bug 6894643 6913636 8005523 + * @bug 6894643 6913636 8005523 8025123 * @summary Test JSSE Kerberos ciphersuite * @run main/othervm SSL TLS_KRB5_WITH_RC4_128_SHA * @run main/othervm SSL TLS_KRB5_WITH_RC4_128_SHA unbound + * @run main/othervm SSL TLS_KRB5_WITH_RC4_128_SHA unbound sni * @run main/othervm SSL TLS_KRB5_WITH_3DES_EDE_CBC_SHA * @run main/othervm SSL TLS_KRB5_WITH_3DES_EDE_CBC_MD5 * @run main/othervm SSL TLS_KRB5_WITH_DES_CBC_SHA @@ -44,6 +45,9 @@ import javax.net.ssl.*; import java.security.Principal; import java.util.Date; +import java.util.List; +import java.util.ArrayList; +import java.util.Locale; import javax.security.auth.kerberos.ServicePermission; import sun.security.jgss.GSSUtil; import sun.security.krb5.PrincipalName; @@ -56,6 +60,8 @@ private static int loopCount = 0; private static volatile String server; private static volatile int port; + private static String sniHostname = null; + private static String sniMatcherPattern = null; private static String permChecks = ""; @@ -84,11 +90,11 @@ System.setSecurityManager(new SSL()); KDC kdc = KDC.create(OneKDC.REALM); - // Run this after KDC, so our own DNS service can be started - try { - server = InetAddress.getLocalHost().getHostName().toLowerCase(); - } catch (java.net.UnknownHostException e) { - server = "localhost"; + server = "host." + OneKDC.REALM.toLowerCase(Locale.US); + + if (args.length > 2) { + sniHostname = "test." + server; + sniMatcherPattern = ".*"; } kdc.addPrincipal(OneKDC.USER, OneKDC.PASS); @@ -98,15 +104,21 @@ // Add 3 versions of keys into keytab KeyTab ktab = KeyTab.create(OneKDC.KTAB); + String serviceName = null; + if (sniHostname != null) { + serviceName = "host/" + sniHostname; + } else { + serviceName = "host/" + server; + } PrincipalName service = new PrincipalName( - "host/" + server, PrincipalName.KRB_NT_SRV_HST); + serviceName, PrincipalName.KRB_NT_SRV_HST); ktab.addEntry(service, "pass1".toCharArray(), 1, true); ktab.addEntry(service, "pass2".toCharArray(), 2, true); ktab.addEntry(service, "pass3".toCharArray(), 3, true); ktab.save(); // and use the middle one as the real key - kdc.addPrincipal("host/" + server, "pass2".toCharArray()); + kdc.addPrincipal(serviceName, "pass2".toCharArray()); // JAAS config entry name ssl @@ -118,7 +130,7 @@ " com.sun.security.auth.module.Krb5LoginModule required\n" + (unbound ? " principal=*\n" : - " principal=\"host/" + server + "\"\n") + + " principal=\"" + serviceName + "\"\n") + " useKeyTab=true\n" + " keyTab=" + OneKDC.KTAB + "\n" + " isInitiator=false\n" + @@ -153,7 +165,7 @@ } c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); - c.startAsClient("host/" + server, GSSUtil.GSS_KRB5_MECH_OID); + c.startAsClient(serviceName, GSSUtil.GSS_KRB5_MECH_OID); c.doAs(new JsseClientAction(), null); // Add another version of key, make sure it can be loaded @@ -161,10 +173,10 @@ ktab = KeyTab.getInstance(OneKDC.KTAB); ktab.addEntry(service, "pass4".toCharArray(), 4, true); ktab.save(); - kdc.addPrincipal("host/" + server, "pass4".toCharArray()); + kdc.addPrincipal(serviceName, "pass4".toCharArray()); c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); - c.startAsClient("host/" + server, GSSUtil.GSS_KRB5_MECH_OID); + c.startAsClient(serviceName, GSSUtil.GSS_KRB5_MECH_OID); c.doAs(new JsseClientAction(), null); // Permission checking check. Please note this is highly @@ -199,6 +211,14 @@ sslSocket.setEnabledCipherSuites(enabledSuites); // Should check for exception if enabledSuites is not supported + if (sniHostname != null) { + List<SNIServerName> serverNames = new ArrayList<>(); + serverNames.add(new SNIHostName(sniHostname)); + SSLParameters params = sslSocket.getSSLParameters(); + params.setServerNames(serverNames); + sslSocket.setSSLParameters(params); + } + BufferedReader in = new BufferedReader(new InputStreamReader( sslSocket.getInputStream())); BufferedWriter out = new BufferedWriter(new OutputStreamWriter( @@ -242,6 +262,14 @@ sslServerSocket.setEnabledCipherSuites(enabledSuites); // Should check for exception if enabledSuites is not supported + if (sniMatcherPattern != null) { + List<SNIMatcher> matchers = new ArrayList<>(); + matchers.add(SNIHostName.createSNIMatcher(sniMatcherPattern)); + SSLParameters params = sslServerSocket.getSSLParameters(); + params.setSNIMatchers(matchers); + sslServerSocket.setSSLParameters(params); + } + while (loopCount++ < LOOP_LIMIT) { System.out.println("Waiting for incoming connection...");