src/share/classes/sun/security/ssl/HandshakeMessage.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>


 206  * Client initiates handshake by telling server what it wants, and what it
 207  * can support (prioritized by what's first in the ciphe suite list).
 208  *
 209  * By RFC2246:7.4.1.2 it's explicitly anticipated that this message
 210  * will have more data added at the end ... e.g. what CAs the client trusts.
 211  * Until we know how to parse it, we will just read what we know
 212  * about, and let our caller handle the jumps over unknown data.
 213  */
 214 static final
 215 class ClientHello extends HandshakeMessage
 216 {
 217     int messageType() { return ht_client_hello; }
 218 
 219     ProtocolVersion     protocolVersion;
 220     RandomCookie        clnt_random;
 221     SessionId           sessionId;
 222     private CipherSuiteList    cipherSuites;
 223     byte[]              compression_methods;
 224 
 225     HelloExtensions extensions = new HelloExtensions();

 226 
 227     private final static byte[]  NULL_COMPRESSION = new byte[] {0};
 228 
 229     ClientHello(SecureRandom generator, ProtocolVersion protocolVersion) {
 230         this.protocolVersion = protocolVersion;
 231         clnt_random = new RandomCookie(generator);
 232         compression_methods = NULL_COMPRESSION;
 233         // sessionId, cipher_suites TBS later






 234     }
 235 
 236     CipherSuiteList getCipherSuites() {
 237         return cipherSuites;
 238     }
 239 
 240     // Set the ciphersuites.
 241     // This method may only be called once.
 242     void setCipherSuites(CipherSuiteList cipherSuites) {
 243         this.cipherSuites = cipherSuites;
 244         if (cipherSuites.containsEC()) {
 245             extensions.add(SupportedEllipticCurvesExtension.DEFAULT);
 246             extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT);
 247         }
 248     }
 249 
















 250     int messageLength() {
 251         /*
 252          * Add fixed size parts of each field...
 253          * version + random + session + cipher + compress
 254          */
 255         return (2 + 32 + 1 + 2 + 1
 256             + sessionId.length()                /* ... + variable parts */
 257             + (cipherSuites.size() * 2)
 258             + compression_methods.length)
 259             + extensions.length();
 260     }
 261 
 262     ClientHello(HandshakeInStream s, int messageLength) throws IOException {
 263         protocolVersion = ProtocolVersion.valueOf(s.getInt8(), s.getInt8());
 264         clnt_random = new RandomCookie(s);
 265         sessionId = new SessionId(s.getBytes8());
 266         cipherSuites = new CipherSuiteList(s);
 267         compression_methods = s.getBytes8();
 268         if (messageLength() != messageLength) {
 269             extensions = new HelloExtensions(s);
 270         }
 271     }
 272 
 273     void send(HandshakeOutStream s) throws IOException {
 274         s.putInt8(protocolVersion.major);
 275         s.putInt8(protocolVersion.minor);
 276         clnt_random.send(s);
 277         s.putBytes8(sessionId.getId());
 278         cipherSuites.send(s);
 279         s.putBytes8(compression_methods);

 280         extensions.send(s);
 281     }

 282 
 283     void print(PrintStream s) throws IOException {
 284         s.println("*** ClientHello, " + protocolVersion);
 285 
 286         if (debug != null && Debug.isOn("verbose")) {
 287             s.print   ("RandomCookie:  "); clnt_random.print(s);
 288 
 289             s.print("Session ID:  ");
 290             s.println(sessionId);
 291 
 292             s.println("Cipher Suites: " + cipherSuites);
 293 
 294             Debug.println(s, "Compression Methods", compression_methods);
 295             extensions.print(s);
 296             s.println("***");
 297         }
 298     }
 299 }
 300 
 301 /*




 206  * Client initiates handshake by telling server what it wants, and what it
 207  * can support (prioritized by what's first in the ciphe suite list).
 208  *
 209  * By RFC2246:7.4.1.2 it's explicitly anticipated that this message
 210  * will have more data added at the end ... e.g. what CAs the client trusts.
 211  * Until we know how to parse it, we will just read what we know
 212  * about, and let our caller handle the jumps over unknown data.
 213  */
 214 static final
 215 class ClientHello extends HandshakeMessage
 216 {
 217     int messageType() { return ht_client_hello; }
 218 
 219     ProtocolVersion     protocolVersion;
 220     RandomCookie        clnt_random;
 221     SessionId           sessionId;
 222     private CipherSuiteList    cipherSuites;
 223     byte[]              compression_methods;
 224 
 225     HelloExtensions extensions = new HelloExtensions();
 226     boolean disableHelloExtensions;
 227 
 228     private final static byte[]  NULL_COMPRESSION = new byte[] {0};
 229 
 230     ClientHello(SecureRandom generator, ProtocolVersion protocolVersion) {
 231         this.protocolVersion = protocolVersion;
 232         clnt_random = new RandomCookie(generator);
 233         compression_methods = NULL_COMPRESSION;
 234         // sessionId, cipher_suites TBS later
 235         
 236         if (System.getProperty("sun.security.ssl.disableHelloExtensions", "no").equalsIgnoreCase("no")) {
 237             this.disableHelloExtensions = false;
 238         } else {
 239             this.disableHelloExtensions = true;
 240         }
 241     }
 242 
 243     CipherSuiteList getCipherSuites() {
 244         return cipherSuites;
 245     }
 246 
 247     // Set the ciphersuites.
 248     // This method may only be called once.
 249     void setCipherSuites(CipherSuiteList cipherSuites) {
 250         this.cipherSuites = cipherSuites;
 251         if (cipherSuites.containsEC()) {
 252             extensions.add(SupportedEllipticCurvesExtension.DEFAULT);
 253             extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT);
 254         }
 255     }
 256     
 257     String serverName;
 258     /**
 259      * <p>Sets the name of the server being connected to, for reasons of sending 
 260      * an SNI (Server Name Indication) Hello Extension. Server name indication
 261      * allows multiple domains to be hosted on the same server, by indicating
 262      * the domain being requested before the server sends its certificate.</p>
 263      * <p>Sending of server name extensions can be disabled by using:</p>
 264      * <code>System.setProperty("sun.security.ssl.disableHelloExtensions","no")</code>
 265      * @param serverName - String representing the name expected on the server's
 266      * certificate, for example "asdf.example.com"
 267      */
 268     void setServerName(String serverName) {
 269         this.serverName = serverName;
 270         extensions.add(new ServerNameExtension(serverName));
 271     }
 272 
 273     int messageLength() {
 274         /*
 275          * Add fixed size parts of each field...
 276          * version + random + session + cipher + compress
 277          */
 278         return (2 + 32 + 1 + 2 + 1
 279             + sessionId.length()                /* ... + variable parts */
 280             + (cipherSuites.size() * 2)
 281             + compression_methods.length)
 282             + extensions.length();
 283     }
 284 
 285     ClientHello(HandshakeInStream s, int messageLength) throws IOException {
 286         protocolVersion = ProtocolVersion.valueOf(s.getInt8(), s.getInt8());
 287         clnt_random = new RandomCookie(s);
 288         sessionId = new SessionId(s.getBytes8());
 289         cipherSuites = new CipherSuiteList(s);
 290         compression_methods = s.getBytes8();
 291         if (messageLength() != messageLength) {
 292             extensions = new HelloExtensions(s);
 293         }
 294     }
 295 
 296     void send(HandshakeOutStream s) throws IOException {
 297         s.putInt8(protocolVersion.major);
 298         s.putInt8(protocolVersion.minor);
 299         clnt_random.send(s);
 300         s.putBytes8(sessionId.getId());
 301         cipherSuites.send(s);
 302         s.putBytes8(compression_methods);
 303         if (this.disableHelloExtensions == false) {
 304             extensions.send(s);
 305         }
 306     }
 307 
 308     void print(PrintStream s) throws IOException {
 309         s.println("*** ClientHello, " + protocolVersion);
 310 
 311         if (debug != null && Debug.isOn("verbose")) {
 312             s.print   ("RandomCookie:  "); clnt_random.print(s);
 313 
 314             s.print("Session ID:  ");
 315             s.println(sessionId);
 316 
 317             s.println("Cipher Suites: " + cipherSuites);
 318 
 319             Debug.println(s, "Compression Methods", compression_methods);
 320             extensions.print(s);
 321             s.println("***");
 322         }
 323     }
 324 }
 325 
 326 /*