src/share/classes/sun/security/ssl/HelloExtensions.java

Print this page
rev 928 : Summary: Added support for Server Name Indication (SNI) hello
extension to SSL client.
Contributed-by: Michael Tandy <michaeltandy at googlemail dot com>

@@ -31,10 +31,11 @@
 
 import java.security.spec.ECParameterSpec;
 
 import javax.net.ssl.SSLProtocolException;
 
+
 /**
  * This file contains all the classes relevant to TLS Extensions for the
  * ClientHello and ServerHello messages. The extension mechanism and
  * several extensions are defined in RFC 3546. Additional extensions are
  * defined in the ECC RFC 4492.

@@ -145,11 +146,10 @@
         for (HelloExtension ext : extensions) {
             s.println(ext.toString());
         }
     }
 }
-
 final class ExtensionType {
 
     final int id;
     final String name;
 

@@ -259,10 +259,18 @@
         if (len != 0) {
             throw new SSLProtocolException("Invalid server_name extension");
         }
     }
 
+    ServerNameExtension(String serverName) {
+        super(ExtensionType.EXT_SERVER_NAME);
+        names = new ArrayList<ServerName>(1);
+        if ((serverName != null)&&(serverName.length()>0)) {
+            names.add(new ServerName(serverName));
+        }
+    }
+
     static class ServerName {
         final int length;
         final int type;
         final byte[] data;
         final String hostname;

@@ -276,29 +284,66 @@
             } else {
                 hostname = null;
             }
         }
 
+        ServerName(String hostname) {
+            this.hostname = hostname;
+            byte[] hostnameAsUTF8 = null;
+            try {
+                hostnameAsUTF8 = hostname.getBytes("UTF-8");
+            } catch (java.io.UnsupportedEncodingException ex) {
+                // UTF-8 encoding should reliably be present.
+                throw new RuntimeException(ex);
+            }
+            this.data = hostnameAsUTF8;
+            this.type = NAME_HOST_NAME;
+            this.length = this.data.length + 3;
+        }
+
         public String toString() {
             if (type == NAME_HOST_NAME) {
                 return "host_name: " + hostname;
             } else {
                 return "unknown-" + type + ": " + Debug.toString(data);
             }
         }
     }
 
     int length() {
-        throw new RuntimeException("not yet supported");
+        if (names.size() == 0)
+            return 0;
+        int serverNameListLength = 0;
+        for (ServerName sn : names) {
+            serverNameListLength += sn.length + 2;
+        }
+        return serverNameListLength + 4;
     }
 
     void send(HandshakeOutStream s) throws IOException {
-        throw new RuntimeException("not yet supported");
+        if (names.size() == 0)
+            return;
+        s.putInt16(type.id);
+        int serverNameListLength = 0;
+        for (ServerName sn : names) {
+            serverNameListLength += sn.length + 2;
+        }
+        s.putInt16(serverNameListLength);
+        for (ServerName sn : names) {
+            s.putInt16(sn.length);
+            s.putInt8(sn.type);
+            s.putBytes16(sn.data);
+        }
     }
 
     public String toString() {
-        return "Unsupported extension " + type + ", " + names.toString();
+        StringBuilder sb = new StringBuilder();
+        sb.append("Extension " + type + ", host names:\n");
+        for (ServerName sn : names) {
+            sb.append("  " + sn + "\n");
+        }
+        return sb.toString();
     }
 }
 
 final class SupportedEllipticCurvesExtension extends HelloExtension {