aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2016-01-15 14:01:49 -0800
committerKenny Root <kroot@google.com>2016-01-27 18:56:02 -0800
commitb96141a0e46ce6e769c70565bec7ec3fdd58d717 (patch)
tree7cd90e678bab92c180a1447132fb2aca001bf1ae
parent8f4a37e63502377157364117c644bc304883bb49 (diff)
downloadlibcore-b96141a0e46ce6e769c70565bec7ec3fdd58d717.tar.gz
Add SNI support to TLS sockets
Pull in changes that relate to SNI on TLS sockets. Change-Id: I23b85308ac25fd00307d37cff1d93ee6c2bfba98
-rw-r--r--luni/src/test/java/libcore/javax/net/ssl/SSLParametersTest.java91
-rw-r--r--luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java44
-rwxr-xr-xojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java32
-rw-r--r--ojluni/src/main/java/javax/net/ssl/SNIHostName.java396
-rw-r--r--ojluni/src/main/java/javax/net/ssl/SNIMatcher.java105
-rw-r--r--ojluni/src/main/java/javax/net/ssl/SNIServerName.java212
-rwxr-xr-xojluni/src/main/java/javax/net/ssl/SSLParameters.java191
-rw-r--r--ojluni/src/main/java/javax/net/ssl/StandardConstants.java56
-rw-r--r--openjdk_java_files.mk4
9 files changed, 1126 insertions, 5 deletions
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLParametersTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLParametersTest.java
index 46d0b416200..03d697e5209 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLParametersTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLParametersTest.java
@@ -16,7 +16,13 @@
package libcore.javax.net.ssl;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.SNIMatcher;
+import javax.net.ssl.SNIServerName;
import javax.net.ssl.SSLParameters;
import junit.framework.TestCase;
@@ -105,4 +111,89 @@ public class SSLParametersTest extends TestCase {
assertTrue(p.getWantClientAuth());
assertFalse(p.getNeedClientAuth());
}
+
+ public void test_SSLParameters_setServerNames_duplicatedNameThrows() throws Exception {
+ SSLParameters p = new SSLParameters();
+ ArrayList<SNIServerName> dupeNames = new ArrayList<SNIServerName>();
+ dupeNames.add((SNIServerName) new SNIHostName("www.example.com"));
+ dupeNames.add((SNIServerName) new SNIHostName("www.example.com"));
+ try {
+ p.setServerNames(dupeNames);
+ fail("Should throw IllegalArgumentException when names are duplicated");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void test_SSLParameters_setServerNames_setNull_getNull() throws Exception {
+ SSLParameters p = new SSLParameters();
+ p.setServerNames(Collections.singletonList(
+ (SNIServerName) new SNIHostName("www.example.com")));
+ assertNotNull(p.getServerNames());
+ p.setServerNames(null);
+ assertNull(p.getServerNames());
+ }
+
+ public void test_SSLParameters_setServerNames_setEmpty_getEmpty() throws Exception {
+ SSLParameters p = new SSLParameters();
+ p.setServerNames(new ArrayList<SNIServerName>());
+ Collection<SNIServerName> actual = p.getServerNames();
+ assertNotNull(actual);
+ assertEquals(0, actual.size());
+ }
+
+ public void test_SSLParameters_getServerNames_unmodifiable() throws Exception {
+ SSLParameters p = new SSLParameters();
+ p.setServerNames(Collections.singletonList(
+ (SNIServerName) new SNIHostName("www.example.com")));
+ Collection<SNIServerName> actual = p.getServerNames();
+ try {
+ actual.add((SNIServerName) new SNIHostName("www.foo.com"));
+ fail("Should not allow modifications to the list");
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
+
+ public void test_SSLParameters_setSNIMatchers_duplicatedNameThrows() throws Exception {
+ SSLParameters p = new SSLParameters();
+ ArrayList<SNIMatcher> dupeMatchers = new ArrayList<SNIMatcher>();
+ dupeMatchers.add(SNIHostName.createSNIMatcher("www\\.example\\.com"));
+ dupeMatchers.add(SNIHostName.createSNIMatcher("www\\.example\\.com"));
+ try {
+ p.setSNIMatchers(dupeMatchers);
+ fail("Should throw IllegalArgumentException when matchers are duplicated");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void test_SSLParameters_setSNIMatchers_setNull_getNull() throws Exception {
+ SSLParameters p = new SSLParameters();
+ p.setSNIMatchers(Collections.singletonList(
+ SNIHostName.createSNIMatcher("www\\.example\\.com")));
+ assertNotNull(p.getSNIMatchers());
+ p.setSNIMatchers(null);
+ assertNull(p.getSNIMatchers());
+ }
+
+ public void test_SSLParameters_setSNIMatchers_setEmpty_getEmpty() throws Exception {
+ SSLParameters p = new SSLParameters();
+ p.setSNIMatchers(Collections.singletonList(
+ SNIHostName.createSNIMatcher("www\\.example\\.com")));
+ assertEquals(1, p.getSNIMatchers().size());
+ p.setSNIMatchers(Collections.<SNIMatcher>emptyList());
+ Collection<SNIMatcher> actual = p.getSNIMatchers();
+ assertNotNull(actual);
+ assertEquals(0, actual.size());
+ }
+
+ public void test_SSLParameters_getSNIMatchers_unmodifiable() throws Exception {
+ SSLParameters p = new SSLParameters();
+ p.setSNIMatchers(Collections.singletonList(
+ SNIHostName.createSNIMatcher("www\\.example\\.com")));
+ Collection<SNIMatcher> actual = p.getSNIMatchers();
+ try {
+ actual.add(SNIHostName.createSNIMatcher("www\\.google\\.com"));
+ fail("Should not allow modification of list");
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
index e29e503d363..278d44e3787 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -39,6 +39,7 @@ import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@@ -50,9 +51,13 @@ import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
+import javax.net.ssl.ExtendedSSLSession;
import javax.net.ssl.HandshakeCompletedEvent;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.KeyManager;
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.SNIMatcher;
+import javax.net.ssl.SNIServerName;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
@@ -1772,6 +1777,45 @@ public class SSLSocketTest extends TestCase {
}
}
+ public void test_SSLSocket_SNIHostName() throws Exception {
+ TestSSLContext c = TestSSLContext.create();
+
+ final SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
+ SSLParameters clientParams = client.getSSLParameters();
+ clientParams.setServerNames(Collections.singletonList(
+ (SNIServerName) new SNIHostName("www.example.com")));
+ client.setSSLParameters(clientParams);
+
+ SSLParameters serverParams = c.serverSocket.getSSLParameters();
+ serverParams.setSNIMatchers(Collections.singletonList(
+ SNIHostName.createSNIMatcher("www\\.example\\.com")));
+ c.serverSocket.setSSLParameters(serverParams);
+
+ client.connect(new InetSocketAddress(c.host, c.port));
+ final SSLSocket server = (SSLSocket) c.serverSocket.accept();
+
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Future<Void> future = executor.submit(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ client.startHandshake();
+ return null;
+ }
+ });
+ executor.shutdown();
+ server.startHandshake();
+
+ SSLSession serverSession = server.getSession();
+ assert(serverSession instanceof ExtendedSSLSession);
+ ExtendedSSLSession extendedServerSession = (ExtendedSSLSession) serverSession;
+ List<SNIServerName> requestedNames = extendedServerSession.getRequestedServerNames();
+ assertNotNull(requestedNames);
+ assertEquals(1, requestedNames.size());
+ SNIServerName serverName = requestedNames.get(0);
+ assertTrue(serverName instanceof SNIHostName);
+ SNIHostName serverHostName = (SNIHostName) serverName;
+ assertEquals("www.example.com", serverHostName.getAsciiName());
+ }
+
public void test_SSLSocket_sendsTlsFallbackScsv_Fallback_Success() throws Exception {
TestSSLContext context = TestSSLContext.create();
diff --git a/ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java b/ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java
index 8afd963458d..70f98ce221d 100755
--- a/ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java
+++ b/ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java
@@ -25,6 +25,8 @@
package javax.net.ssl;
+import java.util.List;
+
/**
* Extends the <code>SSLSession</code> interface to support additional
* session attributes.
@@ -83,4 +85,34 @@ public abstract class ExtendedSSLSession implements SSLSession {
* @see X509ExtendedKeyManager
*/
public abstract String[] getPeerSupportedSignatureAlgorithms();
+
+ /**
+ * Obtains a {@link List} containing all {@link SNIServerName}s
+ * of the requested Server Name Indication (SNI) extension.
+ * <P>
+ * In server mode, unless the return {@link List} is empty,
+ * the server should use the requested server names to guide its
+ * selection of an appropriate authentication certificate, and/or
+ * other aspects of security policy.
+ * <P>
+ * In client mode, unless the return {@link List} is empty,
+ * the client should use the requested server names to guide its
+ * endpoint identification of the peer's identity, and/or
+ * other aspects of security policy.
+ *
+ * @return a non-null immutable list of {@link SNIServerName}s of the
+ * requested server name indications. The returned list may be
+ * empty if no server name indications were requested.
+ * @throws UnsupportedOperationException if the underlying provider
+ * does not implement the operation
+ *
+ * @see SNIServerName
+ * @see X509ExtendedTrustManager
+ * @see X509ExtendedKeyManager
+ *
+ * @since 1.8
+ */
+ public List<SNIServerName> getRequestedServerNames() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/ojluni/src/main/java/javax/net/ssl/SNIHostName.java b/ojluni/src/main/java/javax/net/ssl/SNIHostName.java
new file mode 100644
index 00000000000..d5e71414497
--- /dev/null
+++ b/ojluni/src/main/java/javax/net/ssl/SNIHostName.java
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package javax.net.ssl;
+
+import java.net.IDN;
+import java.nio.ByteBuffer;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharacterCodingException;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+/**
+ * Instances of this class represent a server name of type
+ * {@link StandardConstants#SNI_HOST_NAME host_name} in a Server Name
+ * Indication (SNI) extension.
+ * <P>
+ * As described in section 3, "Server Name Indication", of
+ * <A HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions (RFC 6066)</A>,
+ * "HostName" contains the fully qualified DNS hostname of the server, as
+ * understood by the client. The encoded server name value of a hostname is
+ * represented as a byte string using ASCII encoding without a trailing dot.
+ * This allows the support of Internationalized Domain Names (IDN) through
+ * the use of A-labels (the ASCII-Compatible Encoding (ACE) form of a valid
+ * string of Internationalized Domain Names for Applications (IDNA)) defined
+ * in <A HREF="http://www.ietf.org/rfc/rfc5890.txt">RFC 5890</A>.
+ * <P>
+ * Note that {@code SNIHostName} objects are immutable.
+ *
+ * @see SNIServerName
+ * @see StandardConstants#SNI_HOST_NAME
+ *
+ * @since 1.8
+ */
+public final class SNIHostName extends SNIServerName {
+
+ // the decoded string value of the server name
+ private final String hostname;
+
+ /**
+ * Creates an {@code SNIHostName} using the specified hostname.
+ * <P>
+ * Note that per <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>,
+ * the encoded server name value of a hostname is
+ * {@link StandardCharsets#US_ASCII}-compliant. In this method,
+ * {@code hostname} can be a user-friendly Internationalized Domain Name
+ * (IDN). {@link IDN#toASCII(String, int)} is used to enforce the
+ * restrictions on ASCII characters in hostnames (see
+ * <A HREF="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</A>,
+ * <A HREF="http://www.ietf.org/rfc/rfc1122.txt">RFC 1122</A>,
+ * <A HREF="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</A>) and
+ * translate the {@code hostname} into ASCII Compatible Encoding (ACE), as:
+ * <pre>
+ * IDN.toASCII(hostname, IDN.USE_STD3_ASCII_RULES);
+ * </pre>
+ * <P>
+ * The {@code hostname} argument is illegal if it:
+ * <ul>
+ * <li> {@code hostname} is empty,</li>
+ * <li> {@code hostname} ends with a trailing dot,</li>
+ * <li> {@code hostname} is not a valid Internationalized
+ * Domain Name (IDN) compliant with the RFC 3490 specification.</li>
+ * </ul>
+ * @param hostname
+ * the hostname of this server name
+ *
+ * @throws NullPointerException if {@code hostname} is {@code null}
+ * @throws IllegalArgumentException if {@code hostname} is illegal
+ */
+ public SNIHostName(String hostname) {
+ // IllegalArgumentException will be thrown if {@code hostname} is
+ // not a valid IDN.
+ super(StandardConstants.SNI_HOST_NAME,
+ (hostname = IDN.toASCII(
+ Objects.requireNonNull(hostname,
+ "Server name value of host_name cannot be null"),
+ IDN.USE_STD3_ASCII_RULES))
+ .getBytes(StandardCharsets.US_ASCII));
+
+ this.hostname = hostname;
+
+ // check the validity of the string hostname
+ checkHostName();
+ }
+
+ /**
+ * Creates an {@code SNIHostName} using the specified encoded value.
+ * <P>
+ * This method is normally used to parse the encoded name value in a
+ * requested SNI extension.
+ * <P>
+ * Per <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>,
+ * the encoded name value of a hostname is
+ * {@link StandardCharsets#US_ASCII}-compliant. However, in the previous
+ * version of the SNI extension (
+ * <A HREF="http://www.ietf.org/rfc/rfc4366.txt">RFC 4366</A>),
+ * the encoded hostname is represented as a byte string using UTF-8
+ * encoding. For the purpose of version tolerance, this method allows
+ * that the charset of {@code encoded} argument can be
+ * {@link StandardCharsets#UTF_8}, as well as
+ * {@link StandardCharsets#US_ASCII}. {@link IDN#toASCII(String)} is used
+ * to translate the {@code encoded} argument into ASCII Compatible
+ * Encoding (ACE) hostname.
+ * <P>
+ * It is strongly recommended that this constructor is only used to parse
+ * the encoded name value in a requested SNI extension. Otherwise, to
+ * comply with <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>,
+ * please always use {@link StandardCharsets#US_ASCII}-compliant charset
+ * and enforce the restrictions on ASCII characters in hostnames (see
+ * <A HREF="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</A>,
+ * <A HREF="http://www.ietf.org/rfc/rfc1122.txt">RFC 1122</A>,
+ * <A HREF="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</A>)
+ * for {@code encoded} argument, or use
+ * {@link SNIHostName#SNIHostName(String)} instead.
+ * <P>
+ * The {@code encoded} argument is illegal if it:
+ * <ul>
+ * <li> {@code encoded} is empty,</li>
+ * <li> {@code encoded} ends with a trailing dot,</li>
+ * <li> {@code encoded} is not encoded in
+ * {@link StandardCharsets#US_ASCII} or
+ * {@link StandardCharsets#UTF_8}-compliant charset,</li>
+ * <li> {@code encoded} is not a valid Internationalized
+ * Domain Name (IDN) compliant with the RFC 3490 specification.</li>
+ * </ul>
+ *
+ * <P>
+ * Note that the {@code encoded} byte array is cloned
+ * to protect against subsequent modification.
+ *
+ * @param encoded
+ * the encoded hostname of this server name
+ *
+ * @throws NullPointerException if {@code encoded} is {@code null}
+ * @throws IllegalArgumentException if {@code encoded} is illegal
+ */
+ public SNIHostName(byte[] encoded) {
+ // NullPointerException will be thrown if {@code encoded} is null
+ super(StandardConstants.SNI_HOST_NAME, encoded);
+
+ // Compliance: RFC 4366 requires that the hostname is represented
+ // as a byte string using UTF_8 encoding [UTF8]
+ try {
+ // Please don't use {@link String} constructors because they
+ // do not report coding errors.
+ CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder()
+ .onMalformedInput(CodingErrorAction.REPORT)
+ .onUnmappableCharacter(CodingErrorAction.REPORT);
+
+ this.hostname = IDN.toASCII(
+ decoder.decode(ByteBuffer.wrap(encoded)).toString());
+ } catch (RuntimeException | CharacterCodingException e) {
+ throw new IllegalArgumentException(
+ "The encoded server name value is invalid", e);
+ }
+
+ // check the validity of the string hostname
+ checkHostName();
+ }
+
+ /**
+ * Returns the {@link StandardCharsets#US_ASCII}-compliant hostname of
+ * this {@code SNIHostName} object.
+ * <P>
+ * Note that, per
+ * <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>, the
+ * returned hostname may be an internationalized domain name that
+ * contains A-labels. See
+ * <A HREF="http://www.ietf.org/rfc/rfc5890.txt">RFC 5890</A>
+ * for more information about the detailed A-label specification.
+ *
+ * @return the {@link StandardCharsets#US_ASCII}-compliant hostname
+ * of this {@code SNIHostName} object
+ */
+ public String getAsciiName() {
+ return hostname;
+ }
+
+ /**
+ * Compares this server name to the specified object.
+ * <P>
+ * Per <A HREF="http://www.ietf.org/rfc/rfc6066.txt">RFC 6066</A>, DNS
+ * hostnames are case-insensitive. Two server hostnames are equal if,
+ * and only if, they have the same name type, and the hostnames are
+ * equal in a case-independent comparison.
+ *
+ * @param other
+ * the other server name object to compare with.
+ * @return true if, and only if, the {@code other} is considered
+ * equal to this instance
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other instanceof SNIHostName) {
+ return hostname.equalsIgnoreCase(((SNIHostName)other).hostname);
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for this {@code SNIHostName}.
+ * <P>
+ * The hash code value is generated using the case-insensitive hostname
+ * of this {@code SNIHostName}.
+ *
+ * @return a hash code value for this {@code SNIHostName}.
+ */
+ @Override
+ public int hashCode() {
+ int result = 17; // 17/31: prime number to decrease collisions
+ result = 31 * result + hostname.toUpperCase(Locale.ENGLISH).hashCode();
+
+ return result;
+ }
+
+ /**
+ * Returns a string representation of the object, including the DNS
+ * hostname in this {@code SNIHostName} object.
+ * <P>
+ * The exact details of the representation are unspecified and subject
+ * to change, but the following may be regarded as typical:
+ * <pre>
+ * "type=host_name (0), value={@literal <hostname>}"
+ * </pre>
+ * The "{@literal <hostname>}" is an ASCII representation of the hostname,
+ * which may contains A-labels. For example, a returned value of an pseudo
+ * hostname may look like:
+ * <pre>
+ * "type=host_name (0), value=www.example.com"
+ * </pre>
+ * or
+ * <pre>
+ * "type=host_name (0), value=xn--fsqu00a.xn--0zwm56d"
+ * </pre>
+ * <P>
+ * Please NOTE that the exact details of the representation are unspecified
+ * and subject to change.
+ *
+ * @return a string representation of the object.
+ */
+ @Override
+ public String toString() {
+ return "type=host_name (0), value=" + hostname;
+ }
+
+ /**
+ * Creates an {@link SNIMatcher} object for {@code SNIHostName}s.
+ * <P>
+ * This method can be used by a server to verify the acceptable
+ * {@code SNIHostName}s. For example,
+ * <pre>
+ * SNIMatcher matcher =
+ * SNIHostName.createSNIMatcher("www\\.example\\.com");
+ * </pre>
+ * will accept the hostname "www.example.com".
+ * <pre>
+ * SNIMatcher matcher =
+ * SNIHostName.createSNIMatcher("www\\.example\\.(com|org)");
+ * </pre>
+ * will accept hostnames "www.example.com" and "www.example.org".
+ *
+ * @param regex
+ * the <a href="{@docRoot}/java/util/regex/Pattern.html#sum">
+ * regular expression pattern</a>
+ * representing the hostname(s) to match
+ * @return a {@code SNIMatcher} object for {@code SNIHostName}s
+ * @throws NullPointerException if {@code regex} is
+ * {@code null}
+ * @throws java.util.regex.PatternSyntaxException if the regular expression's
+ * syntax is invalid
+ */
+ public static SNIMatcher createSNIMatcher(String regex) {
+ if (regex == null) {
+ throw new NullPointerException(
+ "The regular expression cannot be null");
+ }
+
+ return new SNIHostNameMatcher(regex);
+ }
+
+ // check the validity of the string hostname
+ private void checkHostName() {
+ if (hostname.isEmpty()) {
+ throw new IllegalArgumentException(
+ "Server name value of host_name cannot be empty");
+ }
+
+ if (hostname.endsWith(".")) {
+ throw new IllegalArgumentException(
+ "Server name value of host_name cannot have the trailing dot");
+ }
+ }
+
+ private final static class SNIHostNameMatcher extends SNIMatcher {
+
+ // the compiled representation of a regular expression.
+ private final Pattern pattern;
+
+ /**
+ * Creates an SNIHostNameMatcher object.
+ *
+ * @param regex
+ * the <a href="{@docRoot}/java/util/regex/Pattern.html#sum">
+ * regular expression pattern</a>
+ * representing the hostname(s) to match
+ * @throws NullPointerException if {@code regex} is
+ * {@code null}
+ * @throws PatternSyntaxException if the regular expression's syntax
+ * is invalid
+ */
+ SNIHostNameMatcher(String regex) {
+ super(StandardConstants.SNI_HOST_NAME);
+ pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
+ }
+
+ /**
+ * Attempts to match the given {@link SNIServerName}.
+ *
+ * @param serverName
+ * the {@link SNIServerName} instance on which this matcher
+ * performs match operations
+ *
+ * @return {@code true} if, and only if, the matcher matches the
+ * given {@code serverName}
+ *
+ * @throws NullPointerException if {@code serverName} is {@code null}
+ * @throws IllegalArgumentException if {@code serverName} is
+ * not of {@code StandardConstants#SNI_HOST_NAME} type
+ *
+ * @see SNIServerName
+ */
+ @Override
+ public boolean matches(SNIServerName serverName) {
+ if (serverName == null) {
+ throw new NullPointerException(
+ "The SNIServerName argument cannot be null");
+ }
+
+ SNIHostName hostname;
+ if (!(serverName instanceof SNIHostName)) {
+ if (serverName.getType() != StandardConstants.SNI_HOST_NAME) {
+ throw new IllegalArgumentException(
+ "The server name type is not host_name");
+ }
+
+ try {
+ hostname = new SNIHostName(serverName.getEncoded());
+ } catch (NullPointerException | IllegalArgumentException e) {
+ return false;
+ }
+ } else {
+ hostname = (SNIHostName)serverName;
+ }
+
+ // Let's first try the ascii name matching
+ String asciiName = hostname.getAsciiName();
+ if (pattern.matcher(asciiName).matches()) {
+ return true;
+ }
+
+ // May be an internationalized domain name, check the Unicode
+ // representations.
+ return pattern.matcher(IDN.toUnicode(asciiName)).matches();
+ }
+ }
+}
diff --git a/ojluni/src/main/java/javax/net/ssl/SNIMatcher.java b/ojluni/src/main/java/javax/net/ssl/SNIMatcher.java
new file mode 100644
index 00000000000..a6c9ab92ee2
--- /dev/null
+++ b/ojluni/src/main/java/javax/net/ssl/SNIMatcher.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package javax.net.ssl;
+
+/**
+ * Instances of this class represent a matcher that performs match
+ * operations on an {@link SNIServerName} instance.
+ * <P>
+ * Servers can use Server Name Indication (SNI) information to decide if
+ * specific {@link SSLSocket} or {@link SSLEngine} instances should accept
+ * a connection. For example, when multiple "virtual" or "name-based"
+ * servers are hosted on a single underlying network address, the server
+ * application can use SNI information to determine whether this server is
+ * the exact server that the client wants to access. Instances of this
+ * class can be used by a server to verify the acceptable server names of
+ * a particular type, such as host names.
+ * <P>
+ * {@code SNIMatcher} objects are immutable. Subclasses should not provide
+ * methods that can change the state of an instance once it has been created.
+ *
+ * @see SNIServerName
+ * @see SNIHostName
+ * @see SSLParameters#getSNIMatchers()
+ * @see SSLParameters#setSNIMatchers(Collection)
+ *
+ * @since 1.8
+ */
+public abstract class SNIMatcher {
+
+ // the type of the server name that this matcher performs on
+ private final int type;
+
+ /**
+ * Creates an {@code SNIMatcher} using the specified server name type.
+ *
+ * @param type
+ * the type of the server name that this matcher performs on
+ *
+ * @throws IllegalArgumentException if {@code type} is not in the range
+ * of 0 to 255, inclusive.
+ */
+ protected SNIMatcher(int type) {
+ if (type < 0) {
+ throw new IllegalArgumentException(
+ "Server name type cannot be less than zero");
+ } else if (type > 255) {
+ throw new IllegalArgumentException(
+ "Server name type cannot be greater than 255");
+ }
+
+ this.type = type;
+ }
+
+ /**
+ * Returns the server name type of this {@code SNIMatcher} object.
+ *
+ * @return the server name type of this {@code SNIMatcher} object.
+ *
+ * @see SNIServerName
+ */
+ public final int getType() {
+ return type;
+ }
+
+ /**
+ * Attempts to match the given {@link SNIServerName}.
+ *
+ * @param serverName
+ * the {@link SNIServerName} instance on which this matcher
+ * performs match operations
+ *
+ * @return {@code true} if, and only if, the matcher matches the
+ * given {@code serverName}
+ *
+ * @throws NullPointerException if {@code serverName} is {@code null}
+ * @throws IllegalArgumentException if {@code serverName} is
+ * not of the given server name type of this matcher
+ *
+ * @see SNIServerName
+ */
+ public abstract boolean matches(SNIServerName serverName);
+}
diff --git a/ojluni/src/main/java/javax/net/ssl/SNIServerName.java b/ojluni/src/main/java/javax/net/ssl/SNIServerName.java
new file mode 100644
index 00000000000..c5bb2536670
--- /dev/null
+++ b/ojluni/src/main/java/javax/net/ssl/SNIServerName.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2012, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package javax.net.ssl;
+
+import java.util.Arrays;
+
+/**
+ * Instances of this class represent a server name in a Server Name
+ * Indication (SNI) extension.
+ * <P>
+ * The SNI extension is a feature that extends the SSL/TLS protocols to
+ * indicate what server name the client is attempting to connect to during
+ * handshaking. See section 3, "Server Name Indication", of <A
+ * HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions (RFC 6066)</A>.
+ * <P>
+ * {@code SNIServerName} objects are immutable. Subclasses should not provide
+ * methods that can change the state of an instance once it has been created.
+ *
+ * @see SSLParameters#getServerNames()
+ * @see SSLParameters#setServerNames(List)
+ *
+ * @since 1.8
+ */
+public abstract class SNIServerName {
+
+ // the type of the server name
+ private final int type;
+
+ // the encoded value of the server name
+ private final byte[] encoded;
+
+ // the hex digitals
+ private static final char[] HEXES = "0123456789ABCDEF".toCharArray();
+
+ /**
+ * Creates an {@code SNIServerName} using the specified name type and
+ * encoded value.
+ * <P>
+ * Note that the {@code encoded} byte array is cloned to protect against
+ * subsequent modification.
+ *
+ * @param type
+ * the type of the server name
+ * @param encoded
+ * the encoded value of the server name
+ *
+ * @throws IllegalArgumentException if {@code type} is not in the range
+ * of 0 to 255, inclusive.
+ * @throws NullPointerException if {@code encoded} is null
+ */
+ protected SNIServerName(int type, byte[] encoded) {
+ if (type < 0) {
+ throw new IllegalArgumentException(
+ "Server name type cannot be less than zero");
+ } else if (type > 255) {
+ throw new IllegalArgumentException(
+ "Server name type cannot be greater than 255");
+ }
+ this.type = type;
+
+ if (encoded == null) {
+ throw new NullPointerException(
+ "Server name encoded value cannot be null");
+ }
+ this.encoded = encoded.clone();
+ }
+
+
+ /**
+ * Returns the name type of this server name.
+ *
+ * @return the name type of this server name
+ */
+ public final int getType() {
+ return type;
+ }
+
+ /**
+ * Returns a copy of the encoded server name value of this server name.
+ *
+ * @return a copy of the encoded server name value of this server name
+ */
+ public final byte[] getEncoded() {
+ return encoded.clone();
+ }
+
+ /**
+ * Indicates whether some other object is "equal to" this server name.
+ *
+ * @return true if, and only if, {@code other} is of the same class
+ * of this object, and has the same name type and
+ * encoded value as this server name.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (this.getClass() != other.getClass()) {
+ return false;
+ }
+
+ SNIServerName that = (SNIServerName)other;
+ return (this.type == that.type) &&
+ Arrays.equals(this.encoded, that.encoded);
+ }
+
+ /**
+ * Returns a hash code value for this server name.
+ * <P>
+ * The hash code value is generated using the name type and encoded
+ * value of this server name.
+ *
+ * @return a hash code value for this server name.
+ */
+ @Override
+ public int hashCode() {
+ int result = 17; // 17/31: prime number to decrease collisions
+ result = 31 * result + type;
+ result = 31 * result + Arrays.hashCode(encoded);
+
+ return result;
+ }
+
+ /**
+ * Returns a string representation of this server name, including the server
+ * name type and the encoded server name value in this
+ * {@code SNIServerName} object.
+ * <P>
+ * The exact details of the representation are unspecified and subject
+ * to change, but the following may be regarded as typical:
+ * <pre>
+ * "type={@literal <name type>}, value={@literal <name value>}"
+ * </pre>
+ * <P>
+ * In this class, the format of "{@literal <name type>}" is
+ * "[LITERAL] (INTEGER)", where the optional "LITERAL" is the literal
+ * name, and INTEGER is the integer value of the name type. The format
+ * of "{@literal <name value>}" is "XX:...:XX", where "XX" is the
+ * hexadecimal digit representation of a byte value. For example, a
+ * returned value of an pseudo server name may look like:
+ * <pre>
+ * "type=(31), value=77:77:77:2E:65:78:61:6D:70:6C:65:2E:63:6E"
+ * </pre>
+ * or
+ * <pre>
+ * "type=host_name (0), value=77:77:77:2E:65:78:61:6D:70:6C:65:2E:63:6E"
+ * </pre>
+ *
+ * <P>
+ * Please NOTE that the exact details of the representation are unspecified
+ * and subject to change, and subclasses may override the method with
+ * their own formats.
+ *
+ * @return a string representation of this server name
+ */
+ @Override
+ public String toString() {
+ if (type == StandardConstants.SNI_HOST_NAME) {
+ return "type=host_name (0), value=" + toHexString(encoded);
+ } else {
+ return "type=(" + type + "), value=" + toHexString(encoded);
+ }
+ }
+
+ // convert byte array to hex string
+ private static String toHexString(byte[] bytes) {
+ if (bytes.length == 0) {
+ return "(empty)";
+ }
+
+ StringBuilder sb = new StringBuilder(bytes.length * 3 - 1);
+ boolean isInitial = true;
+ for (byte b : bytes) {
+ if (isInitial) {
+ isInitial = false;
+ } else {
+ sb.append(':');
+ }
+
+ int k = b & 0xFF;
+ sb.append(HEXES[k >>> 4]);
+ sb.append(HEXES[k & 0xF]);
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLParameters.java b/ojluni/src/main/java/javax/net/ssl/SSLParameters.java
index 0cb5b7d424c..90132ada341 100755
--- a/ojluni/src/main/java/javax/net/ssl/SSLParameters.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLParameters.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -26,13 +26,21 @@
package javax.net.ssl;
import java.security.AlgorithmConstraints;
+import java.util.Map;
+import java.util.List;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
/**
* Encapsulates parameters for an SSL/TLS connection. The parameters
* are the list of ciphersuites to be accepted in an SSL/TLS handshake,
* the list of protocols to be allowed, the endpoint identification
- * algorithm during SSL/TLS handshaking, the algorithm constraints and
- * whether SSL/TLS servers should request or require client authentication.
+ * algorithm during SSL/TLS handshaking, the Server Name Indication (SNI),
+ * the algorithm constraints and whether SSL/TLS servers should request
+ * or require client authentication, etc.
* <p>
* SSLParameters can be created via the constructors in this class.
* Objects can also be obtained using the <code>getSSLParameters()</code>
@@ -47,7 +55,7 @@ import java.security.AlgorithmConstraints;
* SSLParameters can be applied to a connection via the methods
* {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and
* {@link SSLServerSocket#setSSLParameters SSLServerSocket.setSSLParameters()}
- * and {@link SSLEngine#setSSLParameters SSLEngine.getSSLParameters()}.
+ * and {@link SSLEngine#setSSLParameters SSLEngine.setSSLParameters()}.
*
* @see SSLSocket
* @see SSLEngine
@@ -63,11 +71,16 @@ public class SSLParameters {
private boolean needClientAuth;
private String identificationAlgorithm;
private AlgorithmConstraints algorithmConstraints;
+ private Map<Integer, SNIServerName> sniNames = null;
+ private Map<Integer, SNIMatcher> sniMatchers = null;
+ private boolean preferLocalCipherSuites;
/**
* Constructs SSLParameters.
* <p>
- * The cipherSuites and protocols values are set to <code>null</code>,
+ * The values of cipherSuites, protocols, cryptographic algorithm
+ * constraints, endpoint identification algorithm, server names and
+ * server name matchers are set to <code>null</code>, useCipherSuitesOrder,
* wantClientAuth and needClientAuth are set to <code>false</code>.
*/
public SSLParameters() {
@@ -254,4 +267,172 @@ public class SSLParameters {
this.identificationAlgorithm = algorithm;
}
+ /**
+ * Sets the desired {@link SNIServerName}s of the Server Name
+ * Indication (SNI) parameter.
+ * <P>
+ * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
+ * operating in client mode.
+ * <P>
+ * Note that the {@code serverNames} list is cloned
+ * to protect against subsequent modification.
+ *
+ * @param serverNames
+ * the list of desired {@link SNIServerName}s (or null)
+ *
+ * @throws NullPointerException if the {@code serverNames}
+ * contains {@code null} element
+ * @throws IllegalArgumentException if the {@code serverNames}
+ * contains more than one name of the same name type
+ *
+ * @see SNIServerName
+ * @see #getServerNames()
+ *
+ * @since 1.8
+ */
+ public final void setServerNames(List<SNIServerName> serverNames) {
+ if (serverNames != null) {
+ if (!serverNames.isEmpty()) {
+ sniNames = new LinkedHashMap<>(serverNames.size());
+ for (SNIServerName serverName : serverNames) {
+ if (sniNames.put(serverName.getType(),
+ serverName) != null) {
+ throw new IllegalArgumentException(
+ "Duplicated server name of type " +
+ serverName.getType());
+ }
+ }
+ } else {
+ sniNames = Collections.<Integer, SNIServerName>emptyMap();
+ }
+ } else {
+ sniNames = null;
+ }
+ }
+
+ /**
+ * Returns a {@link List} containing all {@link SNIServerName}s of the
+ * Server Name Indication (SNI) parameter, or null if none has been set.
+ * <P>
+ * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
+ * operating in client mode.
+ * <P>
+ * For SSL/TLS connections, the underlying SSL/TLS provider
+ * may specify a default value for a certain server name type. In
+ * client mode, it is recommended that, by default, providers should
+ * include the server name indication whenever the server can be located
+ * by a supported server name type.
+ * <P>
+ * It is recommended that providers initialize default Server Name
+ * Indications when creating {@code SSLSocket}/{@code SSLEngine}s.
+ * In the following examples, the server name could be represented by an
+ * instance of {@link SNIHostName} which has been initialized with the
+ * hostname "www.example.com" and type
+ * {@link StandardConstants#SNI_HOST_NAME}.
+ *
+ * <pre>
+ * Socket socket =
+ * sslSocketFactory.createSocket("www.example.com", 443);
+ * </pre>
+ * or
+ * <pre>
+ * SSLEngine engine =
+ * sslContext.createSSLEngine("www.example.com", 443);
+ * </pre>
+ * <P>
+ *
+ * @return null or an immutable list of non-null {@link SNIServerName}s
+ *
+ * @see List
+ * @see #setServerNames(List)
+ *
+ * @since 1.8
+ */
+ public final List<SNIServerName> getServerNames() {
+ if (sniNames != null) {
+ if (!sniNames.isEmpty()) {
+ return Collections.<SNIServerName>unmodifiableList(
+ new ArrayList<>(sniNames.values()));
+ } else {
+ return Collections.<SNIServerName>emptyList();
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Sets the {@link SNIMatcher}s of the Server Name Indication (SNI)
+ * parameter.
+ * <P>
+ * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
+ * operating in server mode.
+ * <P>
+ * Note that the {@code matchers} collection is cloned to protect
+ * against subsequent modification.
+ *
+ * @param matchers
+ * the collection of {@link SNIMatcher}s (or null)
+ *
+ * @throws NullPointerException if the {@code matchers}
+ * contains {@code null} element
+ * @throws IllegalArgumentException if the {@code matchers}
+ * contains more than one name of the same name type
+ *
+ * @see Collection
+ * @see SNIMatcher
+ * @see #getSNIMatchers()
+ *
+ * @since 1.8
+ */
+ public final void setSNIMatchers(Collection<SNIMatcher> matchers) {
+ if (matchers != null) {
+ if (!matchers.isEmpty()) {
+ sniMatchers = new HashMap<>(matchers.size());
+ for (SNIMatcher matcher : matchers) {
+ if (sniMatchers.put(matcher.getType(),
+ matcher) != null) {
+ throw new IllegalArgumentException(
+ "Duplicated server name of type " +
+ matcher.getType());
+ }
+ }
+ } else {
+ sniMatchers = Collections.<Integer, SNIMatcher>emptyMap();
+ }
+ } else {
+ sniMatchers = null;
+ }
+ }
+
+ /**
+ * Returns a {@link Collection} containing all {@link SNIMatcher}s of the
+ * Server Name Indication (SNI) parameter, or null if none has been set.
+ * <P>
+ * This method is only useful to {@link SSLSocket}s or {@link SSLEngine}s
+ * operating in server mode.
+ * <P>
+ * For better interoperability, providers generally will not define
+ * default matchers so that by default servers will ignore the SNI
+ * extension and continue the handshake.
+ *
+ * @return null or an immutable collection of non-null {@link SNIMatcher}s
+ *
+ * @see SNIMatcher
+ * @see #setSNIMatchers(Collection)
+ *
+ * @since 1.8
+ */
+ public final Collection<SNIMatcher> getSNIMatchers() {
+ if (sniMatchers != null) {
+ if (!sniMatchers.isEmpty()) {
+ return Collections.<SNIMatcher>unmodifiableList(
+ new ArrayList<>(sniMatchers.values()));
+ } else {
+ return Collections.<SNIMatcher>emptyList();
+ }
+ }
+
+ return null;
+ }
}
diff --git a/ojluni/src/main/java/javax/net/ssl/StandardConstants.java b/ojluni/src/main/java/javax/net/ssl/StandardConstants.java
new file mode 100644
index 00000000000..8e1df977b97
--- /dev/null
+++ b/ojluni/src/main/java/javax/net/ssl/StandardConstants.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package javax.net.ssl;
+
+/**
+ * Standard constants definitions
+ *
+ * @since 1.8
+ */
+public final class StandardConstants {
+
+ // Suppress default constructor for noninstantiability
+ private StandardConstants() {
+ throw new AssertionError(
+ "No javax.net.ssl.StandardConstants instances for you!");
+ }
+
+ /**
+ * The "host_name" type representing of a DNS hostname
+ * (see {@link SNIHostName}) in a Server Name Indication (SNI) extension.
+ * <P>
+ * The SNI extension is a feature that extends the SSL/TLS protocols to
+ * indicate what server name the client is attempting to connect to during
+ * handshaking. See section 3, "Server Name Indication", of <A
+ * HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions (RFC 6066)</A>.
+ * <P>
+ * The value of this constant is {@value}.
+ *
+ * @see SNIServerName
+ * @see SNIHostName
+ */
+ public static final int SNI_HOST_NAME = 0x00;
+}
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index d6cb106e92c..cfa9cf828c1 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -886,6 +886,9 @@ openjdk_javadoc_files := \
ojluni/src/main/java/javax/net/ssl/KeyManager.java \
ojluni/src/main/java/javax/net/ssl/KeyStoreBuilderParameters.java \
ojluni/src/main/java/javax/net/ssl/ManagerFactoryParameters.java \
+ ojluni/src/main/java/javax/net/ssl/SNIHostName.java \
+ ojluni/src/main/java/javax/net/ssl/SNIMatcher.java \
+ ojluni/src/main/java/javax/net/ssl/SNIServerName.java \
ojluni/src/main/java/javax/net/ssl/SSLContext.java \
ojluni/src/main/java/javax/net/ssl/SSLContextSpi.java \
ojluni/src/main/java/javax/net/ssl/SSLEngine.java \
@@ -905,6 +908,7 @@ openjdk_javadoc_files := \
ojluni/src/main/java/javax/net/ssl/SSLSession.java \
ojluni/src/main/java/javax/net/ssl/SSLSocketFactory.java \
ojluni/src/main/java/javax/net/ssl/SSLSocket.java \
+ ojluni/src/main/java/javax/net/ssl/StandardConstants.java \
ojluni/src/main/java/javax/net/ssl/TrustManagerFactory.java \
ojluni/src/main/java/javax/net/ssl/TrustManagerFactorySpi.java \
ojluni/src/main/java/javax/net/ssl/TrustManager.java \