Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: net/third_party/nss/ssl/sslnonce.c

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

Powered by Google App Engine
This is Rietveld 408576698