Source for gnu.javax.net.ssl.provider.ClientHello

   1: /* ClientHello.java -- SSL ClientHello message.
   2:    Copyright (C) 2006  Free Software Foundation, Inc.
   3: 
   4: This file is a part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2 of the License, or (at
   9: your option) any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; if not, write to the Free Software
  18: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  19: USA
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version.  */
  37: 
  38: 
  39: package gnu.javax.net.ssl.provider;
  40: 
  41: import java.io.PrintWriter;
  42: import java.io.StringWriter;
  43: 
  44: import java.nio.ByteBuffer;
  45: import java.nio.ByteOrder;
  46: 
  47: /**
  48:  * A ClientHello handshake message.
  49:  *
  50:  * <pre>
  51: struct
  52: {
  53:   ProtocolVersion   client_version;                // 2
  54:   Random            random;                        // 32
  55:   SessionID         session_id;                    // 1 + 0..32
  56:   CipherSuite       cipher_suites&lt;2..2^16-1&gt;
  57:   CompressionMethod compression_methods&lt;1..2^8-1&gt;
  58:   Extension         client_hello_extension_list&lt;0..2^16-1&gt;
  59: } ClientHello;
  60: </pre>
  61:  */
  62: public class ClientHello implements Handshake.Body
  63: {
  64: 
  65:   // Fields.
  66:   // -------------------------------------------------------------------------
  67: 
  68:   // To help track offsets into the message:
  69:   // The location of the 'random' field.
  70:   protected static final int RANDOM_OFFSET = 2;
  71:   // The location of the sesion_id length.
  72:   protected static final int SESSID_OFFSET = 32 + RANDOM_OFFSET;
  73:   // The location of the session_id bytes (if any).
  74:   protected static final int SESSID_OFFSET2 = SESSID_OFFSET + 1;
  75: 
  76:   protected ByteBuffer buffer;
  77:   protected boolean disableExtensions;
  78: 
  79:   // Constructor.
  80:   // -------------------------------------------------------------------------
  81: 
  82:   public ClientHello (final ByteBuffer buffer)
  83:   {
  84:     this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
  85:     disableExtensions = false;
  86:   }
  87: 
  88:   // Instance methods.
  89:   // -------------------------------------------------------------------------
  90: 
  91:   public int length()
  92:   {
  93:     int len = SESSID_OFFSET2 + buffer.get(SESSID_OFFSET);
  94:     len += (buffer.getShort(len) & 0xFFFF) + 2;
  95:     len += (buffer.get(len) & 0xFF) + 1;
  96:     if (!disableExtensions && len + 1 < buffer.capacity())
  97:       len += (buffer.getShort(len) & 0xFFFF) + 2;
  98:     return len;
  99:   }
 100: 
 101:   /**
 102:    * Gets the protocol version field.
 103:    *
 104:    * @return The protocol version field.
 105:    */
 106:   public ProtocolVersion version()
 107:   {
 108:     return ProtocolVersion.getInstance (buffer.getShort (0));
 109:   }
 110: 
 111:   /**
 112:    * Gets the SSL nonce.
 113:    *
 114:    * @return The nonce.
 115:    */
 116:   public Random random()
 117:   {
 118:     ByteBuffer randomBuf =
 119:       ((ByteBuffer) buffer.duplicate ().position (RANDOM_OFFSET)
 120:        .limit (SESSID_OFFSET)).slice ();
 121:     return new Random (randomBuf);
 122:   }
 123: 
 124:   public byte[] sessionId()
 125:   {
 126:     int idlen = buffer.get (SESSID_OFFSET) & 0xFF;
 127:     byte[] sessionId = new byte[idlen];
 128:     buffer.position (SESSID_OFFSET2);
 129:     buffer.get (sessionId);
 130:     return sessionId;
 131:   }
 132: 
 133:   public CipherSuiteList cipherSuites()
 134:   {
 135:     int offset = getCipherSuitesOffset ();
 136: 
 137:     // We give the CipherSuiteList all the remaining bytes to play with,
 138:     // since this might be an in-construction packet that will fill in
 139:     // the length field itself.
 140:     ByteBuffer listBuf = ((ByteBuffer) buffer.duplicate ().position (offset)
 141:                           .limit (buffer.capacity ())).slice ();
 142:     return new CipherSuiteList (listBuf, version ());
 143:   }
 144: 
 145:   public CompressionMethodList compressionMethods()
 146:   {
 147:     int offset = getCompressionMethodsOffset ();
 148:     ByteBuffer listBuf = ((ByteBuffer) buffer.duplicate ().position (offset)
 149:                           .limit (buffer.capacity ())).slice ();
 150:     return new CompressionMethodList (listBuf);
 151:   }
 152: 
 153:   public boolean hasExtensions()
 154:   {
 155:     int offset = getExtensionsOffset();
 156:     return (offset + 1 < buffer.limit());
 157:   }
 158: 
 159:   public ExtensionList extensions()
 160:   {
 161:     int offset = getExtensionsOffset ();
 162:     if (offset + 1 >= buffer.limit())
 163:       return null;
 164:     int len = buffer.getShort(offset) & 0xFFFF;
 165:     if (len == 0)
 166:       len = buffer.limit() - offset - 2;
 167:     ByteBuffer ebuf = ((ByteBuffer) buffer.duplicate().position(offset)
 168:                        .limit(offset + len + 2)).slice ();
 169:     return new ExtensionList(ebuf);
 170:   }
 171: 
 172:   public int extensionsLength()
 173:   {
 174:     if (hasExtensions())
 175:       return 0;
 176:     return buffer.getShort(getExtensionsOffset()) & 0xFFFF;
 177:   }
 178: 
 179:   protected int getCipherSuitesOffset ()
 180:   {
 181:     return (SESSID_OFFSET2 + (buffer.get (SESSID_OFFSET) & 0xFF));
 182:   }
 183: 
 184:   protected int getCompressionMethodsOffset ()
 185:   {
 186:     int csOffset = getCipherSuitesOffset ();
 187:     int csLen = buffer.getShort (csOffset) & 0xFFFF;
 188:     return csOffset + csLen + 2;
 189:   }
 190: 
 191:   protected int getExtensionsOffset ()
 192:   {
 193:     int cmOffset = getCompressionMethodsOffset ();
 194:     return (buffer.get (cmOffset) & 0xFF) + cmOffset + 1;
 195:   }
 196: 
 197:   public String toString ()
 198:   {
 199:     return toString (null);
 200:   }
 201: 
 202:   public String toString (final String prefix)
 203:   {
 204:     StringWriter str = new StringWriter ();
 205:     PrintWriter out = new PrintWriter (str);
 206:     String subprefix = "  ";
 207:     if (prefix != null)
 208:       subprefix += prefix;
 209:     if (prefix != null)
 210:       out.print (prefix);
 211:     out.println ("struct {");
 212:     if (prefix != null)
 213:       out.print (prefix);
 214:     out.print ("  version: ");
 215:     out.print (version ());
 216:     out.println (";");
 217:     out.print (subprefix);
 218:     out.println ("random:");
 219:     out.print (random ().toString (subprefix));
 220:     if (prefix != null)
 221:       out.print (prefix);
 222:     out.print ("  sessionId: ");
 223:     out.print (Util.toHexString (sessionId (), ':'));
 224:     out.println (";");
 225:     out.print (subprefix);
 226:     out.println ("cipher_suites:");
 227:     out.println (cipherSuites ().toString (subprefix));
 228:     out.print (subprefix);
 229:     out.println ("compression_methods:");
 230:     out.println (compressionMethods ().toString (subprefix));
 231:     out.print (subprefix);
 232:     out.print ("extensions: ");
 233:     ExtensionList el = extensions();
 234:     out.println (el != null ? el.toString(subprefix+"  ") : "(nil)");
 235:     if (prefix != null)
 236:       out.print (prefix);
 237:     out.print ("} ClientHello;");
 238:     return str.toString();
 239:   }
 240: }