OLD | NEW |
1 /* | 1 /* |
2 * This file implements the CLIENT Session ID cache. | 2 * This file implements the CLIENT Session ID cache. |
3 * | 3 * |
4 * This Source Code Form is subject to the terms of the Mozilla Public | 4 * This Source Code Form is subject to the terms of the Mozilla Public |
5 * License, v. 2.0. If a copy of the MPL was not distributed with this | 5 * License, v. 2.0. If a copy of the MPL was not distributed with this |
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
7 | 7 |
8 #include "cert.h" | 8 #include "cert.h" |
9 #include "pk11pub.h" | 9 #include "pk11pub.h" |
10 #include "secitem.h" | 10 #include "secitem.h" |
11 #include "ssl.h" | 11 #include "ssl.h" |
12 #include "nss.h" | 12 #include "nss.h" |
13 | 13 |
14 #include "sslimpl.h" | 14 #include "sslimpl.h" |
15 #include "sslproto.h" | 15 #include "sslproto.h" |
16 #include "nssilock.h" | 16 #include "nssilock.h" |
17 #if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS) | 17 #if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS) |
18 #include <time.h> | 18 #include <time.h> |
19 #endif | 19 #endif |
20 | 20 |
21 PRUint32 ssl_sid_timeout = 100; | 21 PRUint32 ssl_sid_timeout = 100; |
22 PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */ | 22 PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */ |
23 | 23 |
24 static sslSessionID *cache = NULL; | 24 static sslSessionID *cache = NULL; |
25 static PZLock * cacheLock = NULL; | 25 static PZLock *cacheLock = NULL; |
26 | 26 |
27 /* sids can be in one of 4 states: | 27 /* sids can be in one of 4 states: |
28 * | 28 * |
29 * never_cached, » created, but not yet put into cache. | 29 * never_cached, created, but not yet put into cache. |
30 * in_client_cache, » in the client cache's linked list. | 30 * in_client_cache, in the client cache's linked list. |
31 * in_server_cache, » entry came from the server's cache file. | 31 * in_server_cache, entry came from the server's cache file. |
32 * invalid_cache» has been removed from the cache. | 32 * invalid_cache has been removed from the cache. |
33 */ | 33 */ |
34 | 34 |
35 #define LOCK_CACHE » lock_cache() | 35 #define LOCK_CACHE lock_cache() |
36 #define UNLOCK_CACHE» PZ_Unlock(cacheLock) | 36 #define UNLOCK_CACHE PZ_Unlock(cacheLock) |
37 | 37 |
38 static PRCallOnceType lockOnce; | 38 static PRCallOnceType lockOnce; |
39 | 39 |
40 /* FreeSessionCacheLocks is a callback from NSS_RegisterShutdown which destroys | 40 /* FreeSessionCacheLocks is a callback from NSS_RegisterShutdown which destroys |
41 * the session cache locks on shutdown and resets them to their initial | 41 * the session cache locks on shutdown and resets them to their initial |
42 * state. */ | 42 * state. */ |
43 static SECStatus | 43 static SECStatus |
44 FreeSessionCacheLocks(void* appData, void* nssData) | 44 FreeSessionCacheLocks(void *appData, void *nssData) |
45 { | 45 { |
46 static const PRCallOnceType pristineCallOnce; | 46 static const PRCallOnceType pristineCallOnce; |
47 SECStatus rv; | 47 SECStatus rv; |
48 | 48 |
49 if (!cacheLock) { | 49 if (!cacheLock) { |
50 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); | 50 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); |
51 return SECFailure; | 51 return SECFailure; |
52 } | 52 } |
53 | 53 |
54 PZ_DestroyLock(cacheLock); | 54 PZ_DestroyLock(cacheLock); |
(...skipping 30 matching lines...) Expand all Loading... |
85 | 85 |
86 rv = NSS_RegisterShutdown(FreeSessionCacheLocks, NULL); | 86 rv = NSS_RegisterShutdown(FreeSessionCacheLocks, NULL); |
87 PORT_Assert(SECSuccess == rv); | 87 PORT_Assert(SECSuccess == rv); |
88 if (SECSuccess != rv) { | 88 if (SECSuccess != rv) { |
89 return PR_FAILURE; | 89 return PR_FAILURE; |
90 } | 90 } |
91 return PR_SUCCESS; | 91 return PR_SUCCESS; |
92 } | 92 } |
93 | 93 |
94 SECStatus | 94 SECStatus |
95 ssl_InitSessionCacheLocks(void) | 95 ssl_InitSessionCacheLocks() |
96 { | 96 { |
97 return (PR_SUCCESS == | 97 return (PR_SUCCESS == |
98 PR_CallOnce(&lockOnce, InitSessionCacheLocks)) ? | 98 PR_CallOnce(&lockOnce, InitSessionCacheLocks)) |
99 SECSuccess : SECFailure; | 99 ? SECSuccess |
| 100 : SECFailure; |
100 } | 101 } |
101 | 102 |
102 static void | 103 static void |
103 lock_cache(void) | 104 lock_cache(void) |
104 { | 105 { |
105 ssl_InitSessionCacheLocks(); | 106 ssl_InitSessionCacheLocks(); |
106 PZ_Lock(cacheLock); | 107 PZ_Lock(cacheLock); |
107 } | 108 } |
108 | 109 |
109 /* BEWARE: This function gets called for both client and server SIDs !! | 110 /* BEWARE: This function gets called for both client and server SIDs !! |
110 * If the unreferenced sid is not in the cache, Free sid and its contents. | 111 * If the unreferenced sid is not in the cache, Free sid and its contents. |
111 */ | 112 */ |
112 static void | 113 static void |
113 ssl_DestroySID(sslSessionID *sid) | 114 ssl_DestroySID(sslSessionID *sid) |
114 { | 115 { |
115 int i; | 116 int i; |
116 SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached)); | 117 SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached)); |
117 PORT_Assert(sid->references == 0); | 118 PORT_Assert(sid->references == 0); |
118 PORT_Assert(sid->cached != in_client_cache); | 119 PORT_Assert(sid->cached != in_client_cache); |
119 | 120 |
120 if (sid->version < SSL_LIBRARY_VERSION_3_0) { | 121 if (sid->version < SSL_LIBRARY_VERSION_3_0) { |
121 » SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE); | 122 SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE); |
122 » SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE); | 123 SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE); |
123 } else { | 124 } else { |
124 if (sid->u.ssl3.locked.sessionTicket.ticket.data) { | 125 if (sid->u.ssl3.locked.sessionTicket.ticket.data) { |
125 SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, | 126 SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, |
126 PR_FALSE); | 127 PR_FALSE); |
127 } | 128 } |
128 if (sid->u.ssl3.srvName.data) { | 129 if (sid->u.ssl3.srvName.data) { |
129 SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE); | 130 SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE); |
130 } | 131 } |
| 132 if (sid->u.ssl3.signedCertTimestamps.data) { |
| 133 SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE); |
| 134 } |
131 if (sid->u.ssl3.originalHandshakeHash.data) { | 135 if (sid->u.ssl3.originalHandshakeHash.data) { |
132 SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE); | 136 SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE); |
133 } | 137 } |
134 if (sid->u.ssl3.signedCertTimestamps.data) { | |
135 SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE); | |
136 } | |
137 | 138 |
138 if (sid->u.ssl3.lock) { | 139 if (sid->u.ssl3.lock) { |
139 NSSRWLock_Destroy(sid->u.ssl3.lock); | 140 PR_DestroyRWLock(sid->u.ssl3.lock); |
140 } | 141 } |
141 } | 142 } |
142 | 143 |
143 if (sid->peerID != NULL) | 144 if (sid->peerID != NULL) |
144 » PORT_Free((void *)sid->peerID);»» /* CONST */ | 145 PORT_Free((void *)sid->peerID); /* CONST */ |
145 | 146 |
146 if (sid->urlSvrName != NULL) | 147 if (sid->urlSvrName != NULL) |
147 » PORT_Free((void *)sid->urlSvrName);» /* CONST */ | 148 PORT_Free((void *)sid->urlSvrName); /* CONST */ |
148 | 149 |
149 if ( sid->peerCert ) { | 150 if (sid->peerCert) { |
150 » CERT_DestroyCertificate(sid->peerCert); | 151 CERT_DestroyCertificate(sid->peerCert); |
151 } | 152 } |
152 for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) { | 153 for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) { |
153 CERT_DestroyCertificate(sid->peerCertChain[i]); | 154 CERT_DestroyCertificate(sid->peerCertChain[i]); |
154 } | 155 } |
155 if (sid->peerCertStatus.items) { | 156 if (sid->peerCertStatus.items) { |
156 SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE); | 157 SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE); |
157 } | 158 } |
158 | 159 |
159 if ( sid->localCert ) { | 160 if (sid->localCert) { |
160 » CERT_DestroyCertificate(sid->localCert); | 161 CERT_DestroyCertificate(sid->localCert); |
161 } | 162 } |
162 | 163 |
163 PORT_ZFree(sid, sizeof(sslSessionID)); | 164 PORT_ZFree(sid, sizeof(sslSessionID)); |
164 } | 165 } |
165 | 166 |
166 /* BEWARE: This function gets called for both client and server SIDs !! | 167 /* BEWARE: This function gets called for both client and server SIDs !! |
167 * Decrement reference count, and | 168 * Decrement reference count, and |
168 * free sid if ref count is zero, and sid is not in the cache. | 169 * free sid if ref count is zero, and sid is not in the cache. |
169 * Does NOT remove from the cache first. | 170 * Does NOT remove from the cache first. |
170 * If the sid is still in the cache, it is left there until next time | 171 * If the sid is still in the cache, it is left there until next time |
171 * the cache list is traversed. | 172 * the cache list is traversed. |
172 */ | 173 */ |
173 static void | 174 static void |
174 ssl_FreeLockedSID(sslSessionID *sid) | 175 ssl_FreeLockedSID(sslSessionID *sid) |
175 { | 176 { |
176 PORT_Assert(sid->references >= 1); | 177 PORT_Assert(sid->references >= 1); |
177 if (--sid->references == 0) { | 178 if (--sid->references == 0) { |
178 » ssl_DestroySID(sid); | 179 ssl_DestroySID(sid); |
179 } | 180 } |
180 } | 181 } |
181 | 182 |
182 /* BEWARE: This function gets called for both client and server SIDs !! | 183 /* BEWARE: This function gets called for both client and server SIDs !! |
183 * Decrement reference count, and | 184 * Decrement reference count, and |
184 * free sid if ref count is zero, and sid is not in the cache. | 185 * free sid if ref count is zero, and sid is not in the cache. |
185 * Does NOT remove from the cache first. | 186 * Does NOT remove from the cache first. |
186 * These locks are necessary because the sid _might_ be in the cache list. | 187 * These locks are necessary because the sid _might_ be in the cache list. |
187 */ | 188 */ |
188 void | 189 void |
189 ssl_FreeSID(sslSessionID *sid) | 190 ssl_FreeSID(sslSessionID *sid) |
190 { | 191 { |
191 LOCK_CACHE; | 192 LOCK_CACHE; |
192 ssl_FreeLockedSID(sid); | 193 ssl_FreeLockedSID(sid); |
193 UNLOCK_CACHE; | 194 UNLOCK_CACHE; |
194 } | 195 } |
195 | 196 |
196 /************************************************************************/ | 197 /************************************************************************/ |
197 | 198 |
198 /* | 199 /* |
199 ** Lookup sid entry in cache by Address, port, and peerID string. | 200 ** Lookup sid entry in cache by Address, port, and peerID string. |
200 ** If found, Increment reference count, and return pointer to caller. | 201 ** If found, Increment reference count, and return pointer to caller. |
201 ** If it has timed out or ref count is zero, remove from list and free it. | 202 ** If it has timed out or ref count is zero, remove from list and free it. |
202 */ | 203 */ |
203 | 204 |
204 sslSessionID * | 205 sslSessionID * |
205 ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID, | 206 ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID, |
206 const char * urlSvrName) | 207 const char *urlSvrName) |
207 { | 208 { |
208 sslSessionID **sidp; | 209 sslSessionID **sidp; |
209 sslSessionID * sid; | 210 sslSessionID *sid; |
210 PRUint32 now; | 211 PRUint32 now; |
211 | 212 |
212 if (!urlSvrName) | 213 if (!urlSvrName) |
213 » return NULL; | 214 return NULL; |
214 now = ssl_Time(); | 215 now = ssl_Time(); |
215 LOCK_CACHE; | 216 LOCK_CACHE; |
216 sidp = &cache; | 217 sidp = &cache; |
217 while ((sid = *sidp) != 0) { | 218 while ((sid = *sidp) != 0) { |
218 » PORT_Assert(sid->cached == in_client_cache); | 219 PORT_Assert(sid->cached == in_client_cache); |
219 » PORT_Assert(sid->references >= 1); | 220 PORT_Assert(sid->references >= 1); |
220 | 221 |
221 » SSL_TRC(8, ("SSL: Lookup1: sid=0x%x", sid)); | 222 SSL_TRC(8, ("SSL: Lookup1: sid=0x%x", sid)); |
222 | 223 |
223 » if (sid->expirationTime < now) { | 224 if (sid->expirationTime < now) { |
224 » /* | 225 /* |
225 » ** This session-id timed out. | 226 ** This session-id timed out. |
226 » ** Don't even care who it belongs to, blow it out of our cache. | 227 ** Don't even care who it belongs to, blow it out of our cache. |
227 » */ | 228 */ |
228 » SSL_TRC(7, ("SSL: lookup1, throwing sid out, age=%d refs=%d", | 229 SSL_TRC(7, ("SSL: lookup1, throwing sid out, age=%d refs=%d", |
229 » » » now - sid->creationTime, sid->references)); | 230 now - sid->creationTime, sid->references)); |
230 | 231 |
231 » *sidp = sid->next; »» » /* delink it from the list. */ | 232 *sidp = sid->next; /* delink it
from the list. */ |
232 » sid->cached = invalid_cache;» /* mark not on list. */ | 233 sid->cached = invalid_cache; /* mark not
on list. */ |
233 » ssl_FreeLockedSID(sid);» » /* drop ref count, free. */ | 234 ssl_FreeLockedSID(sid); /* drop ref
count, free. */ |
234 » } else if (!memcmp(&sid->addr, addr, sizeof(PRIPv6Addr)) && /* server IP
addr matches */ | 235 } else if (!memcmp(&sid->addr, addr, sizeof(PRIPv6Addr)) && /* server IP
addr matches */ |
235 » (sid->port == port) && /* server port matches */ | 236 (sid->port == port) && /* server po
rt matches */ |
236 » » /* proxy (peerID) matches */ | 237 /* proxy (peerID) matches */ |
237 » » (((peerID == NULL) && (sid->peerID == NULL)) || | 238 (((peerID == NULL) && (sid->peerID == NULL)) || |
238 » » ((peerID != NULL) && (sid->peerID != NULL) && | 239 ((peerID != NULL) && (sid->peerID != NULL) && |
239 » » PORT_Strcmp(sid->peerID, peerID) == 0)) && | 240 PORT_Strcmp(sid->peerID, peerID) == 0)) && |
240 » » /* is cacheable */ | 241 /* is cacheable */ |
241 » » (sid->version < SSL_LIBRARY_VERSION_3_0 || | 242 (sid->version < SSL_LIBRARY_VERSION_3_0 || |
242 » » sid->u.ssl3.keys.resumable) && | 243 sid->u.ssl3.keys.resumable) && |
243 » » /* server hostname matches. */ | 244 /* server hostname matches. */ |
244 » (sid->urlSvrName != NULL) && | 245 (sid->urlSvrName != NULL) && |
245 » » ((0 == PORT_Strcmp(urlSvrName, sid->urlSvrName)) || | 246 (0 == PORT_Strcmp(urlSvrName, sid->urlSvrName))) { |
246 » » ((sid->peerCert != NULL) && (SECSuccess == | 247 /* Hit */ |
247 » » CERT_VerifyCertName(sid->peerCert, urlSvrName))) ) | 248 sid->lastAccessTime = now; |
248 » » ) { | 249 sid->references++; |
249 » /* Hit */ | 250 break; |
250 » sid->lastAccessTime = now; | 251 } else { |
251 » sid->references++; | 252 sidp = &sid->next; |
252 » break; | 253 } |
253 » } else { | |
254 » sidp = &sid->next; | |
255 » } | |
256 } | 254 } |
257 UNLOCK_CACHE; | 255 UNLOCK_CACHE; |
258 return sid; | 256 return sid; |
259 } | 257 } |
260 | 258 |
261 /* | 259 /* |
262 ** Add an sid to the cache or return a previously cached entry to the cache. | 260 ** Add an sid to the cache or return a previously cached entry to the cache. |
263 ** Although this is static, it is called via ss->sec.cache(). | 261 ** Although this is static, it is called via ss->sec.cache(). |
264 */ | 262 */ |
265 static void | 263 static void |
266 CacheSID(sslSessionID *sid) | 264 CacheSID(sslSessionID *sid) |
267 { | 265 { |
268 PRUint32 expirationPeriod; | 266 PRUint32 expirationPeriod; |
269 | 267 |
270 PORT_Assert(sid->cached == never_cached); | 268 PORT_Assert(sid->cached == never_cached); |
271 | 269 |
272 SSL_TRC(8, ("SSL: Cache: sid=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%
04x " | 270 SSL_TRC(8, ("SSL: Cache: sid=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%
04x " |
273 » » "time=%x cached=%d", | 271 "time=%x cached=%d", |
274 » » sid, sid->cached, sid->addr.pr_s6_addr32[0], | 272 sid, sid->cached, sid->addr.pr_s6_addr32[0], |
275 » » sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2], | 273 sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2], |
276 » » sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime, | 274 sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime, |
277 » » sid->cached)); | 275 sid->cached)); |
278 | 276 |
279 if (!sid->urlSvrName) { | 277 if (!sid->urlSvrName) { |
280 /* don't cache this SID because it can never be matched */ | 278 /* don't cache this SID because it can never be matched */ |
281 return; | 279 return; |
282 } | 280 } |
283 | 281 |
284 /* XXX should be different trace for version 2 vs. version 3 */ | 282 /* XXX should be different trace for version 2 vs. version 3 */ |
285 if (sid->version < SSL_LIBRARY_VERSION_3_0) { | 283 if (sid->version < SSL_LIBRARY_VERSION_3_0) { |
286 » expirationPeriod = ssl_sid_timeout; | 284 expirationPeriod = ssl_sid_timeout; |
287 » PRINT_BUF(8, (0, "sessionID:", | 285 PRINT_BUF(8, (0, "sessionID:", |
288 » » sid->u.ssl2.sessionID, sizeof(sid->u.ssl2.sessionID))); | 286 sid->u.ssl2.sessionID, sizeof(sid->u.ssl2.sessionID))); |
289 » PRINT_BUF(8, (0, "masterKey:", | 287 PRINT_BUF(8, (0, "masterKey:", |
290 » » sid->u.ssl2.masterKey.data, sid->u.ssl2.masterKey.len)); | 288 sid->u.ssl2.masterKey.data, sid->u.ssl2.masterKey.len)); |
291 » PRINT_BUF(8, (0, "cipherArg:", | 289 PRINT_BUF(8, (0, "cipherArg:", |
292 » » sid->u.ssl2.cipherArg.data, sid->u.ssl2.cipherArg.len)); | 290 sid->u.ssl2.cipherArg.data, sid->u.ssl2.cipherArg.len)); |
293 } else { | 291 } else { |
294 » if (sid->u.ssl3.sessionIDLength == 0 && | 292 if (sid->u.ssl3.sessionIDLength == 0 && |
295 » sid->u.ssl3.locked.sessionTicket.ticket.data == NULL) | 293 sid->u.ssl3.locked.sessionTicket.ticket.data == NULL) |
296 » return; | 294 return; |
297 | 295 |
298 » /* Client generates the SessionID if this was a stateless resume. */ | 296 /* Client generates the SessionID if this was a stateless resume. */ |
299 » if (sid->u.ssl3.sessionIDLength == 0) { | 297 if (sid->u.ssl3.sessionIDLength == 0) { |
300 » SECStatus rv; | 298 SECStatus rv; |
301 » rv = PK11_GenerateRandom(sid->u.ssl3.sessionID, | 299 rv = PK11_GenerateRandom(sid->u.ssl3.sessionID, |
302 » » SSL3_SESSIONID_BYTES); | 300 SSL3_SESSIONID_BYTES); |
303 » if (rv != SECSuccess) | 301 if (rv != SECSuccess) |
304 » » return; | 302 return; |
305 » sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES; | 303 sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES; |
306 » } | 304 } |
307 » expirationPeriod = ssl3_sid_timeout; | 305 expirationPeriod = ssl3_sid_timeout; |
308 » PRINT_BUF(8, (0, "sessionID:", | 306 PRINT_BUF(8, (0, "sessionID:", |
309 » » sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength)); | 307 sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength)); |
310 | 308 |
311 » sid->u.ssl3.lock = NSSRWLock_New(NSS_RWLOCK_RANK_NONE, NULL); | 309 sid->u.ssl3.lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, NULL); |
312 » if (!sid->u.ssl3.lock) { | 310 if (!sid->u.ssl3.lock) { |
313 » return; | 311 return; |
314 » } | 312 } |
315 } | 313 } |
316 PORT_Assert(sid->creationTime != 0 && sid->expirationTime != 0); | 314 PORT_Assert(sid->creationTime != 0 && sid->expirationTime != 0); |
317 if (!sid->creationTime) | 315 if (!sid->creationTime) |
318 » sid->lastAccessTime = sid->creationTime = ssl_Time(); | 316 sid->lastAccessTime = sid->creationTime = ssl_Time(); |
319 if (!sid->expirationTime) | 317 if (!sid->expirationTime) |
320 » sid->expirationTime = sid->creationTime + expirationPeriod; | 318 sid->expirationTime = sid->creationTime + expirationPeriod; |
321 | 319 |
322 /* | 320 /* |
323 * Put sid into the cache. Bump reference count to indicate that | 321 * Put sid into the cache. Bump reference count to indicate that |
324 * cache is holding a reference. Uncache will reduce the cache | 322 * cache is holding a reference. Uncache will reduce the cache |
325 * reference. | 323 * reference. |
326 */ | 324 */ |
327 LOCK_CACHE; | 325 LOCK_CACHE; |
328 sid->references++; | 326 sid->references++; |
329 sid->cached = in_client_cache; | 327 sid->cached = in_client_cache; |
330 sid->next = cache; | 328 sid->next = cache; |
331 cache = sid; | 329 cache = sid; |
332 UNLOCK_CACHE; | 330 UNLOCK_CACHE; |
333 } | 331 } |
334 | 332 |
335 /* | 333 /* |
336 * If sid "zap" is in the cache, | 334 * If sid "zap" is in the cache, |
337 * removes sid from cache, and decrements reference count. | 335 * removes sid from cache, and decrements reference count. |
338 * Caller must hold cache lock. | 336 * Caller must hold cache lock. |
339 */ | 337 */ |
340 static void | 338 static void |
341 UncacheSID(sslSessionID *zap) | 339 UncacheSID(sslSessionID *zap) |
342 { | 340 { |
343 sslSessionID **sidp = &cache; | 341 sslSessionID **sidp = &cache; |
344 sslSessionID *sid; | 342 sslSessionID *sid; |
345 | 343 |
346 if (zap->cached != in_client_cache) { | 344 if (zap->cached != in_client_cache) { |
347 » return; | 345 return; |
348 } | 346 } |
349 | 347 |
350 SSL_TRC(8,("SSL: Uncache: zap=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x
%04x " | 348 SSL_TRC(8, ("SSL: Uncache: zap=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0
x%04x " |
351 » "time=%x cipher=%d", | 349 "time=%x cipher=%d", |
352 » zap, zap->cached, zap->addr.pr_s6_addr32[0], | 350 zap, zap->cached, zap->addr.pr_s6_addr32[0], |
353 » zap->addr.pr_s6_addr32[1], zap->addr.pr_s6_addr32[2], | 351 zap->addr.pr_s6_addr32[1], zap->addr.pr_s6_addr32[2], |
354 » zap->addr.pr_s6_addr32[3], zap->port, zap->creationTime, | 352 zap->addr.pr_s6_addr32[3], zap->port, zap->creationTime, |
355 » zap->u.ssl2.cipherType)); | 353 zap->u.ssl2.cipherType)); |
356 if (zap->version < SSL_LIBRARY_VERSION_3_0) { | 354 if (zap->version < SSL_LIBRARY_VERSION_3_0) { |
357 » PRINT_BUF(8, (0, "sessionID:", | 355 PRINT_BUF(8, (0, "sessionID:", |
358 » » zap->u.ssl2.sessionID, sizeof(zap->u.ssl2.sessionID))); | 356 zap->u.ssl2.sessionID, sizeof(zap->u.ssl2.sessionID))); |
359 » PRINT_BUF(8, (0, "masterKey:", | 357 PRINT_BUF(8, (0, "masterKey:", |
360 » » zap->u.ssl2.masterKey.data, zap->u.ssl2.masterKey.len)); | 358 zap->u.ssl2.masterKey.data, zap->u.ssl2.masterKey.len)); |
361 » PRINT_BUF(8, (0, "cipherArg:", | 359 PRINT_BUF(8, (0, "cipherArg:", |
362 » » zap->u.ssl2.cipherArg.data, zap->u.ssl2.cipherArg.len)); | 360 zap->u.ssl2.cipherArg.data, zap->u.ssl2.cipherArg.len)); |
363 } | 361 } |
364 | 362 |
365 /* See if it's in the cache, if so nuke it */ | 363 /* See if it's in the cache, if so nuke it */ |
366 while ((sid = *sidp) != 0) { | 364 while ((sid = *sidp) != 0) { |
367 » if (sid == zap) { | 365 if (sid == zap) { |
368 » /* | 366 /* |
369 » ** Bingo. Reduce reference count by one so that when | 367 ** Bingo. Reduce reference count by one so that when |
370 » ** everyone is done with the sid we can free it up. | 368 ** everyone is done with the sid we can free it up. |
371 » */ | 369 */ |
372 » *sidp = zap->next; | 370 *sidp = zap->next; |
373 » zap->cached = invalid_cache; | 371 zap->cached = invalid_cache; |
374 » ssl_FreeLockedSID(zap); | 372 ssl_FreeLockedSID(zap); |
375 » return; | 373 return; |
376 » } | 374 } |
377 » sidp = &sid->next; | 375 sidp = &sid->next; |
378 } | 376 } |
379 } | 377 } |
380 | 378 |
381 /* If sid "zap" is in the cache, | 379 /* If sid "zap" is in the cache, |
382 * removes sid from cache, and decrements reference count. | 380 * removes sid from cache, and decrements reference count. |
383 * Although this function is static, it is called externally via | 381 * Although this function is static, it is called externally via |
384 * ss->sec.uncache(). | 382 * ss->sec.uncache(). |
385 */ | 383 */ |
386 static void | 384 static void |
387 LockAndUncacheSID(sslSessionID *zap) | 385 LockAndUncacheSID(sslSessionID *zap) |
388 { | 386 { |
389 LOCK_CACHE; | 387 LOCK_CACHE; |
390 UncacheSID(zap); | 388 UncacheSID(zap); |
391 UNLOCK_CACHE; | 389 UNLOCK_CACHE; |
392 | |
393 } | 390 } |
394 | 391 |
395 /* choose client or server cache functions for this sslsocket. */ | 392 /* choose client or server cache functions for this sslsocket. */ |
396 void | 393 void |
397 ssl_ChooseSessionIDProcs(sslSecurityInfo *sec) | 394 ssl_ChooseSessionIDProcs(sslSecurityInfo *sec) |
398 { | 395 { |
399 if (sec->isServer) { | 396 if (sec->isServer) { |
400 » sec->cache = ssl_sid_cache; | 397 sec->cache = ssl_sid_cache; |
401 » sec->uncache = ssl_sid_uncache; | 398 sec->uncache = ssl_sid_uncache; |
402 } else { | 399 } else { |
403 » sec->cache = CacheSID; | 400 sec->cache = CacheSID; |
404 » sec->uncache = LockAndUncacheSID; | 401 sec->uncache = LockAndUncacheSID; |
405 } | 402 } |
406 } | 403 } |
407 | 404 |
408 /* wipe out the entire client session cache. */ | 405 /* wipe out the entire client session cache. */ |
409 void | 406 void |
410 SSL_ClearSessionCache(void) | 407 SSL_ClearSessionCache(void) |
411 { | 408 { |
412 LOCK_CACHE; | 409 LOCK_CACHE; |
413 while(cache != NULL) | 410 while (cache != NULL) |
414 » UncacheSID(cache); | 411 UncacheSID(cache); |
415 UNLOCK_CACHE; | 412 UNLOCK_CACHE; |
416 } | 413 } |
417 | 414 |
418 /* returns an unsigned int containing the number of seconds in PR_Now() */ | 415 /* returns an unsigned int containing the number of seconds in PR_Now() */ |
419 PRUint32 | 416 PRUint32 |
420 ssl_Time(void) | 417 ssl_Time(void) |
421 { | 418 { |
422 PRUint32 myTime; | 419 PRUint32 myTime; |
423 #if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS) | 420 #if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS) |
424 myTime = time(NULL);» /* accurate until the year 2038. */ | 421 myTime = time(NULL); /* accurate until the year 2038. */ |
425 #else | 422 #else |
426 /* portable, but possibly slower */ | 423 /* portable, but possibly slower */ |
427 PRTime now; | 424 PRTime now; |
428 PRInt64 ll; | 425 PRInt64 ll; |
429 | 426 |
430 now = PR_Now(); | 427 now = PR_Now(); |
431 LL_I2L(ll, 1000000L); | 428 LL_I2L(ll, 1000000L); |
432 LL_DIV(now, now, ll); | 429 LL_DIV(now, now, ll); |
433 LL_L2UI(myTime, now); | 430 LL_L2UI(myTime, now); |
434 #endif | 431 #endif |
435 return myTime; | 432 return myTime; |
436 } | 433 } |
437 | 434 |
438 void | 435 void |
439 ssl3_SetSIDSessionTicket(sslSessionID *sid, | 436 ssl3_SetSIDSessionTicket(sslSessionID *sid, |
440 /*in/out*/ NewSessionTicket *newSessionTicket) | 437 /*in/out*/ NewSessionTicket *newSessionTicket) |
441 { | 438 { |
442 PORT_Assert(sid); | 439 PORT_Assert(sid); |
443 PORT_Assert(newSessionTicket); | 440 PORT_Assert(newSessionTicket); |
444 PORT_Assert(newSessionTicket->ticket.data); | 441 PORT_Assert(newSessionTicket->ticket.data); |
445 PORT_Assert(newSessionTicket->ticket.len != 0); | 442 PORT_Assert(newSessionTicket->ticket.len != 0); |
446 | 443 |
447 /* if sid->u.ssl3.lock, we are updating an existing entry that is already | 444 /* if sid->u.ssl3.lock, we are updating an existing entry that is already |
448 * cached or was once cached, so we need to acquire and release the write | 445 * cached or was once cached, so we need to acquire and release the write |
449 * lock. Otherwise, this is a new session that isn't shared with anything | 446 * lock. Otherwise, this is a new session that isn't shared with anything |
450 * yet, so no locking is needed. | 447 * yet, so no locking is needed. |
451 */ | 448 */ |
452 if (sid->u.ssl3.lock) { | 449 if (sid->u.ssl3.lock) { |
453 » NSSRWLock_LockWrite(sid->u.ssl3.lock); | 450 PR_RWLock_Wlock(sid->u.ssl3.lock); |
454 » if (sid->u.ssl3.locked.sessionTicket.ticket.data) { | 451 if (sid->u.ssl3.locked.sessionTicket.ticket.data) { |
455 » SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, | 452 SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, |
456 » » » PR_FALSE); | 453 PR_FALSE); |
457 » } | 454 } |
458 } | 455 } |
459 | 456 |
460 PORT_Assert(!sid->u.ssl3.locked.sessionTicket.ticket.data); | 457 PORT_Assert(!sid->u.ssl3.locked.sessionTicket.ticket.data); |
461 | 458 |
462 /* Do a shallow copy, moving the ticket data. */ | 459 /* Do a shallow copy, moving the ticket data. */ |
463 sid->u.ssl3.locked.sessionTicket = *newSessionTicket; | 460 sid->u.ssl3.locked.sessionTicket = *newSessionTicket; |
464 newSessionTicket->ticket.data = NULL; | 461 newSessionTicket->ticket.data = NULL; |
465 newSessionTicket->ticket.len = 0; | 462 newSessionTicket->ticket.len = 0; |
466 | 463 |
467 if (sid->u.ssl3.lock) { | 464 if (sid->u.ssl3.lock) { |
468 » NSSRWLock_UnlockWrite(sid->u.ssl3.lock); | 465 PR_RWLock_Unlock(sid->u.ssl3.lock); |
469 } | 466 } |
470 } | 467 } |
OLD | NEW |