Source for gnu.javax.net.ssl.Session

   1: /* SessionImpl.java -- concrete definition of SSLSession.
   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;
  40: 
  41: import gnu.java.lang.CPStringBuilder;
  42: 
  43: import java.io.Serializable;
  44: 
  45: import java.security.Principal;
  46: import java.security.SecureRandom;
  47: import java.security.cert.Certificate;
  48: 
  49: import java.util.Arrays;
  50: import java.util.HashMap;
  51: import java.util.Set;
  52: 
  53: import javax.crypto.SealedObject;
  54: import javax.net.ssl.SSLException;
  55: import javax.net.ssl.SSLPeerUnverifiedException;
  56: import javax.net.ssl.SSLSession;
  57: import javax.net.ssl.SSLSessionBindingEvent;
  58: import javax.net.ssl.SSLSessionBindingListener;
  59: import javax.net.ssl.SSLSessionContext;
  60: import javax.security.cert.X509Certificate;
  61: 
  62: /**
  63:  * A concrete implementation of the {@link SSLSession} interface. This
  64:  * class is provided to allow pluggable {@link AbstractSessionContext}
  65:  * implementations.
  66:  */
  67: public abstract class Session implements SSLSession, Serializable
  68: {
  69:   protected final long creationTime;
  70:   protected long lastAccessedTime;
  71:   protected int applicationBufferSize;
  72: 
  73:   protected ID sessionId;
  74:   protected Certificate[] localCerts;
  75:   protected Certificate[] peerCerts;
  76:   protected X509Certificate[] peerCertChain;
  77:   protected String peerHost;
  78:   protected int peerPort;
  79:   protected boolean peerVerified;
  80:   protected HashMap<String,Object> values;
  81:   protected boolean valid;
  82:   protected boolean truncatedMac = false;
  83:   transient protected SecureRandom random;
  84:   transient protected SSLSessionContext context;
  85: 
  86:   protected Session()
  87:   {
  88:     creationTime = System.currentTimeMillis();
  89:     values = new HashMap<String, Object>();
  90:     applicationBufferSize = (1 << 14);
  91:   }
  92: 
  93:   public void access()
  94:   {
  95:     lastAccessedTime = System.currentTimeMillis ();
  96:   }
  97: 
  98:   public int getApplicationBufferSize()
  99:   {
 100:     return applicationBufferSize;
 101:   }
 102: 
 103:   public String getCipherSuite()
 104:   {
 105:     return null;
 106:   }
 107: 
 108:   public long getCreationTime()
 109:   {
 110:     return creationTime;
 111:   }
 112: 
 113:   public byte[] getId()
 114:   {
 115:     return sessionId.id();
 116:   }
 117: 
 118:   public ID id()
 119:   {
 120:     return sessionId;
 121:   }
 122: 
 123:   public long getLastAccessedTime()
 124:   {
 125:     return lastAccessedTime;
 126:   }
 127: 
 128:   public Certificate[] getLocalCertificates()
 129:   {
 130:     if (localCerts == null)
 131:       return null;
 132:     return (Certificate[]) localCerts.clone();
 133:   }
 134: 
 135:   public Principal getLocalPrincipal()
 136:   {
 137:     if (localCerts != null)
 138:       {
 139:         if (localCerts[0] instanceof java.security.cert.X509Certificate)
 140:           return ((java.security.cert.X509Certificate) localCerts[0]).getSubjectDN();
 141:       }
 142:     return null;
 143:   }
 144: 
 145:   public int getPacketBufferSize()
 146:   {
 147:     return applicationBufferSize + 2048;
 148:   }
 149: 
 150:   public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException
 151:   {
 152:     if (!peerVerified)
 153:       throw new SSLPeerUnverifiedException("peer not verified");
 154:     if (peerCerts == null)
 155:       return null;
 156:     return (Certificate[]) peerCerts.clone();
 157:   }
 158: 
 159:   public X509Certificate[] getPeerCertificateChain()
 160:     throws SSLPeerUnverifiedException
 161:   {
 162:     if (!peerVerified)
 163:       throw new SSLPeerUnverifiedException("peer not verified");
 164:     if (peerCertChain == null)
 165:       return null;
 166:     return (X509Certificate[]) peerCertChain.clone();
 167:   }
 168: 
 169:   public String getPeerHost()
 170:   {
 171:     return peerHost;
 172:   }
 173: 
 174:   public int getPeerPort()
 175:   {
 176:     return peerPort;
 177:   }
 178: 
 179:   public Principal getPeerPrincipal() throws SSLPeerUnverifiedException
 180:   {
 181:     if (!peerVerified)
 182:       throw new SSLPeerUnverifiedException("peer not verified");
 183:     if (peerCertChain == null)
 184:       return null;
 185:     return peerCertChain[0].getSubjectDN();
 186:   }
 187: 
 188:   public SSLSessionContext getSessionContext()
 189:   {
 190:     return context;
 191:   }
 192: 
 193:   public String[] getValueNames()
 194:   {
 195:     Set<String> keys = this.values.keySet();
 196:     return keys.toArray(new String[keys.size()]);
 197:   }
 198: 
 199:   public Object getValue(String name)
 200:   {
 201:     return values.get(name);
 202:   }
 203: 
 204:   public void invalidate()
 205:   {
 206:     valid = false;
 207:   }
 208: 
 209:   public boolean isValid()
 210:   {
 211:     return valid;
 212:   }
 213: 
 214:   public void putValue(String name, Object value)
 215:   {
 216:     values.put(name, value);
 217:     try
 218:       {
 219:         if (value instanceof SSLSessionBindingListener)
 220:           ((SSLSessionBindingListener) value).valueBound
 221:             (new SSLSessionBindingEvent(this, name));
 222:       }
 223:     catch (Exception x)
 224:       {
 225:       }
 226:   }
 227: 
 228:   public void removeValue(String name)
 229:   {
 230:     Object value = values.remove(name);
 231:     try
 232:       {
 233:         if (value instanceof SSLSessionBindingListener)
 234:           ((SSLSessionBindingListener) value).valueUnbound
 235:             (new SSLSessionBindingEvent(this, name));
 236:       }
 237:     catch (Exception x)
 238:       {
 239:       }
 240:   }
 241: 
 242:   public final boolean isTruncatedMac()
 243:   {
 244:     return truncatedMac;
 245:   }
 246: 
 247:   /**
 248:    * Prepare this session for serialization. Private data will be encrypted
 249:    * with the given password, and this object will then be ready to be
 250:    * serialized.
 251:    *
 252:    * @param password The password to protect this session with.
 253:    * @throws SSLException If encrypting this session's private data fails.
 254:    */
 255:   public abstract void prepare (char[] password) throws SSLException;
 256: 
 257:   /**
 258:    * Repair this session's private data after deserialization. This method
 259:    * will decrypt this session's private data, and prepare the session for
 260:    * use in new SSL connections.
 261:    *
 262:    * @param password The password to decrypt the private data with.
 263:    * @throws SSLException
 264:    */
 265:   public abstract void repair(char[] password) throws SSLException;
 266: 
 267:   /**
 268:    * Get the private data of this session. This method may only be called
 269:    * after first calling {@link #prepare(char[])}.
 270:    *
 271:    * @return The sealed private data.
 272:    * @throws SSLException If the private data have not been sealed.
 273:    */
 274:   public abstract SealedObject privateData() throws SSLException;
 275: 
 276:   /**
 277:    * Set the private data of this session.
 278:    * @param data
 279:    * @throws SSLException
 280:    */
 281:   public abstract void setPrivateData(SealedObject data) throws SSLException;
 282: 
 283:   // Inner classes.
 284:   // -------------------------------------------------------------------------
 285: 
 286:   /**
 287:    * An SSL or TLS session ID.
 288:    */
 289:   public static final class ID implements Comparable, Serializable
 290:   {
 291: 
 292:     // Fields.
 293:     // -----------------------------------------------------------------------
 294: 
 295:     static final long serialVersionUID = 7887036954666565936L;
 296:     /** The ID itself. */
 297:     private final byte[] id;
 298: 
 299:     // Constructor.
 300:     // -----------------------------------------------------------------------
 301: 
 302:     /**
 303:      * Creates a new ID.
 304:      *
 305:      * @param id The ID. The array is cloned.
 306:      */
 307:     public ID (final byte[] id)
 308:     {
 309:       if (id.length > 32)
 310:         throw new IllegalArgumentException ("session ID's are limited to 32 bytes");
 311:       this.id = (byte[]) id.clone();
 312:     }
 313: 
 314:     // Instance methods.
 315:     // -----------------------------------------------------------------------
 316: 
 317:     public byte[] id()
 318:     {
 319:       return (byte[]) id.clone();
 320:     }
 321: 
 322:     public boolean equals(Object other)
 323:     {
 324:       if (!(other instanceof ID))
 325:         return false;
 326:       return Arrays.equals(id, ((ID) other).id);
 327:     }
 328: 
 329:     public int hashCode()
 330:     {
 331:       int code = 0;
 332:       for (int i = 0; i < id.length; i++)
 333:         code |= (id[i] & 0xFF) << ((i & 3) << 3);
 334:       return code;
 335:     }
 336: 
 337:     public int compareTo(Object other)
 338:     {
 339:       byte[] id2 = ((ID) other).id;
 340:       if (id.length != id2.length)
 341:         return (id.length < id2.length) ? -1 : 1;
 342:       for (int i = 0; i < id.length; i++)
 343:         {
 344:           if ((id[i] & 0xFF) < (id2[i] & 0xFF))
 345:             return -1;
 346:           if ((id[i] & 0xFF) > (id2[i] & 0xFF))
 347:             return 1;
 348:         }
 349:       return 0;
 350:     }
 351: 
 352:     public String toString()
 353:     {
 354:       CPStringBuilder str = new CPStringBuilder (3 * id.length + 1);
 355:       for (int i = 0; i < id.length; i++)
 356:         {
 357:           int x = id[i] & 0xFF;
 358:           str.append (Character.forDigit ((x >>> 4) & 0xF, 16));
 359:           str.append (Character.forDigit (x & 0xF, 16));
 360:           if (i != id.length - 1)
 361:             str.append (':');
 362:         }
 363:       return str.toString ();
 364:     }
 365:   }
 366: }