Back to index

lightning-sunbird  0.9+nobinonly
sslsnce.c
Go to the documentation of this file.
00001 /* This file implements the SERVER Session ID cache. 
00002  * NOTE:  The contents of this file are NOT used by the client.
00003  *
00004  * ***** BEGIN LICENSE BLOCK *****
00005  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  * The contents of this file are subject to the Mozilla Public License Version
00008  * 1.1 (the "License"); you may not use this file except in compliance with
00009  * the License. You may obtain a copy of the License at
00010  * http://www.mozilla.org/MPL/
00011  *
00012  * Software distributed under the License is distributed on an "AS IS" basis,
00013  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00014  * for the specific language governing rights and limitations under the
00015  * License.
00016  *
00017  * The Original Code is the Netscape security libraries.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 /* $Id: sslsnce.c,v 1.36.2.4 2007/05/03 21:26:04 glen.beasley%sun.com Exp $ */
00040 
00041 /* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server 
00042  * cache sids!
00043  *
00044  * About record locking among different server processes:
00045  *
00046  * All processes that are part of the same conceptual server (serving on 
00047  * the same address and port) MUST share a common SSL session cache. 
00048  * This code makes the content of the shared cache accessible to all
00049  * processes on the same "server".  This code works on Unix and Win32 only.
00050  *
00051  * We use NSPR anonymous shared memory and move data to & from shared memory.
00052  * We must do explicit locking of the records for all reads and writes.
00053  * The set of Cache entries are divided up into "sets" of 128 entries. 
00054  * Each set is protected by a lock.  There may be one or more sets protected
00055  * by each lock.  That is, locks to sets are 1:N.
00056  * There is one lock for the entire cert cache.
00057  * There is one lock for the set of wrapped sym wrap keys.
00058  *
00059  * The anonymous shared memory is laid out as if it were declared like this:
00060  *
00061  * struct {
00062  *     cacheDescriptor          desc;
00063  *     sidCacheLock             sidCacheLocks[ numSIDCacheLocks];
00064  *     sidCacheLock             keyCacheLock;
00065  *     sidCacheLock             certCacheLock;
00066  *     sidCacheSet              sidCacheSets[ numSIDCacheSets ];
00067  *     sidCacheEntry            sidCacheData[ numSIDCacheEntries];
00068  *     certCacheEntry           certCacheData[numCertCacheEntries];
00069  *     SSLWrappedSymWrappingKey keyCacheData[kt_kea_size][SSL_NUM_WRAP_MECHS];
00070  * } cacheMemCacheData;
00071  */
00072 #include "nssrenam.h"
00073 #include "seccomon.h"
00074 
00075 #if (defined(XP_UNIX) || defined(XP_WIN32) || defined (XP_OS2) || defined(XP_BEOS)) && !defined(_WIN32_WCE)
00076 
00077 #include "cert.h"
00078 #include "ssl.h"
00079 #include "sslimpl.h"
00080 #include "sslproto.h"
00081 #include "pk11func.h"
00082 #include "base64.h"
00083 
00084 #include <stdio.h>
00085 
00086 #if defined(XP_UNIX) || defined(XP_BEOS)
00087 
00088 #include <syslog.h>
00089 #include <fcntl.h>
00090 #include <unistd.h>
00091 #include <errno.h>
00092 #include <signal.h>
00093 #include "unix_err.h"
00094 
00095 #else
00096 
00097 #ifdef XP_WIN32
00098 #include <wtypes.h>
00099 #include "win32err.h"
00100 #endif
00101 
00102 #endif 
00103 #include <sys/types.h>
00104 
00105 #define SET_ERROR_CODE /* reminder */
00106 
00107 #include "nspr.h"
00108 #include "nsslocks.h"
00109 #include "sslmutex.h"
00110 
00111 #ifdef XP_OS2_VACPP
00112 #pragma pack(1)
00113 #endif
00114 
00115 /*
00116 ** Format of a cache entry in the shared memory.
00117 */ 
00118 struct sidCacheEntryStr {
00119 /* 16 */    PRIPv6Addr  addr;      /* client's IP address */
00120 /*  4 */    PRUint32    creationTime;
00121 /*  4 */    PRUint32    lastAccessTime;   
00122 /*  4 */    PRUint32    expirationTime;
00123 /*  2 */    PRUint16 version;
00124 /*  1 */    PRUint8  valid;
00125 /*  1 */    PRUint8     sessionIDLength;
00126 /* 32 */    PRUint8     sessionID[SSL3_SESSIONID_BYTES];
00127 /*  2 */    PRUint16    authAlgorithm;
00128 /*  2 */    PRUint16    authKeyBits;
00129 /*  2 */    PRUint16    keaType;
00130 /*  2 */    PRUint16    keaKeyBits;
00131 /* 72  - common header total */
00132 
00133     union {
00134        struct {
00135 /* 64 */    PRUint8  masterKey[SSL_MAX_MASTER_KEY_BYTES];
00136 /* 32 */    PRUint8  cipherArg[SSL_MAX_CYPHER_ARG_BYTES];
00137 
00138 /*  1 */    PRUint8  cipherType;
00139 /*  1 */    PRUint8  masterKeyLen;
00140 /*  1 */    PRUint8  keyBits;
00141 /*  1 */    PRUint8  secretKeyBits;
00142 /*  1 */    PRUint8  cipherArgLen;
00143 /*101 */} ssl2;
00144 
00145        struct {
00146 /*  2 */    ssl3CipherSuite  cipherSuite;
00147 /*  2 */    PRUint16    compression;      /* SSL3CompressionMethod */
00148 
00149 /*100 */    ssl3SidKeys keys;      /* keys and ivs, wrapped as needed. */
00150 
00151 /*  4 */    PRUint32    masterWrapMech; 
00152 /*  4 */    SSL3KEAType exchKeyType;
00153 /*  4 */    PRInt32     certIndex;
00154 /*116 */} ssl3;
00155 /* force sizeof(sidCacheEntry) to be a multiple of cache line size */
00156         struct {
00157 /*120 */    PRUint8     filler[120]; /* 72+120==196, a multiple of 16 */
00158        } forceSize;
00159     } u;
00160 };
00161 typedef struct sidCacheEntryStr sidCacheEntry;
00162 
00163 /* The length of this struct is supposed to be a power of 2, e.g. 4KB */
00164 struct certCacheEntryStr {
00165     PRUint16    certLength;                      /*    2 */
00166     PRUint16    sessionIDLength;                 /*    2 */
00167     PRUint8   sessionID[SSL3_SESSIONID_BYTES];   /*   32 */
00168     PRUint8   cert[SSL_MAX_CACHED_CERT_LEN];            /* 4060 */
00169 };                                        /* total   4096 */
00170 typedef struct certCacheEntryStr certCacheEntry;
00171 
00172 struct sidCacheLockStr {
00173     PRUint32  timeStamp;
00174     sslMutex  mutex;
00175     sslPID    pid;
00176 };
00177 typedef struct sidCacheLockStr sidCacheLock;
00178 
00179 struct sidCacheSetStr {
00180     PRIntn    next;
00181 };
00182 typedef struct sidCacheSetStr sidCacheSet;
00183 
00184 struct cacheDescStr {
00185 
00186     PRUint32            cacheMemSize;
00187 
00188     PRUint32         numSIDCacheLocks;
00189     PRUint32         numSIDCacheSets;
00190     PRUint32         numSIDCacheSetsPerLock;
00191 
00192     PRUint32            numSIDCacheEntries; 
00193     PRUint32            sidCacheSize;
00194 
00195     PRUint32            numCertCacheEntries;
00196     PRUint32            certCacheSize;
00197 
00198     PRUint32            numKeyCacheEntries;
00199     PRUint32            keyCacheSize;
00200 
00201     PRUint32         ssl2Timeout;
00202     PRUint32         ssl3Timeout;
00203 
00204     PRUint32            numSIDCacheLocksInitialized;
00205 
00206     /* These values are volatile, and are accessed through sharedCache-> */
00207     PRUint32         nextCertCacheEntry;  /* certCacheLock protects */
00208     PRBool           stopPolling;
00209     PRBool           everInherited;
00210 
00211     /* The private copies of these values are pointers into shared mem */
00212     /* The copies of these values in shared memory are merely offsets */
00213     sidCacheLock    *          sidCacheLocks;
00214     sidCacheLock    *          keyCacheLock;
00215     sidCacheLock    *          certCacheLock;
00216     sidCacheSet     *          sidCacheSets;
00217     sidCacheEntry   *          sidCacheData;
00218     certCacheEntry  *          certCacheData;
00219     SSLWrappedSymWrappingKey * keyCacheData;
00220 
00221     /* Only the private copies of these pointers are valid */
00222     char *                     cacheMem;
00223     struct cacheDescStr *      sharedCache;  /* shared copy of this struct */
00224     PRFileMap *                cacheMemMap;
00225     PRThread  *                poller;
00226     PRUint32                   mutexTimeout;
00227     PRBool                     shared;
00228 };
00229 typedef struct cacheDescStr cacheDesc;
00230 
00231 static cacheDesc globalCache;
00232 
00233 static const char envVarName[] = { SSL_ENV_VAR_NAME };
00234 
00235 static PRBool isMultiProcess  = PR_FALSE;
00236 
00237 
00238 #define DEF_SID_CACHE_ENTRIES  10000
00239 #define DEF_CERT_CACHE_ENTRIES 250
00240 #define MIN_CERT_CACHE_ENTRIES 125 /* the effective size in old releases. */
00241 #define DEF_KEY_CACHE_ENTRIES  250
00242 
00243 #define SID_CACHE_ENTRIES_PER_SET  128
00244 #define SID_ALIGNMENT          16
00245 
00246 #define DEF_SSL2_TIMEOUT    100   /* seconds */
00247 #define MAX_SSL2_TIMEOUT    100   /* seconds */
00248 #define MIN_SSL2_TIMEOUT      5   /* seconds */
00249 
00250 #define DEF_SSL3_TIMEOUT      86400L  /* 24 hours */
00251 #define MAX_SSL3_TIMEOUT      86400L  /* 24 hours */
00252 #define MIN_SSL3_TIMEOUT          5   /* seconds  */
00253 
00254 #if defined(AIX) || defined(LINUX) || defined(VMS)
00255 #define MAX_SID_CACHE_LOCKS 8      /* two FDs per lock */
00256 #elif defined(OSF1)
00257 #define MAX_SID_CACHE_LOCKS 16     /* one FD per lock */
00258 #else
00259 #define MAX_SID_CACHE_LOCKS 256
00260 #endif
00261 
00262 #define SID_HOWMANY(val, size) (((val) + ((size) - 1)) / (size))
00263 #define SID_ROUNDUP(val, size) ((size) * SID_HOWMANY((val), (size)))
00264 
00265 
00266 static sslPID myPid;
00267 static PRUint32  ssl_max_sid_cache_locks = MAX_SID_CACHE_LOCKS;
00268 
00269 /* forward static function declarations */
00270 static PRUint32 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s, 
00271                          unsigned nl);
00272 static SECStatus LaunchLockPoller(cacheDesc *cache);
00273 static SECStatus StopLockPoller(cacheDesc *cache);
00274 
00275 
00276 struct inheritanceStr {
00277     PRUint32 cacheMemSize;
00278     PRUint32 fmStrLen;
00279 };
00280 
00281 typedef struct inheritanceStr inheritance;
00282 
00283 #if defined(_WIN32) || defined(XP_OS2)
00284 
00285 #define DEFAULT_CACHE_DIRECTORY "\\temp"
00286 
00287 #endif /* _win32 */
00288 
00289 #if defined(XP_UNIX) || defined(XP_BEOS)
00290 
00291 #define DEFAULT_CACHE_DIRECTORY "/tmp"
00292 
00293 #endif /* XP_UNIX || XP_BEOS */
00294 
00295 
00296 /************************************************************************/
00297 
00298 static PRUint32
00299 LockSidCacheLock(sidCacheLock *lock, PRUint32 now)
00300 {
00301     SECStatus      rv      = sslMutex_Lock(&lock->mutex);
00302     if (rv != SECSuccess)
00303        return 0;
00304     if (!now)
00305        now  = ssl_Time();
00306     lock->timeStamp = now;
00307     lock->pid       = myPid;
00308     return now;
00309 }
00310 
00311 static SECStatus
00312 UnlockSidCacheLock(sidCacheLock *lock)
00313 {
00314     SECStatus      rv;
00315 
00316     lock->pid = 0;
00317     rv        = sslMutex_Unlock(&lock->mutex);
00318     return rv;
00319 }
00320 
00321 /* returns the value of ssl_Time on success, zero on failure. */
00322 static PRUint32
00323 LockSet(cacheDesc *cache, PRUint32 set, PRUint32 now)
00324 {
00325     PRUint32       lockNum = set % cache->numSIDCacheLocks;
00326     sidCacheLock * lock    = cache->sidCacheLocks + lockNum;
00327 
00328     return LockSidCacheLock(lock, now);
00329 }
00330 
00331 static SECStatus
00332 UnlockSet(cacheDesc *cache, PRUint32 set)
00333 {
00334     PRUint32       lockNum = set % cache->numSIDCacheLocks;
00335     sidCacheLock * lock    = cache->sidCacheLocks + lockNum;
00336 
00337     return UnlockSidCacheLock(lock);
00338 }
00339 
00340 /************************************************************************/
00341 
00342 
00343 /* Put a certificate in the cache.  Update the cert index in the sce.
00344 */
00345 static PRUint32
00346 CacheCert(cacheDesc * cache, CERTCertificate *cert, sidCacheEntry *sce)
00347 {
00348     PRUint32        now;
00349     certCacheEntry  cce;
00350 
00351     if ((cert->derCert.len > SSL_MAX_CACHED_CERT_LEN) ||
00352         (cert->derCert.len <= 0) ||
00353        (cert->derCert.data == NULL)) {
00354        PORT_SetError(SEC_ERROR_INVALID_ARGS);
00355        return 0;
00356     }
00357 
00358     cce.sessionIDLength = sce->sessionIDLength;
00359     PORT_Memcpy(cce.sessionID, sce->sessionID, cce.sessionIDLength);
00360 
00361     cce.certLength = cert->derCert.len;
00362     PORT_Memcpy(cce.cert, cert->derCert.data, cce.certLength);
00363 
00364     /* get lock on cert cache */
00365     now = LockSidCacheLock(cache->certCacheLock, 0);
00366     if (now) {
00367 
00368        /* Find where to place the next cert cache entry. */
00369        cacheDesc * sharedCache = cache->sharedCache;
00370        PRUint32    ndx         = sharedCache->nextCertCacheEntry;
00371 
00372        /* write the entry */
00373        cache->certCacheData[ndx] = cce;
00374 
00375        /* remember where we put it. */
00376        sce->u.ssl3.certIndex = ndx;
00377 
00378        /* update the "next" cache entry index */
00379        sharedCache->nextCertCacheEntry = 
00380                                    (ndx + 1) % cache->numCertCacheEntries;
00381 
00382        UnlockSidCacheLock(cache->certCacheLock);
00383     }
00384     return now;
00385 
00386 }
00387 
00388 /*
00389 ** Convert local SID to shared memory one
00390 */
00391 static void 
00392 ConvertFromSID(sidCacheEntry *to, sslSessionID *from)
00393 {
00394     to->valid   = 1;
00395     to->version = from->version;
00396     to->addr    = from->addr;
00397     to->creationTime    = from->creationTime;
00398     to->lastAccessTime  = from->lastAccessTime;
00399     to->expirationTime  = from->expirationTime;
00400     to->authAlgorithm       = from->authAlgorithm;
00401     to->authKeyBits  = from->authKeyBits;
00402     to->keaType             = from->keaType;
00403     to->keaKeyBits   = from->keaKeyBits;
00404 
00405     if (from->version < SSL_LIBRARY_VERSION_3_0) {
00406        if ((from->u.ssl2.masterKey.len > SSL_MAX_MASTER_KEY_BYTES) ||
00407            (from->u.ssl2.cipherArg.len > SSL_MAX_CYPHER_ARG_BYTES)) {
00408            SSL_DBG(("%d: SSL: masterKeyLen=%d cipherArgLen=%d",
00409                    myPid, from->u.ssl2.masterKey.len,
00410                    from->u.ssl2.cipherArg.len));
00411            to->valid = 0;
00412            return;
00413        }
00414 
00415        to->u.ssl2.cipherType    = from->u.ssl2.cipherType;
00416        to->u.ssl2.masterKeyLen  = from->u.ssl2.masterKey.len;
00417        to->u.ssl2.cipherArgLen  = from->u.ssl2.cipherArg.len;
00418        to->u.ssl2.keyBits       = from->u.ssl2.keyBits;
00419        to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
00420        to->sessionIDLength      = SSL2_SESSIONID_BYTES;
00421        PORT_Memcpy(to->sessionID, from->u.ssl2.sessionID, SSL2_SESSIONID_BYTES);
00422        PORT_Memcpy(to->u.ssl2.masterKey, from->u.ssl2.masterKey.data,
00423                 from->u.ssl2.masterKey.len);
00424        PORT_Memcpy(to->u.ssl2.cipherArg, from->u.ssl2.cipherArg.data,
00425                 from->u.ssl2.cipherArg.len);
00426 #ifdef DEBUG
00427        PORT_Memset(to->u.ssl2.masterKey+from->u.ssl2.masterKey.len, 0,
00428                 sizeof(to->u.ssl2.masterKey) - from->u.ssl2.masterKey.len);
00429        PORT_Memset(to->u.ssl2.cipherArg+from->u.ssl2.cipherArg.len, 0,
00430                 sizeof(to->u.ssl2.cipherArg) - from->u.ssl2.cipherArg.len);
00431 #endif
00432        SSL_TRC(8, ("%d: SSL: ConvertSID: masterKeyLen=%d cipherArgLen=%d "
00433                   "time=%d addr=0x%08x%08x%08x%08x cipherType=%d", myPid,
00434                   to->u.ssl2.masterKeyLen, to->u.ssl2.cipherArgLen,
00435                   to->creationTime, to->addr.pr_s6_addr32[0],
00436                   to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
00437                   to->addr.pr_s6_addr32[3], to->u.ssl2.cipherType));
00438     } else {
00439        /* This is an SSL v3 session */
00440 
00441        to->u.ssl3.cipherSuite      = from->u.ssl3.cipherSuite;
00442        to->u.ssl3.compression      = (uint16)from->u.ssl3.compression;
00443        to->u.ssl3.keys             = from->u.ssl3.keys;
00444        to->u.ssl3.masterWrapMech   = from->u.ssl3.masterWrapMech;
00445        to->u.ssl3.exchKeyType      = from->u.ssl3.exchKeyType;
00446        to->sessionIDLength         = from->u.ssl3.sessionIDLength;
00447        to->u.ssl3.certIndex        = -1;
00448 
00449        PORT_Memcpy(to->sessionID, from->u.ssl3.sessionID,
00450                   to->sessionIDLength);
00451 
00452        SSL_TRC(8, ("%d: SSL3: ConvertSID: time=%d addr=0x%08x%08x%08x%08x "
00453                    "cipherSuite=%d",
00454                   myPid, to->creationTime, to->addr.pr_s6_addr32[0],
00455                   to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
00456                   to->addr.pr_s6_addr32[3], to->u.ssl3.cipherSuite));
00457     }
00458 }
00459 
00460 /*
00461 ** Convert shared memory cache-entry to local memory based one
00462 ** This is only called from ServerSessionIDLookup().
00463 ** Caller must hold cache lock when calling this.
00464 */
00465 static sslSessionID *
00466 ConvertToSID(sidCacheEntry *from, certCacheEntry *pcce, 
00467              CERTCertDBHandle * dbHandle)
00468 {
00469     sslSessionID *to;
00470     uint16 version = from->version;
00471 
00472     to = (sslSessionID*) PORT_ZAlloc(sizeof(sslSessionID));
00473     if (!to) {
00474        return 0;
00475     }
00476 
00477     if (version < SSL_LIBRARY_VERSION_3_0) {
00478        /* This is an SSL v2 session */
00479        to->u.ssl2.masterKey.data =
00480            (unsigned char*) PORT_Alloc(from->u.ssl2.masterKeyLen);
00481        if (!to->u.ssl2.masterKey.data) {
00482            goto loser;
00483        }
00484        if (from->u.ssl2.cipherArgLen) {
00485            to->u.ssl2.cipherArg.data = 
00486               (unsigned char*)PORT_Alloc(from->u.ssl2.cipherArgLen);
00487            if (!to->u.ssl2.cipherArg.data) {
00488               goto loser;
00489            }
00490            PORT_Memcpy(to->u.ssl2.cipherArg.data, from->u.ssl2.cipherArg,
00491                       from->u.ssl2.cipherArgLen);
00492        }
00493 
00494        to->u.ssl2.cipherType    = from->u.ssl2.cipherType;
00495        to->u.ssl2.masterKey.len = from->u.ssl2.masterKeyLen;
00496        to->u.ssl2.cipherArg.len = from->u.ssl2.cipherArgLen;
00497        to->u.ssl2.keyBits       = from->u.ssl2.keyBits;
00498        to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
00499 /*     to->sessionIDLength      = SSL2_SESSIONID_BYTES; */
00500        PORT_Memcpy(to->u.ssl2.sessionID, from->sessionID, SSL2_SESSIONID_BYTES);
00501        PORT_Memcpy(to->u.ssl2.masterKey.data, from->u.ssl2.masterKey,
00502                   from->u.ssl2.masterKeyLen);
00503 
00504        SSL_TRC(8, ("%d: SSL: ConvertToSID: masterKeyLen=%d cipherArgLen=%d "
00505                   "time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
00506                   myPid, to->u.ssl2.masterKey.len,
00507                   to->u.ssl2.cipherArg.len, to->creationTime,
00508                   to->addr.pr_s6_addr32[0], to->addr.pr_s6_addr32[1],
00509                   to->addr.pr_s6_addr32[2], to->addr.pr_s6_addr32[3],
00510                   to->u.ssl2.cipherType));
00511     } else {
00512        /* This is an SSL v3 session */
00513 
00514        to->u.ssl3.sessionIDLength  = from->sessionIDLength;
00515        to->u.ssl3.cipherSuite      = from->u.ssl3.cipherSuite;
00516        to->u.ssl3.compression      = (SSL3CompressionMethod)from->u.ssl3.compression;
00517        to->u.ssl3.keys             = from->u.ssl3.keys;
00518        to->u.ssl3.masterWrapMech   = from->u.ssl3.masterWrapMech;
00519        to->u.ssl3.exchKeyType      = from->u.ssl3.exchKeyType;
00520 
00521        PORT_Memcpy(to->u.ssl3.sessionID, from->sessionID, from->sessionIDLength);
00522 
00523        /* the portions of the SID that are only restored on the client
00524         * are set to invalid values on the server.
00525         */
00526        to->u.ssl3.clientWriteKey   = NULL;
00527        to->u.ssl3.serverWriteKey   = NULL;
00528 
00529        to->urlSvrName              = NULL;
00530 
00531        to->u.ssl3.masterModuleID   = (SECMODModuleID)-1; /* invalid value */
00532        to->u.ssl3.masterSlotID     = (CK_SLOT_ID)-1;     /* invalid value */
00533        to->u.ssl3.masterWrapIndex  = 0;
00534        to->u.ssl3.masterWrapSeries = 0;
00535        to->u.ssl3.masterValid      = PR_FALSE;
00536 
00537        to->u.ssl3.clAuthModuleID   = (SECMODModuleID)-1; /* invalid value */
00538        to->u.ssl3.clAuthSlotID     = (CK_SLOT_ID)-1;     /* invalid value */
00539        to->u.ssl3.clAuthSeries     = 0;
00540        to->u.ssl3.clAuthValid      = PR_FALSE;
00541 
00542        if (from->u.ssl3.certIndex != -1 && pcce) {
00543            SECItem          derCert;
00544 
00545            derCert.len  = pcce->certLength;
00546            derCert.data = pcce->cert;
00547 
00548            to->peerCert = CERT_NewTempCertificate(dbHandle, &derCert, NULL,
00549                                               PR_FALSE, PR_TRUE);
00550            if (to->peerCert == NULL)
00551               goto loser;
00552        }
00553     }
00554 
00555     to->version         = from->version;
00556     to->creationTime    = from->creationTime;
00557     to->lastAccessTime  = from->lastAccessTime;
00558     to->expirationTime  = from->expirationTime;
00559     to->cached          = in_server_cache;
00560     to->addr            = from->addr;
00561     to->references      = 1;
00562     to->authAlgorithm       = from->authAlgorithm;
00563     to->authKeyBits  = from->authKeyBits;
00564     to->keaType             = from->keaType;
00565     to->keaKeyBits   = from->keaKeyBits;
00566     
00567     return to;
00568 
00569   loser:
00570     if (to) {
00571        if (version < SSL_LIBRARY_VERSION_3_0) {
00572            if (to->u.ssl2.masterKey.data)
00573               PORT_Free(to->u.ssl2.masterKey.data);
00574            if (to->u.ssl2.cipherArg.data)
00575               PORT_Free(to->u.ssl2.cipherArg.data);
00576        }
00577        PORT_Free(to);
00578     }
00579     return NULL;
00580 }
00581 
00582 
00583 
00584 /*
00585 ** Perform some mumbo jumbo on the ip-address and the session-id value to
00586 ** compute a hash value.
00587 */
00588 static PRUint32 
00589 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s, unsigned nl)
00590 {
00591     PRUint32 rv;
00592     PRUint32 x[8];
00593 
00594     memset(x, 0, sizeof x);
00595     if (nl > sizeof x)
00596        nl = sizeof x;
00597     memcpy(x, s, nl);
00598 
00599     rv = (addr->pr_s6_addr32[0] ^ addr->pr_s6_addr32[1] ^
00600          addr->pr_s6_addr32[2] ^ addr->pr_s6_addr32[3] ^
00601           x[0] ^ x[1] ^ x[2] ^ x[3] ^ x[4] ^ x[5] ^ x[6] ^ x[7])
00602          % cache->numSIDCacheSets;
00603     return rv;
00604 }
00605 
00606 
00607 
00608 /*
00609 ** Look something up in the cache. This will invalidate old entries
00610 ** in the process. Caller has locked the cache set!
00611 ** Returns PR_TRUE if found a valid match.  PR_FALSE otherwise.
00612 */
00613 static sidCacheEntry *
00614 FindSID(cacheDesc *cache, PRUint32 setNum, PRUint32 now,
00615         const PRIPv6Addr *addr, unsigned char *sessionID,
00616        unsigned sessionIDLength)
00617 {
00618     PRUint32      ndx   = cache->sidCacheSets[setNum].next;
00619     int           i;
00620 
00621     sidCacheEntry * set = cache->sidCacheData + 
00622                       (setNum * SID_CACHE_ENTRIES_PER_SET);
00623 
00624     for (i = SID_CACHE_ENTRIES_PER_SET; i > 0; --i) {
00625        sidCacheEntry * sce;
00626 
00627        ndx  = (ndx - 1) % SID_CACHE_ENTRIES_PER_SET;
00628        sce = set + ndx;
00629 
00630        if (!sce->valid)
00631            continue;
00632 
00633        if (now > sce->expirationTime) {
00634            /* SessionID has timed out. Invalidate the entry. */
00635            SSL_TRC(7, ("%d: timed out sid entry addr=%08x%08x%08x%08x now=%x "
00636                      "time+=%x",
00637                      myPid, sce->addr.pr_s6_addr32[0],
00638                      sce->addr.pr_s6_addr32[1], sce->addr.pr_s6_addr32[2],
00639                      sce->addr.pr_s6_addr32[3], now,
00640                      sce->expirationTime ));
00641            sce->valid = 0;
00642            continue;
00643        }
00644 
00645        /*
00646        ** Next, examine specific session-id/addr data to see if the cache
00647        ** entry matches our addr+session-id value
00648        */
00649        if (sessionIDLength == sce->sessionIDLength      &&
00650            !memcmp(&sce->addr, addr, sizeof(PRIPv6Addr)) &&
00651            !memcmp(sce->sessionID, sessionID, sessionIDLength)) {
00652            /* Found it */
00653            return sce;
00654        }
00655     }
00656 
00657     PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND);
00658     return NULL;
00659 }
00660 
00661 /************************************************************************/
00662 
00663 /* This is the primary function for finding entries in the server's sid cache.
00664  * Although it is static, this function is called via the global function 
00665  * pointer ssl_sid_lookup.
00666  */
00667 static sslSessionID *
00668 ServerSessionIDLookup(const PRIPv6Addr *addr,
00669                      unsigned char *sessionID,
00670                      unsigned int   sessionIDLength,
00671                         CERTCertDBHandle * dbHandle)
00672 {
00673     sslSessionID *  sid      = 0;
00674     sidCacheEntry * psce;
00675     certCacheEntry *pcce     = 0;
00676     cacheDesc *     cache    = &globalCache;
00677     PRUint32        now;
00678     PRUint32        set;
00679     PRInt32         cndx;
00680     sidCacheEntry   sce;
00681     certCacheEntry  cce;
00682 
00683     set = SIDindex(cache, addr, sessionID, sessionIDLength);
00684     now = LockSet(cache, set, 0);
00685     if (!now)
00686        return NULL;
00687 
00688     psce = FindSID(cache, set, now, addr, sessionID, sessionIDLength);
00689     if (psce) {
00690        if (psce->version >= SSL_LIBRARY_VERSION_3_0 && 
00691            (cndx = psce->u.ssl3.certIndex) != -1) {
00692 
00693            PRUint32 gotLock = LockSidCacheLock(cache->certCacheLock, now);
00694            if (gotLock) {
00695               pcce = &cache->certCacheData[cndx];
00696 
00697               /* See if the cert's session ID matches the sce cache. */
00698               if ((pcce->sessionIDLength == psce->sessionIDLength) &&
00699                   !PORT_Memcmp(pcce->sessionID, psce->sessionID, 
00700                                pcce->sessionIDLength)) {
00701                   cce = *pcce;
00702               } else {
00703                   /* The cert doesen't match the SID cache entry, 
00704                   ** so invalidate the SID cache entry. 
00705                   */
00706                   psce->valid = 0;
00707                   psce = 0;
00708                   pcce = 0;
00709               }
00710               UnlockSidCacheLock(cache->certCacheLock);
00711            } else {
00712               /* what the ??.  Didn't get the cert cache lock.
00713               ** Don't invalidate the SID cache entry, but don't find it.
00714               */
00715               PORT_Assert(!("Didn't get cert Cache Lock!"));
00716               psce = 0;
00717               pcce = 0;
00718            }
00719        }
00720        if (psce) {
00721            psce->lastAccessTime = now;
00722            sce = *psce;     /* grab a copy while holding the lock */
00723        }
00724     }
00725     UnlockSet(cache, set);
00726     if (psce) {
00727        /* sce conains a copy of the cache entry.
00728        ** Convert shared memory format to local format 
00729        */
00730        sid = ConvertToSID(&sce, pcce ? &cce : 0, dbHandle);
00731     }
00732     return sid;
00733 }
00734 
00735 /*
00736 ** Place a sid into the cache, if it isn't already there. 
00737 */
00738 static void 
00739 ServerSessionIDCache(sslSessionID *sid)
00740 {
00741     sidCacheEntry sce;
00742     PRUint32      now     = 0;
00743     uint16        version = sid->version;
00744     cacheDesc *   cache   = &globalCache;
00745 
00746     if ((version >= SSL_LIBRARY_VERSION_3_0) &&
00747        (sid->u.ssl3.sessionIDLength == 0)) {
00748        return;
00749     }
00750 
00751     if (sid->cached == never_cached || sid->cached == invalid_cache) {
00752        PRUint32 set;
00753 
00754        PORT_Assert(sid->creationTime != 0);
00755        if (!sid->creationTime)
00756            sid->lastAccessTime = sid->creationTime = ssl_Time();
00757        if (version < SSL_LIBRARY_VERSION_3_0) {
00758            /* override caller's expiration time, which uses client timeout
00759             * duration, not server timeout duration.
00760             */
00761            sid->expirationTime = sid->creationTime + cache->ssl2Timeout;
00762            SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
00763                      "cipher=%d", myPid, sid->cached,
00764                      sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
00765                      sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
00766                      sid->creationTime, sid->u.ssl2.cipherType));
00767            PRINT_BUF(8, (0, "sessionID:", sid->u.ssl2.sessionID,
00768                        SSL2_SESSIONID_BYTES));
00769            PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
00770                        sid->u.ssl2.masterKey.len));
00771            PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
00772                        sid->u.ssl2.cipherArg.len));
00773 
00774        } else {
00775            /* override caller's expiration time, which uses client timeout
00776             * duration, not server timeout duration.
00777             */
00778            sid->expirationTime = sid->creationTime + cache->ssl3Timeout;
00779            SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
00780                      "cipherSuite=%d", myPid, sid->cached,
00781                      sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
00782                      sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
00783                      sid->creationTime, sid->u.ssl3.cipherSuite));
00784            PRINT_BUF(8, (0, "sessionID:", sid->u.ssl3.sessionID,
00785                        sid->u.ssl3.sessionIDLength));
00786        }
00787 
00788        ConvertFromSID(&sce, sid);
00789 
00790        if ((version >= SSL_LIBRARY_VERSION_3_0) && 
00791            (sid->peerCert != NULL)) {
00792            now = CacheCert(cache, sid->peerCert, &sce);
00793        }
00794 
00795        set = SIDindex(cache, &sce.addr, sce.sessionID, sce.sessionIDLength);
00796        now = LockSet(cache, set, now);
00797        if (now) {
00798            PRUint32  next = cache->sidCacheSets[set].next;
00799            PRUint32  ndx  = set * SID_CACHE_ENTRIES_PER_SET + next;
00800 
00801            /* Write out new cache entry */
00802            cache->sidCacheData[ndx] = sce;
00803 
00804            cache->sidCacheSets[set].next = 
00805                                    (next + 1) % SID_CACHE_ENTRIES_PER_SET;
00806 
00807            UnlockSet(cache, set);
00808            sid->cached = in_server_cache;
00809        }
00810     }
00811 }
00812 
00813 /*
00814 ** Although this is static, it is called from ssl via global function pointer
00815 **     ssl_sid_uncache.  This invalidates the referenced cache entry.
00816 */
00817 static void 
00818 ServerSessionIDUncache(sslSessionID *sid)
00819 {
00820     cacheDesc *    cache   = &globalCache;
00821     PRUint8 *      sessionID;
00822     unsigned int   sessionIDLength;
00823     PRErrorCode    err;
00824     PRUint32       set;
00825     PRUint32       now;
00826     sidCacheEntry *psce;
00827 
00828     if (sid == NULL) 
00829        return;
00830     
00831     /* Uncaching a SID should never change the error code. 
00832     ** So save it here and restore it before exiting.
00833     */
00834     err = PR_GetError();
00835 
00836     if (sid->version < SSL_LIBRARY_VERSION_3_0) {
00837        sessionID       = sid->u.ssl2.sessionID;
00838        sessionIDLength = SSL2_SESSIONID_BYTES;
00839        SSL_TRC(8, ("%d: SSL: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
00840                   "cipher=%d", myPid, sid->cached,
00841                   sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
00842                   sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
00843                   sid->creationTime, sid->u.ssl2.cipherType));
00844        PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
00845        PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
00846                     sid->u.ssl2.masterKey.len));
00847        PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
00848                     sid->u.ssl2.cipherArg.len));
00849     } else {
00850        sessionID       = sid->u.ssl3.sessionID;
00851        sessionIDLength = sid->u.ssl3.sessionIDLength;
00852        SSL_TRC(8, ("%d: SSL3: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
00853                   "cipherSuite=%d", myPid, sid->cached,
00854                   sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
00855                   sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
00856                   sid->creationTime, sid->u.ssl3.cipherSuite));
00857        PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
00858     }
00859     set = SIDindex(cache, &sid->addr, sessionID, sessionIDLength);
00860     now = LockSet(cache, set, 0);
00861     if (now) {
00862        psce = FindSID(cache, set, now, &sid->addr, sessionID, sessionIDLength);
00863        if (psce) {
00864            psce->valid = 0;
00865        }
00866        UnlockSet(cache, set);
00867     }
00868     sid->cached = invalid_cache;
00869     PORT_SetError(err);
00870 }
00871 
00872 #ifdef XP_OS2
00873 
00874 #define INCL_DOSPROCESS
00875 #include <os2.h>
00876 
00877 long gettid(void)
00878 {
00879     PTIB ptib;
00880     PPIB ppib;
00881     DosGetInfoBlocks(&ptib, &ppib);
00882     return ((long)ptib->tib_ordinal); /* thread id */
00883 }
00884 #endif
00885 
00886 static void
00887 CloseCache(cacheDesc *cache)
00888 {
00889     int locks_initialized = cache->numSIDCacheLocksInitialized;
00890 
00891     if (cache->cacheMem) {
00892        /* If everInherited is true, this shared cache was (and may still
00893        ** be) in use by multiple processes.  We do not wish to destroy
00894        ** the mutexes while they are still in use.  
00895        */
00896        if (cache->sharedCache &&
00897             PR_FALSE == cache->sharedCache->everInherited) {
00898            sidCacheLock *pLock = cache->sidCacheLocks;
00899            for (; locks_initialized > 0; --locks_initialized, ++pLock ) {
00900               sslMutex_Destroy(&pLock->mutex);
00901            }
00902        }
00903        if (cache->shared) {
00904            PR_MemUnmap(cache->cacheMem, cache->cacheMemSize);
00905        } else {
00906            PORT_Free(cache->cacheMem);
00907        }
00908        cache->cacheMem = NULL;
00909     }
00910     if (cache->cacheMemMap) {
00911        PR_CloseFileMap(cache->cacheMemMap);
00912        cache->cacheMemMap = NULL;
00913     }
00914     memset(cache, 0, sizeof *cache);
00915 }
00916 
00917 static SECStatus
00918 InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout, 
00919           PRUint32 ssl3_timeout, const char *directory, PRBool shared)
00920 {
00921     ptrdiff_t     ptr;
00922     sidCacheLock *pLock;
00923     char *        cacheMem;
00924     PRFileMap *   cacheMemMap;
00925     char *        cfn = NULL;      /* cache file name */
00926     int           locks_initialized = 0;
00927     int           locks_to_initialize = 0;
00928     PRUint32      init_time;
00929 
00930     if ( (!cache) || (maxCacheEntries < 0) || (!directory) ) {
00931         PORT_SetError(SEC_ERROR_INVALID_ARGS);
00932         return SECFailure;
00933     }
00934 
00935     if (cache->cacheMem) {
00936        /* Already done */
00937        return SECSuccess;
00938     }
00939 
00940     /* make sure loser can clean up properly */
00941     cache->shared = shared;
00942     cache->cacheMem    = cacheMem    = NULL;
00943     cache->cacheMemMap = cacheMemMap = NULL;
00944     cache->sharedCache = (cacheDesc *)0;
00945 
00946     cache->numSIDCacheLocksInitialized = 0;
00947     cache->nextCertCacheEntry = 0;
00948     cache->stopPolling = PR_FALSE;
00949     cache->everInherited = PR_FALSE;
00950     cache->poller = NULL;
00951     cache->mutexTimeout = 0;
00952 
00953     cache->numSIDCacheEntries = maxCacheEntries ? maxCacheEntries 
00954                                                 : DEF_SID_CACHE_ENTRIES;
00955     cache->numSIDCacheSets    = 
00956        SID_HOWMANY(cache->numSIDCacheEntries, SID_CACHE_ENTRIES_PER_SET);
00957 
00958     cache->numSIDCacheEntries = 
00959        cache->numSIDCacheSets * SID_CACHE_ENTRIES_PER_SET;
00960 
00961     cache->numSIDCacheLocks   = 
00962        PR_MIN(cache->numSIDCacheSets, ssl_max_sid_cache_locks);
00963 
00964     cache->numSIDCacheSetsPerLock = 
00965        SID_HOWMANY(cache->numSIDCacheSets, cache->numSIDCacheLocks);
00966 
00967     /* compute size of shared memory, and offsets of all pointers */
00968     ptr = 0;
00969     cache->cacheMem     = (char *)ptr;
00970     ptr += SID_ROUNDUP(sizeof(cacheDesc), SID_ALIGNMENT);
00971 
00972     cache->sidCacheLocks = (sidCacheLock *)ptr;
00973     cache->keyCacheLock  = cache->sidCacheLocks + cache->numSIDCacheLocks;
00974     cache->certCacheLock = cache->keyCacheLock  + 1;
00975     ptr = (ptrdiff_t)(cache->certCacheLock + 1);
00976     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
00977 
00978     cache->sidCacheSets  = (sidCacheSet *)ptr;
00979     ptr = (ptrdiff_t)(cache->sidCacheSets + cache->numSIDCacheSets);
00980     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
00981 
00982     cache->sidCacheData  = (sidCacheEntry *)ptr;
00983     ptr = (ptrdiff_t)(cache->sidCacheData + cache->numSIDCacheEntries);
00984     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
00985 
00986     cache->certCacheData = (certCacheEntry *)ptr;
00987     cache->sidCacheSize  = 
00988        (char *)cache->certCacheData - (char *)cache->sidCacheData;
00989 
00990     /* This is really a poor way to computer this! */
00991     cache->numCertCacheEntries = cache->sidCacheSize / sizeof(certCacheEntry);
00992     if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES)
00993        cache->numCertCacheEntries = MIN_CERT_CACHE_ENTRIES;
00994     ptr = (ptrdiff_t)(cache->certCacheData + cache->numCertCacheEntries);
00995     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
00996 
00997     cache->keyCacheData  = (SSLWrappedSymWrappingKey *)ptr;
00998     cache->certCacheSize = 
00999        (char *)cache->keyCacheData - (char *)cache->certCacheData;
01000 
01001     cache->numKeyCacheEntries = kt_kea_size * SSL_NUM_WRAP_MECHS;
01002     ptr = (ptrdiff_t)(cache->keyCacheData + cache->numKeyCacheEntries);
01003     ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
01004 
01005     cache->cacheMemSize = ptr;
01006 
01007     cache->keyCacheSize  = (char *)ptr - (char *)cache->keyCacheData;
01008 
01009     if (ssl2_timeout) {   
01010        if (ssl2_timeout > MAX_SSL2_TIMEOUT) {
01011            ssl2_timeout = MAX_SSL2_TIMEOUT;
01012        }
01013        if (ssl2_timeout < MIN_SSL2_TIMEOUT) {
01014            ssl2_timeout = MIN_SSL2_TIMEOUT;
01015        }
01016        cache->ssl2Timeout = ssl2_timeout;
01017     } else {
01018        cache->ssl2Timeout = DEF_SSL2_TIMEOUT;
01019     }
01020 
01021     if (ssl3_timeout) {   
01022        if (ssl3_timeout > MAX_SSL3_TIMEOUT) {
01023            ssl3_timeout = MAX_SSL3_TIMEOUT;
01024        }
01025        if (ssl3_timeout < MIN_SSL3_TIMEOUT) {
01026            ssl3_timeout = MIN_SSL3_TIMEOUT;
01027        }
01028        cache->ssl3Timeout = ssl3_timeout;
01029     } else {
01030        cache->ssl3Timeout = DEF_SSL3_TIMEOUT;
01031     }
01032 
01033     if (shared) {
01034        /* Create file names */
01035 #if defined(XP_UNIX) || defined(XP_BEOS)
01036        /* there's some confusion here about whether PR_OpenAnonFileMap wants
01037        ** a directory name or a file name for its first argument.
01038        cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid);
01039        */
01040        cfn = PR_smprintf("%s", directory);
01041 #elif defined(XP_WIN32)
01042        cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid, 
01043                          GetCurrentThreadId());
01044 #elif defined(XP_OS2)
01045        cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid, 
01046                          gettid());
01047 #else
01048 #error "Don't know how to create file name for this platform!"
01049 #endif
01050        if (!cfn) {
01051            goto loser;
01052        }
01053 
01054        /* Create cache */
01055        cacheMemMap = PR_OpenAnonFileMap(cfn, cache->cacheMemSize, 
01056                                     PR_PROT_READWRITE);
01057 
01058        PR_smprintf_free(cfn);
01059        if(!cacheMemMap) {
01060            goto loser;
01061        }
01062 
01063         cacheMem = PR_MemMap(cacheMemMap, 0, cache->cacheMemSize);
01064     } else {
01065         cacheMem = PORT_Alloc(cache->cacheMemSize);
01066     }
01067     
01068     if (! cacheMem) {
01069         goto loser;
01070     }
01071 
01072     /* Initialize shared memory. This may not be necessary on all platforms */
01073     memset(cacheMem, 0, cache->cacheMemSize);
01074 
01075     /* Copy cache descriptor header into shared memory */
01076     memcpy(cacheMem, cache, sizeof *cache);
01077 
01078     /* save private copies of these values */
01079     cache->cacheMemMap = cacheMemMap;
01080     cache->cacheMem    = cacheMem;
01081     cache->sharedCache = (cacheDesc *)cacheMem;
01082 
01083     /* Fix pointers in our private copy of cache descriptor to point to 
01084     ** spaces in shared memory 
01085     */
01086     ptr = (ptrdiff_t)cache->cacheMem;
01087     *(ptrdiff_t *)(&cache->sidCacheLocks) += ptr;
01088     *(ptrdiff_t *)(&cache->keyCacheLock ) += ptr;
01089     *(ptrdiff_t *)(&cache->certCacheLock) += ptr;
01090     *(ptrdiff_t *)(&cache->sidCacheSets ) += ptr;
01091     *(ptrdiff_t *)(&cache->sidCacheData ) += ptr;
01092     *(ptrdiff_t *)(&cache->certCacheData) += ptr;
01093     *(ptrdiff_t *)(&cache->keyCacheData ) += ptr;
01094 
01095     /* initialize the locks */
01096     init_time = ssl_Time();
01097     pLock = cache->sidCacheLocks;
01098     for (locks_to_initialize = cache->numSIDCacheLocks + 2;
01099          locks_initialized < locks_to_initialize; 
01100         ++locks_initialized, ++pLock ) {
01101 
01102        SECStatus err = sslMutex_Init(&pLock->mutex, shared);
01103        if (err) {
01104            cache->numSIDCacheLocksInitialized = locks_initialized;
01105            goto loser;
01106        }
01107         pLock->timeStamp = init_time;
01108        pLock->pid       = 0;
01109     }
01110     cache->numSIDCacheLocksInitialized = locks_initialized;
01111 
01112     return SECSuccess;
01113 
01114 loser:
01115     CloseCache(cache);
01116     return SECFailure;
01117 }
01118 
01119 PRUint32
01120 SSL_GetMaxServerCacheLocks(void)
01121 {
01122     return ssl_max_sid_cache_locks + 2;
01123     /* The extra two are the cert cache lock and the key cache lock. */
01124 }
01125 
01126 SECStatus
01127 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
01128 {
01129     /* Minimum is 1 sid cache lock, 1 cert cache lock and 1 key cache lock.
01130     ** We'd like to test for a maximum value, but not all platforms' header
01131     ** files provide a symbol or function or other means of determining
01132     ** the maximum, other than trial and error.
01133     */
01134     if (maxLocks < 3) {
01135        PORT_SetError(SEC_ERROR_INVALID_ARGS);
01136        return SECFailure;
01137     }
01138     ssl_max_sid_cache_locks = maxLocks - 2;
01139     /* The extra two are the cert cache lock and the key cache lock. */
01140     return SECSuccess;
01141 }
01142 
01143 SECStatus
01144 SSL_ConfigServerSessionIDCacheInstance(   cacheDesc *cache,
01145                                 int      maxCacheEntries, 
01146                             PRUint32 ssl2_timeout,
01147                                    PRUint32 ssl3_timeout, 
01148                        const char *   directory, PRBool shared)
01149 {
01150     SECStatus rv;
01151 
01152 #if defined(DEBUG_nelsonb)
01153     printf("sizeof(sidCacheEntry) == %u\n", sizeof(sidCacheEntry));
01154 #endif
01155     PORT_Assert(sizeof(sidCacheEntry) == 192);
01156     PORT_Assert(sizeof(certCacheEntry) == 4096);
01157 
01158     myPid = SSL_GETPID();
01159     if (!directory) {
01160        directory = DEFAULT_CACHE_DIRECTORY;
01161     }
01162     rv = InitCache(cache, maxCacheEntries, ssl2_timeout, ssl3_timeout, 
01163                    directory, shared);
01164     if (rv) {
01165        SET_ERROR_CODE
01166        return SECFailure;
01167     }
01168 
01169     ssl_sid_lookup  = ServerSessionIDLookup;
01170     ssl_sid_cache   = ServerSessionIDCache;
01171     ssl_sid_uncache = ServerSessionIDUncache;
01172     return SECSuccess;
01173 }
01174 
01175 SECStatus
01176 SSL_ConfigServerSessionIDCache(    int      maxCacheEntries, 
01177                             PRUint32 ssl2_timeout,
01178                                    PRUint32 ssl3_timeout, 
01179                        const char *   directory)
01180 {
01181     ssl_InitClientSessionCacheLock();
01182     ssl_InitSymWrapKeysLock();
01183     return SSL_ConfigServerSessionIDCacheInstance(&globalCache, 
01184               maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE);
01185 }
01186 
01187 SECStatus
01188 SSL_ShutdownServerSessionIDCacheInstance(cacheDesc *cache)
01189 {
01190     CloseCache(cache);
01191     return SECSuccess;
01192 }
01193 
01194 SECStatus
01195 SSL_ShutdownServerSessionIDCache(void)
01196 {
01197 #if defined(XP_UNIX) || defined(XP_BEOS)
01198     /* Stop the thread that polls cache for expired locks on Unix */
01199     StopLockPoller(&globalCache);
01200 #endif
01201     SSL3_ShutdownServerCache();
01202     return SSL_ShutdownServerSessionIDCacheInstance(&globalCache);
01203 }
01204 
01205 /* Use this function, instead of SSL_ConfigServerSessionIDCache,
01206  * if the cache will be shared by multiple processes.
01207  */
01208 SECStatus
01209 SSL_ConfigMPServerSIDCache( int      maxCacheEntries, 
01210                             PRUint32 ssl2_timeout,
01211                                    PRUint32 ssl3_timeout, 
01212                         const char *   directory)
01213 {
01214     char *    envValue;
01215     char *    inhValue;
01216     cacheDesc * cache         = &globalCache;
01217     PRUint32    fmStrLen;
01218     SECStatus        result;
01219     PRStatus  prStatus;
01220     SECStatus putEnvFailed;
01221     inheritance inherit;
01222     char        fmString[PR_FILEMAP_STRING_BUFSIZE];
01223 
01224     isMultiProcess = PR_TRUE;
01225     result = SSL_ConfigServerSessionIDCacheInstance(cache, maxCacheEntries, 
01226                      ssl2_timeout, ssl3_timeout, directory, PR_TRUE);
01227     if (result != SECSuccess) 
01228         return result;
01229 
01230     prStatus = PR_ExportFileMapAsString(cache->cacheMemMap, 
01231                                         sizeof fmString, fmString);
01232     if ((prStatus != PR_SUCCESS) || !(fmStrLen = strlen(fmString))) {
01233        SET_ERROR_CODE
01234        return SECFailure;
01235     }
01236 
01237     inherit.cacheMemSize    = cache->cacheMemSize;
01238     inherit.fmStrLen            = fmStrLen;
01239 
01240     inhValue = BTOA_DataToAscii((unsigned char *)&inherit, sizeof inherit);
01241     if (!inhValue || !strlen(inhValue)) {
01242        SET_ERROR_CODE
01243        return SECFailure;
01244     }
01245     envValue = PR_smprintf("%s,%s", inhValue, fmString);
01246     if (!envValue || !strlen(envValue)) {
01247        SET_ERROR_CODE
01248        return SECFailure;
01249     }
01250     PORT_Free(inhValue);
01251 
01252     putEnvFailed = (SECStatus)NSS_PutEnv(envVarName, envValue);
01253     PR_smprintf_free(envValue);
01254     if (putEnvFailed) {
01255         SET_ERROR_CODE
01256         result = SECFailure;
01257     }
01258 
01259 #if defined(XP_UNIX) || defined(XP_BEOS)
01260     /* Launch thread to poll cache for expired locks on Unix */
01261     LaunchLockPoller(cache);
01262 #endif
01263     return result;
01264 }
01265 
01266 SECStatus
01267 SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
01268 {
01269     unsigned char * decoString = NULL;
01270     char *          fmString   = NULL;
01271     char *          myEnvString = NULL;
01272     unsigned int    decoLen;
01273     ptrdiff_t       ptr;
01274     inheritance     inherit;
01275     cacheDesc       my;
01276 #ifdef WINNT
01277     sidCacheLock* newLocks;
01278     int           locks_initialized = 0;
01279     int           locks_to_initialize = 0;
01280 #endif
01281 
01282     myPid = SSL_GETPID();
01283 
01284     /* If this child was created by fork(), and not by exec() on unix,
01285     ** then isMultiProcess will already be set.
01286     ** If not, we'll set it below.
01287     */
01288     if (isMultiProcess) {
01289        if (cache && cache->sharedCache) {
01290            cache->sharedCache->everInherited = PR_TRUE;
01291        }
01292        return SECSuccess;   /* already done. */
01293     }
01294 
01295     ssl_InitClientSessionCacheLock();
01296     ssl_InitSymWrapKeysLock();
01297 
01298     ssl_sid_lookup  = ServerSessionIDLookup;
01299     ssl_sid_cache   = ServerSessionIDCache;
01300     ssl_sid_uncache = ServerSessionIDUncache;
01301 
01302     if (!envString) {
01303        envString  = getenv(envVarName);
01304        if (!envString) {
01305            SET_ERROR_CODE
01306            return SECFailure;
01307        }
01308     }
01309     myEnvString = PORT_Strdup(envString);
01310     if (!myEnvString) 
01311        return SECFailure;
01312     fmString = strchr(myEnvString, ',');
01313     if (!fmString) 
01314        goto loser;
01315     *fmString++ = 0;
01316 
01317     decoString = ATOB_AsciiToData(myEnvString, &decoLen);
01318     if (!decoString) {
01319        SET_ERROR_CODE
01320        goto loser;
01321     }
01322     if (decoLen != sizeof inherit) {
01323        SET_ERROR_CODE
01324        goto loser;
01325     }
01326 
01327     PORT_Memcpy(&inherit, decoString, sizeof inherit);
01328 
01329     if (strlen(fmString)  != inherit.fmStrLen ) {
01330        goto loser;
01331     }
01332 
01333     memset(cache, 0, sizeof *cache);
01334     cache->cacheMemSize     = inherit.cacheMemSize;
01335 
01336     /* Create cache */
01337     cache->cacheMemMap = PR_ImportFileMapFromString(fmString);
01338     if(! cache->cacheMemMap) {
01339        goto loser;
01340     }
01341     cache->cacheMem = PR_MemMap(cache->cacheMemMap, 0, cache->cacheMemSize);
01342     if (! cache->cacheMem) {
01343        goto loser;
01344     }
01345     cache->sharedCache   = (cacheDesc *)cache->cacheMem;
01346 
01347     if (cache->sharedCache->cacheMemSize != cache->cacheMemSize) {
01348        SET_ERROR_CODE
01349        goto loser;
01350     }
01351 
01352     /* We're now going to overwrite the local cache instance with the 
01353     ** shared copy of the cache struct, then update several values in 
01354     ** the local cache using the values for cache->cacheMemMap and 
01355     ** cache->cacheMem computed just above.  So, we copy cache into 
01356     ** the automatic variable "my", to preserve the variables while
01357     ** cache is overwritten.
01358     */
01359     my = *cache;  /* save values computed above. */
01360     memcpy(cache, cache->sharedCache, sizeof *cache); /* overwrite */
01361 
01362     /* Fix pointers in our private copy of cache descriptor to point to 
01363     ** spaces in shared memory, whose address is now in "my".
01364     */
01365     ptr = (ptrdiff_t)my.cacheMem;
01366     *(ptrdiff_t *)(&cache->sidCacheLocks) += ptr;
01367     *(ptrdiff_t *)(&cache->keyCacheLock ) += ptr;
01368     *(ptrdiff_t *)(&cache->certCacheLock) += ptr;
01369     *(ptrdiff_t *)(&cache->sidCacheSets ) += ptr;
01370     *(ptrdiff_t *)(&cache->sidCacheData ) += ptr;
01371     *(ptrdiff_t *)(&cache->certCacheData) += ptr;
01372     *(ptrdiff_t *)(&cache->keyCacheData ) += ptr;
01373 
01374     cache->cacheMemMap = my.cacheMemMap;
01375     cache->cacheMem    = my.cacheMem;
01376     cache->sharedCache = (cacheDesc *)cache->cacheMem;
01377 
01378 #ifdef WINNT
01379     /*  On Windows NT we need to "fix" the sidCacheLocks here to support fibers
01380     **  When NT fibers are used in a multi-process server, a second level of
01381     **  locking is needed to prevent a deadlock, in case a fiber acquires the
01382     **  cross-process mutex, yields, and another fiber is later scheduled on
01383     **  the same native thread and tries to acquire the cross-process mutex.
01384     **  We do this by using a PRLock in the sslMutex. However, it is stored in
01385     **  shared memory as part of sidCacheLocks, and we don't want to overwrite
01386     **  the PRLock of the parent process. So we need to make new, private
01387     **  copies of sidCacheLocks before modifying the sslMutex with our own
01388     **  PRLock
01389     */
01390     
01391     /* note from jpierre : this should be free'd in child processes when
01392     ** a function is added to delete the SSL session cache in the future. 
01393     */
01394     locks_to_initialize = cache->numSIDCacheLocks + 2;
01395     newLocks = PORT_NewArray(sidCacheLock, locks_to_initialize);
01396     if (!newLocks)
01397        goto loser;
01398     /* copy the old locks */
01399     memcpy(newLocks, cache->sidCacheLocks, 
01400            locks_to_initialize * sizeof(sidCacheLock));
01401     cache->sidCacheLocks = newLocks;
01402     /* fix the locks */            
01403     for (; locks_initialized < locks_to_initialize; ++locks_initialized) {
01404         /* now, make a local PRLock in this sslMutex for this child process */
01405        SECStatus err;
01406         err = sslMutex_2LevelInit(&newLocks[locks_initialized].mutex);
01407        if (err != SECSuccess) {
01408            cache->numSIDCacheLocksInitialized = locks_initialized;
01409            goto loser;
01410        }
01411     }
01412     cache->numSIDCacheLocksInitialized = locks_initialized;
01413 
01414     /* also fix the key and cert cache which use the last 2 lock entries */
01415     cache->keyCacheLock  = cache->sidCacheLocks + cache->numSIDCacheLocks;
01416     cache->certCacheLock = cache->keyCacheLock  + 1;
01417 #endif
01418 
01419     PORT_Free(myEnvString);
01420     PORT_Free(decoString);
01421 
01422     /* mark that we have inherited this. */
01423     cache->sharedCache->everInherited = PR_TRUE;
01424     isMultiProcess = PR_TRUE;
01425 
01426     return SECSuccess;
01427 
01428 loser:
01429     PORT_Free(myEnvString);
01430     if (decoString) 
01431        PORT_Free(decoString);
01432     CloseCache(cache);
01433     return SECFailure;
01434 }
01435 
01436 SECStatus
01437 SSL_InheritMPServerSIDCache(const char * envString)
01438 {
01439     return SSL_InheritMPServerSIDCacheInstance(&globalCache, envString);
01440 }
01441 
01442 #if defined(XP_UNIX) || defined(XP_BEOS)
01443 
01444 #define SID_LOCK_EXPIRATION_TIMEOUT  30 /* seconds */
01445 
01446 static void
01447 LockPoller(void * arg)
01448 {
01449     cacheDesc *    cache         = (cacheDesc *)arg;
01450     cacheDesc *    sharedCache   = cache->sharedCache;
01451     sidCacheLock * pLock;
01452     PRIntervalTime timeout;
01453     PRUint32       now;
01454     PRUint32       then;
01455     int            locks_polled  = 0;
01456     int            locks_to_poll = cache->numSIDCacheLocks + 2;
01457     PRUint32       expiration    = cache->mutexTimeout;
01458 
01459     timeout = PR_SecondsToInterval(expiration);
01460     while(!sharedCache->stopPolling) {
01461        PR_Sleep(timeout);
01462        if (sharedCache->stopPolling)
01463            break;
01464 
01465        now   = ssl_Time();
01466        then  = now - expiration;
01467        for (pLock = cache->sidCacheLocks, locks_polled = 0;
01468             locks_to_poll > locks_polled && !sharedCache->stopPolling; 
01469             ++locks_polled, ++pLock ) {
01470            pid_t pid;
01471 
01472            if (pLock->timeStamp   < then && 
01473                pLock->timeStamp   != 0 && 
01474               (pid = pLock->pid) != 0) {
01475 
01476               /* maybe we should try the lock? */
01477               int result = kill(pid, 0);
01478               if (result < 0 && errno == ESRCH) {
01479                   SECStatus rv;
01480                   /* No process exists by that pid any more.
01481                   ** Treat this mutex as abandoned.
01482                   */
01483                   pLock->timeStamp = now;
01484                   pLock->pid       = 0;
01485                   rv = sslMutex_Unlock(&pLock->mutex);
01486                   if (rv != SECSuccess) {
01487                      /* Now what? */
01488                   }
01489               }
01490            }
01491        } /* end of loop over locks */
01492     } /* end of entire polling loop */
01493 }
01494 
01495 /* Launch thread to poll cache for expired locks */
01496 static SECStatus 
01497 LaunchLockPoller(cacheDesc *cache)
01498 {
01499     const char * timeoutString;
01500     PRThread *   pollerThread;
01501 
01502     cache->mutexTimeout = SID_LOCK_EXPIRATION_TIMEOUT;
01503     timeoutString       = getenv("NSS_SSL_SERVER_CACHE_MUTEX_TIMEOUT");
01504     if (timeoutString) {
01505        long newTime = strtol(timeoutString, 0, 0);
01506        if (newTime == 0) 
01507            return SECSuccess;  /* application doesn't want poller thread */
01508        if (newTime > 0)
01509            cache->mutexTimeout = (PRUint32)newTime;
01510        /* if error (newTime < 0) ignore it and use default */
01511     }
01512 
01513     pollerThread = 
01514        PR_CreateThread(PR_USER_THREAD, LockPoller, cache, PR_PRIORITY_NORMAL, 
01515                        PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
01516     if (!pollerThread) {
01517        return SECFailure;
01518     }
01519     cache->poller = pollerThread;
01520     return SECSuccess;
01521 }
01522 
01523 /* Stop the thread that polls cache for expired locks */
01524 static SECStatus 
01525 StopLockPoller(cacheDesc *cache)
01526 {
01527     if (!cache->poller) {
01528        return SECSuccess;
01529     }
01530     cache->sharedCache->stopPolling = PR_TRUE;
01531     if (PR_Interrupt(cache->poller) != PR_SUCCESS) {
01532        return SECFailure;
01533     }
01534     if (PR_JoinThread(cache->poller) != PR_SUCCESS) {
01535        return SECFailure;
01536     }
01537     cache->poller = NULL;
01538     return SECSuccess;
01539 }
01540 #endif
01541 
01542 /************************************************************************
01543  *  Code dealing with shared wrapped symmetric wrapping keys below      *
01544  ************************************************************************/
01545 
01546 /* If now is zero, it implies that the lock is not held, and must be 
01547 ** aquired here.  
01548 */
01549 static PRBool
01550 getSvrWrappingKey(PRInt32                symWrapMechIndex,
01551                SSL3KEAType               exchKeyType, 
01552                SSLWrappedSymWrappingKey *wswk, 
01553               cacheDesc *               cache,
01554               PRUint32                  lockTime)
01555 {
01556     PRUint32  ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
01557     SSLWrappedSymWrappingKey * pwswk = cache->keyCacheData + ndx;
01558     PRUint32  now = 0;
01559     PRBool    rv  = PR_FALSE;
01560 
01561     if (!cache->cacheMem) { /* cache is uninitialized */
01562        PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
01563        return rv;
01564     }
01565     if (!lockTime) {
01566        lockTime = now = LockSidCacheLock(cache->keyCacheLock, now);
01567        if (!lockTime) {
01568            return rv;
01569        }
01570     }
01571     if (pwswk->exchKeyType      == exchKeyType && 
01572        pwswk->symWrapMechIndex == symWrapMechIndex &&
01573        pwswk->wrappedSymKeyLen != 0) {
01574        *wswk = *pwswk;
01575        rv = PR_TRUE;
01576     }
01577     if (now) {
01578        UnlockSidCacheLock(cache->keyCacheLock);
01579     }
01580     return rv;
01581 }
01582 
01583 PRBool
01584 ssl_GetWrappingKey( PRInt32                   symWrapMechIndex,
01585                     SSL3KEAType               exchKeyType, 
01586                   SSLWrappedSymWrappingKey *wswk)
01587 {
01588     PRBool rv;
01589 
01590     PORT_Assert( (unsigned)exchKeyType < kt_kea_size);
01591     PORT_Assert( (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
01592     if ((unsigned)exchKeyType < kt_kea_size &&
01593         (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS) {
01594        rv = getSvrWrappingKey(symWrapMechIndex, exchKeyType, wswk, 
01595                               &globalCache, 0);
01596     } else {
01597        rv = PR_FALSE;
01598     }
01599 
01600     return rv;
01601 }
01602 
01603 /* The caller passes in the new value it wants
01604  * to set.  This code tests the wrapped sym key entry in the shared memory.
01605  * If it is uninitialized, this function writes the caller's value into 
01606  * the disk entry, and returns false.  
01607  * Otherwise, it overwrites the caller's wswk with the value obtained from 
01608  * the disk, and returns PR_TRUE.  
01609  * This is all done while holding the locks/mutexes necessary to make 
01610  * the operation atomic.
01611  */
01612 PRBool
01613 ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
01614 {
01615     cacheDesc *   cache            = &globalCache;
01616     PRBool        rv               = PR_FALSE;
01617     SSL3KEAType   exchKeyType      = wswk->exchKeyType;   
01618                                 /* type of keys used to wrap SymWrapKey*/
01619     PRInt32       symWrapMechIndex = wswk->symWrapMechIndex;
01620     PRUint32      ndx;
01621     PRUint32      now = 0;
01622     SSLWrappedSymWrappingKey myWswk;
01623 
01624     if (!cache->cacheMem) { /* cache is uninitialized */
01625        PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
01626        return 0;
01627     }
01628 
01629     PORT_Assert( (unsigned)exchKeyType < kt_kea_size);
01630     if ((unsigned)exchKeyType >= kt_kea_size)
01631        return 0;
01632 
01633     PORT_Assert( (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
01634     if ((unsigned)symWrapMechIndex >=  SSL_NUM_WRAP_MECHS)
01635        return 0;
01636 
01637     ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
01638     PORT_Memset(&myWswk, 0, sizeof myWswk);      /* eliminate UMRs. */
01639 
01640     now = LockSidCacheLock(cache->keyCacheLock, now);
01641     if (now) {
01642        rv = getSvrWrappingKey(wswk->symWrapMechIndex, wswk->exchKeyType, 
01643                               &myWswk, cache, now);
01644        if (rv) {
01645            /* we found it on disk, copy it out to the caller. */
01646            PORT_Memcpy(wswk, &myWswk, sizeof *wswk);
01647        } else {
01648            /* Wasn't on disk, and we're still holding the lock, so write it. */
01649            cache->keyCacheData[ndx] = *wswk;
01650        }
01651        UnlockSidCacheLock(cache->keyCacheLock);
01652     }
01653     return rv;
01654 }
01655 
01656 #else  /* MAC version or other platform */
01657 
01658 #include "seccomon.h"
01659 #include "cert.h"
01660 #include "ssl.h"
01661 #include "sslimpl.h"
01662 
01663 SECStatus
01664 SSL_ConfigServerSessionIDCache(    int      maxCacheEntries, 
01665                             PRUint32 ssl2_timeout,
01666                                    PRUint32 ssl3_timeout, 
01667                        const char *   directory)
01668 {
01669     PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigServerSessionIDCache)");    
01670     return SECFailure;
01671 }
01672 
01673 SECStatus
01674 SSL_ConfigMPServerSIDCache( int      maxCacheEntries, 
01675                             PRUint32 ssl2_timeout,
01676                                    PRUint32 ssl3_timeout, 
01677                         const char *   directory)
01678 {
01679     PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigMPServerSIDCache)");    
01680     return SECFailure;
01681 }
01682 
01683 SECStatus
01684 SSL_InheritMPServerSIDCache(const char * envString)
01685 {
01686     PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_InheritMPServerSIDCache)");    
01687     return SECFailure;
01688 }
01689 
01690 PRBool
01691 ssl_GetWrappingKey( PRInt32                   symWrapMechIndex,
01692                     SSL3KEAType               exchKeyType, 
01693                   SSLWrappedSymWrappingKey *wswk)
01694 {
01695     PRBool rv = PR_FALSE;
01696     PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_GetWrappingKey)");    
01697     return rv;
01698 }
01699 
01700 /* This is a kind of test-and-set.  The caller passes in the new value it wants
01701  * to set.  This code tests the wrapped sym key entry in the shared memory.
01702  * If it is uninitialized, this function writes the caller's value into 
01703  * the disk entry, and returns false.  
01704  * Otherwise, it overwrites the caller's wswk with the value obtained from 
01705  * the disk, and returns PR_TRUE.  
01706  * This is all done while holding the locks/mutexes necessary to make 
01707  * the operation atomic.
01708  */
01709 PRBool
01710 ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
01711 {
01712     PRBool        rv = PR_FALSE;
01713     PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_SetWrappingKey)");
01714     return rv;
01715 }
01716 
01717 PRUint32  
01718 SSL_GetMaxServerCacheLocks(void)
01719 {
01720     PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_GetMaxServerCacheLocks)");
01721     return -1;
01722 }
01723 
01724 SECStatus 
01725 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
01726 {
01727     PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_SetMaxServerCacheLocks)");
01728     return SECFailure;
01729 }
01730 
01731 #endif /* XP_UNIX || XP_WIN32 */