• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* This file implements the SERVER Session ID cache.
2  * NOTE:  The contents of this file are NOT used by the client.
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 /* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
9  * cache sids!
10  *
11  * About record locking among different server processes:
12  *
13  * All processes that are part of the same conceptual server (serving on
14  * the same address and port) MUST share a common SSL session cache.
15  * This code makes the content of the shared cache accessible to all
16  * processes on the same "server".  This code works on Unix and Win32 only.
17  *
18  * We use NSPR anonymous shared memory and move data to & from shared memory.
19  * We must do explicit locking of the records for all reads and writes.
20  * The set of Cache entries are divided up into "sets" of 128 entries.
21  * Each set is protected by a lock.  There may be one or more sets protected
22  * by each lock.  That is, locks to sets are 1:N.
23  * There is one lock for the entire cert cache.
24  * There is one lock for the set of wrapped sym wrap keys.
25  *
26  * The anonymous shared memory is laid out as if it were declared like this:
27  *
28  * struct {
29  *     cacheDescriptor          desc;
30  *     sidCacheLock             sidCacheLocks[ numSIDCacheLocks];
31  *     sidCacheLock             keyCacheLock;
32  *     sidCacheLock             certCacheLock;
33  *     sidCacheSet              sidCacheSets[ numSIDCacheSets ];
34  *     sidCacheEntry            sidCacheData[ numSIDCacheEntries];
35  *     certCacheEntry           certCacheData[numCertCacheEntries];
36  *     SSLWrappedSymWrappingKey keyCacheData[kt_kea_size][SSL_NUM_WRAP_MECHS];
37  *     PRUint8                  keyNameSuffix[SESS_TICKET_KEY_VAR_NAME_LEN]
38  *     encKeyCacheEntry         ticketEncKey; // Wrapped in non-bypass mode
39  *     encKeyCacheEntry         ticketMacKey; // Wrapped in non-bypass mode
40  *     PRBool                   ticketKeysValid;
41  *     sidCacheLock             srvNameCacheLock;
42  *     srvNameCacheEntry        srvNameData[ numSrvNameCacheEntries ];
43  * } cacheMemCacheData;
44  */
45 #include "seccomon.h"
46 
47 #if defined(XP_UNIX) || defined(XP_WIN32) || defined (XP_OS2) || defined(XP_BEOS)
48 
49 #include "cert.h"
50 #include "ssl.h"
51 #include "sslimpl.h"
52 #include "sslproto.h"
53 #include "pk11func.h"
54 #include "base64.h"
55 #include "keyhi.h"
56 #ifdef NO_PKCS11_BYPASS
57 #include "blapit.h"
58 #include "sechash.h"
59 #else
60 #include "blapi.h"
61 #endif
62 
63 #include <stdio.h>
64 
65 #if defined(XP_UNIX) || defined(XP_BEOS)
66 
67 #include <syslog.h>
68 #include <fcntl.h>
69 #include <unistd.h>
70 #include <errno.h>
71 #include <signal.h>
72 #include "unix_err.h"
73 
74 #else
75 
76 #ifdef XP_WIN32
77 #include <wtypes.h>
78 #include "win32err.h"
79 #endif
80 
81 #endif
82 #include <sys/types.h>
83 
84 #define SET_ERROR_CODE /* reminder */
85 
86 #include "nspr.h"
87 #include "sslmutex.h"
88 
89 /*
90 ** Format of a cache entry in the shared memory.
91 */
92 struct sidCacheEntryStr {
93 /* 16 */    PRIPv6Addr  addr;	/* client's IP address */
94 /*  4 */    PRUint32    creationTime;
95 /*  4 */    PRUint32    lastAccessTime;
96 /*  4 */    PRUint32    expirationTime;
97 /*  2 */    PRUint16	version;
98 /*  1 */    PRUint8	valid;
99 /*  1 */    PRUint8     sessionIDLength;
100 /* 32 */    PRUint8     sessionID[SSL3_SESSIONID_BYTES];
101 /*  2 */    PRUint16    authAlgorithm;
102 /*  2 */    PRUint16    authKeyBits;
103 /*  2 */    PRUint16    keaType;
104 /*  2 */    PRUint16    keaKeyBits;
105 /* 72  - common header total */
106 
107     union {
108 	struct {
109 /* 64 */    PRUint8	masterKey[SSL_MAX_MASTER_KEY_BYTES];
110 /* 32 */    PRUint8	cipherArg[SSL_MAX_CYPHER_ARG_BYTES];
111 
112 /*  1 */    PRUint8	cipherType;
113 /*  1 */    PRUint8	masterKeyLen;
114 /*  1 */    PRUint8	keyBits;
115 /*  1 */    PRUint8	secretKeyBits;
116 /*  1 */    PRUint8	cipherArgLen;
117 /*101 */} ssl2;
118 
119 	struct {
120 /*  2 */    ssl3CipherSuite  cipherSuite;
121 /*  2 */    PRUint16    compression; 	/* SSLCompressionMethod */
122 
123 /* 52 */    ssl3SidKeys keys;	/* keys, wrapped as needed. */
124 
125 /*  4 */    PRUint32    masterWrapMech;
126 /*  4 */    SSL3KEAType exchKeyType;
127 /*  4 */    PRInt32     certIndex;
128 /*  4 */    PRInt32     srvNameIndex;
129 /* 32 */    PRUint8     srvNameHash[SHA256_LENGTH]; /* SHA256 name hash */
130 /*104 */} ssl3;
131 /* force sizeof(sidCacheEntry) to be a multiple of cache line size */
132         struct {
133 /*120 */    PRUint8     filler[120]; /* 72+120==192, a multiple of 16 */
134 	} forceSize;
135     } u;
136 };
137 typedef struct sidCacheEntryStr sidCacheEntry;
138 
139 /* The length of this struct is supposed to be a power of 2, e.g. 4KB */
140 struct certCacheEntryStr {
141     PRUint16    certLength;				/*    2 */
142     PRUint16    sessionIDLength;			/*    2 */
143     PRUint8 	sessionID[SSL3_SESSIONID_BYTES];	/*   32 */
144     PRUint8 	cert[SSL_MAX_CACHED_CERT_LEN];		/* 4060 */
145 };						/* total   4096 */
146 typedef struct certCacheEntryStr certCacheEntry;
147 
148 struct sidCacheLockStr {
149     PRUint32	timeStamp;
150     sslMutex	mutex;
151     sslPID	pid;
152 };
153 typedef struct sidCacheLockStr sidCacheLock;
154 
155 struct sidCacheSetStr {
156     PRIntn	next;
157 };
158 typedef struct sidCacheSetStr sidCacheSet;
159 
160 struct encKeyCacheEntryStr {
161     PRUint8	bytes[512];
162     PRInt32	length;
163 };
164 typedef struct encKeyCacheEntryStr encKeyCacheEntry;
165 
166 #define SSL_MAX_DNS_HOST_NAME  1024
167 
168 struct srvNameCacheEntryStr {
169     PRUint16    type;                                   /*    2 */
170     PRUint16    nameLen;                                /*    2 */
171     PRUint8	name[SSL_MAX_DNS_HOST_NAME + 12];       /* 1034 */
172     PRUint8 	nameHash[SHA256_LENGTH];                /*   32 */
173                                                         /* 1072 */
174 };
175 typedef struct srvNameCacheEntryStr srvNameCacheEntry;
176 
177 
178 struct cacheDescStr {
179 
180     PRUint32            cacheMemSize;
181 
182     PRUint32		numSIDCacheLocks;
183     PRUint32		numSIDCacheSets;
184     PRUint32		numSIDCacheSetsPerLock;
185 
186     PRUint32            numSIDCacheEntries;
187     PRUint32            sidCacheSize;
188 
189     PRUint32            numCertCacheEntries;
190     PRUint32            certCacheSize;
191 
192     PRUint32            numKeyCacheEntries;
193     PRUint32            keyCacheSize;
194 
195     PRUint32            numSrvNameCacheEntries;
196     PRUint32            srvNameCacheSize;
197 
198     PRUint32		ssl2Timeout;
199     PRUint32		ssl3Timeout;
200 
201     PRUint32            numSIDCacheLocksInitialized;
202 
203     /* These values are volatile, and are accessed through sharedCache-> */
204     PRUint32		nextCertCacheEntry;	/* certCacheLock protects */
205     PRBool      	stopPolling;
206     PRBool		everInherited;
207 
208     /* The private copies of these values are pointers into shared mem */
209     /* The copies of these values in shared memory are merely offsets */
210     sidCacheLock    *          sidCacheLocks;
211     sidCacheLock    *          keyCacheLock;
212     sidCacheLock    *          certCacheLock;
213     sidCacheLock    *          srvNameCacheLock;
214     sidCacheSet     *          sidCacheSets;
215     sidCacheEntry   *          sidCacheData;
216     certCacheEntry  *          certCacheData;
217     SSLWrappedSymWrappingKey * keyCacheData;
218     PRUint8         *          ticketKeyNameSuffix;
219     encKeyCacheEntry         * ticketEncKey;
220     encKeyCacheEntry         * ticketMacKey;
221     PRUint32        *          ticketKeysValid;
222     srvNameCacheEntry *        srvNameCacheData;
223 
224     /* Only the private copies of these pointers are valid */
225     char *                     cacheMem;
226     struct cacheDescStr *      sharedCache;  /* shared copy of this struct */
227     PRFileMap *                cacheMemMap;
228     PRThread  *                poller;
229     PRUint32                   mutexTimeout;
230     PRBool                     shared;
231 };
232 typedef struct cacheDescStr cacheDesc;
233 
234 static cacheDesc globalCache;
235 
236 static const char envVarName[] = { SSL_ENV_VAR_NAME };
237 
238 static PRBool isMultiProcess  = PR_FALSE;
239 
240 
241 #define DEF_SID_CACHE_ENTRIES  10000
242 #define DEF_CERT_CACHE_ENTRIES 250
243 #define MIN_CERT_CACHE_ENTRIES 125 /* the effective size in old releases. */
244 #define DEF_KEY_CACHE_ENTRIES  250
245 #define DEF_NAME_CACHE_ENTRIES  1000
246 
247 #define SID_CACHE_ENTRIES_PER_SET  128
248 #define SID_ALIGNMENT          16
249 
250 #define DEF_SSL2_TIMEOUT	100   /* seconds */
251 #define MAX_SSL2_TIMEOUT	100   /* seconds */
252 #define MIN_SSL2_TIMEOUT	  5   /* seconds */
253 
254 #define DEF_SSL3_TIMEOUT      86400L  /* 24 hours */
255 #define MAX_SSL3_TIMEOUT      86400L  /* 24 hours */
256 #define MIN_SSL3_TIMEOUT          5   /* seconds  */
257 
258 #if defined(AIX) || defined(LINUX) || defined(NETBSD) || defined(OPENBSD)
259 #define MAX_SID_CACHE_LOCKS 8	/* two FDs per lock */
260 #elif defined(OSF1)
261 #define MAX_SID_CACHE_LOCKS 16	/* one FD per lock */
262 #else
263 #define MAX_SID_CACHE_LOCKS 256
264 #endif
265 
266 #define SID_HOWMANY(val, size) (((val) + ((size) - 1)) / (size))
267 #define SID_ROUNDUP(val, size) ((size) * SID_HOWMANY((val), (size)))
268 
269 
270 static sslPID myPid;
271 static PRUint32  ssl_max_sid_cache_locks = MAX_SID_CACHE_LOCKS;
272 
273 /* forward static function declarations */
274 static PRUint32 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s,
275                          unsigned nl);
276 static SECStatus LaunchLockPoller(cacheDesc *cache);
277 static SECStatus StopLockPoller(cacheDesc *cache);
278 
279 
280 struct inheritanceStr {
281     PRUint32 cacheMemSize;
282     PRUint32 fmStrLen;
283 };
284 
285 typedef struct inheritanceStr inheritance;
286 
287 #if defined(_WIN32) || defined(XP_OS2)
288 
289 #define DEFAULT_CACHE_DIRECTORY "\\temp"
290 
291 #endif /* _win32 */
292 
293 #if defined(XP_UNIX) || defined(XP_BEOS)
294 
295 #define DEFAULT_CACHE_DIRECTORY "/tmp"
296 
297 #endif /* XP_UNIX || XP_BEOS */
298 
299 
300 /************************************************************************/
301 
302 static PRUint32
LockSidCacheLock(sidCacheLock * lock,PRUint32 now)303 LockSidCacheLock(sidCacheLock *lock, PRUint32 now)
304 {
305     SECStatus      rv      = sslMutex_Lock(&lock->mutex);
306     if (rv != SECSuccess)
307     	return 0;
308     if (!now)
309 	now  = ssl_Time();
310     lock->timeStamp = now;
311     lock->pid       = myPid;
312     return now;
313 }
314 
315 static SECStatus
UnlockSidCacheLock(sidCacheLock * lock)316 UnlockSidCacheLock(sidCacheLock *lock)
317 {
318     SECStatus      rv;
319 
320     lock->pid = 0;
321     rv        = sslMutex_Unlock(&lock->mutex);
322     return rv;
323 }
324 
325 /* returns the value of ssl_Time on success, zero on failure. */
326 static PRUint32
LockSet(cacheDesc * cache,PRUint32 set,PRUint32 now)327 LockSet(cacheDesc *cache, PRUint32 set, PRUint32 now)
328 {
329     PRUint32       lockNum = set % cache->numSIDCacheLocks;
330     sidCacheLock * lock    = cache->sidCacheLocks + lockNum;
331 
332     return LockSidCacheLock(lock, now);
333 }
334 
335 static SECStatus
UnlockSet(cacheDesc * cache,PRUint32 set)336 UnlockSet(cacheDesc *cache, PRUint32 set)
337 {
338     PRUint32       lockNum = set % cache->numSIDCacheLocks;
339     sidCacheLock * lock    = cache->sidCacheLocks + lockNum;
340 
341     return UnlockSidCacheLock(lock);
342 }
343 
344 /************************************************************************/
345 
346 
347 /* Put a certificate in the cache.  Update the cert index in the sce.
348 */
349 static PRUint32
CacheCert(cacheDesc * cache,CERTCertificate * cert,sidCacheEntry * sce)350 CacheCert(cacheDesc * cache, CERTCertificate *cert, sidCacheEntry *sce)
351 {
352     PRUint32        now;
353     certCacheEntry  cce;
354 
355     if ((cert->derCert.len > SSL_MAX_CACHED_CERT_LEN) ||
356         (cert->derCert.len <= 0) ||
357 	(cert->derCert.data == NULL)) {
358 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
359 	return 0;
360     }
361 
362     cce.sessionIDLength = sce->sessionIDLength;
363     PORT_Memcpy(cce.sessionID, sce->sessionID, cce.sessionIDLength);
364 
365     cce.certLength = cert->derCert.len;
366     PORT_Memcpy(cce.cert, cert->derCert.data, cce.certLength);
367 
368     /* get lock on cert cache */
369     now = LockSidCacheLock(cache->certCacheLock, 0);
370     if (now) {
371 
372 	/* Find where to place the next cert cache entry. */
373 	cacheDesc * sharedCache = cache->sharedCache;
374 	PRUint32    ndx         = sharedCache->nextCertCacheEntry;
375 
376 	/* write the entry */
377 	cache->certCacheData[ndx] = cce;
378 
379 	/* remember where we put it. */
380 	sce->u.ssl3.certIndex = ndx;
381 
382 	/* update the "next" cache entry index */
383 	sharedCache->nextCertCacheEntry =
384 					(ndx + 1) % cache->numCertCacheEntries;
385 
386 	UnlockSidCacheLock(cache->certCacheLock);
387     }
388     return now;
389 
390 }
391 
392 /* Server configuration hash tables need to account the SECITEM.type
393  * field as well. These functions accomplish that. */
394 static PLHashNumber
Get32BitNameHash(const SECItem * name)395 Get32BitNameHash(const SECItem *name)
396 {
397     PLHashNumber rv = SECITEM_Hash(name);
398 
399     PRUint8 *rvc = (PRUint8 *)&rv;
400     rvc[ name->len % sizeof(rv) ] ^= name->type;
401 
402     return rv;
403 }
404 
405 /* Put a name in the cache.  Update the cert index in the sce.
406 */
407 static PRUint32
CacheSrvName(cacheDesc * cache,SECItem * name,sidCacheEntry * sce)408 CacheSrvName(cacheDesc * cache, SECItem *name, sidCacheEntry *sce)
409 {
410     PRUint32           now;
411     PRUint32           ndx;
412     srvNameCacheEntry  snce;
413 
414     if (!name || name->len <= 0 ||
415         name->len > SSL_MAX_DNS_HOST_NAME) {
416 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
417 	return 0;
418     }
419 
420     snce.type = name->type;
421     snce.nameLen = name->len;
422     PORT_Memcpy(snce.name, name->data, snce.nameLen);
423 #ifdef NO_PKCS11_BYPASS
424     HASH_HashBuf(HASH_AlgSHA256, snce.nameHash, name->data, name->len);
425 #else
426     SHA256_HashBuf(snce.nameHash, (unsigned char*)name->data,
427                    name->len);
428 #endif
429     /* get index of the next name */
430     ndx = Get32BitNameHash(name);
431     /* get lock on cert cache */
432     now = LockSidCacheLock(cache->srvNameCacheLock, 0);
433     if (now) {
434         if (cache->numSrvNameCacheEntries > 0) {
435             /* Fit the index into array */
436             ndx %= cache->numSrvNameCacheEntries;
437             /* write the entry */
438             cache->srvNameCacheData[ndx] = snce;
439             /* remember where we put it. */
440             sce->u.ssl3.srvNameIndex = ndx;
441             /* Copy hash into sid hash */
442             PORT_Memcpy(sce->u.ssl3.srvNameHash, snce.nameHash, SHA256_LENGTH);
443         }
444 	UnlockSidCacheLock(cache->srvNameCacheLock);
445     }
446     return now;
447 }
448 
449 /*
450 ** Convert local SID to shared memory one
451 */
452 static void
ConvertFromSID(sidCacheEntry * to,sslSessionID * from)453 ConvertFromSID(sidCacheEntry *to, sslSessionID *from)
454 {
455     to->valid   = 1;
456     to->version = from->version;
457     to->addr    = from->addr;
458     to->creationTime    = from->creationTime;
459     to->lastAccessTime  = from->lastAccessTime;
460     to->expirationTime  = from->expirationTime;
461     to->authAlgorithm	= from->authAlgorithm;
462     to->authKeyBits	= from->authKeyBits;
463     to->keaType		= from->keaType;
464     to->keaKeyBits	= from->keaKeyBits;
465 
466     if (from->version < SSL_LIBRARY_VERSION_3_0) {
467 	if ((from->u.ssl2.masterKey.len > SSL_MAX_MASTER_KEY_BYTES) ||
468 	    (from->u.ssl2.cipherArg.len > SSL_MAX_CYPHER_ARG_BYTES)) {
469 	    SSL_DBG(("%d: SSL: masterKeyLen=%d cipherArgLen=%d",
470 		     myPid, from->u.ssl2.masterKey.len,
471 		     from->u.ssl2.cipherArg.len));
472 	    to->valid = 0;
473 	    return;
474 	}
475 
476 	to->u.ssl2.cipherType    = from->u.ssl2.cipherType;
477 	to->u.ssl2.masterKeyLen  = from->u.ssl2.masterKey.len;
478 	to->u.ssl2.cipherArgLen  = from->u.ssl2.cipherArg.len;
479 	to->u.ssl2.keyBits       = from->u.ssl2.keyBits;
480 	to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
481 	to->sessionIDLength      = SSL2_SESSIONID_BYTES;
482 	PORT_Memcpy(to->sessionID, from->u.ssl2.sessionID, SSL2_SESSIONID_BYTES);
483 	PORT_Memcpy(to->u.ssl2.masterKey, from->u.ssl2.masterKey.data,
484 		  from->u.ssl2.masterKey.len);
485 	PORT_Memcpy(to->u.ssl2.cipherArg, from->u.ssl2.cipherArg.data,
486 		  from->u.ssl2.cipherArg.len);
487 #ifdef DEBUG
488 	PORT_Memset(to->u.ssl2.masterKey+from->u.ssl2.masterKey.len, 0,
489 		  sizeof(to->u.ssl2.masterKey) - from->u.ssl2.masterKey.len);
490 	PORT_Memset(to->u.ssl2.cipherArg+from->u.ssl2.cipherArg.len, 0,
491 		  sizeof(to->u.ssl2.cipherArg) - from->u.ssl2.cipherArg.len);
492 #endif
493 	SSL_TRC(8, ("%d: SSL: ConvertSID: masterKeyLen=%d cipherArgLen=%d "
494 		    "time=%d addr=0x%08x%08x%08x%08x cipherType=%d", myPid,
495 		    to->u.ssl2.masterKeyLen, to->u.ssl2.cipherArgLen,
496 		    to->creationTime, to->addr.pr_s6_addr32[0],
497 		    to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
498 		    to->addr.pr_s6_addr32[3], to->u.ssl2.cipherType));
499     } else {
500 	/* This is an SSL v3 session */
501 
502 	to->u.ssl3.cipherSuite      = from->u.ssl3.cipherSuite;
503 	to->u.ssl3.compression      = (PRUint16)from->u.ssl3.compression;
504 	to->u.ssl3.keys             = from->u.ssl3.keys;
505 	to->u.ssl3.masterWrapMech   = from->u.ssl3.masterWrapMech;
506 	to->u.ssl3.exchKeyType      = from->u.ssl3.exchKeyType;
507 	to->sessionIDLength         = from->u.ssl3.sessionIDLength;
508 	to->u.ssl3.certIndex        = -1;
509 	to->u.ssl3.srvNameIndex     = -1;
510 
511 	PORT_Memcpy(to->sessionID, from->u.ssl3.sessionID,
512 		    to->sessionIDLength);
513 
514 	SSL_TRC(8, ("%d: SSL3: ConvertSID: time=%d addr=0x%08x%08x%08x%08x "
515 	            "cipherSuite=%d",
516 		    myPid, to->creationTime, to->addr.pr_s6_addr32[0],
517 		    to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
518 		    to->addr.pr_s6_addr32[3], to->u.ssl3.cipherSuite));
519     }
520 }
521 
522 /*
523 ** Convert shared memory cache-entry to local memory based one
524 ** This is only called from ServerSessionIDLookup().
525 ** Caller must hold cache lock when calling this.
526 */
527 static sslSessionID *
ConvertToSID(sidCacheEntry * from,certCacheEntry * pcce,srvNameCacheEntry * psnce,CERTCertDBHandle * dbHandle)528 ConvertToSID(sidCacheEntry *    from,
529              certCacheEntry *   pcce,
530              srvNameCacheEntry *psnce,
531              CERTCertDBHandle * dbHandle)
532 {
533     sslSessionID *to;
534     PRUint16 version = from->version;
535 
536     to = PORT_ZNew(sslSessionID);
537     if (!to) {
538 	return 0;
539     }
540 
541     if (version < SSL_LIBRARY_VERSION_3_0) {
542 	/* This is an SSL v2 session */
543 	to->u.ssl2.masterKey.data =
544 	    (unsigned char*) PORT_Alloc(from->u.ssl2.masterKeyLen);
545 	if (!to->u.ssl2.masterKey.data) {
546 	    goto loser;
547 	}
548 	if (from->u.ssl2.cipherArgLen) {
549 	    to->u.ssl2.cipherArg.data =
550 	    	(unsigned char*)PORT_Alloc(from->u.ssl2.cipherArgLen);
551 	    if (!to->u.ssl2.cipherArg.data) {
552 		goto loser;
553 	    }
554 	    PORT_Memcpy(to->u.ssl2.cipherArg.data, from->u.ssl2.cipherArg,
555 		        from->u.ssl2.cipherArgLen);
556 	}
557 
558 	to->u.ssl2.cipherType    = from->u.ssl2.cipherType;
559 	to->u.ssl2.masterKey.len = from->u.ssl2.masterKeyLen;
560 	to->u.ssl2.cipherArg.len = from->u.ssl2.cipherArgLen;
561 	to->u.ssl2.keyBits       = from->u.ssl2.keyBits;
562 	to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
563 /*	to->sessionIDLength      = SSL2_SESSIONID_BYTES; */
564 	PORT_Memcpy(to->u.ssl2.sessionID, from->sessionID, SSL2_SESSIONID_BYTES);
565 	PORT_Memcpy(to->u.ssl2.masterKey.data, from->u.ssl2.masterKey,
566 		    from->u.ssl2.masterKeyLen);
567 
568 	SSL_TRC(8, ("%d: SSL: ConvertToSID: masterKeyLen=%d cipherArgLen=%d "
569 		    "time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
570 		    myPid, to->u.ssl2.masterKey.len,
571 		    to->u.ssl2.cipherArg.len, to->creationTime,
572 		    to->addr.pr_s6_addr32[0], to->addr.pr_s6_addr32[1],
573 		    to->addr.pr_s6_addr32[2], to->addr.pr_s6_addr32[3],
574 		    to->u.ssl2.cipherType));
575     } else {
576 	/* This is an SSL v3 session */
577 
578 	to->u.ssl3.sessionIDLength  = from->sessionIDLength;
579 	to->u.ssl3.cipherSuite      = from->u.ssl3.cipherSuite;
580 	to->u.ssl3.compression      = (SSLCompressionMethod)from->u.ssl3.compression;
581 	to->u.ssl3.keys             = from->u.ssl3.keys;
582 	to->u.ssl3.masterWrapMech   = from->u.ssl3.masterWrapMech;
583 	to->u.ssl3.exchKeyType      = from->u.ssl3.exchKeyType;
584 	if (from->u.ssl3.srvNameIndex != -1 && psnce) {
585             SECItem name;
586             SECStatus rv;
587             name.type                   = psnce->type;
588             name.len                    = psnce->nameLen;
589             name.data                   = psnce->name;
590             rv = SECITEM_CopyItem(NULL, &to->u.ssl3.srvName, &name);
591             if (rv != SECSuccess) {
592                 goto loser;
593             }
594         }
595 
596 	PORT_Memcpy(to->u.ssl3.sessionID, from->sessionID, from->sessionIDLength);
597 
598 	/* the portions of the SID that are only restored on the client
599 	 * are set to invalid values on the server.
600 	 */
601 	to->u.ssl3.clientWriteKey   = NULL;
602 	to->u.ssl3.serverWriteKey   = NULL;
603 
604 	to->urlSvrName              = NULL;
605 
606 	to->u.ssl3.masterModuleID   = (SECMODModuleID)-1; /* invalid value */
607 	to->u.ssl3.masterSlotID     = (CK_SLOT_ID)-1;     /* invalid value */
608 	to->u.ssl3.masterWrapIndex  = 0;
609 	to->u.ssl3.masterWrapSeries = 0;
610 	to->u.ssl3.masterValid      = PR_FALSE;
611 
612 	to->u.ssl3.clAuthModuleID   = (SECMODModuleID)-1; /* invalid value */
613 	to->u.ssl3.clAuthSlotID     = (CK_SLOT_ID)-1;     /* invalid value */
614 	to->u.ssl3.clAuthSeries     = 0;
615 	to->u.ssl3.clAuthValid      = PR_FALSE;
616 
617 	if (from->u.ssl3.certIndex != -1 && pcce) {
618 	    SECItem          derCert;
619 
620 	    derCert.len  = pcce->certLength;
621 	    derCert.data = pcce->cert;
622 
623 	    to->peerCert = CERT_NewTempCertificate(dbHandle, &derCert, NULL,
624 					           PR_FALSE, PR_TRUE);
625 	    if (to->peerCert == NULL)
626 		goto loser;
627 	}
628     }
629 
630     to->version         = from->version;
631     to->creationTime    = from->creationTime;
632     to->lastAccessTime  = from->lastAccessTime;
633     to->expirationTime  = from->expirationTime;
634     to->cached          = in_server_cache;
635     to->addr            = from->addr;
636     to->references      = 1;
637     to->authAlgorithm	= from->authAlgorithm;
638     to->authKeyBits	= from->authKeyBits;
639     to->keaType		= from->keaType;
640     to->keaKeyBits	= from->keaKeyBits;
641 
642     return to;
643 
644   loser:
645     if (to) {
646 	if (version < SSL_LIBRARY_VERSION_3_0) {
647 	    if (to->u.ssl2.masterKey.data)
648 		PORT_Free(to->u.ssl2.masterKey.data);
649 	    if (to->u.ssl2.cipherArg.data)
650 		PORT_Free(to->u.ssl2.cipherArg.data);
651 	} else {
652             SECITEM_FreeItem(&to->u.ssl3.srvName, PR_FALSE);
653         }
654 	PORT_Free(to);
655     }
656     return NULL;
657 }
658 
659 
660 
661 /*
662 ** Perform some mumbo jumbo on the ip-address and the session-id value to
663 ** compute a hash value.
664 */
665 static PRUint32
SIDindex(cacheDesc * cache,const PRIPv6Addr * addr,PRUint8 * s,unsigned nl)666 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s, unsigned nl)
667 {
668     PRUint32 rv;
669     PRUint32 x[8];
670 
671     memset(x, 0, sizeof x);
672     if (nl > sizeof x)
673     	nl = sizeof x;
674     memcpy(x, s, nl);
675 
676     rv = (addr->pr_s6_addr32[0] ^ addr->pr_s6_addr32[1] ^
677 	  addr->pr_s6_addr32[2] ^ addr->pr_s6_addr32[3] ^
678           x[0] ^ x[1] ^ x[2] ^ x[3] ^ x[4] ^ x[5] ^ x[6] ^ x[7])
679 	  % cache->numSIDCacheSets;
680     return rv;
681 }
682 
683 
684 
685 /*
686 ** Look something up in the cache. This will invalidate old entries
687 ** in the process. Caller has locked the cache set!
688 ** Returns PR_TRUE if found a valid match.  PR_FALSE otherwise.
689 */
690 static sidCacheEntry *
FindSID(cacheDesc * cache,PRUint32 setNum,PRUint32 now,const PRIPv6Addr * addr,unsigned char * sessionID,unsigned sessionIDLength)691 FindSID(cacheDesc *cache, PRUint32 setNum, PRUint32 now,
692         const PRIPv6Addr *addr, unsigned char *sessionID,
693 	unsigned sessionIDLength)
694 {
695     PRUint32      ndx   = cache->sidCacheSets[setNum].next;
696     int           i;
697 
698     sidCacheEntry * set = cache->sidCacheData +
699     			 (setNum * SID_CACHE_ENTRIES_PER_SET);
700 
701     for (i = SID_CACHE_ENTRIES_PER_SET; i > 0; --i) {
702 	sidCacheEntry * sce;
703 
704 	ndx  = (ndx - 1) % SID_CACHE_ENTRIES_PER_SET;
705 	sce = set + ndx;
706 
707 	if (!sce->valid)
708 	    continue;
709 
710 	if (now > sce->expirationTime) {
711 	    /* SessionID has timed out. Invalidate the entry. */
712 	    SSL_TRC(7, ("%d: timed out sid entry addr=%08x%08x%08x%08x now=%x "
713 			"time+=%x",
714 			myPid, sce->addr.pr_s6_addr32[0],
715 			sce->addr.pr_s6_addr32[1], sce->addr.pr_s6_addr32[2],
716 			sce->addr.pr_s6_addr32[3], now,
717 			sce->expirationTime ));
718 	    sce->valid = 0;
719 	    continue;
720 	}
721 
722 	/*
723 	** Next, examine specific session-id/addr data to see if the cache
724 	** entry matches our addr+session-id value
725 	*/
726 	if (sessionIDLength == sce->sessionIDLength      &&
727 	    !memcmp(&sce->addr, addr, sizeof(PRIPv6Addr)) &&
728 	    !memcmp(sce->sessionID, sessionID, sessionIDLength)) {
729 	    /* Found it */
730 	    return sce;
731 	}
732     }
733 
734     PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND);
735     return NULL;
736 }
737 
738 /************************************************************************/
739 
740 /* This is the primary function for finding entries in the server's sid cache.
741  * Although it is static, this function is called via the global function
742  * pointer ssl_sid_lookup.
743  */
744 static sslSessionID *
ServerSessionIDLookup(const PRIPv6Addr * addr,unsigned char * sessionID,unsigned int sessionIDLength,CERTCertDBHandle * dbHandle)745 ServerSessionIDLookup(const PRIPv6Addr *addr,
746 			unsigned char *sessionID,
747 			unsigned int   sessionIDLength,
748                         CERTCertDBHandle * dbHandle)
749 {
750     sslSessionID *  sid      = 0;
751     sidCacheEntry * psce;
752     certCacheEntry *pcce     = 0;
753     srvNameCacheEntry *psnce = 0;
754     cacheDesc *     cache    = &globalCache;
755     PRUint32        now;
756     PRUint32        set;
757     PRInt32         cndx;
758     sidCacheEntry   sce;
759     certCacheEntry  cce;
760     srvNameCacheEntry snce;
761 
762     set = SIDindex(cache, addr, sessionID, sessionIDLength);
763     now = LockSet(cache, set, 0);
764     if (!now)
765     	return NULL;
766 
767     psce = FindSID(cache, set, now, addr, sessionID, sessionIDLength);
768     if (psce) {
769 	if (psce->version >= SSL_LIBRARY_VERSION_3_0) {
770 	    if ((cndx = psce->u.ssl3.certIndex) != -1) {
771 
772                 PRUint32 gotLock = LockSidCacheLock(cache->certCacheLock, now);
773                 if (gotLock) {
774                     pcce = &cache->certCacheData[cndx];
775 
776                     /* See if the cert's session ID matches the sce cache. */
777                     if ((pcce->sessionIDLength == psce->sessionIDLength) &&
778                         !PORT_Memcmp(pcce->sessionID, psce->sessionID,
779                                      pcce->sessionIDLength)) {
780                         cce = *pcce;
781                     } else {
782                         /* The cert doesen't match the SID cache entry,
783                         ** so invalidate the SID cache entry.
784                         */
785                         psce->valid = 0;
786                         psce = 0;
787                         pcce = 0;
788                     }
789                     UnlockSidCacheLock(cache->certCacheLock);
790                 } else {
791                     /* what the ??.  Didn't get the cert cache lock.
792                     ** Don't invalidate the SID cache entry, but don't find it.
793                     */
794                     PORT_Assert(!("Didn't get cert Cache Lock!"));
795                     psce = 0;
796                     pcce = 0;
797                 }
798             }
799             if (psce && ((cndx = psce->u.ssl3.srvNameIndex) != -1)) {
800                 PRUint32 gotLock = LockSidCacheLock(cache->srvNameCacheLock,
801                                                     now);
802                 if (gotLock) {
803                     psnce = &cache->srvNameCacheData[cndx];
804 
805                     if (!PORT_Memcmp(psnce->nameHash, psce->u.ssl3.srvNameHash,
806                                      SHA256_LENGTH)) {
807                         snce = *psnce;
808                     } else {
809                         /* The name doesen't match the SID cache entry,
810                         ** so invalidate the SID cache entry.
811                         */
812                         psce->valid = 0;
813                         psce = 0;
814                         psnce = 0;
815                     }
816                     UnlockSidCacheLock(cache->srvNameCacheLock);
817                 } else {
818                     /* what the ??.  Didn't get the cert cache lock.
819                     ** Don't invalidate the SID cache entry, but don't find it.
820                     */
821                     PORT_Assert(!("Didn't get name Cache Lock!"));
822                     psce = 0;
823                     psnce = 0;
824                 }
825 
826             }
827         }
828 	if (psce) {
829 	    psce->lastAccessTime = now;
830 	    sce = *psce;	/* grab a copy while holding the lock */
831     	}
832     }
833     UnlockSet(cache, set);
834     if (psce) {
835 	/* sce conains a copy of the cache entry.
836 	** Convert shared memory format to local format
837 	*/
838 	sid = ConvertToSID(&sce, pcce ? &cce : 0, psnce ? &snce : 0, dbHandle);
839     }
840     return sid;
841 }
842 
843 /*
844 ** Place a sid into the cache, if it isn't already there.
845 */
846 static void
ServerSessionIDCache(sslSessionID * sid)847 ServerSessionIDCache(sslSessionID *sid)
848 {
849     sidCacheEntry sce;
850     PRUint32      now     = 0;
851     PRUint16      version = sid->version;
852     cacheDesc *   cache   = &globalCache;
853 
854     if ((version >= SSL_LIBRARY_VERSION_3_0) &&
855 	(sid->u.ssl3.sessionIDLength == 0)) {
856 	return;
857     }
858 
859     if (sid->cached == never_cached || sid->cached == invalid_cache) {
860 	PRUint32 set;
861 
862 	PORT_Assert(sid->creationTime != 0);
863 	if (!sid->creationTime)
864 	    sid->lastAccessTime = sid->creationTime = ssl_Time();
865 	if (version < SSL_LIBRARY_VERSION_3_0) {
866 	    /* override caller's expiration time, which uses client timeout
867 	     * duration, not server timeout duration.
868 	     */
869 	    sid->expirationTime = sid->creationTime + cache->ssl2Timeout;
870 	    SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
871 			"cipher=%d", myPid, sid->cached,
872 			sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
873 			sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
874 			sid->creationTime, sid->u.ssl2.cipherType));
875 	    PRINT_BUF(8, (0, "sessionID:", sid->u.ssl2.sessionID,
876 			  SSL2_SESSIONID_BYTES));
877 	    PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
878 			  sid->u.ssl2.masterKey.len));
879 	    PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
880 			  sid->u.ssl2.cipherArg.len));
881 
882 	} else {
883 	    /* override caller's expiration time, which uses client timeout
884 	     * duration, not server timeout duration.
885 	     */
886 	    sid->expirationTime = sid->creationTime + cache->ssl3Timeout;
887 	    SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
888 			"cipherSuite=%d", myPid, sid->cached,
889 			sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
890 			sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
891 			sid->creationTime, sid->u.ssl3.cipherSuite));
892 	    PRINT_BUF(8, (0, "sessionID:", sid->u.ssl3.sessionID,
893 			  sid->u.ssl3.sessionIDLength));
894 	}
895 
896 	ConvertFromSID(&sce, sid);
897 
898 	if (version >= SSL_LIBRARY_VERSION_3_0) {
899             SECItem *name = &sid->u.ssl3.srvName;
900             if (name->len && name->data) {
901                 now = CacheSrvName(cache, name, &sce);
902             }
903             if (sid->peerCert != NULL) {
904                 now = CacheCert(cache, sid->peerCert, &sce);
905             }
906 	}
907 
908 	set = SIDindex(cache, &sce.addr, sce.sessionID, sce.sessionIDLength);
909 	now = LockSet(cache, set, now);
910 	if (now) {
911 	    PRUint32  next = cache->sidCacheSets[set].next;
912 	    PRUint32  ndx  = set * SID_CACHE_ENTRIES_PER_SET + next;
913 
914 	    /* Write out new cache entry */
915 	    cache->sidCacheData[ndx] = sce;
916 
917 	    cache->sidCacheSets[set].next =
918 	    				(next + 1) % SID_CACHE_ENTRIES_PER_SET;
919 
920 	    UnlockSet(cache, set);
921 	    sid->cached = in_server_cache;
922 	}
923     }
924 }
925 
926 /*
927 ** Although this is static, it is called from ssl via global function pointer
928 **	ssl_sid_uncache.  This invalidates the referenced cache entry.
929 */
930 static void
ServerSessionIDUncache(sslSessionID * sid)931 ServerSessionIDUncache(sslSessionID *sid)
932 {
933     cacheDesc *    cache   = &globalCache;
934     PRUint8 *      sessionID;
935     unsigned int   sessionIDLength;
936     PRErrorCode    err;
937     PRUint32       set;
938     PRUint32       now;
939     sidCacheEntry *psce;
940 
941     if (sid == NULL)
942     	return;
943 
944     /* Uncaching a SID should never change the error code.
945     ** So save it here and restore it before exiting.
946     */
947     err = PR_GetError();
948 
949     if (sid->version < SSL_LIBRARY_VERSION_3_0) {
950 	sessionID       = sid->u.ssl2.sessionID;
951 	sessionIDLength = SSL2_SESSIONID_BYTES;
952 	SSL_TRC(8, ("%d: SSL: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
953 		    "cipher=%d", myPid, sid->cached,
954 		    sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
955 		    sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
956 		    sid->creationTime, sid->u.ssl2.cipherType));
957 	PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
958 	PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
959 		      sid->u.ssl2.masterKey.len));
960 	PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
961 		      sid->u.ssl2.cipherArg.len));
962     } else {
963 	sessionID       = sid->u.ssl3.sessionID;
964 	sessionIDLength = sid->u.ssl3.sessionIDLength;
965 	SSL_TRC(8, ("%d: SSL3: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
966 		    "cipherSuite=%d", myPid, sid->cached,
967 		    sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
968 		    sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
969 		    sid->creationTime, sid->u.ssl3.cipherSuite));
970 	PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
971     }
972     set = SIDindex(cache, &sid->addr, sessionID, sessionIDLength);
973     now = LockSet(cache, set, 0);
974     if (now) {
975 	psce = FindSID(cache, set, now, &sid->addr, sessionID, sessionIDLength);
976 	if (psce) {
977 	    psce->valid = 0;
978 	}
979 	UnlockSet(cache, set);
980     }
981     sid->cached = invalid_cache;
982     PORT_SetError(err);
983 }
984 
985 #ifdef XP_OS2
986 
987 #define INCL_DOSPROCESS
988 #include <os2.h>
989 
gettid(void)990 long gettid(void)
991 {
992     PTIB ptib;
993     PPIB ppib;
994     DosGetInfoBlocks(&ptib, &ppib);
995     return ((long)ptib->tib_ordinal); /* thread id */
996 }
997 #endif
998 
999 static void
CloseCache(cacheDesc * cache)1000 CloseCache(cacheDesc *cache)
1001 {
1002     int locks_initialized = cache->numSIDCacheLocksInitialized;
1003 
1004     if (cache->cacheMem) {
1005 	if (cache->sharedCache) {
1006 	    sidCacheLock *pLock = cache->sidCacheLocks;
1007 	    for (; locks_initialized > 0; --locks_initialized, ++pLock ) {
1008 		/* If everInherited is true, this shared cache was (and may
1009 		** still be) in use by multiple processes.  We do not wish to
1010 		** destroy the mutexes while they are still in use, but we do
1011 		** want to free mutex resources associated with this process.
1012 		*/
1013 		sslMutex_Destroy(&pLock->mutex,
1014 				 cache->sharedCache->everInherited);
1015 	    }
1016 	}
1017 	if (cache->shared) {
1018 	    PR_MemUnmap(cache->cacheMem, cache->cacheMemSize);
1019 	} else {
1020 	    PORT_Free(cache->cacheMem);
1021 	}
1022 	cache->cacheMem = NULL;
1023     }
1024     if (cache->cacheMemMap) {
1025 	PR_CloseFileMap(cache->cacheMemMap);
1026 	cache->cacheMemMap = NULL;
1027     }
1028     memset(cache, 0, sizeof *cache);
1029 }
1030 
1031 static SECStatus
InitCache(cacheDesc * cache,int maxCacheEntries,int maxCertCacheEntries,int maxSrvNameCacheEntries,PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory,PRBool shared)1032 InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries,
1033           int maxSrvNameCacheEntries, PRUint32 ssl2_timeout,
1034           PRUint32 ssl3_timeout, const char *directory, PRBool shared)
1035 {
1036     ptrdiff_t     ptr;
1037     sidCacheLock *pLock;
1038     char *        cacheMem;
1039     PRFileMap *   cacheMemMap;
1040     char *        cfn = NULL;	/* cache file name */
1041     int           locks_initialized = 0;
1042     int           locks_to_initialize = 0;
1043     PRUint32      init_time;
1044 
1045     if ( (!cache) || (maxCacheEntries < 0) || (!directory) ) {
1046         PORT_SetError(SEC_ERROR_INVALID_ARGS);
1047         return SECFailure;
1048     }
1049 
1050     if (cache->cacheMem) {
1051 	/* Already done */
1052 	return SECSuccess;
1053     }
1054 
1055     /* make sure loser can clean up properly */
1056     cache->shared = shared;
1057     cache->cacheMem    = cacheMem    = NULL;
1058     cache->cacheMemMap = cacheMemMap = NULL;
1059     cache->sharedCache = (cacheDesc *)0;
1060 
1061     cache->numSIDCacheLocksInitialized = 0;
1062     cache->nextCertCacheEntry = 0;
1063     cache->stopPolling = PR_FALSE;
1064     cache->everInherited = PR_FALSE;
1065     cache->poller = NULL;
1066     cache->mutexTimeout = 0;
1067 
1068     cache->numSIDCacheEntries = maxCacheEntries ? maxCacheEntries
1069                                                 : DEF_SID_CACHE_ENTRIES;
1070     cache->numSIDCacheSets    =
1071     	SID_HOWMANY(cache->numSIDCacheEntries, SID_CACHE_ENTRIES_PER_SET);
1072 
1073     cache->numSIDCacheEntries =
1074     	cache->numSIDCacheSets * SID_CACHE_ENTRIES_PER_SET;
1075 
1076     cache->numSIDCacheLocks   =
1077     	PR_MIN(cache->numSIDCacheSets, ssl_max_sid_cache_locks);
1078 
1079     cache->numSIDCacheSetsPerLock =
1080     	SID_HOWMANY(cache->numSIDCacheSets, cache->numSIDCacheLocks);
1081 
1082     cache->numCertCacheEntries = (maxCertCacheEntries > 0) ?
1083                                              maxCertCacheEntries : 0;
1084     cache->numSrvNameCacheEntries = (maxSrvNameCacheEntries >= 0) ?
1085                                              maxSrvNameCacheEntries : DEF_NAME_CACHE_ENTRIES;
1086 
1087     /* compute size of shared memory, and offsets of all pointers */
1088     ptr = 0;
1089     cache->cacheMem     = (char *)ptr;
1090     ptr += SID_ROUNDUP(sizeof(cacheDesc), SID_ALIGNMENT);
1091 
1092     cache->sidCacheLocks = (sidCacheLock *)ptr;
1093     cache->keyCacheLock  = cache->sidCacheLocks + cache->numSIDCacheLocks;
1094     cache->certCacheLock = cache->keyCacheLock  + 1;
1095     cache->srvNameCacheLock = cache->certCacheLock  + 1;
1096     ptr = (ptrdiff_t)(cache->srvNameCacheLock + 1);
1097     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1098 
1099     cache->sidCacheSets  = (sidCacheSet *)ptr;
1100     ptr = (ptrdiff_t)(cache->sidCacheSets + cache->numSIDCacheSets);
1101     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1102 
1103     cache->sidCacheData  = (sidCacheEntry *)ptr;
1104     ptr = (ptrdiff_t)(cache->sidCacheData + cache->numSIDCacheEntries);
1105     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1106 
1107     cache->certCacheData = (certCacheEntry *)ptr;
1108     cache->sidCacheSize  =
1109     	(char *)cache->certCacheData - (char *)cache->sidCacheData;
1110 
1111     if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES) {
1112         /* This is really a poor way to computer this! */
1113         cache->numCertCacheEntries = cache->sidCacheSize / sizeof(certCacheEntry);
1114         if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES)
1115     	cache->numCertCacheEntries = MIN_CERT_CACHE_ENTRIES;
1116     }
1117     ptr = (ptrdiff_t)(cache->certCacheData + cache->numCertCacheEntries);
1118     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1119 
1120     cache->keyCacheData  = (SSLWrappedSymWrappingKey *)ptr;
1121     cache->certCacheSize =
1122     	(char *)cache->keyCacheData - (char *)cache->certCacheData;
1123 
1124     cache->numKeyCacheEntries = kt_kea_size * SSL_NUM_WRAP_MECHS;
1125     ptr = (ptrdiff_t)(cache->keyCacheData + cache->numKeyCacheEntries);
1126     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1127 
1128     cache->keyCacheSize  = (char *)ptr - (char *)cache->keyCacheData;
1129 
1130     cache->ticketKeyNameSuffix = (PRUint8 *)ptr;
1131     ptr = (ptrdiff_t)(cache->ticketKeyNameSuffix +
1132 	SESS_TICKET_KEY_VAR_NAME_LEN);
1133     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1134 
1135     cache->ticketEncKey = (encKeyCacheEntry *)ptr;
1136     ptr = (ptrdiff_t)(cache->ticketEncKey + 1);
1137     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1138 
1139     cache->ticketMacKey = (encKeyCacheEntry *)ptr;
1140     ptr = (ptrdiff_t)(cache->ticketMacKey + 1);
1141     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1142 
1143     cache->ticketKeysValid = (PRUint32 *)ptr;
1144     ptr = (ptrdiff_t)(cache->ticketKeysValid + 1);
1145     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1146 
1147     cache->srvNameCacheData = (srvNameCacheEntry *)ptr;
1148     cache->srvNameCacheSize =
1149         cache->numSrvNameCacheEntries * sizeof(srvNameCacheEntry);
1150     ptr = (ptrdiff_t)(cache->srvNameCacheData + cache->numSrvNameCacheEntries);
1151     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1152 
1153     cache->cacheMemSize = ptr;
1154 
1155     if (ssl2_timeout) {
1156 	if (ssl2_timeout > MAX_SSL2_TIMEOUT) {
1157 	    ssl2_timeout = MAX_SSL2_TIMEOUT;
1158 	}
1159 	if (ssl2_timeout < MIN_SSL2_TIMEOUT) {
1160 	    ssl2_timeout = MIN_SSL2_TIMEOUT;
1161 	}
1162 	cache->ssl2Timeout = ssl2_timeout;
1163     } else {
1164 	cache->ssl2Timeout = DEF_SSL2_TIMEOUT;
1165     }
1166 
1167     if (ssl3_timeout) {
1168 	if (ssl3_timeout > MAX_SSL3_TIMEOUT) {
1169 	    ssl3_timeout = MAX_SSL3_TIMEOUT;
1170 	}
1171 	if (ssl3_timeout < MIN_SSL3_TIMEOUT) {
1172 	    ssl3_timeout = MIN_SSL3_TIMEOUT;
1173 	}
1174 	cache->ssl3Timeout = ssl3_timeout;
1175     } else {
1176 	cache->ssl3Timeout = DEF_SSL3_TIMEOUT;
1177     }
1178 
1179     if (shared) {
1180 	/* Create file names */
1181 #if defined(XP_UNIX) || defined(XP_BEOS)
1182 	/* there's some confusion here about whether PR_OpenAnonFileMap wants
1183 	** a directory name or a file name for its first argument.
1184 	cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid);
1185 	*/
1186 	cfn = PR_smprintf("%s", directory);
1187 #elif defined(XP_WIN32)
1188 	cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
1189 			    GetCurrentThreadId());
1190 #elif defined(XP_OS2)
1191 	cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
1192 			    gettid());
1193 #else
1194 #error "Don't know how to create file name for this platform!"
1195 #endif
1196 	if (!cfn) {
1197 	    goto loser;
1198 	}
1199 
1200 	/* Create cache */
1201 	cacheMemMap = PR_OpenAnonFileMap(cfn, cache->cacheMemSize,
1202 					 PR_PROT_READWRITE);
1203 
1204 	PR_smprintf_free(cfn);
1205 	if(!cacheMemMap) {
1206 	    goto loser;
1207 	}
1208 
1209         cacheMem = PR_MemMap(cacheMemMap, 0, cache->cacheMemSize);
1210     } else {
1211         cacheMem = PORT_Alloc(cache->cacheMemSize);
1212     }
1213 
1214     if (! cacheMem) {
1215         goto loser;
1216     }
1217 
1218     /* Initialize shared memory. This may not be necessary on all platforms */
1219     memset(cacheMem, 0, cache->cacheMemSize);
1220 
1221     /* Copy cache descriptor header into shared memory */
1222     memcpy(cacheMem, cache, sizeof *cache);
1223 
1224     /* save private copies of these values */
1225     cache->cacheMemMap = cacheMemMap;
1226     cache->cacheMem    = cacheMem;
1227     cache->sharedCache = (cacheDesc *)cacheMem;
1228 
1229     /* Fix pointers in our private copy of cache descriptor to point to
1230     ** spaces in shared memory
1231     */
1232     ptr = (ptrdiff_t)cache->cacheMem;
1233     *(ptrdiff_t *)(&cache->sidCacheLocks) += ptr;
1234     *(ptrdiff_t *)(&cache->keyCacheLock ) += ptr;
1235     *(ptrdiff_t *)(&cache->certCacheLock) += ptr;
1236     *(ptrdiff_t *)(&cache->srvNameCacheLock) += ptr;
1237     *(ptrdiff_t *)(&cache->sidCacheSets ) += ptr;
1238     *(ptrdiff_t *)(&cache->sidCacheData ) += ptr;
1239     *(ptrdiff_t *)(&cache->certCacheData) += ptr;
1240     *(ptrdiff_t *)(&cache->keyCacheData ) += ptr;
1241     *(ptrdiff_t *)(&cache->ticketKeyNameSuffix) += ptr;
1242     *(ptrdiff_t *)(&cache->ticketEncKey ) += ptr;
1243     *(ptrdiff_t *)(&cache->ticketMacKey ) += ptr;
1244     *(ptrdiff_t *)(&cache->ticketKeysValid) += ptr;
1245     *(ptrdiff_t *)(&cache->srvNameCacheData) += ptr;
1246 
1247     /* initialize the locks */
1248     init_time = ssl_Time();
1249     pLock = cache->sidCacheLocks;
1250     for (locks_to_initialize = cache->numSIDCacheLocks + 3;
1251          locks_initialized < locks_to_initialize;
1252 	 ++locks_initialized, ++pLock ) {
1253 
1254 	SECStatus err = sslMutex_Init(&pLock->mutex, shared);
1255 	if (err) {
1256 	    cache->numSIDCacheLocksInitialized = locks_initialized;
1257 	    goto loser;
1258 	}
1259         pLock->timeStamp = init_time;
1260 	pLock->pid       = 0;
1261     }
1262     cache->numSIDCacheLocksInitialized = locks_initialized;
1263 
1264     return SECSuccess;
1265 
1266 loser:
1267     CloseCache(cache);
1268     return SECFailure;
1269 }
1270 
1271 PRUint32
SSL_GetMaxServerCacheLocks(void)1272 SSL_GetMaxServerCacheLocks(void)
1273 {
1274     return ssl_max_sid_cache_locks + 2;
1275     /* The extra two are the cert cache lock and the key cache lock. */
1276 }
1277 
1278 SECStatus
SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)1279 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
1280 {
1281     /* Minimum is 1 sid cache lock, 1 cert cache lock and 1 key cache lock.
1282     ** We'd like to test for a maximum value, but not all platforms' header
1283     ** files provide a symbol or function or other means of determining
1284     ** the maximum, other than trial and error.
1285     */
1286     if (maxLocks < 3) {
1287 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
1288 	return SECFailure;
1289     }
1290     ssl_max_sid_cache_locks = maxLocks - 2;
1291     /* The extra two are the cert cache lock and the key cache lock. */
1292     return SECSuccess;
1293 }
1294 
1295 static SECStatus
ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc * cache,PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory,PRBool shared,int maxCacheEntries,int maxCertCacheEntries,int maxSrvNameCacheEntries)1296 ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc *cache,
1297                                               PRUint32 ssl2_timeout,
1298                                               PRUint32 ssl3_timeout,
1299                                               const char *   directory,
1300                                               PRBool shared,
1301                                               int      maxCacheEntries,
1302                                               int      maxCertCacheEntries,
1303                                               int      maxSrvNameCacheEntries)
1304 {
1305     SECStatus rv;
1306 
1307     PORT_Assert(sizeof(sidCacheEntry) == 192);
1308     PORT_Assert(sizeof(certCacheEntry) == 4096);
1309     PORT_Assert(sizeof(srvNameCacheEntry) == 1072);
1310 
1311     rv = ssl_Init();
1312     if (rv != SECSuccess) {
1313 	return rv;
1314     }
1315 
1316     myPid = SSL_GETPID();
1317     if (!directory) {
1318 	directory = DEFAULT_CACHE_DIRECTORY;
1319     }
1320     rv = InitCache(cache, maxCacheEntries, maxCertCacheEntries,
1321                    maxSrvNameCacheEntries, ssl2_timeout, ssl3_timeout,
1322                    directory, shared);
1323     if (rv) {
1324 	SET_ERROR_CODE
1325     	return SECFailure;
1326     }
1327 
1328     ssl_sid_lookup  = ServerSessionIDLookup;
1329     ssl_sid_cache   = ServerSessionIDCache;
1330     ssl_sid_uncache = ServerSessionIDUncache;
1331     return SECSuccess;
1332 }
1333 
1334 SECStatus
SSL_ConfigServerSessionIDCacheInstance(cacheDesc * cache,int maxCacheEntries,PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory,PRBool shared)1335 SSL_ConfigServerSessionIDCacheInstance(	cacheDesc *cache,
1336                                 int      maxCacheEntries,
1337                                 PRUint32 ssl2_timeout,
1338                                 PRUint32 ssl3_timeout,
1339                                 const char *   directory, PRBool shared)
1340 {
1341     return ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache,
1342                                                          ssl2_timeout,
1343                                                          ssl3_timeout,
1344                                                          directory,
1345                                                          shared,
1346                                                          maxCacheEntries,
1347                                                          -1, -1);
1348 }
1349 
1350 SECStatus
SSL_ConfigServerSessionIDCache(int maxCacheEntries,PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory)1351 SSL_ConfigServerSessionIDCache(	int      maxCacheEntries,
1352 				PRUint32 ssl2_timeout,
1353 			       	PRUint32 ssl3_timeout,
1354 			  const char *   directory)
1355 {
1356     ssl_InitSessionCacheLocks();
1357     return SSL_ConfigServerSessionIDCacheInstance(&globalCache,
1358     		maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE);
1359 }
1360 
1361 SECStatus
SSL_ShutdownServerSessionIDCacheInstance(cacheDesc * cache)1362 SSL_ShutdownServerSessionIDCacheInstance(cacheDesc *cache)
1363 {
1364     CloseCache(cache);
1365     return SECSuccess;
1366 }
1367 
1368 SECStatus
SSL_ShutdownServerSessionIDCache(void)1369 SSL_ShutdownServerSessionIDCache(void)
1370 {
1371 #if defined(XP_UNIX) || defined(XP_BEOS)
1372     /* Stop the thread that polls cache for expired locks on Unix */
1373     StopLockPoller(&globalCache);
1374 #endif
1375     SSL3_ShutdownServerCache();
1376     return SSL_ShutdownServerSessionIDCacheInstance(&globalCache);
1377 }
1378 
1379 /* Use this function, instead of SSL_ConfigServerSessionIDCache,
1380  * if the cache will be shared by multiple processes.
1381  */
1382 static SECStatus
ssl_ConfigMPServerSIDCacheWithOpt(PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory,int maxCacheEntries,int maxCertCacheEntries,int maxSrvNameCacheEntries)1383 ssl_ConfigMPServerSIDCacheWithOpt(      PRUint32 ssl2_timeout,
1384                                         PRUint32 ssl3_timeout,
1385                                         const char *   directory,
1386                                         int maxCacheEntries,
1387                                         int maxCertCacheEntries,
1388                                         int maxSrvNameCacheEntries)
1389 {
1390     char *	envValue;
1391     char *	inhValue;
1392     cacheDesc * cache         = &globalCache;
1393     PRUint32    fmStrLen;
1394     SECStatus 	result;
1395     PRStatus 	prStatus;
1396     SECStatus	putEnvFailed;
1397     inheritance inherit;
1398     char        fmString[PR_FILEMAP_STRING_BUFSIZE];
1399 
1400     isMultiProcess = PR_TRUE;
1401     result = ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache,
1402                   ssl2_timeout, ssl3_timeout, directory, PR_TRUE,
1403         maxCacheEntries, maxCacheEntries, maxSrvNameCacheEntries);
1404     if (result != SECSuccess)
1405         return result;
1406 
1407     prStatus = PR_ExportFileMapAsString(cache->cacheMemMap,
1408                                         sizeof fmString, fmString);
1409     if ((prStatus != PR_SUCCESS) || !(fmStrLen = strlen(fmString))) {
1410 	SET_ERROR_CODE
1411 	return SECFailure;
1412     }
1413 
1414     inherit.cacheMemSize	= cache->cacheMemSize;
1415     inherit.fmStrLen            = fmStrLen;
1416 
1417     inhValue = BTOA_DataToAscii((unsigned char *)&inherit, sizeof inherit);
1418     if (!inhValue || !strlen(inhValue)) {
1419 	SET_ERROR_CODE
1420 	return SECFailure;
1421     }
1422     envValue = PR_smprintf("%s,%s", inhValue, fmString);
1423     if (!envValue || !strlen(envValue)) {
1424 	SET_ERROR_CODE
1425 	return SECFailure;
1426     }
1427     PORT_Free(inhValue);
1428 
1429     putEnvFailed = (SECStatus)NSS_PutEnv(envVarName, envValue);
1430     PR_smprintf_free(envValue);
1431     if (putEnvFailed) {
1432         SET_ERROR_CODE
1433         result = SECFailure;
1434     }
1435 
1436 #if defined(XP_UNIX) || defined(XP_BEOS)
1437     /* Launch thread to poll cache for expired locks on Unix */
1438     LaunchLockPoller(cache);
1439 #endif
1440     return result;
1441 }
1442 
1443 /* Use this function, instead of SSL_ConfigServerSessionIDCache,
1444  * if the cache will be shared by multiple processes.
1445  */
1446 SECStatus
SSL_ConfigMPServerSIDCache(int maxCacheEntries,PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory)1447 SSL_ConfigMPServerSIDCache(	int      maxCacheEntries,
1448 				PRUint32 ssl2_timeout,
1449 			       	PRUint32 ssl3_timeout,
1450 		          const char *   directory)
1451 {
1452     return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout,
1453                                              ssl3_timeout,
1454                                              directory,
1455                                              maxCacheEntries,
1456                                              -1, -1);
1457 }
1458 
1459 SECStatus
SSL_ConfigServerSessionIDCacheWithOpt(PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory,int maxCacheEntries,int maxCertCacheEntries,int maxSrvNameCacheEntries,PRBool enableMPCache)1460 SSL_ConfigServerSessionIDCacheWithOpt(
1461 				PRUint32 ssl2_timeout,
1462 			       	PRUint32 ssl3_timeout,
1463                                 const char *   directory,
1464                                 int maxCacheEntries,
1465                                 int maxCertCacheEntries,
1466                                 int maxSrvNameCacheEntries,
1467                                 PRBool enableMPCache)
1468 {
1469     if (!enableMPCache) {
1470         ssl_InitSessionCacheLocks();
1471         return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache,
1472            ssl2_timeout, ssl3_timeout, directory, PR_FALSE,
1473            maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries);
1474     } else {
1475         return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout, ssl3_timeout,
1476                 directory, maxCacheEntries, maxCertCacheEntries,
1477                                                  maxSrvNameCacheEntries);
1478     }
1479 }
1480 
1481 SECStatus
SSL_InheritMPServerSIDCacheInstance(cacheDesc * cache,const char * envString)1482 SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
1483 {
1484     unsigned char * decoString = NULL;
1485     char *          fmString   = NULL;
1486     char *          myEnvString = NULL;
1487     unsigned int    decoLen;
1488     ptrdiff_t       ptr;
1489     inheritance     inherit;
1490     cacheDesc       my;
1491 #ifdef WINNT
1492     sidCacheLock* newLocks;
1493     int           locks_initialized = 0;
1494     int           locks_to_initialize = 0;
1495 #endif
1496     SECStatus     status = ssl_Init();
1497 
1498     if (status != SECSuccess) {
1499 	return status;
1500     }
1501 
1502     myPid = SSL_GETPID();
1503 
1504     /* If this child was created by fork(), and not by exec() on unix,
1505     ** then isMultiProcess will already be set.
1506     ** If not, we'll set it below.
1507     */
1508     if (isMultiProcess) {
1509 	if (cache && cache->sharedCache) {
1510 	    cache->sharedCache->everInherited = PR_TRUE;
1511 	}
1512     	return SECSuccess;	/* already done. */
1513     }
1514 
1515     ssl_InitSessionCacheLocks();
1516 
1517     ssl_sid_lookup  = ServerSessionIDLookup;
1518     ssl_sid_cache   = ServerSessionIDCache;
1519     ssl_sid_uncache = ServerSessionIDUncache;
1520 
1521     if (!envString) {
1522     	envString  = getenv(envVarName);
1523 	if (!envString) {
1524 	    SET_ERROR_CODE
1525 	    return SECFailure;
1526 	}
1527     }
1528     myEnvString = PORT_Strdup(envString);
1529     if (!myEnvString)
1530 	return SECFailure;
1531     fmString = strchr(myEnvString, ',');
1532     if (!fmString)
1533     	goto loser;
1534     *fmString++ = 0;
1535 
1536     decoString = ATOB_AsciiToData(myEnvString, &decoLen);
1537     if (!decoString) {
1538     	SET_ERROR_CODE
1539 	goto loser;
1540     }
1541     if (decoLen != sizeof inherit) {
1542     	SET_ERROR_CODE
1543     	goto loser;
1544     }
1545 
1546     PORT_Memcpy(&inherit, decoString, sizeof inherit);
1547 
1548     if (strlen(fmString)  != inherit.fmStrLen ) {
1549     	goto loser;
1550     }
1551 
1552     memset(cache, 0, sizeof *cache);
1553     cache->cacheMemSize	= inherit.cacheMemSize;
1554 
1555     /* Create cache */
1556     cache->cacheMemMap = PR_ImportFileMapFromString(fmString);
1557     if(! cache->cacheMemMap) {
1558 	goto loser;
1559     }
1560     cache->cacheMem = PR_MemMap(cache->cacheMemMap, 0, cache->cacheMemSize);
1561     if (! cache->cacheMem) {
1562 	goto loser;
1563     }
1564     cache->sharedCache   = (cacheDesc *)cache->cacheMem;
1565 
1566     if (cache->sharedCache->cacheMemSize != cache->cacheMemSize) {
1567 	SET_ERROR_CODE
1568     	goto loser;
1569     }
1570 
1571     /* We're now going to overwrite the local cache instance with the
1572     ** shared copy of the cache struct, then update several values in
1573     ** the local cache using the values for cache->cacheMemMap and
1574     ** cache->cacheMem computed just above.  So, we copy cache into
1575     ** the automatic variable "my", to preserve the variables while
1576     ** cache is overwritten.
1577     */
1578     my = *cache;  /* save values computed above. */
1579     memcpy(cache, cache->sharedCache, sizeof *cache); /* overwrite */
1580 
1581     /* Fix pointers in our private copy of cache descriptor to point to
1582     ** spaces in shared memory, whose address is now in "my".
1583     */
1584     ptr = (ptrdiff_t)my.cacheMem;
1585     *(ptrdiff_t *)(&cache->sidCacheLocks) += ptr;
1586     *(ptrdiff_t *)(&cache->keyCacheLock ) += ptr;
1587     *(ptrdiff_t *)(&cache->certCacheLock) += ptr;
1588     *(ptrdiff_t *)(&cache->srvNameCacheLock) += ptr;
1589     *(ptrdiff_t *)(&cache->sidCacheSets ) += ptr;
1590     *(ptrdiff_t *)(&cache->sidCacheData ) += ptr;
1591     *(ptrdiff_t *)(&cache->certCacheData) += ptr;
1592     *(ptrdiff_t *)(&cache->keyCacheData ) += ptr;
1593     *(ptrdiff_t *)(&cache->ticketKeyNameSuffix) += ptr;
1594     *(ptrdiff_t *)(&cache->ticketEncKey ) += ptr;
1595     *(ptrdiff_t *)(&cache->ticketMacKey ) += ptr;
1596     *(ptrdiff_t *)(&cache->ticketKeysValid) += ptr;
1597     *(ptrdiff_t *)(&cache->srvNameCacheData) += ptr;
1598 
1599     cache->cacheMemMap = my.cacheMemMap;
1600     cache->cacheMem    = my.cacheMem;
1601     cache->sharedCache = (cacheDesc *)cache->cacheMem;
1602 
1603 #ifdef WINNT
1604     /*  On Windows NT we need to "fix" the sidCacheLocks here to support fibers
1605     **  When NT fibers are used in a multi-process server, a second level of
1606     **  locking is needed to prevent a deadlock, in case a fiber acquires the
1607     **  cross-process mutex, yields, and another fiber is later scheduled on
1608     **  the same native thread and tries to acquire the cross-process mutex.
1609     **  We do this by using a PRLock in the sslMutex. However, it is stored in
1610     **  shared memory as part of sidCacheLocks, and we don't want to overwrite
1611     **  the PRLock of the parent process. So we need to make new, private
1612     **  copies of sidCacheLocks before modifying the sslMutex with our own
1613     **  PRLock
1614     */
1615 
1616     /* note from jpierre : this should be free'd in child processes when
1617     ** a function is added to delete the SSL session cache in the future.
1618     */
1619     locks_to_initialize = cache->numSIDCacheLocks + 3;
1620     newLocks = PORT_NewArray(sidCacheLock, locks_to_initialize);
1621     if (!newLocks)
1622     	goto loser;
1623     /* copy the old locks */
1624     memcpy(newLocks, cache->sidCacheLocks,
1625            locks_to_initialize * sizeof(sidCacheLock));
1626     cache->sidCacheLocks = newLocks;
1627     /* fix the locks */
1628     for (; locks_initialized < locks_to_initialize; ++locks_initialized) {
1629         /* now, make a local PRLock in this sslMutex for this child process */
1630 	SECStatus err;
1631         err = sslMutex_2LevelInit(&newLocks[locks_initialized].mutex);
1632 	if (err != SECSuccess) {
1633 	    cache->numSIDCacheLocksInitialized = locks_initialized;
1634 	    goto loser;
1635     	}
1636     }
1637     cache->numSIDCacheLocksInitialized = locks_initialized;
1638 
1639     /* also fix the key and cert cache which use the last 2 lock entries */
1640     cache->keyCacheLock  = cache->sidCacheLocks + cache->numSIDCacheLocks;
1641     cache->certCacheLock = cache->keyCacheLock  + 1;
1642     cache->srvNameCacheLock = cache->certCacheLock  + 1;
1643 #endif
1644 
1645     PORT_Free(myEnvString);
1646     PORT_Free(decoString);
1647 
1648     /* mark that we have inherited this. */
1649     cache->sharedCache->everInherited = PR_TRUE;
1650     isMultiProcess = PR_TRUE;
1651 
1652     return SECSuccess;
1653 
1654 loser:
1655     PORT_Free(myEnvString);
1656     if (decoString)
1657 	PORT_Free(decoString);
1658     CloseCache(cache);
1659     return SECFailure;
1660 }
1661 
1662 SECStatus
SSL_InheritMPServerSIDCache(const char * envString)1663 SSL_InheritMPServerSIDCache(const char * envString)
1664 {
1665     return SSL_InheritMPServerSIDCacheInstance(&globalCache, envString);
1666 }
1667 
1668 #if defined(XP_UNIX) || defined(XP_BEOS)
1669 
1670 #define SID_LOCK_EXPIRATION_TIMEOUT  30 /* seconds */
1671 
1672 static void
LockPoller(void * arg)1673 LockPoller(void * arg)
1674 {
1675     cacheDesc *    cache         = (cacheDesc *)arg;
1676     cacheDesc *    sharedCache   = cache->sharedCache;
1677     sidCacheLock * pLock;
1678     PRIntervalTime timeout;
1679     PRUint32       now;
1680     PRUint32       then;
1681     int            locks_polled  = 0;
1682     int            locks_to_poll = cache->numSIDCacheLocks + 2;
1683     PRUint32       expiration    = cache->mutexTimeout;
1684 
1685     timeout = PR_SecondsToInterval(expiration);
1686     while(!sharedCache->stopPolling) {
1687     	PR_Sleep(timeout);
1688 	if (sharedCache->stopPolling)
1689 	    break;
1690 
1691 	now   = ssl_Time();
1692 	then  = now - expiration;
1693 	for (pLock = cache->sidCacheLocks, locks_polled = 0;
1694 	     locks_to_poll > locks_polled && !sharedCache->stopPolling;
1695 	     ++locks_polled, ++pLock ) {
1696 	    pid_t pid;
1697 
1698 	    if (pLock->timeStamp   < then &&
1699 	        pLock->timeStamp   != 0 &&
1700 		(pid = pLock->pid) != 0) {
1701 
1702 	    	/* maybe we should try the lock? */
1703 		int result = kill(pid, 0);
1704 		if (result < 0 && errno == ESRCH) {
1705 		    SECStatus rv;
1706 		    /* No process exists by that pid any more.
1707 		    ** Treat this mutex as abandoned.
1708 		    */
1709 		    pLock->timeStamp = now;
1710 		    pLock->pid       = 0;
1711 		    rv = sslMutex_Unlock(&pLock->mutex);
1712 		    if (rv != SECSuccess) {
1713 		    	/* Now what? */
1714 		    }
1715 		}
1716 	    }
1717 	} /* end of loop over locks */
1718     } /* end of entire polling loop */
1719 }
1720 
1721 /* Launch thread to poll cache for expired locks */
1722 static SECStatus
LaunchLockPoller(cacheDesc * cache)1723 LaunchLockPoller(cacheDesc *cache)
1724 {
1725     const char * timeoutString;
1726     PRThread *   pollerThread;
1727 
1728     cache->mutexTimeout = SID_LOCK_EXPIRATION_TIMEOUT;
1729     timeoutString       = getenv("NSS_SSL_SERVER_CACHE_MUTEX_TIMEOUT");
1730     if (timeoutString) {
1731 	long newTime = strtol(timeoutString, 0, 0);
1732 	if (newTime == 0)
1733 	    return SECSuccess;  /* application doesn't want poller thread */
1734 	if (newTime > 0)
1735 	    cache->mutexTimeout = (PRUint32)newTime;
1736 	/* if error (newTime < 0) ignore it and use default */
1737     }
1738 
1739     pollerThread =
1740 	PR_CreateThread(PR_USER_THREAD, LockPoller, cache, PR_PRIORITY_NORMAL,
1741 	                PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
1742     if (!pollerThread) {
1743     	return SECFailure;
1744     }
1745     cache->poller = pollerThread;
1746     return SECSuccess;
1747 }
1748 
1749 /* Stop the thread that polls cache for expired locks */
1750 static SECStatus
StopLockPoller(cacheDesc * cache)1751 StopLockPoller(cacheDesc *cache)
1752 {
1753     if (!cache->poller) {
1754 	return SECSuccess;
1755     }
1756     cache->sharedCache->stopPolling = PR_TRUE;
1757     if (PR_Interrupt(cache->poller) != PR_SUCCESS) {
1758 	return SECFailure;
1759     }
1760     if (PR_JoinThread(cache->poller) != PR_SUCCESS) {
1761 	return SECFailure;
1762     }
1763     cache->poller = NULL;
1764     return SECSuccess;
1765 }
1766 #endif
1767 
1768 /************************************************************************
1769  *  Code dealing with shared wrapped symmetric wrapping keys below      *
1770  ************************************************************************/
1771 
1772 /* If now is zero, it implies that the lock is not held, and must be
1773 ** aquired here.
1774 */
1775 static PRBool
getSvrWrappingKey(PRInt32 symWrapMechIndex,SSL3KEAType exchKeyType,SSLWrappedSymWrappingKey * wswk,cacheDesc * cache,PRUint32 lockTime)1776 getSvrWrappingKey(PRInt32                symWrapMechIndex,
1777                SSL3KEAType               exchKeyType,
1778                SSLWrappedSymWrappingKey *wswk,
1779 	       cacheDesc *               cache,
1780 	       PRUint32                  lockTime)
1781 {
1782     PRUint32  ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
1783     SSLWrappedSymWrappingKey * pwswk = cache->keyCacheData + ndx;
1784     PRUint32  now = 0;
1785     PRBool    rv  = PR_FALSE;
1786 
1787     if (!cache->cacheMem) { /* cache is uninitialized */
1788 	PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
1789 	return rv;
1790     }
1791     if (!lockTime) {
1792 	lockTime = now = LockSidCacheLock(cache->keyCacheLock, now);
1793 	if (!lockTime) {
1794 	    return rv;
1795 	}
1796     }
1797     if (pwswk->exchKeyType      == exchKeyType &&
1798 	pwswk->symWrapMechIndex == symWrapMechIndex &&
1799 	pwswk->wrappedSymKeyLen != 0) {
1800 	*wswk = *pwswk;
1801 	rv = PR_TRUE;
1802     }
1803     if (now) {
1804 	UnlockSidCacheLock(cache->keyCacheLock);
1805     }
1806     return rv;
1807 }
1808 
1809 PRBool
ssl_GetWrappingKey(PRInt32 symWrapMechIndex,SSL3KEAType exchKeyType,SSLWrappedSymWrappingKey * wswk)1810 ssl_GetWrappingKey( PRInt32                   symWrapMechIndex,
1811                     SSL3KEAType               exchKeyType,
1812 		    SSLWrappedSymWrappingKey *wswk)
1813 {
1814     PRBool rv;
1815 
1816     PORT_Assert( (unsigned)exchKeyType < kt_kea_size);
1817     PORT_Assert( (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
1818     if ((unsigned)exchKeyType < kt_kea_size &&
1819         (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS) {
1820 	rv = getSvrWrappingKey(symWrapMechIndex, exchKeyType, wswk,
1821 	                       &globalCache, 0);
1822     } else {
1823     	rv = PR_FALSE;
1824     }
1825 
1826     return rv;
1827 }
1828 
1829 /* Wrap and cache a session ticket key. */
1830 static PRBool
WrapTicketKey(SECKEYPublicKey * svrPubKey,PK11SymKey * symKey,const char * keyName,encKeyCacheEntry * cacheEntry)1831 WrapTicketKey(SECKEYPublicKey *svrPubKey, PK11SymKey *symKey,
1832               const char *keyName, encKeyCacheEntry* cacheEntry)
1833 {
1834     SECItem wrappedKey = {siBuffer, NULL, 0};
1835 
1836     wrappedKey.len = SECKEY_PublicKeyStrength(svrPubKey);
1837     PORT_Assert(wrappedKey.len <= sizeof(cacheEntry->bytes));
1838     if (wrappedKey.len > sizeof(cacheEntry->bytes))
1839 	return PR_FALSE;
1840     wrappedKey.data = cacheEntry->bytes;
1841 
1842     if (PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, symKey, &wrappedKey)
1843 	    != SECSuccess) {
1844 	SSL_DBG(("%d: SSL[%s]: Unable to wrap session ticket %s.",
1845 		    SSL_GETPID(), "unknown", keyName));
1846 	return PR_FALSE;
1847     }
1848     cacheEntry->length = wrappedKey.len;
1849     return PR_TRUE;
1850 }
1851 
1852 static PRBool
GenerateTicketKeys(void * pwArg,unsigned char * keyName,PK11SymKey ** aesKey,PK11SymKey ** macKey)1853 GenerateTicketKeys(void *pwArg, unsigned char *keyName, PK11SymKey **aesKey,
1854                    PK11SymKey **macKey)
1855 {
1856     PK11SlotInfo *slot;
1857     CK_MECHANISM_TYPE mechanismArray[2];
1858     PK11SymKey *aesKeyTmp = NULL;
1859     PK11SymKey *macKeyTmp = NULL;
1860     cacheDesc *cache = &globalCache;
1861     PRUint8 ticketKeyNameSuffixLocal[SESS_TICKET_KEY_VAR_NAME_LEN];
1862     PRUint8 *ticketKeyNameSuffix;
1863 
1864     if (!cache->cacheMem) {
1865         /* cache is not initalized. Use stack buffer */
1866         ticketKeyNameSuffix = ticketKeyNameSuffixLocal;
1867     } else {
1868         ticketKeyNameSuffix = cache->ticketKeyNameSuffix;
1869     }
1870 
1871     if (PK11_GenerateRandom(ticketKeyNameSuffix,
1872 	    SESS_TICKET_KEY_VAR_NAME_LEN) != SECSuccess) {
1873 	SSL_DBG(("%d: SSL[%s]: Unable to generate random key name bytes.",
1874 		    SSL_GETPID(), "unknown"));
1875 	goto loser;
1876     }
1877 
1878     mechanismArray[0] = CKM_AES_CBC;
1879     mechanismArray[1] = CKM_SHA256_HMAC;
1880 
1881     slot = PK11_GetBestSlotMultiple(mechanismArray, 2, pwArg);
1882     if (slot) {
1883 	aesKeyTmp = PK11_KeyGen(slot, mechanismArray[0], NULL,
1884                                 AES_256_KEY_LENGTH, pwArg);
1885 	macKeyTmp = PK11_KeyGen(slot, mechanismArray[1], NULL,
1886                                 SHA256_LENGTH, pwArg);
1887 	PK11_FreeSlot(slot);
1888     }
1889 
1890     if (aesKeyTmp == NULL || macKeyTmp == NULL) {
1891 	SSL_DBG(("%d: SSL[%s]: Unable to generate session ticket keys.",
1892 		    SSL_GETPID(), "unknown"));
1893 	goto loser;
1894     }
1895     PORT_Memcpy(keyName, ticketKeyNameSuffix, SESS_TICKET_KEY_VAR_NAME_LEN);
1896     *aesKey = aesKeyTmp;
1897     *macKey = macKeyTmp;
1898     return PR_TRUE;
1899 
1900 loser:
1901     if (aesKeyTmp)
1902 	PK11_FreeSymKey(aesKeyTmp);
1903     if (macKeyTmp)
1904 	PK11_FreeSymKey(macKeyTmp);
1905     return PR_FALSE;
1906 }
1907 
1908 static PRBool
GenerateAndWrapTicketKeys(SECKEYPublicKey * svrPubKey,void * pwArg,unsigned char * keyName,PK11SymKey ** aesKey,PK11SymKey ** macKey)1909 GenerateAndWrapTicketKeys(SECKEYPublicKey *svrPubKey, void *pwArg,
1910                           unsigned char *keyName, PK11SymKey **aesKey,
1911                           PK11SymKey **macKey)
1912 {
1913     PK11SymKey *aesKeyTmp = NULL;
1914     PK11SymKey *macKeyTmp = NULL;
1915     cacheDesc *cache = &globalCache;
1916 
1917     if (!GenerateTicketKeys(pwArg, keyName, &aesKeyTmp, &macKeyTmp)) {
1918         goto loser;
1919     }
1920 
1921     if (cache->cacheMem) {
1922         /* Export the keys to the shared cache in wrapped form. */
1923         if (!WrapTicketKey(svrPubKey, aesKeyTmp, "enc key", cache->ticketEncKey))
1924             goto loser;
1925         if (!WrapTicketKey(svrPubKey, macKeyTmp, "mac key", cache->ticketMacKey))
1926             goto loser;
1927     }
1928     *aesKey = aesKeyTmp;
1929     *macKey = macKeyTmp;
1930     return PR_TRUE;
1931 
1932 loser:
1933     if (aesKeyTmp)
1934 	PK11_FreeSymKey(aesKeyTmp);
1935     if (macKeyTmp)
1936 	PK11_FreeSymKey(macKeyTmp);
1937     return PR_FALSE;
1938 }
1939 
1940 static PRBool
UnwrapCachedTicketKeys(SECKEYPrivateKey * svrPrivKey,unsigned char * keyName,PK11SymKey ** aesKey,PK11SymKey ** macKey)1941 UnwrapCachedTicketKeys(SECKEYPrivateKey *svrPrivKey, unsigned char *keyName,
1942                        PK11SymKey **aesKey, PK11SymKey **macKey)
1943 {
1944     SECItem wrappedKey = {siBuffer, NULL, 0};
1945     PK11SymKey *aesKeyTmp = NULL;
1946     PK11SymKey *macKeyTmp = NULL;
1947     cacheDesc *cache = &globalCache;
1948 
1949     wrappedKey.data = cache->ticketEncKey->bytes;
1950     wrappedKey.len = cache->ticketEncKey->length;
1951     PORT_Assert(wrappedKey.len <= sizeof(cache->ticketEncKey->bytes));
1952     aesKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
1953 	CKM_AES_CBC, CKA_DECRYPT, 0);
1954 
1955     wrappedKey.data = cache->ticketMacKey->bytes;
1956     wrappedKey.len = cache->ticketMacKey->length;
1957     PORT_Assert(wrappedKey.len <= sizeof(cache->ticketMacKey->bytes));
1958     macKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
1959 	CKM_SHA256_HMAC, CKA_SIGN, 0);
1960 
1961     if (aesKeyTmp == NULL || macKeyTmp == NULL) {
1962 	SSL_DBG(("%d: SSL[%s]: Unable to unwrap session ticket keys.",
1963 		    SSL_GETPID(), "unknown"));
1964 	goto loser;
1965     }
1966     SSL_DBG(("%d: SSL[%s]: Successfully unwrapped session ticket keys.",
1967 		SSL_GETPID(), "unknown"));
1968 
1969     PORT_Memcpy(keyName, cache->ticketKeyNameSuffix,
1970 	SESS_TICKET_KEY_VAR_NAME_LEN);
1971     *aesKey = aesKeyTmp;
1972     *macKey = macKeyTmp;
1973     return PR_TRUE;
1974 
1975 loser:
1976     if (aesKeyTmp)
1977 	PK11_FreeSymKey(aesKeyTmp);
1978     if (macKeyTmp)
1979 	PK11_FreeSymKey(macKeyTmp);
1980     return PR_FALSE;
1981 }
1982 
1983 PRBool
ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey * svrPrivKey,SECKEYPublicKey * svrPubKey,void * pwArg,unsigned char * keyName,PK11SymKey ** aesKey,PK11SymKey ** macKey)1984 ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey,
1985                                SECKEYPublicKey *svrPubKey, void *pwArg,
1986                                unsigned char *keyName, PK11SymKey **aesKey,
1987                                PK11SymKey **macKey)
1988 {
1989     PRUint32 now = 0;
1990     PRBool rv = PR_FALSE;
1991     PRBool keysGenerated = PR_FALSE;
1992     cacheDesc *cache = &globalCache;
1993 
1994     if (!cache->cacheMem) {
1995         /* cache is uninitialized. Generate keys and return them
1996          * without caching. */
1997         return GenerateTicketKeys(pwArg, keyName, aesKey, macKey);
1998     }
1999 
2000     now = LockSidCacheLock(cache->keyCacheLock, now);
2001     if (!now)
2002 	return rv;
2003 
2004     if (!*(cache->ticketKeysValid)) {
2005 	/* Keys do not exist, create them. */
2006 	if (!GenerateAndWrapTicketKeys(svrPubKey, pwArg, keyName,
2007 		aesKey, macKey))
2008 	    goto loser;
2009 	keysGenerated = PR_TRUE;
2010 	*(cache->ticketKeysValid) = 1;
2011     }
2012 
2013     rv = PR_TRUE;
2014 
2015  loser:
2016     UnlockSidCacheLock(cache->keyCacheLock);
2017     if (rv && !keysGenerated)
2018 	rv = UnwrapCachedTicketKeys(svrPrivKey, keyName, aesKey, macKey);
2019     return rv;
2020 }
2021 
2022 PRBool
ssl_GetSessionTicketKeys(unsigned char * keyName,unsigned char * encKey,unsigned char * macKey)2023 ssl_GetSessionTicketKeys(unsigned char *keyName, unsigned char *encKey,
2024                          unsigned char *macKey)
2025 {
2026     PRBool rv = PR_FALSE;
2027     PRUint32 now = 0;
2028     cacheDesc *cache = &globalCache;
2029     PRUint8 ticketMacKey[SHA256_LENGTH], ticketEncKey[AES_256_KEY_LENGTH];
2030     PRUint8 ticketKeyNameSuffixLocal[SESS_TICKET_KEY_VAR_NAME_LEN];
2031     PRUint8 *ticketMacKeyPtr, *ticketEncKeyPtr, *ticketKeyNameSuffix;
2032     PRBool cacheIsEnabled = PR_TRUE;
2033 
2034     if (!cache->cacheMem) { /* cache is uninitialized */
2035         cacheIsEnabled = PR_FALSE;
2036         ticketKeyNameSuffix = ticketKeyNameSuffixLocal;
2037         ticketEncKeyPtr = ticketEncKey;
2038         ticketMacKeyPtr = ticketMacKey;
2039     } else {
2040         /* these values have constant memory locations in the cache.
2041          * Ok to reference them without holding the lock. */
2042         ticketKeyNameSuffix = cache->ticketKeyNameSuffix;
2043         ticketEncKeyPtr = cache->ticketEncKey->bytes;
2044         ticketMacKeyPtr = cache->ticketMacKey->bytes;
2045     }
2046 
2047     if (cacheIsEnabled) {
2048         /* Grab lock if initialized. */
2049         now = LockSidCacheLock(cache->keyCacheLock, now);
2050         if (!now)
2051             return rv;
2052     }
2053     /* Going to regenerate keys on every call if cache was not
2054      * initialized. */
2055     if (!cacheIsEnabled || !*(cache->ticketKeysValid)) {
2056 	if (PK11_GenerateRandom(ticketKeyNameSuffix,
2057 		SESS_TICKET_KEY_VAR_NAME_LEN) != SECSuccess)
2058 	    goto loser;
2059 	if (PK11_GenerateRandom(ticketEncKeyPtr,
2060                                 AES_256_KEY_LENGTH) != SECSuccess)
2061 	    goto loser;
2062 	if (PK11_GenerateRandom(ticketMacKeyPtr,
2063                                 SHA256_LENGTH) != SECSuccess)
2064 	    goto loser;
2065         if (cacheIsEnabled) {
2066             *(cache->ticketKeysValid) = 1;
2067         }
2068     }
2069 
2070     rv = PR_TRUE;
2071 
2072  loser:
2073     if (cacheIsEnabled) {
2074         UnlockSidCacheLock(cache->keyCacheLock);
2075     }
2076     if (rv) {
2077 	PORT_Memcpy(keyName, ticketKeyNameSuffix,
2078                     SESS_TICKET_KEY_VAR_NAME_LEN);
2079 	PORT_Memcpy(encKey, ticketEncKeyPtr, AES_256_KEY_LENGTH);
2080 	PORT_Memcpy(macKey, ticketMacKeyPtr, SHA256_LENGTH);
2081     }
2082     return rv;
2083 }
2084 
2085 /* The caller passes in the new value it wants
2086  * to set.  This code tests the wrapped sym key entry in the shared memory.
2087  * If it is uninitialized, this function writes the caller's value into
2088  * the disk entry, and returns false.
2089  * Otherwise, it overwrites the caller's wswk with the value obtained from
2090  * the disk, and returns PR_TRUE.
2091  * This is all done while holding the locks/mutexes necessary to make
2092  * the operation atomic.
2093  */
2094 PRBool
ssl_SetWrappingKey(SSLWrappedSymWrappingKey * wswk)2095 ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
2096 {
2097     cacheDesc *   cache            = &globalCache;
2098     PRBool        rv               = PR_FALSE;
2099     SSL3KEAType   exchKeyType      = wswk->exchKeyType;
2100                                 /* type of keys used to wrap SymWrapKey*/
2101     PRInt32       symWrapMechIndex = wswk->symWrapMechIndex;
2102     PRUint32      ndx;
2103     PRUint32      now = 0;
2104     SSLWrappedSymWrappingKey myWswk;
2105 
2106     if (!cache->cacheMem) { /* cache is uninitialized */
2107 	PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
2108 	return 0;
2109     }
2110 
2111     PORT_Assert( (unsigned)exchKeyType < kt_kea_size);
2112     if ((unsigned)exchKeyType >= kt_kea_size)
2113     	return 0;
2114 
2115     PORT_Assert( (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
2116     if ((unsigned)symWrapMechIndex >=  SSL_NUM_WRAP_MECHS)
2117     	return 0;
2118 
2119     ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
2120     PORT_Memset(&myWswk, 0, sizeof myWswk);	/* eliminate UMRs. */
2121 
2122     now = LockSidCacheLock(cache->keyCacheLock, now);
2123     if (now) {
2124 	rv = getSvrWrappingKey(wswk->symWrapMechIndex, wswk->exchKeyType,
2125 	                       &myWswk, cache, now);
2126 	if (rv) {
2127 	    /* we found it on disk, copy it out to the caller. */
2128 	    PORT_Memcpy(wswk, &myWswk, sizeof *wswk);
2129 	} else {
2130 	    /* Wasn't on disk, and we're still holding the lock, so write it. */
2131 	    cache->keyCacheData[ndx] = *wswk;
2132 	}
2133 	UnlockSidCacheLock(cache->keyCacheLock);
2134     }
2135     return rv;
2136 }
2137 
2138 #else  /* MAC version or other platform */
2139 
2140 #include "seccomon.h"
2141 #include "cert.h"
2142 #include "ssl.h"
2143 #include "sslimpl.h"
2144 
2145 SECStatus
SSL_ConfigServerSessionIDCache(int maxCacheEntries,PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory)2146 SSL_ConfigServerSessionIDCache(	int      maxCacheEntries,
2147 				PRUint32 ssl2_timeout,
2148 			       	PRUint32 ssl3_timeout,
2149 			  const char *   directory)
2150 {
2151     PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigServerSessionIDCache)");
2152     return SECFailure;
2153 }
2154 
2155 SECStatus
SSL_ConfigMPServerSIDCache(int maxCacheEntries,PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory)2156 SSL_ConfigMPServerSIDCache(	int      maxCacheEntries,
2157 				PRUint32 ssl2_timeout,
2158 			       	PRUint32 ssl3_timeout,
2159 		          const char *   directory)
2160 {
2161     PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigMPServerSIDCache)");
2162     return SECFailure;
2163 }
2164 
2165 SECStatus
SSL_InheritMPServerSIDCache(const char * envString)2166 SSL_InheritMPServerSIDCache(const char * envString)
2167 {
2168     PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_InheritMPServerSIDCache)");
2169     return SECFailure;
2170 }
2171 
2172 PRBool
ssl_GetWrappingKey(PRInt32 symWrapMechIndex,SSL3KEAType exchKeyType,SSLWrappedSymWrappingKey * wswk)2173 ssl_GetWrappingKey( PRInt32                   symWrapMechIndex,
2174                     SSL3KEAType               exchKeyType,
2175 		    SSLWrappedSymWrappingKey *wswk)
2176 {
2177     PRBool rv = PR_FALSE;
2178     PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_GetWrappingKey)");
2179     return rv;
2180 }
2181 
2182 /* This is a kind of test-and-set.  The caller passes in the new value it wants
2183  * to set.  This code tests the wrapped sym key entry in the shared memory.
2184  * If it is uninitialized, this function writes the caller's value into
2185  * the disk entry, and returns false.
2186  * Otherwise, it overwrites the caller's wswk with the value obtained from
2187  * the disk, and returns PR_TRUE.
2188  * This is all done while holding the locks/mutexes necessary to make
2189  * the operation atomic.
2190  */
2191 PRBool
ssl_SetWrappingKey(SSLWrappedSymWrappingKey * wswk)2192 ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
2193 {
2194     PRBool        rv = PR_FALSE;
2195     PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_SetWrappingKey)");
2196     return rv;
2197 }
2198 
2199 PRUint32
SSL_GetMaxServerCacheLocks(void)2200 SSL_GetMaxServerCacheLocks(void)
2201 {
2202     PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_GetMaxServerCacheLocks)");
2203     return -1;
2204 }
2205 
2206 SECStatus
SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)2207 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
2208 {
2209     PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_SetMaxServerCacheLocks)");
2210     return SECFailure;
2211 }
2212 
2213 #endif /* XP_UNIX || XP_WIN32 */
2214