1
/* This file implements the SERVER Session ID cache.
2
* NOTE: The contents of this file are NOT used by the client.
4
* ***** BEGIN LICENSE BLOCK *****
5
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
7
* The contents of this file are subject to the Mozilla Public License Version
8
* 1.1 (the "License"); you may not use this file except in compliance with
9
* the License. You may obtain a copy of the License at
10
* http://www.mozilla.org/MPL/
12
* Software distributed under the License is distributed on an "AS IS" basis,
13
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14
* for the specific language governing rights and limitations under the
17
* The Original Code is the Netscape security libraries.
19
* The Initial Developer of the Original Code is
20
* Netscape Communications Corporation.
21
* Portions created by the Initial Developer are Copyright (C) 1994-2000
22
* the Initial Developer. All Rights Reserved.
26
* Alternatively, the contents of this file may be used under the terms of
27
* either the GNU General Public License Version 2 or later (the "GPL"), or
28
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
* in which case the provisions of the GPL or the LGPL are applicable instead
30
* of those above. If you wish to allow use of your version of this file only
31
* under the terms of either the GPL or the LGPL, and not to allow others to
32
* use your version of this file under the terms of the MPL, indicate your
33
* decision by deleting the provisions above and replace them with the notice
34
* and other provisions required by the GPL or the LGPL. If you do not delete
35
* the provisions above, a recipient may use your version of this file under
36
* the terms of any one of the MPL, the GPL or the LGPL.
38
* ***** END LICENSE BLOCK ***** */
39
/* $Id: sslsnce.c,v 1.36.2.2 2006/07/17 22:15:10 alexei.volkov.bugs%sun.com Exp $ */
41
/* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
44
* About record locking among different server processes:
46
* All processes that are part of the same conceptual server (serving on
47
* the same address and port) MUST share a common SSL session cache.
48
* This code makes the content of the shared cache accessible to all
49
* processes on the same "server". This code works on Unix and Win32 only.
51
* We use NSPR anonymous shared memory and move data to & from shared memory.
52
* We must do explicit locking of the records for all reads and writes.
53
* The set of Cache entries are divided up into "sets" of 128 entries.
54
* Each set is protected by a lock. There may be one or more sets protected
55
* by each lock. That is, locks to sets are 1:N.
56
* There is one lock for the entire cert cache.
57
* There is one lock for the set of wrapped sym wrap keys.
59
* The anonymous shared memory is laid out as if it were declared like this:
62
* cacheDescriptor desc;
63
* sidCacheLock sidCacheLocks[ numSIDCacheLocks];
64
* sidCacheLock keyCacheLock;
65
* sidCacheLock certCacheLock;
66
* sidCacheSet sidCacheSets[ numSIDCacheSets ];
67
* sidCacheEntry sidCacheData[ numSIDCacheEntries];
68
* certCacheEntry certCacheData[numCertCacheEntries];
69
* SSLWrappedSymWrappingKey keyCacheData[kt_kea_size][SSL_NUM_WRAP_MECHS];
70
* } cacheMemCacheData;
75
#if (defined(XP_UNIX) || defined(XP_WIN32) || defined (XP_OS2) || defined(XP_BEOS)) && !defined(_WIN32_WCE)
86
#if defined(XP_UNIX) || defined(XP_BEOS)
103
#include <sys/types.h>
105
#define SET_ERROR_CODE /* reminder */
108
#include "nsslocks.h"
109
#include "sslmutex.h"
116
** Format of a cache entry in the shared memory.
118
struct sidCacheEntryStr {
119
/* 16 */ PRIPv6Addr addr; /* client's IP address */
120
/* 4 */ PRUint32 creationTime;
121
/* 4 */ PRUint32 lastAccessTime;
122
/* 4 */ PRUint32 expirationTime;
123
/* 2 */ PRUint16 version;
124
/* 1 */ PRUint8 valid;
125
/* 1 */ PRUint8 sessionIDLength;
126
/* 32 */ PRUint8 sessionID[SSL3_SESSIONID_BYTES];
127
/* 2 */ PRUint16 authAlgorithm;
128
/* 2 */ PRUint16 authKeyBits;
129
/* 2 */ PRUint16 keaType;
130
/* 2 */ PRUint16 keaKeyBits;
131
/* 72 - common header total */
135
/* 64 */ PRUint8 masterKey[SSL_MAX_MASTER_KEY_BYTES];
136
/* 32 */ PRUint8 cipherArg[SSL_MAX_CYPHER_ARG_BYTES];
138
/* 1 */ PRUint8 cipherType;
139
/* 1 */ PRUint8 masterKeyLen;
140
/* 1 */ PRUint8 keyBits;
141
/* 1 */ PRUint8 secretKeyBits;
142
/* 1 */ PRUint8 cipherArgLen;
146
/* 2 */ ssl3CipherSuite cipherSuite;
147
/* 2 */ PRUint16 compression; /* SSL3CompressionMethod */
149
/*100 */ ssl3SidKeys keys; /* keys and ivs, wrapped as needed. */
151
/* 4 */ PRUint32 masterWrapMech;
152
/* 4 */ SSL3KEAType exchKeyType;
153
/* 4 */ PRInt32 certIndex;
155
#if defined(LINUX) /* XXX Why only on Linux ? */
157
PRUint8 filler[144]; /* XXX why this number ? */
162
typedef struct sidCacheEntryStr sidCacheEntry;
164
/* The length of this struct is supposed to be a power of 2, e.g. 4KB */
165
struct certCacheEntryStr {
166
PRUint16 certLength; /* 2 */
167
PRUint16 sessionIDLength; /* 2 */
168
PRUint8 sessionID[SSL3_SESSIONID_BYTES]; /* 32 */
169
PRUint8 cert[SSL_MAX_CACHED_CERT_LEN]; /* 4060 */
171
typedef struct certCacheEntryStr certCacheEntry;
173
struct sidCacheLockStr {
178
typedef struct sidCacheLockStr sidCacheLock;
180
struct sidCacheSetStr {
183
typedef struct sidCacheSetStr sidCacheSet;
185
struct cacheDescStr {
187
PRUint32 cacheMemSize;
189
PRUint32 numSIDCacheLocks;
190
PRUint32 numSIDCacheSets;
191
PRUint32 numSIDCacheSetsPerLock;
193
PRUint32 numSIDCacheEntries;
194
PRUint32 sidCacheSize;
196
PRUint32 numCertCacheEntries;
197
PRUint32 certCacheSize;
199
PRUint32 numKeyCacheEntries;
200
PRUint32 keyCacheSize;
202
PRUint32 ssl2Timeout;
203
PRUint32 ssl3Timeout;
205
PRUint32 numSIDCacheLocksInitialized;
207
/* These values are volatile, and are accessed through sharedCache-> */
208
PRUint32 nextCertCacheEntry; /* certCacheLock protects */
210
PRBool everInherited;
212
/* The private copies of these values are pointers into shared mem */
213
/* The copies of these values in shared memory are merely offsets */
214
sidCacheLock * sidCacheLocks;
215
sidCacheLock * keyCacheLock;
216
sidCacheLock * certCacheLock;
217
sidCacheSet * sidCacheSets;
218
sidCacheEntry * sidCacheData;
219
certCacheEntry * certCacheData;
220
SSLWrappedSymWrappingKey * keyCacheData;
222
/* Only the private copies of these pointers are valid */
224
struct cacheDescStr * sharedCache; /* shared copy of this struct */
225
PRFileMap * cacheMemMap;
229
typedef struct cacheDescStr cacheDesc;
231
static cacheDesc globalCache;
233
static const char envVarName[] = { SSL_ENV_VAR_NAME };
235
static PRBool isMultiProcess = PR_FALSE;
238
#define DEF_SID_CACHE_ENTRIES 10000
239
#define DEF_CERT_CACHE_ENTRIES 250
240
#define MIN_CERT_CACHE_ENTRIES 125 /* the effective size in old releases. */
241
#define DEF_KEY_CACHE_ENTRIES 250
243
#define SID_CACHE_ENTRIES_PER_SET 128
244
#define SID_ALIGNMENT 16
246
#define DEF_SSL2_TIMEOUT 100 /* seconds */
247
#define MAX_SSL2_TIMEOUT 100 /* seconds */
248
#define MIN_SSL2_TIMEOUT 5 /* seconds */
250
#define DEF_SSL3_TIMEOUT 86400L /* 24 hours */
251
#define MAX_SSL3_TIMEOUT 86400L /* 24 hours */
252
#define MIN_SSL3_TIMEOUT 5 /* seconds */
254
#if defined(AIX) || defined(LINUX) || defined(VMS)
255
#define MAX_SID_CACHE_LOCKS 8 /* two FDs per lock */
257
#define MAX_SID_CACHE_LOCKS 16 /* one FD per lock */
259
#define MAX_SID_CACHE_LOCKS 256
262
#define SID_HOWMANY(val, size) (((val) + ((size) - 1)) / (size))
263
#define SID_ROUNDUP(val, size) ((size) * SID_HOWMANY((val), (size)))
267
static PRUint32 ssl_max_sid_cache_locks = MAX_SID_CACHE_LOCKS;
269
/* forward static function declarations */
270
static PRUint32 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s,
272
static SECStatus LaunchLockPoller(cacheDesc *cache);
275
struct inheritanceStr {
276
PRUint32 cacheMemSize;
280
typedef struct inheritanceStr inheritance;
282
#if defined(_WIN32) || defined(XP_OS2)
284
#define DEFAULT_CACHE_DIRECTORY "\\temp"
288
#if defined(XP_UNIX) || defined(XP_BEOS)
290
#define DEFAULT_CACHE_DIRECTORY "/tmp"
292
#endif /* XP_UNIX || XP_BEOS */
295
/************************************************************************/
298
LockSidCacheLock(sidCacheLock *lock, PRUint32 now)
300
SECStatus rv = sslMutex_Lock(&lock->mutex);
301
if (rv != SECSuccess)
305
lock->timeStamp = now;
311
UnlockSidCacheLock(sidCacheLock *lock)
316
rv = sslMutex_Unlock(&lock->mutex);
320
/* returns the value of ssl_Time on success, zero on failure. */
322
LockSet(cacheDesc *cache, PRUint32 set, PRUint32 now)
324
PRUint32 lockNum = set % cache->numSIDCacheLocks;
325
sidCacheLock * lock = cache->sidCacheLocks + lockNum;
327
return LockSidCacheLock(lock, now);
331
UnlockSet(cacheDesc *cache, PRUint32 set)
333
PRUint32 lockNum = set % cache->numSIDCacheLocks;
334
sidCacheLock * lock = cache->sidCacheLocks + lockNum;
336
return UnlockSidCacheLock(lock);
339
/************************************************************************/
342
/* Put a certificate in the cache. Update the cert index in the sce.
345
CacheCert(cacheDesc * cache, CERTCertificate *cert, sidCacheEntry *sce)
350
if ((cert->derCert.len > SSL_MAX_CACHED_CERT_LEN) ||
351
(cert->derCert.len <= 0) ||
352
(cert->derCert.data == NULL)) {
353
PORT_SetError(SEC_ERROR_INVALID_ARGS);
357
cce.sessionIDLength = sce->sessionIDLength;
358
PORT_Memcpy(cce.sessionID, sce->sessionID, cce.sessionIDLength);
360
cce.certLength = cert->derCert.len;
361
PORT_Memcpy(cce.cert, cert->derCert.data, cce.certLength);
363
/* get lock on cert cache */
364
now = LockSidCacheLock(cache->certCacheLock, 0);
367
/* Find where to place the next cert cache entry. */
368
cacheDesc * sharedCache = cache->sharedCache;
369
PRUint32 ndx = sharedCache->nextCertCacheEntry;
371
/* write the entry */
372
cache->certCacheData[ndx] = cce;
374
/* remember where we put it. */
375
sce->u.ssl3.certIndex = ndx;
377
/* update the "next" cache entry index */
378
sharedCache->nextCertCacheEntry =
379
(ndx + 1) % cache->numCertCacheEntries;
381
UnlockSidCacheLock(cache->certCacheLock);
388
** Convert local SID to shared memory one
391
ConvertFromSID(sidCacheEntry *to, sslSessionID *from)
394
to->version = from->version;
395
to->addr = from->addr;
396
to->creationTime = from->creationTime;
397
to->lastAccessTime = from->lastAccessTime;
398
to->expirationTime = from->expirationTime;
399
to->authAlgorithm = from->authAlgorithm;
400
to->authKeyBits = from->authKeyBits;
401
to->keaType = from->keaType;
402
to->keaKeyBits = from->keaKeyBits;
404
if (from->version < SSL_LIBRARY_VERSION_3_0) {
405
if ((from->u.ssl2.masterKey.len > SSL_MAX_MASTER_KEY_BYTES) ||
406
(from->u.ssl2.cipherArg.len > SSL_MAX_CYPHER_ARG_BYTES)) {
407
SSL_DBG(("%d: SSL: masterKeyLen=%d cipherArgLen=%d",
408
myPid, from->u.ssl2.masterKey.len,
409
from->u.ssl2.cipherArg.len));
414
to->u.ssl2.cipherType = from->u.ssl2.cipherType;
415
to->u.ssl2.masterKeyLen = from->u.ssl2.masterKey.len;
416
to->u.ssl2.cipherArgLen = from->u.ssl2.cipherArg.len;
417
to->u.ssl2.keyBits = from->u.ssl2.keyBits;
418
to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
419
to->sessionIDLength = SSL2_SESSIONID_BYTES;
420
PORT_Memcpy(to->sessionID, from->u.ssl2.sessionID, SSL2_SESSIONID_BYTES);
421
PORT_Memcpy(to->u.ssl2.masterKey, from->u.ssl2.masterKey.data,
422
from->u.ssl2.masterKey.len);
423
PORT_Memcpy(to->u.ssl2.cipherArg, from->u.ssl2.cipherArg.data,
424
from->u.ssl2.cipherArg.len);
426
PORT_Memset(to->u.ssl2.masterKey+from->u.ssl2.masterKey.len, 0,
427
sizeof(to->u.ssl2.masterKey) - from->u.ssl2.masterKey.len);
428
PORT_Memset(to->u.ssl2.cipherArg+from->u.ssl2.cipherArg.len, 0,
429
sizeof(to->u.ssl2.cipherArg) - from->u.ssl2.cipherArg.len);
431
SSL_TRC(8, ("%d: SSL: ConvertSID: masterKeyLen=%d cipherArgLen=%d "
432
"time=%d addr=0x%08x%08x%08x%08x cipherType=%d", myPid,
433
to->u.ssl2.masterKeyLen, to->u.ssl2.cipherArgLen,
434
to->creationTime, to->addr.pr_s6_addr32[0],
435
to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
436
to->addr.pr_s6_addr32[3], to->u.ssl2.cipherType));
438
/* This is an SSL v3 session */
440
to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
441
to->u.ssl3.compression = (uint16)from->u.ssl3.compression;
442
to->u.ssl3.keys = from->u.ssl3.keys;
443
to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
444
to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
445
to->sessionIDLength = from->u.ssl3.sessionIDLength;
446
to->u.ssl3.certIndex = -1;
448
PORT_Memcpy(to->sessionID, from->u.ssl3.sessionID,
449
to->sessionIDLength);
451
SSL_TRC(8, ("%d: SSL3: ConvertSID: time=%d addr=0x%08x%08x%08x%08x "
453
myPid, to->creationTime, to->addr.pr_s6_addr32[0],
454
to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
455
to->addr.pr_s6_addr32[3], to->u.ssl3.cipherSuite));
460
** Convert shared memory cache-entry to local memory based one
461
** This is only called from ServerSessionIDLookup().
462
** Caller must hold cache lock when calling this.
464
static sslSessionID *
465
ConvertToSID(sidCacheEntry *from, certCacheEntry *pcce,
466
CERTCertDBHandle * dbHandle)
469
uint16 version = from->version;
471
to = (sslSessionID*) PORT_ZAlloc(sizeof(sslSessionID));
476
if (version < SSL_LIBRARY_VERSION_3_0) {
477
/* This is an SSL v2 session */
478
to->u.ssl2.masterKey.data =
479
(unsigned char*) PORT_Alloc(from->u.ssl2.masterKeyLen);
480
if (!to->u.ssl2.masterKey.data) {
483
if (from->u.ssl2.cipherArgLen) {
484
to->u.ssl2.cipherArg.data =
485
(unsigned char*)PORT_Alloc(from->u.ssl2.cipherArgLen);
486
if (!to->u.ssl2.cipherArg.data) {
489
PORT_Memcpy(to->u.ssl2.cipherArg.data, from->u.ssl2.cipherArg,
490
from->u.ssl2.cipherArgLen);
493
to->u.ssl2.cipherType = from->u.ssl2.cipherType;
494
to->u.ssl2.masterKey.len = from->u.ssl2.masterKeyLen;
495
to->u.ssl2.cipherArg.len = from->u.ssl2.cipherArgLen;
496
to->u.ssl2.keyBits = from->u.ssl2.keyBits;
497
to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
498
/* to->sessionIDLength = SSL2_SESSIONID_BYTES; */
499
PORT_Memcpy(to->u.ssl2.sessionID, from->sessionID, SSL2_SESSIONID_BYTES);
500
PORT_Memcpy(to->u.ssl2.masterKey.data, from->u.ssl2.masterKey,
501
from->u.ssl2.masterKeyLen);
503
SSL_TRC(8, ("%d: SSL: ConvertToSID: masterKeyLen=%d cipherArgLen=%d "
504
"time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
505
myPid, to->u.ssl2.masterKey.len,
506
to->u.ssl2.cipherArg.len, to->creationTime,
507
to->addr.pr_s6_addr32[0], to->addr.pr_s6_addr32[1],
508
to->addr.pr_s6_addr32[2], to->addr.pr_s6_addr32[3],
509
to->u.ssl2.cipherType));
511
/* This is an SSL v3 session */
513
to->u.ssl3.sessionIDLength = from->sessionIDLength;
514
to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
515
to->u.ssl3.compression = (SSL3CompressionMethod)from->u.ssl3.compression;
516
to->u.ssl3.keys = from->u.ssl3.keys;
517
to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
518
to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
520
PORT_Memcpy(to->u.ssl3.sessionID, from->sessionID, from->sessionIDLength);
522
/* the portions of the SID that are only restored on the client
523
* are set to invalid values on the server.
525
to->u.ssl3.clientWriteKey = NULL;
526
to->u.ssl3.serverWriteKey = NULL;
528
to->urlSvrName = NULL;
530
to->u.ssl3.masterModuleID = (SECMODModuleID)-1; /* invalid value */
531
to->u.ssl3.masterSlotID = (CK_SLOT_ID)-1; /* invalid value */
532
to->u.ssl3.masterWrapIndex = 0;
533
to->u.ssl3.masterWrapSeries = 0;
534
to->u.ssl3.masterValid = PR_FALSE;
536
to->u.ssl3.clAuthModuleID = (SECMODModuleID)-1; /* invalid value */
537
to->u.ssl3.clAuthSlotID = (CK_SLOT_ID)-1; /* invalid value */
538
to->u.ssl3.clAuthSeries = 0;
539
to->u.ssl3.clAuthValid = PR_FALSE;
541
if (from->u.ssl3.certIndex != -1 && pcce) {
544
derCert.len = pcce->certLength;
545
derCert.data = pcce->cert;
547
to->peerCert = CERT_NewTempCertificate(dbHandle, &derCert, NULL,
549
if (to->peerCert == NULL)
554
to->version = from->version;
555
to->creationTime = from->creationTime;
556
to->lastAccessTime = from->lastAccessTime;
557
to->expirationTime = from->expirationTime;
558
to->cached = in_server_cache;
559
to->addr = from->addr;
561
to->authAlgorithm = from->authAlgorithm;
562
to->authKeyBits = from->authKeyBits;
563
to->keaType = from->keaType;
564
to->keaKeyBits = from->keaKeyBits;
570
if (version < SSL_LIBRARY_VERSION_3_0) {
571
if (to->u.ssl2.masterKey.data)
572
PORT_Free(to->u.ssl2.masterKey.data);
573
if (to->u.ssl2.cipherArg.data)
574
PORT_Free(to->u.ssl2.cipherArg.data);
584
** Perform some mumbo jumbo on the ip-address and the session-id value to
585
** compute a hash value.
588
SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s, unsigned nl)
593
memset(x, 0, sizeof x);
598
rv = (addr->pr_s6_addr32[0] ^ addr->pr_s6_addr32[1] ^
599
addr->pr_s6_addr32[2] ^ addr->pr_s6_addr32[3] ^
600
x[0] ^ x[1] ^ x[2] ^ x[3] ^ x[4] ^ x[5] ^ x[6] ^ x[7])
601
% cache->numSIDCacheSets;
608
** Look something up in the cache. This will invalidate old entries
609
** in the process. Caller has locked the cache set!
610
** Returns PR_TRUE if found a valid match. PR_FALSE otherwise.
612
static sidCacheEntry *
613
FindSID(cacheDesc *cache, PRUint32 setNum, PRUint32 now,
614
const PRIPv6Addr *addr, unsigned char *sessionID,
615
unsigned sessionIDLength)
617
PRUint32 ndx = cache->sidCacheSets[setNum].next;
620
sidCacheEntry * set = cache->sidCacheData +
621
(setNum * SID_CACHE_ENTRIES_PER_SET);
623
for (i = SID_CACHE_ENTRIES_PER_SET; i > 0; --i) {
626
ndx = (ndx - 1) % SID_CACHE_ENTRIES_PER_SET;
632
if (now > sce->expirationTime) {
633
/* SessionID has timed out. Invalidate the entry. */
634
SSL_TRC(7, ("%d: timed out sid entry addr=%08x%08x%08x%08x now=%x "
636
myPid, sce->addr.pr_s6_addr32[0],
637
sce->addr.pr_s6_addr32[1], sce->addr.pr_s6_addr32[2],
638
sce->addr.pr_s6_addr32[3], now,
639
sce->expirationTime ));
645
** Next, examine specific session-id/addr data to see if the cache
646
** entry matches our addr+session-id value
648
if (sessionIDLength == sce->sessionIDLength &&
649
!memcmp(&sce->addr, addr, sizeof(PRIPv6Addr)) &&
650
!memcmp(sce->sessionID, sessionID, sessionIDLength)) {
656
PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND);
660
/************************************************************************/
662
/* This is the primary function for finding entries in the server's sid cache.
663
* Although it is static, this function is called via the global function
664
* pointer ssl_sid_lookup.
666
static sslSessionID *
667
ServerSessionIDLookup(const PRIPv6Addr *addr,
668
unsigned char *sessionID,
669
unsigned int sessionIDLength,
670
CERTCertDBHandle * dbHandle)
672
sslSessionID * sid = 0;
673
sidCacheEntry * psce;
674
certCacheEntry *pcce = 0;
675
cacheDesc * cache = &globalCache;
682
set = SIDindex(cache, addr, sessionID, sessionIDLength);
683
now = LockSet(cache, set, 0);
687
psce = FindSID(cache, set, now, addr, sessionID, sessionIDLength);
689
if (psce->version >= SSL_LIBRARY_VERSION_3_0 &&
690
(cndx = psce->u.ssl3.certIndex) != -1) {
692
PRUint32 gotLock = LockSidCacheLock(cache->certCacheLock, now);
694
pcce = &cache->certCacheData[cndx];
696
/* See if the cert's session ID matches the sce cache. */
697
if ((pcce->sessionIDLength == psce->sessionIDLength) &&
698
!PORT_Memcmp(pcce->sessionID, psce->sessionID,
699
pcce->sessionIDLength)) {
702
/* The cert doesen't match the SID cache entry,
703
** so invalidate the SID cache entry.
709
UnlockSidCacheLock(cache->certCacheLock);
711
/* what the ??. Didn't get the cert cache lock.
712
** Don't invalidate the SID cache entry, but don't find it.
714
PORT_Assert(!("Didn't get cert Cache Lock!"));
720
psce->lastAccessTime = now;
721
sce = *psce; /* grab a copy while holding the lock */
724
UnlockSet(cache, set);
726
/* sce conains a copy of the cache entry.
727
** Convert shared memory format to local format
729
sid = ConvertToSID(&sce, pcce ? &cce : 0, dbHandle);
735
** Place a sid into the cache, if it isn't already there.
738
ServerSessionIDCache(sslSessionID *sid)
742
uint16 version = sid->version;
743
cacheDesc * cache = &globalCache;
745
if ((version >= SSL_LIBRARY_VERSION_3_0) &&
746
(sid->u.ssl3.sessionIDLength == 0)) {
750
if (sid->cached == never_cached || sid->cached == invalid_cache) {
753
PORT_Assert(sid->creationTime != 0);
754
if (!sid->creationTime)
755
sid->lastAccessTime = sid->creationTime = ssl_Time();
756
if (version < SSL_LIBRARY_VERSION_3_0) {
757
/* override caller's expiration time, which uses client timeout
758
* duration, not server timeout duration.
760
sid->expirationTime = sid->creationTime + cache->ssl2Timeout;
761
SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
762
"cipher=%d", myPid, sid->cached,
763
sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
764
sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
765
sid->creationTime, sid->u.ssl2.cipherType));
766
PRINT_BUF(8, (0, "sessionID:", sid->u.ssl2.sessionID,
767
SSL2_SESSIONID_BYTES));
768
PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
769
sid->u.ssl2.masterKey.len));
770
PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
771
sid->u.ssl2.cipherArg.len));
774
/* override caller's expiration time, which uses client timeout
775
* duration, not server timeout duration.
777
sid->expirationTime = sid->creationTime + cache->ssl3Timeout;
778
SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
779
"cipherSuite=%d", myPid, sid->cached,
780
sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
781
sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
782
sid->creationTime, sid->u.ssl3.cipherSuite));
783
PRINT_BUF(8, (0, "sessionID:", sid->u.ssl3.sessionID,
784
sid->u.ssl3.sessionIDLength));
787
ConvertFromSID(&sce, sid);
789
if ((version >= SSL_LIBRARY_VERSION_3_0) &&
790
(sid->peerCert != NULL)) {
791
now = CacheCert(cache, sid->peerCert, &sce);
794
set = SIDindex(cache, &sce.addr, sce.sessionID, sce.sessionIDLength);
795
now = LockSet(cache, set, now);
797
PRUint32 next = cache->sidCacheSets[set].next;
798
PRUint32 ndx = set * SID_CACHE_ENTRIES_PER_SET + next;
800
/* Write out new cache entry */
801
cache->sidCacheData[ndx] = sce;
803
cache->sidCacheSets[set].next =
804
(next + 1) % SID_CACHE_ENTRIES_PER_SET;
806
UnlockSet(cache, set);
807
sid->cached = in_server_cache;
813
** Although this is static, it is called from ssl via global function pointer
814
** ssl_sid_uncache. This invalidates the referenced cache entry.
817
ServerSessionIDUncache(sslSessionID *sid)
819
cacheDesc * cache = &globalCache;
821
unsigned int sessionIDLength;
830
/* Uncaching a SID should never change the error code.
831
** So save it here and restore it before exiting.
835
if (sid->version < SSL_LIBRARY_VERSION_3_0) {
836
sessionID = sid->u.ssl2.sessionID;
837
sessionIDLength = SSL2_SESSIONID_BYTES;
838
SSL_TRC(8, ("%d: SSL: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
839
"cipher=%d", myPid, sid->cached,
840
sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
841
sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
842
sid->creationTime, sid->u.ssl2.cipherType));
843
PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
844
PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
845
sid->u.ssl2.masterKey.len));
846
PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
847
sid->u.ssl2.cipherArg.len));
849
sessionID = sid->u.ssl3.sessionID;
850
sessionIDLength = sid->u.ssl3.sessionIDLength;
851
SSL_TRC(8, ("%d: SSL3: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
852
"cipherSuite=%d", myPid, sid->cached,
853
sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
854
sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
855
sid->creationTime, sid->u.ssl3.cipherSuite));
856
PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
858
set = SIDindex(cache, &sid->addr, sessionID, sessionIDLength);
859
now = LockSet(cache, set, 0);
861
psce = FindSID(cache, set, now, &sid->addr, sessionID, sessionIDLength);
865
UnlockSet(cache, set);
867
sid->cached = invalid_cache;
873
#define INCL_DOSPROCESS
880
DosGetInfoBlocks(&ptib, &ppib);
881
return ((long)ptib->tib_ordinal); /* thread id */
886
CloseCache(cacheDesc *cache)
888
int locks_initialized = cache->numSIDCacheLocksInitialized;
890
if (cache->cacheMem) {
891
/* If everInherited is true, this shared cache was (and may still
892
** be) in use by multiple processes. We do not wish to destroy
893
** the mutexes while they are still in use.
895
if (cache->sharedCache &&
896
PR_FALSE == cache->sharedCache->everInherited) {
897
sidCacheLock *pLock = cache->sidCacheLocks;
898
for (; locks_initialized > 0; --locks_initialized, ++pLock ) {
899
sslMutex_Destroy(&pLock->mutex);
903
PR_MemUnmap(cache->cacheMem, cache->cacheMemSize);
905
PORT_Free(cache->cacheMem);
907
cache->cacheMem = NULL;
909
if (cache->cacheMemMap) {
910
PR_CloseFileMap(cache->cacheMemMap);
911
cache->cacheMemMap = NULL;
913
memset(cache, 0, sizeof *cache);
917
InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
918
PRUint32 ssl3_timeout, const char *directory, PRBool shared)
923
PRFileMap * cacheMemMap;
924
char * cfn = NULL; /* cache file name */
925
int locks_initialized = 0;
926
int locks_to_initialize = 0;
929
if ( (!cache) || (maxCacheEntries < 0) || (!directory) ) {
930
PORT_SetError(SEC_ERROR_INVALID_ARGS);
934
if (cache->cacheMem) {
939
/* make sure loser can clean up properly */
940
cache->shared = shared;
941
cache->cacheMem = cacheMem = NULL;
942
cache->cacheMemMap = cacheMemMap = NULL;
943
cache->sharedCache = (cacheDesc *)0;
945
cache->numSIDCacheLocksInitialized = 0;
946
cache->nextCertCacheEntry = 0;
947
cache->stopPolling = PR_FALSE;
948
cache->everInherited = PR_FALSE;
949
cache->poller = NULL;
951
cache->numSIDCacheEntries = maxCacheEntries ? maxCacheEntries
952
: DEF_SID_CACHE_ENTRIES;
953
cache->numSIDCacheSets =
954
SID_HOWMANY(cache->numSIDCacheEntries, SID_CACHE_ENTRIES_PER_SET);
956
cache->numSIDCacheEntries =
957
cache->numSIDCacheSets * SID_CACHE_ENTRIES_PER_SET;
959
cache->numSIDCacheLocks =
960
PR_MIN(cache->numSIDCacheSets, ssl_max_sid_cache_locks);
962
cache->numSIDCacheSetsPerLock =
963
SID_HOWMANY(cache->numSIDCacheSets, cache->numSIDCacheLocks);
965
/* compute size of shared memory, and offsets of all pointers */
967
cache->cacheMem = (char *)ptr;
968
ptr += SID_ROUNDUP(sizeof(cacheDesc), SID_ALIGNMENT);
970
cache->sidCacheLocks = (sidCacheLock *)ptr;
971
cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
972
cache->certCacheLock = cache->keyCacheLock + 1;
973
ptr = (ptrdiff_t)(cache->certCacheLock + 1);
974
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
976
cache->sidCacheSets = (sidCacheSet *)ptr;
977
ptr = (ptrdiff_t)(cache->sidCacheSets + cache->numSIDCacheSets);
978
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
980
cache->sidCacheData = (sidCacheEntry *)ptr;
981
ptr = (ptrdiff_t)(cache->sidCacheData + cache->numSIDCacheEntries);
982
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
984
cache->certCacheData = (certCacheEntry *)ptr;
985
cache->sidCacheSize =
986
(char *)cache->certCacheData - (char *)cache->sidCacheData;
988
/* This is really a poor way to computer this! */
989
cache->numCertCacheEntries = cache->sidCacheSize / sizeof(certCacheEntry);
990
if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES)
991
cache->numCertCacheEntries = MIN_CERT_CACHE_ENTRIES;
992
ptr = (ptrdiff_t)(cache->certCacheData + cache->numCertCacheEntries);
993
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
995
cache->keyCacheData = (SSLWrappedSymWrappingKey *)ptr;
996
cache->certCacheSize =
997
(char *)cache->keyCacheData - (char *)cache->certCacheData;
999
cache->numKeyCacheEntries = kt_kea_size * SSL_NUM_WRAP_MECHS;
1000
ptr = (ptrdiff_t)(cache->keyCacheData + cache->numKeyCacheEntries);
1001
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1003
cache->cacheMemSize = ptr;
1005
cache->keyCacheSize = (char *)ptr - (char *)cache->keyCacheData;
1008
if (ssl2_timeout > MAX_SSL2_TIMEOUT) {
1009
ssl2_timeout = MAX_SSL2_TIMEOUT;
1011
if (ssl2_timeout < MIN_SSL2_TIMEOUT) {
1012
ssl2_timeout = MIN_SSL2_TIMEOUT;
1014
cache->ssl2Timeout = ssl2_timeout;
1016
cache->ssl2Timeout = DEF_SSL2_TIMEOUT;
1020
if (ssl3_timeout > MAX_SSL3_TIMEOUT) {
1021
ssl3_timeout = MAX_SSL3_TIMEOUT;
1023
if (ssl3_timeout < MIN_SSL3_TIMEOUT) {
1024
ssl3_timeout = MIN_SSL3_TIMEOUT;
1026
cache->ssl3Timeout = ssl3_timeout;
1028
cache->ssl3Timeout = DEF_SSL3_TIMEOUT;
1032
/* Create file names */
1033
#if defined(XP_UNIX) || defined(XP_BEOS)
1034
/* there's some confusion here about whether PR_OpenAnonFileMap wants
1035
** a directory name or a file name for its first argument.
1036
cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid);
1038
cfn = PR_smprintf("%s", directory);
1039
#elif defined(XP_WIN32)
1040
cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
1041
GetCurrentThreadId());
1042
#elif defined(XP_OS2)
1043
cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
1046
#error "Don't know how to create file name for this platform!"
1053
cacheMemMap = PR_OpenAnonFileMap(cfn, cache->cacheMemSize,
1056
PR_smprintf_free(cfn);
1061
cacheMem = PR_MemMap(cacheMemMap, 0, cache->cacheMemSize);
1063
cacheMem = PORT_Alloc(cache->cacheMemSize);
1070
/* Initialize shared memory. This may not be necessary on all platforms */
1071
memset(cacheMem, 0, cache->cacheMemSize);
1073
/* Copy cache descriptor header into shared memory */
1074
memcpy(cacheMem, cache, sizeof *cache);
1076
/* save private copies of these values */
1077
cache->cacheMemMap = cacheMemMap;
1078
cache->cacheMem = cacheMem;
1079
cache->sharedCache = (cacheDesc *)cacheMem;
1081
/* Fix pointers in our private copy of cache descriptor to point to
1082
** spaces in shared memory
1084
ptr = (ptrdiff_t)cache->cacheMem;
1085
*(ptrdiff_t *)(&cache->sidCacheLocks) += ptr;
1086
*(ptrdiff_t *)(&cache->keyCacheLock ) += ptr;
1087
*(ptrdiff_t *)(&cache->certCacheLock) += ptr;
1088
*(ptrdiff_t *)(&cache->sidCacheSets ) += ptr;
1089
*(ptrdiff_t *)(&cache->sidCacheData ) += ptr;
1090
*(ptrdiff_t *)(&cache->certCacheData) += ptr;
1091
*(ptrdiff_t *)(&cache->keyCacheData ) += ptr;
1093
/* initialize the locks */
1094
init_time = ssl_Time();
1095
pLock = cache->sidCacheLocks;
1096
for (locks_to_initialize = cache->numSIDCacheLocks + 2;
1097
locks_initialized < locks_to_initialize;
1098
++locks_initialized, ++pLock ) {
1100
SECStatus err = sslMutex_Init(&pLock->mutex, shared);
1102
cache->numSIDCacheLocksInitialized = locks_initialized;
1105
pLock->timeStamp = init_time;
1108
cache->numSIDCacheLocksInitialized = locks_initialized;
1118
SSL_GetMaxServerCacheLocks(void)
1120
return ssl_max_sid_cache_locks + 2;
1121
/* The extra two are the cert cache lock and the key cache lock. */
1125
SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
1127
/* Minimum is 1 sid cache lock, 1 cert cache lock and 1 key cache lock.
1128
** We'd like to test for a maximum value, but not all platforms' header
1129
** files provide a symbol or function or other means of determining
1130
** the maximum, other than trial and error.
1133
PORT_SetError(SEC_ERROR_INVALID_ARGS);
1136
ssl_max_sid_cache_locks = maxLocks - 2;
1137
/* The extra two are the cert cache lock and the key cache lock. */
1142
SSL_ConfigServerSessionIDCacheInstance( cacheDesc *cache,
1143
int maxCacheEntries,
1144
PRUint32 ssl2_timeout,
1145
PRUint32 ssl3_timeout,
1146
const char * directory, PRBool shared)
1150
#if defined(DEBUG_nelsonb)
1151
printf("sizeof(sidCacheEntry) == %u\n", sizeof(sidCacheEntry));
1153
#if !(defined(SOLARIS) && defined(i386))
1155
PORT_Assert(sizeof(sidCacheEntry) % 8 == 0);
1158
PORT_Assert(sizeof(certCacheEntry) == 4096);
1160
myPid = SSL_GETPID();
1162
directory = DEFAULT_CACHE_DIRECTORY;
1164
rv = InitCache(cache, maxCacheEntries, ssl2_timeout, ssl3_timeout,
1171
ssl_sid_lookup = ServerSessionIDLookup;
1172
ssl_sid_cache = ServerSessionIDCache;
1173
ssl_sid_uncache = ServerSessionIDUncache;
1178
SSL_ConfigServerSessionIDCache( int maxCacheEntries,
1179
PRUint32 ssl2_timeout,
1180
PRUint32 ssl3_timeout,
1181
const char * directory)
1183
ssl_InitClientSessionCacheLock();
1184
ssl_InitSymWrapKeysLock();
1185
return SSL_ConfigServerSessionIDCacheInstance(&globalCache,
1186
maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE);
1190
SSL_ShutdownServerSessionIDCacheInstance(cacheDesc *cache)
1197
SSL_ShutdownServerSessionIDCache(void)
1199
SSL3_ShutdownServerCache();
1200
return SSL_ShutdownServerSessionIDCacheInstance(&globalCache);
1203
/* Use this function, instead of SSL_ConfigServerSessionIDCache,
1204
* if the cache will be shared by multiple processes.
1207
SSL_ConfigMPServerSIDCache( int maxCacheEntries,
1208
PRUint32 ssl2_timeout,
1209
PRUint32 ssl3_timeout,
1210
const char * directory)
1214
cacheDesc * cache = &globalCache;
1218
SECStatus putEnvFailed;
1219
inheritance inherit;
1220
char fmString[PR_FILEMAP_STRING_BUFSIZE];
1222
isMultiProcess = PR_TRUE;
1223
result = SSL_ConfigServerSessionIDCacheInstance(cache, maxCacheEntries,
1224
ssl2_timeout, ssl3_timeout, directory, PR_TRUE);
1225
if (result != SECSuccess)
1228
prStatus = PR_ExportFileMapAsString(cache->cacheMemMap,
1229
sizeof fmString, fmString);
1230
if ((prStatus != PR_SUCCESS) || !(fmStrLen = strlen(fmString))) {
1235
inherit.cacheMemSize = cache->cacheMemSize;
1236
inherit.fmStrLen = fmStrLen;
1238
inhValue = BTOA_DataToAscii((unsigned char *)&inherit, sizeof inherit);
1239
if (!inhValue || !strlen(inhValue)) {
1243
envValue = PR_smprintf("%s,%s", inhValue, fmString);
1244
if (!envValue || !strlen(envValue)) {
1248
PORT_Free(inhValue);
1250
putEnvFailed = (SECStatus)NSS_PutEnv(envVarName, envValue);
1251
PR_smprintf_free(envValue);
1254
result = SECFailure;
1257
#if defined(XP_UNIX) || defined(XP_BEOS)
1258
/* Launch thread to poll cache for expired locks on Unix */
1259
LaunchLockPoller(cache);
1265
SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
1267
unsigned char * decoString = NULL;
1268
char * fmString = NULL;
1269
char * myEnvString = NULL;
1270
unsigned int decoLen;
1272
inheritance inherit;
1275
sidCacheLock* newLocks;
1276
int locks_initialized = 0;
1277
int locks_to_initialize = 0;
1280
myPid = SSL_GETPID();
1282
/* If this child was created by fork(), and not by exec() on unix,
1283
** then isMultiProcess will already be set.
1284
** If not, we'll set it below.
1286
if (isMultiProcess) {
1287
if (cache && cache->sharedCache) {
1288
cache->sharedCache->everInherited = PR_TRUE;
1290
return SECSuccess; /* already done. */
1293
ssl_InitClientSessionCacheLock();
1294
ssl_InitSymWrapKeysLock();
1296
ssl_sid_lookup = ServerSessionIDLookup;
1297
ssl_sid_cache = ServerSessionIDCache;
1298
ssl_sid_uncache = ServerSessionIDUncache;
1301
envString = getenv(envVarName);
1307
myEnvString = PORT_Strdup(envString);
1310
fmString = strchr(myEnvString, ',');
1315
decoString = ATOB_AsciiToData(myEnvString, &decoLen);
1320
if (decoLen != sizeof inherit) {
1325
PORT_Memcpy(&inherit, decoString, sizeof inherit);
1327
if (strlen(fmString) != inherit.fmStrLen ) {
1331
memset(cache, 0, sizeof *cache);
1332
cache->cacheMemSize = inherit.cacheMemSize;
1335
cache->cacheMemMap = PR_ImportFileMapFromString(fmString);
1336
if(! cache->cacheMemMap) {
1339
cache->cacheMem = PR_MemMap(cache->cacheMemMap, 0, cache->cacheMemSize);
1340
if (! cache->cacheMem) {
1343
cache->sharedCache = (cacheDesc *)cache->cacheMem;
1345
if (cache->sharedCache->cacheMemSize != cache->cacheMemSize) {
1350
/* We're now going to overwrite the local cache instance with the
1351
** shared copy of the cache struct, then update several values in
1352
** the local cache using the values for cache->cacheMemMap and
1353
** cache->cacheMem computed just above. So, we copy cache into
1354
** the automatic variable "my", to preserve the variables while
1355
** cache is overwritten.
1357
my = *cache; /* save values computed above. */
1358
memcpy(cache, cache->sharedCache, sizeof *cache); /* overwrite */
1360
/* Fix pointers in our private copy of cache descriptor to point to
1361
** spaces in shared memory, whose address is now in "my".
1363
ptr = (ptrdiff_t)my.cacheMem;
1364
*(ptrdiff_t *)(&cache->sidCacheLocks) += ptr;
1365
*(ptrdiff_t *)(&cache->keyCacheLock ) += ptr;
1366
*(ptrdiff_t *)(&cache->certCacheLock) += ptr;
1367
*(ptrdiff_t *)(&cache->sidCacheSets ) += ptr;
1368
*(ptrdiff_t *)(&cache->sidCacheData ) += ptr;
1369
*(ptrdiff_t *)(&cache->certCacheData) += ptr;
1370
*(ptrdiff_t *)(&cache->keyCacheData ) += ptr;
1372
cache->cacheMemMap = my.cacheMemMap;
1373
cache->cacheMem = my.cacheMem;
1374
cache->sharedCache = (cacheDesc *)cache->cacheMem;
1377
/* On Windows NT we need to "fix" the sidCacheLocks here to support fibers
1378
** When NT fibers are used in a multi-process server, a second level of
1379
** locking is needed to prevent a deadlock, in case a fiber acquires the
1380
** cross-process mutex, yields, and another fiber is later scheduled on
1381
** the same native thread and tries to acquire the cross-process mutex.
1382
** We do this by using a PRLock in the sslMutex. However, it is stored in
1383
** shared memory as part of sidCacheLocks, and we don't want to overwrite
1384
** the PRLock of the parent process. So we need to make new, private
1385
** copies of sidCacheLocks before modifying the sslMutex with our own
1389
/* note from jpierre : this should be free'd in child processes when
1390
** a function is added to delete the SSL session cache in the future.
1392
locks_to_initialize = cache->numSIDCacheLocks + 2;
1393
newLocks = PORT_NewArray(sidCacheLock, locks_to_initialize);
1396
/* copy the old locks */
1397
memcpy(newLocks, cache->sidCacheLocks,
1398
locks_to_initialize * sizeof(sidCacheLock));
1399
cache->sidCacheLocks = newLocks;
1401
for (; locks_initialized < locks_to_initialize; ++locks_initialized) {
1402
/* now, make a local PRLock in this sslMutex for this child process */
1404
err = sslMutex_2LevelInit(&newLocks[locks_initialized].mutex);
1405
if (err != SECSuccess) {
1406
cache->numSIDCacheLocksInitialized = locks_initialized;
1410
cache->numSIDCacheLocksInitialized = locks_initialized;
1412
/* also fix the key and cert cache which use the last 2 lock entries */
1413
cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
1414
cache->certCacheLock = cache->keyCacheLock + 1;
1417
PORT_Free(myEnvString);
1418
PORT_Free(decoString);
1420
/* mark that we have inherited this. */
1421
cache->sharedCache->everInherited = PR_TRUE;
1422
isMultiProcess = PR_TRUE;
1427
PORT_Free(myEnvString);
1429
PORT_Free(decoString);
1435
SSL_InheritMPServerSIDCache(const char * envString)
1437
return SSL_InheritMPServerSIDCacheInstance(&globalCache, envString);
1440
#if defined(XP_UNIX) || defined(XP_BEOS)
1442
#define SID_LOCK_EXPIRATION_TIMEOUT 30 /* seconds */
1445
LockPoller(void * arg)
1447
cacheDesc * cache = (cacheDesc *)arg;
1448
cacheDesc * sharedCache = cache->sharedCache;
1449
sidCacheLock * pLock;
1450
const char * timeoutString;
1451
PRIntervalTime timeout;
1454
int locks_polled = 0;
1455
int locks_to_poll = cache->numSIDCacheLocks + 2;
1456
PRUint32 expiration = SID_LOCK_EXPIRATION_TIMEOUT;
1458
timeoutString = getenv("NSS_SSL_SERVER_CACHE_MUTEX_TIMEOUT");
1459
if (timeoutString) {
1460
long newTime = strtol(timeoutString, 0, 0);
1462
return; /* application doesn't want this function */
1464
expiration = (PRUint32)newTime;
1465
/* if error (newTime < 0) ignore it and use default */
1468
timeout = PR_SecondsToInterval(expiration);
1469
while(!sharedCache->stopPolling) {
1471
if (sharedCache->stopPolling)
1475
then = now - expiration;
1476
for (pLock = cache->sidCacheLocks, locks_polled = 0;
1477
locks_to_poll > locks_polled && !sharedCache->stopPolling;
1478
++locks_polled, ++pLock ) {
1481
if (pLock->timeStamp < then &&
1482
pLock->timeStamp != 0 &&
1483
(pid = pLock->pid) != 0) {
1485
/* maybe we should try the lock? */
1486
int result = kill(pid, 0);
1487
if (result < 0 && errno == ESRCH) {
1489
/* No process exists by that pid any more.
1490
** Treat this mutex as abandoned.
1492
pLock->timeStamp = now;
1494
rv = sslMutex_Unlock(&pLock->mutex);
1495
if (rv != SECSuccess) {
1500
} /* end of loop over locks */
1501
} /* end of entire polling loop */
1504
/* Launch thread to poll cache for expired locks */
1506
LaunchLockPoller(cacheDesc *cache)
1508
PRThread * pollerThread;
1511
PR_CreateThread(PR_USER_THREAD, LockPoller, cache, PR_PRIORITY_NORMAL,
1512
PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
1513
if (!pollerThread) {
1516
cache->poller = pollerThread;
1521
/************************************************************************
1522
* Code dealing with shared wrapped symmetric wrapping keys below *
1523
************************************************************************/
1525
/* If now is zero, it implies that the lock is not held, and must be
1529
getSvrWrappingKey(PRInt32 symWrapMechIndex,
1530
SSL3KEAType exchKeyType,
1531
SSLWrappedSymWrappingKey *wswk,
1535
PRUint32 ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
1536
SSLWrappedSymWrappingKey * pwswk = cache->keyCacheData + ndx;
1538
PRBool rv = PR_FALSE;
1540
if (!cache->cacheMem) { /* cache is uninitialized */
1541
PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
1545
lockTime = now = LockSidCacheLock(cache->keyCacheLock, now);
1550
if (pwswk->exchKeyType == exchKeyType &&
1551
pwswk->symWrapMechIndex == symWrapMechIndex &&
1552
pwswk->wrappedSymKeyLen != 0) {
1557
UnlockSidCacheLock(cache->keyCacheLock);
1563
ssl_GetWrappingKey( PRInt32 symWrapMechIndex,
1564
SSL3KEAType exchKeyType,
1565
SSLWrappedSymWrappingKey *wswk)
1569
PORT_Assert( (unsigned)exchKeyType < kt_kea_size);
1570
PORT_Assert( (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
1571
if ((unsigned)exchKeyType < kt_kea_size &&
1572
(unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS) {
1573
rv = getSvrWrappingKey(symWrapMechIndex, exchKeyType, wswk,
1582
/* The caller passes in the new value it wants
1583
* to set. This code tests the wrapped sym key entry in the shared memory.
1584
* If it is uninitialized, this function writes the caller's value into
1585
* the disk entry, and returns false.
1586
* Otherwise, it overwrites the caller's wswk with the value obtained from
1587
* the disk, and returns PR_TRUE.
1588
* This is all done while holding the locks/mutexes necessary to make
1589
* the operation atomic.
1592
ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
1594
cacheDesc * cache = &globalCache;
1595
PRBool rv = PR_FALSE;
1596
SSL3KEAType exchKeyType = wswk->exchKeyType;
1597
/* type of keys used to wrap SymWrapKey*/
1598
PRInt32 symWrapMechIndex = wswk->symWrapMechIndex;
1601
SSLWrappedSymWrappingKey myWswk;
1603
if (!cache->cacheMem) { /* cache is uninitialized */
1604
PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
1608
PORT_Assert( (unsigned)exchKeyType < kt_kea_size);
1609
if ((unsigned)exchKeyType >= kt_kea_size)
1612
PORT_Assert( (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
1613
if ((unsigned)symWrapMechIndex >= SSL_NUM_WRAP_MECHS)
1616
ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
1617
PORT_Memset(&myWswk, 0, sizeof myWswk); /* eliminate UMRs. */
1619
now = LockSidCacheLock(cache->keyCacheLock, now);
1621
rv = getSvrWrappingKey(wswk->symWrapMechIndex, wswk->exchKeyType,
1622
&myWswk, cache, now);
1624
/* we found it on disk, copy it out to the caller. */
1625
PORT_Memcpy(wswk, &myWswk, sizeof *wswk);
1627
/* Wasn't on disk, and we're still holding the lock, so write it. */
1628
cache->keyCacheData[ndx] = *wswk;
1630
UnlockSidCacheLock(cache->keyCacheLock);
1635
#else /* MAC version or other platform */
1637
#include "seccomon.h"
1640
#include "sslimpl.h"
1643
SSL_ConfigServerSessionIDCache( int maxCacheEntries,
1644
PRUint32 ssl2_timeout,
1645
PRUint32 ssl3_timeout,
1646
const char * directory)
1648
PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigServerSessionIDCache)");
1653
SSL_ConfigMPServerSIDCache( int maxCacheEntries,
1654
PRUint32 ssl2_timeout,
1655
PRUint32 ssl3_timeout,
1656
const char * directory)
1658
PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigMPServerSIDCache)");
1663
SSL_InheritMPServerSIDCache(const char * envString)
1665
PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_InheritMPServerSIDCache)");
1670
ssl_GetWrappingKey( PRInt32 symWrapMechIndex,
1671
SSL3KEAType exchKeyType,
1672
SSLWrappedSymWrappingKey *wswk)
1674
PRBool rv = PR_FALSE;
1675
PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_GetWrappingKey)");
1679
/* This is a kind of test-and-set. The caller passes in the new value it wants
1680
* to set. This code tests the wrapped sym key entry in the shared memory.
1681
* If it is uninitialized, this function writes the caller's value into
1682
* the disk entry, and returns false.
1683
* Otherwise, it overwrites the caller's wswk with the value obtained from
1684
* the disk, and returns PR_TRUE.
1685
* This is all done while holding the locks/mutexes necessary to make
1686
* the operation atomic.
1689
ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
1691
PRBool rv = PR_FALSE;
1692
PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_SetWrappingKey)");
1697
SSL_GetMaxServerCacheLocks(void)
1699
PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_GetMaxServerCacheLocks)");
1704
SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
1706
PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_SetMaxServerCacheLocks)");
1710
#endif /* XP_UNIX || XP_WIN32 */