--- old/src/share/classes/sun/security/ssl/ClientHandshaker.java	2009-03-05 10:53:34.000000000 +0000
+++ new/src/share/classes/sun/security/ssl/ClientHandshaker.java	2009-03-05 10:53:34.000000000 +0000
@@ -418,7 +418,8 @@
         for (HelloExtension ext : mesg.extensions.list()) {
             ExtensionType type = ext.type;
             if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
-                    && (type != ExtensionType.EXT_EC_POINT_FORMATS)) {
+                    && (type != ExtensionType.EXT_EC_POINT_FORMATS)
+                    && (type != ExtensionType.EXT_SERVER_NAME)) {
                 fatalSE(Alerts.alert_unsupported_extension,
                     "Server sent an unsupported extension: " + type);
             }
@@ -969,6 +970,7 @@
                     throw new SSLException(
                         "Can't reuse existing SSL client session");
                 }
+                mesg.setServerName(this.getHostSE());
                 mesg.setCipherSuites(new CipherSuiteList(sessionSuite));
                 return mesg;
             }
@@ -980,6 +982,9 @@
                 throw new SSLException("No existing session to resume.");
             }
         }
+        
+        // Put an RFC4366 TLS server name indication extension into ClientHello.
+        mesg.setServerName(this.getHostSE());
 
         //
         // All we have left to do is fill out the cipher suites.
--- old/src/share/classes/sun/security/ssl/HandshakeMessage.java	2009-03-05 10:53:36.000000000 +0000
+++ new/src/share/classes/sun/security/ssl/HandshakeMessage.java	2009-03-05 10:53:35.000000000 +0000
@@ -223,6 +223,7 @@
     byte[]              compression_methods;
 
     HelloExtensions extensions = new HelloExtensions();
+    boolean disableHelloExtensions;
 
     private final static byte[]  NULL_COMPRESSION = new byte[] {0};
 
@@ -231,6 +232,12 @@
         clnt_random = new RandomCookie(generator);
         compression_methods = NULL_COMPRESSION;
         // sessionId, cipher_suites TBS later
+        
+        if (System.getProperty("sun.security.ssl.disableHelloExtensions", "no").equalsIgnoreCase("no")) {
+            this.disableHelloExtensions = false;
+        } else {
+            this.disableHelloExtensions = true;
+        }
     }
 
     CipherSuiteList getCipherSuites() {
@@ -246,6 +253,22 @@
             extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT);
         }
     }
+    
+    String serverName;
+    /**
+     * <p>Sets the name of the server being connected to, for reasons of sending 
+     * an SNI (Server Name Indication) Hello Extension. Server name indication
+     * allows multiple domains to be hosted on the same server, by indicating
+     * the domain being requested before the server sends its certificate.</p>
+     * <p>Sending of server name extensions can be disabled by using:</p>
+     * <code>System.setProperty("sun.security.ssl.disableHelloExtensions","no")</code>
+     * @param serverName - String representing the name expected on the server's
+     * certificate, for example "asdf.example.com"
+     */
+    void setServerName(String serverName) {
+        this.serverName = serverName;
+        extensions.add(new ServerNameExtension(serverName));
+    }
 
     int messageLength() {
         /*
@@ -277,7 +300,9 @@
         s.putBytes8(sessionId.getId());
         cipherSuites.send(s);
         s.putBytes8(compression_methods);
-        extensions.send(s);
+        if (this.disableHelloExtensions == false) {
+            extensions.send(s);
+        }
     }
 
     void print(PrintStream s) throws IOException {
--- old/src/share/classes/sun/security/ssl/HelloExtensions.java	2009-03-05 10:53:37.000000000 +0000
+++ new/src/share/classes/sun/security/ssl/HelloExtensions.java	2009-03-05 10:53:36.000000000 +0000
@@ -33,6 +33,7 @@
 
 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
@@ -147,7 +148,6 @@
         }
     }
 }
-
 final class ExtensionType {
 
     final int id;
@@ -260,6 +260,14 @@
             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;
@@ -277,6 +285,20 @@
                 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) {
@@ -286,17 +308,40 @@
             }
         }
     }
-
+    
     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();
     }
 }
 
