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 Session()86 protected Session() 87 { 88 creationTime = System.currentTimeMillis(); 89 values = new HashMap<String, Object>(); 90 applicationBufferSize = (1 << 14); 91 } 92 access()93 public void access() 94 { 95 lastAccessedTime = System.currentTimeMillis (); 96 } 97 getApplicationBufferSize()98 public int getApplicationBufferSize() 99 { 100 return applicationBufferSize; 101 } 102 getCipherSuite()103 public String getCipherSuite() 104 { 105 return null; 106 } 107 getCreationTime()108 public long getCreationTime() 109 { 110 return creationTime; 111 } 112 getId()113 public byte[] getId() 114 { 115 return sessionId.id(); 116 } 117 id()118 public ID id() 119 { 120 return sessionId; 121 } 122 getLastAccessedTime()123 public long getLastAccessedTime() 124 { 125 return lastAccessedTime; 126 } 127 getLocalCertificates()128 public Certificate[] getLocalCertificates() 129 { 130 if (localCerts == null) 131 return null; 132 return (Certificate[]) localCerts.clone(); 133 } 134 getLocalPrincipal()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 getPacketBufferSize()145 public int getPacketBufferSize() 146 { 147 return applicationBufferSize + 2048; 148 } 149 getPeerCertificates()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 getPeerCertificateChain()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 getPeerHost()169 public String getPeerHost() 170 { 171 return peerHost; 172 } 173 getPeerPort()174 public int getPeerPort() 175 { 176 return peerPort; 177 } 178 getPeerPrincipal()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 getSessionContext()188 public SSLSessionContext getSessionContext() 189 { 190 return context; 191 } 192 getValueNames()193 public String[] getValueNames() 194 { 195 Set<String> keys = this.values.keySet(); 196 return keys.toArray(new String[keys.size()]); 197 } 198 getValue(String name)199 public Object getValue(String name) 200 { 201 return values.get(name); 202 } 203 invalidate()204 public void invalidate() 205 { 206 valid = false; 207 } 208 isValid()209 public boolean isValid() 210 { 211 return valid; 212 } 213 putValue(String name, Object value)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 removeValue(String name)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 isTruncatedMac()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 */ prepare(char[] password)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 */ repair(char[] password)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 */ privateData()274 public abstract SealedObject privateData() throws SSLException; 275 276 /** 277 * Set the private data of this session. 278 * @param data 279 * @throws SSLException 280 */ setPrivateData(SealedObject data)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 */ ID(final byte[] id)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 id()317 public byte[] id() 318 { 319 return (byte[]) id.clone(); 320 } 321 equals(Object other)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 hashCode()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 compareTo(Object other)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 toString()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 } 367