21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 * or visit www.oracle.com if you need additional information or have any |
22 * or visit www.oracle.com if you need additional information or have any |
23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 |
|
27 package sun.security.ssl; |
26 package sun.security.ssl; |
28 |
27 |
29 import java.security.SecureRandom; |
28 import java.security.SecureRandom; |
|
29 import java.util.Arrays; |
30 import javax.net.ssl.SSLProtocolException; |
30 import javax.net.ssl.SSLProtocolException; |
31 |
31 |
32 /** |
32 /** |
33 * Encapsulates an SSL session ID. SSL Session IDs are not reused by |
33 * Encapsulates an SSL session ID. |
34 * servers during the lifetime of any sessions it created. Sessions may |
|
35 * be used by many connections, either concurrently (for example, two |
|
36 * connections to a web server at the same time) or sequentially (over as |
|
37 * long a time period as is allowed by a given server). |
|
38 * |
34 * |
39 * @author Satish Dharmaraj |
35 * @author Satish Dharmaraj |
40 * @author David Brownell |
36 * @author David Brownell |
41 */ |
37 */ |
42 final |
38 final class SessionId { |
43 class SessionId |
39 private static final int MAX_LENGTH = 32; |
44 { |
40 private final byte[] sessionId; // max 32 bytes |
45 static int MAX_LENGTH = 32; |
|
46 private byte[] sessionId; // max 32 bytes |
|
47 |
41 |
48 /** Constructs a new session ID ... perhaps for a rejoinable session */ |
42 // Constructs a new session ID ... perhaps for a rejoinable session |
49 SessionId (boolean isRejoinable, SecureRandom generator) |
43 SessionId(boolean isRejoinable, SecureRandom generator) { |
50 { |
44 if (isRejoinable && (generator != null)) { |
51 if (isRejoinable) |
45 sessionId = new RandomCookie(generator).randomBytes; |
52 // this will be unique, it's a timestamp plus much randomness |
46 } else { |
53 sessionId = new RandomCookie (generator).random_bytes; |
47 sessionId = new byte[0]; |
54 else |
48 } |
55 sessionId = new byte [0]; |
|
56 } |
49 } |
57 |
50 |
58 /** Constructs a session ID from a byte array (max size 32 bytes) */ |
51 // Constructs a session ID from a byte array (max size 32 bytes) |
59 SessionId (byte[] sessionId) |
52 SessionId(byte[] sessionId) { |
60 { this.sessionId = sessionId; } |
53 this.sessionId = sessionId.clone(); |
61 |
|
62 /** Returns the length of the ID, in bytes */ |
|
63 int length () |
|
64 { return sessionId.length; } |
|
65 |
|
66 /** Returns the bytes in the ID. May be an empty array. */ |
|
67 byte[] getId () |
|
68 { |
|
69 return sessionId.clone (); |
|
70 } |
54 } |
71 |
55 |
72 /** Returns the ID as a string */ |
56 // Returns the length of the ID, in bytes |
|
57 int length() { |
|
58 return sessionId.length; |
|
59 } |
|
60 |
|
61 // Returns the bytes in the ID. May be an empty array. |
|
62 byte[] getId() { |
|
63 return sessionId.clone(); |
|
64 } |
|
65 |
|
66 // Returns the ID as a string |
73 @Override |
67 @Override |
74 public String toString () |
68 public String toString() { |
75 { |
69 if (sessionId.length == 0) { |
76 int len = sessionId.length; |
70 return ""; |
77 StringBuilder sb = new StringBuilder (10 + 2 * len); |
71 } |
78 |
72 |
79 sb.append("{"); |
73 return Utilities.toHexString(sessionId); |
80 for (int i = 0; i < len; i++) { |
|
81 sb.append(0x0ff & sessionId[i]); |
|
82 if (i != (len - 1)) |
|
83 sb.append (", "); |
|
84 } |
|
85 sb.append("}"); |
|
86 return sb.toString (); |
|
87 } |
74 } |
88 |
75 |
89 |
76 |
90 /** Returns a value which is the same for session IDs which are equal */ |
77 // Returns a value which is the same for session IDs which are equal |
91 @Override |
78 @Override |
92 public int hashCode () |
79 public int hashCode() { |
93 { |
80 return Arrays.hashCode(sessionId); |
94 int retval = 0; |
|
95 |
|
96 for (int i = 0; i < sessionId.length; i++) |
|
97 retval += sessionId [i]; |
|
98 return retval; |
|
99 } |
81 } |
100 |
82 |
101 /** Returns true if the parameter is the same session ID */ |
83 // Returns true if the parameter is the same session ID |
102 @Override |
84 @Override |
103 public boolean equals (Object obj) |
85 public boolean equals (Object obj) { |
104 { |
86 if (obj == this) { |
105 if (!(obj instanceof SessionId)) |
87 return true; |
106 return false; |
88 } |
107 |
89 |
108 SessionId s = (SessionId) obj; |
90 if (obj instanceof SessionId) { |
109 byte[] b = s.getId (); |
91 SessionId that = (SessionId)obj; |
|
92 return Arrays.equals(this.sessionId, that.sessionId); |
|
93 } |
110 |
94 |
111 if (b.length != sessionId.length) |
95 return false; |
112 return false; |
|
113 for (int i = 0; i < sessionId.length; i++) { |
|
114 if (b [i] != sessionId [i]) |
|
115 return false; |
|
116 } |
|
117 return true; |
|
118 } |
96 } |
119 |
97 |
120 /** |
98 /** |
121 * Checks the length of the session ID to make sure it sits within |
99 * Checks the length of the session ID to make sure it sits within |
122 * the range called out in the specification |
100 * the range called out in the specification |
123 */ |
101 */ |
124 void checkLength(ProtocolVersion pv) throws SSLProtocolException { |
102 void checkLength(int protocolVersion) throws SSLProtocolException { |
125 // As of today all versions of TLS have a 32-byte maximum length. |
103 // As of today all versions of TLS have a 32-byte maximum length. |
126 // In the future we can do more here to support protocol versions |
104 // In the future we can do more here to support protocol versions |
127 // that may have longer max lengths. |
105 // that may have longer max lengths. |
128 if (sessionId.length > MAX_LENGTH) { |
106 if (sessionId.length > MAX_LENGTH) { |
129 throw new SSLProtocolException("Invalid session ID length (" + |
107 throw new SSLProtocolException("Invalid session ID length (" + |
130 sessionId.length + " bytes)"); |
108 sessionId.length + " bytes)"); |
131 } |
109 } |
132 } |
110 } |
133 |
|
134 } |
111 } |