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