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

   1: /* ServerHello.java -- SSL ServerHello 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: 
  46: /**
  47:  * The server hello message.
  48:  *
  49:  * <pre>
  50: struct
  51: {
  52:   ProtocolVersion server_version;
  53:   Random random;
  54:   SessionID session_id;
  55:   CipherSuite cipher_suite;
  56:   CompressionMethod compression_method;
  57:   Extensions server_hello_extension_list&lt;0..2^16-1&gt;
  58: } ServerHello;
  59: </pre>
  60:  *
  61:  * <p>Server hello messages may contain extra data after the
  62:  * <tt>compression_method</tt> field, which are interpreted as
  63:  * extensions to the basic handshake.
  64:  */
  65: public class ServerHello implements Handshake.Body
  66: {
  67: 
  68:   // Fields.
  69:   // -------------------------------------------------------------------------
  70: 
  71:   protected static final int RANDOM_OFFSET = 2;
  72:   protected static final int SESSID_OFFSET = 32 + RANDOM_OFFSET;
  73:   protected static final int SESSID_OFFSET2 = SESSID_OFFSET + 1;
  74: 
  75:   protected ByteBuffer buffer;
  76:   protected boolean disableExtensions;
  77: 
  78:   // Constructor.
  79:   // -------------------------------------------------------------------------
  80: 
  81:   public ServerHello (final ByteBuffer buffer)
  82:   {
  83:     this.buffer = buffer;
  84:     disableExtensions = false;
  85:   }
  86: 
  87:   public int length ()
  88:   {
  89:     int sessionLen = buffer.get(SESSID_OFFSET) & 0xFF;
  90:     int len = SESSID_OFFSET2 + sessionLen + 3;
  91:     int elen = 0;
  92:     if (!disableExtensions && len + 1 < buffer.limit()
  93:         && (elen = buffer.getShort(len)) != 0)
  94:       len += 2 + elen;
  95:     return len;
  96:   }
  97: 
  98:   /**
  99:    * Returns the server's protocol version. This will read two bytes
 100:    * from the beginning of the underlying buffer, and return an
 101:    * instance of the appropriate {@link ProtocolVersion}; if the
 102:    * version read is a supported version, this method returns a static
 103:    * constant instance.
 104:    *
 105:    * @return The server's protocol version.
 106:    */
 107:   public ProtocolVersion version()
 108:   {
 109:     return ProtocolVersion.getInstance (buffer.getShort (0));
 110:   }
 111: 
 112:   /**
 113:    * Returns the server's random value. This method returns a
 114:    * lightwieght wrapper around the existing bytes; modifications to
 115:    * the underlying buffer will modify the returned object, and
 116:    * vice-versa.
 117:    *
 118:    * @return The server's random value.
 119:    */
 120:   public Random random()
 121:   {
 122:     ByteBuffer randomBuf =
 123:       ((ByteBuffer) buffer.duplicate ().position (RANDOM_OFFSET)
 124:        .limit (SESSID_OFFSET)).slice ();
 125:     return new Random (randomBuf);
 126:   }
 127: 
 128:   /**
 129:    * Returns the session ID. This method returns a new byte array with
 130:    * the session ID bytes.
 131:    *
 132:    * @return The session ID.
 133:    */
 134:   public byte[] sessionId()
 135:   {
 136:     int idlen = buffer.get (SESSID_OFFSET) & 0xFF;
 137:     byte[] sessionId = new byte[idlen];
 138:     buffer.position (SESSID_OFFSET2);
 139:     buffer.get (sessionId);
 140:     return sessionId;
 141:   }
 142: 
 143:   /**
 144:    * Returns the server's chosen cipher suite. The returned cipher
 145:    * suite will be "resolved" to this structure's version.
 146:    *
 147:    * @return The server's chosen cipher suite.
 148:    */
 149:   public CipherSuite cipherSuite()
 150:   {
 151:     int offset = SESSID_OFFSET2 + (buffer.get(SESSID_OFFSET) & 0xFF);
 152:     return CipherSuite.forValue(buffer.getShort(offset)).resolve();
 153:   }
 154: 
 155:   /**
 156:    * Returns the server's chosen compression method.
 157:    *
 158:    * @return The chosen compression method.
 159:    */
 160:   public CompressionMethod compressionMethod()
 161:   {
 162:     int offset = SESSID_OFFSET2 + (buffer.get(SESSID_OFFSET) & 0xFF) + 2;
 163:     return CompressionMethod.getInstance(buffer.get(offset) & 0xFF);
 164:   }
 165: 
 166:   public int extensionsLength()
 167:   {
 168:     int offset = SESSID_OFFSET2 + (buffer.get (SESSID_OFFSET) & 0xFF) + 3;
 169:     if (offset + 1 >= buffer.limit())
 170:       return 0;
 171:     return buffer.getShort(offset) & 0xFFFF;
 172:   }
 173: 
 174:   public ExtensionList extensions ()
 175:   {
 176:     int offset = SESSID_OFFSET2 + (buffer.get (SESSID_OFFSET) & 0xFF) + 3;
 177:     if (offset + 1 >= buffer.limit())
 178:       return null;
 179:     int len = buffer.getShort(offset) & 0xFFFF;
 180:     if (len == 0)
 181:       len = buffer.limit() - offset - 2;
 182:     ByteBuffer ebuf = ((ByteBuffer) buffer.duplicate().position(offset)
 183:                        .limit(offset + len + 2)).slice();
 184:     return new ExtensionList(ebuf);
 185:   }
 186: 
 187:   public String toString()
 188:   {
 189:     return toString(null);
 190:   }
 191: 
 192:   public String toString (final String prefix)
 193:   {
 194:     StringWriter str = new StringWriter();
 195:     PrintWriter out = new PrintWriter(str);
 196:     if (prefix != null)
 197:       out.print (prefix);
 198:     out.println ("struct {");
 199:     String subprefix = "  ";
 200:     if (prefix != null)
 201:       subprefix += prefix;
 202:     out.print (subprefix);
 203:     out.print ("version: ");
 204:     out.print (version ());
 205:     out.println (";");
 206:     out.print (subprefix);
 207:     out.println ("random:");
 208:     out.println (random ().toString (subprefix));
 209:     out.print (subprefix);
 210:     out.print ("sessionId:         ");
 211:     out.print (Util.toHexString(sessionId (), ':'));
 212:     out.println (";");
 213:     out.print (subprefix);
 214:     out.print ("cipherSuite:       ");
 215:     out.print (cipherSuite ());
 216:     out.println (";");
 217:     out.print (subprefix);
 218:     out.print ("compressionMethod: ");
 219:     out.print (compressionMethod ());
 220:     out.println (";");
 221:     ExtensionList exts = extensions ();
 222:     out.print (subprefix);
 223:     out.println ("extensions:");
 224:     out.println (exts != null ? exts.toString (subprefix+"  ")
 225:                                 : subprefix + "  (nil)");
 226:     if (prefix != null)
 227:       out.print (prefix);
 228:     out.print ("} ServerHello;");
 229:     return str.toString();
 230:   }
 231: }