sslsnce.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,927 行 · 第 1/4 页
C
1,927 行
*/ sslLockArgs * args = PORT_New(sslLockArgs); if (!args) return rv; args->offset = offset; args->size = size; args->rv = SECFailure; args->fd = fd; args->type = type; selectThread = PR_CreateThread(PR_USER_THREAD, _doGetServerCacheLock, args, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (selectThread != NULL) { /* rv will be set by _doGetServerCacheLock() */ PR_JoinThread(selectThread); rv = args->rv; if (rv != SECSuccess) { PORT_SetError(args->err); } } PORT_Free(args); } return rv;}static SECStatusreleaseServerCacheLock(int fd, PRUint32 offset, PRUint32 size){ int result; struct flock lock; memset(&lock, 0, sizeof lock); lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; /* absolute file offsets. */ lock.l_start = 0; lock.l_len = 128;#ifdef TRACE if (ssl_trace) { fprintf(stderr, "%d: unlock, offset %8x, size %4d\n", myPid, offset, size); fflush(stderr); }#endif result = fcntl(fd, F_SETLK, &lock); if (result == -1) { nss_MD_unix_map_default_error(errno); FCNTL_FAILED(&lock); return SECFailure; } return SECSuccess;}/* these defines take the arguments needed to do record locking, * however the present implementation does only file locking. */#define GET_SERVER_CACHE_READ_LOCK( fd, offset, size) \ if (isMultiProcess) getServerCacheLock(fd, F_RDLCK, offset, size);#define GET_SERVER_CACHE_WRITE_LOCK(fd, offset, size) \ if (isMultiProcess) getServerCacheLock(fd, F_WRLCK, offset, size);#define RELEASE_SERVER_CACHE_LOCK( fd, offset, size) \ if (isMultiProcess) releaseServerCacheLock(fd, offset, size);/*** Zero a file out to nb bytes*/static SECStatus ZeroFile(int fd, int nb){ off_t off; int amount, rv; char buf[16384]; PORT_Memset(buf, 0, sizeof(buf)); off = lseek(fd, 0, SEEK_SET); if (off != 0) { if (off == -1) nss_MD_unix_map_lseek_error(errno); else PORT_SetError(PR_FILE_SEEK_ERROR); return SECFailure; } while (nb > 0) { amount = (nb > sizeof buf) ? sizeof buf : nb; rv = write(fd, buf, amount); if (rv <= 0) { if (!rv) PORT_SetError(PR_IO_ERROR); else nss_MD_unix_map_write_error(errno); IOError(rv, "zero-write"); return SECFailure; } nb -= rv; } return SECSuccess;}#endif /* XP_UNIX *//************************************************************************//*** Reconstitute a cert from the cache** This is only called from ConvertToSID().** Caller must hold the cache lock before calling this.*/static CERTCertificate *GetCertFromCache(SIDCacheEntry *sce, CERTCertDBHandle *dbHandle){ CERTCertificate *cert; PRUint32 offset; int rv;#ifdef XP_UNIX off_t off;#endif SECItem derCert; CertCacheEntry cce; offset = (PRUint32)sce->u.ssl3.certIndex * sizeof(CertCacheEntry); GET_SERVER_CACHE_READ_LOCK(certCacheFD, offset, sizeof(CertCacheEntry));#ifdef XP_UNIX off = lseek(certCacheFD, offset, SEEK_SET); rv = -1; if (off != offset) { if (off == -1) nss_MD_unix_map_lseek_error(errno); else PORT_SetError(PR_FILE_SEEK_ERROR); } else { rv = read(certCacheFD, &cce, sizeof(CertCacheEntry)); if (rv != sizeof(CertCacheEntry)) { if (rv == -1) nss_MD_unix_map_read_error(errno); else PORT_SetError(PR_IO_ERROR); } }#else /* XP_WIN32 */ /* Use memory mapped I/O and just memcpy() the data */ CopyMemory(&cce, &certCacheData[offset], sizeof(CertCacheEntry)); rv = sizeof cce;#endif /* XP_WIN32 */ RELEASE_SERVER_CACHE_LOCK(certCacheFD, offset, sizeof(CertCacheEntry)) if (rv != sizeof(CertCacheEntry)) { IOError(rv, "read"); /* error set above */ return NULL; } /* See if the session ID matches with that in the sce cache. */ if((cce.sessionIDLength != sce->u.ssl3.sessionIDLength) || PORT_Memcmp(cce.sessionID, sce->u.ssl3.sessionID, cce.sessionIDLength)) { /* this is a cache miss, not an error */ PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND); return NULL; } derCert.len = cce.certLength; derCert.data = cce.cert; cert = CERT_NewTempCertificate(dbHandle, &derCert, NULL, PR_FALSE, PR_TRUE); return cert;}/* Put a certificate in the cache. We assume that the certIndex in** sid is valid.*/static voidCacheCert(CERTCertificate *cert, SIDCacheEntry *sce){ PRUint32 offset; CertCacheEntry cce;#ifdef XP_UNIX off_t off; int rv;#endif offset = (PRUint32)sce->u.ssl3.certIndex * sizeof(CertCacheEntry); if (cert->derCert.len > SSL_MAX_CACHED_CERT_LEN) return; cce.sessionIDLength = sce->u.ssl3.sessionIDLength; PORT_Memcpy(cce.sessionID, sce->u.ssl3.sessionID, cce.sessionIDLength); cce.certLength = cert->derCert.len; PORT_Memcpy(cce.cert, cert->derCert.data, cce.certLength); GET_SERVER_CACHE_WRITE_LOCK(certCacheFD, offset, sizeof cce);#ifdef XP_UNIX off = lseek(certCacheFD, offset, SEEK_SET); if (off != offset) { if (off == -1) nss_MD_unix_map_lseek_error(errno); else PORT_SetError(PR_FILE_SEEK_ERROR); } else { rv = write(certCacheFD, &cce, sizeof cce); if (rv != sizeof(CertCacheEntry)) { if (rv == -1) nss_MD_unix_map_write_error(errno); else PORT_SetError(PR_IO_ERROR); IOError(rv, "cert-write"); Invalidate(sce); } }#else /* WIN32 */ /* Use memory mapped I/O and just memcpy() the data */ CopyMemory(&certCacheData[offset], &cce, sizeof cce);#endif /* XP_UNIX */ RELEASE_SERVER_CACHE_LOCK(certCacheFD, offset, sizeof cce); return;}/*** Convert memory based SID to file based one*/static void ConvertFromSID(SIDCacheEntry *to, sslSessionID *from){ to->u.ssl2.valid = 1; to->u.ssl2.version = from->version; to->addr = from->addr; to->time = from->time; if (from->version < SSL_LIBRARY_VERSION_3_0) { if ((from->u.ssl2.masterKey.len > SSL_MAX_MASTER_KEY_BYTES) || (from->u.ssl2.cipherArg.len > SSL_MAX_CYPHER_ARG_BYTES)) { SSL_DBG(("%d: SSL: masterKeyLen=%d cipherArgLen=%d", myPid, from->u.ssl2.masterKey.len, from->u.ssl2.cipherArg.len)); to->u.ssl2.valid = 0; return; } to->u.ssl2.cipherType = from->u.ssl2.cipherType; to->u.ssl2.masterKeyLen = from->u.ssl2.masterKey.len; to->u.ssl2.cipherArgLen = from->u.ssl2.cipherArg.len; to->u.ssl2.keyBits = from->u.ssl2.keyBits; to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits; PORT_Memcpy(to->u.ssl2.sessionID, from->u.ssl2.sessionID, sizeof(to->u.ssl2.sessionID)); PORT_Memcpy(to->u.ssl2.masterKey, from->u.ssl2.masterKey.data, from->u.ssl2.masterKey.len); PORT_Memcpy(to->u.ssl2.cipherArg, from->u.ssl2.cipherArg.data, from->u.ssl2.cipherArg.len);#ifdef DEBUG PORT_Memset(to->u.ssl2.masterKey+from->u.ssl2.masterKey.len, 0, sizeof(to->u.ssl2.masterKey) - from->u.ssl2.masterKey.len); PORT_Memset(to->u.ssl2.cipherArg+from->u.ssl2.cipherArg.len, 0, sizeof(to->u.ssl2.cipherArg) - from->u.ssl2.cipherArg.len);#endif SSL_TRC(8, ("%d: SSL: ConvertSID: masterKeyLen=%d cipherArgLen=%d " "time=%d addr=0x%08x%08x%08x%08x cipherType=%d", myPid, to->u.ssl2.masterKeyLen, to->u.ssl2.cipherArgLen, to->time, to->addr.pr_s6_addr32[0], to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2], to->addr.pr_s6_addr32[3], to->u.ssl2.cipherType)); } else { /* This is an SSL v3 session */ to->u.ssl3.sessionIDLength = from->u.ssl3.sessionIDLength; to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite; to->u.ssl3.compression = (uint16)from->u.ssl3.compression; to->u.ssl3.resumable = from->u.ssl3.resumable; to->u.ssl3.hasFortezza = from->u.ssl3.hasFortezza; to->u.ssl3.keys = from->u.ssl3.keys; to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech; to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType; PORT_Memcpy(to->u.ssl3.sessionID, from->u.ssl3.sessionID, from->u.ssl3.sessionIDLength); SSL_TRC(8, ("%d: SSL3: ConvertSID: time=%d addr=0x%08x%08x%08x%08x cipherSuite=%d", myPid, to->time, to->addr.pr_s6_addr32[0], to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2], to->addr.pr_s6_addr32[3], to->u.ssl3.cipherSuite)); }}/*** Convert file based cache-entry to memory based one** This is only called from ServerSessionIDLookup().** Caller must hold cache lock when calling this.*/static sslSessionID *ConvertToSID(SIDCacheEntry *from, CERTCertDBHandle * dbHandle){ sslSessionID *to; uint16 version = from->u.ssl2.version; to = (sslSessionID*) PORT_ZAlloc(sizeof(sslSessionID)); if (!to) { return 0; } if (version < SSL_LIBRARY_VERSION_3_0) { /* This is an SSL v2 session */ to->u.ssl2.masterKey.data = (unsigned char*) PORT_Alloc(from->u.ssl2.masterKeyLen); if (!to->u.ssl2.masterKey.data) { goto loser; } if (from->u.ssl2.cipherArgLen) { to->u.ssl2.cipherArg.data = (unsigned char*) PORT_Alloc(from->u.ssl2.cipherArgLen); if (!to->u.ssl2.cipherArg.data) { goto loser; } PORT_Memcpy(to->u.ssl2.cipherArg.data, from->u.ssl2.cipherArg, from->u.ssl2.cipherArgLen); } to->u.ssl2.cipherType = from->u.ssl2.cipherType; to->u.ssl2.masterKey.len = from->u.ssl2.masterKeyLen; to->u.ssl2.cipherArg.len = from->u.ssl2.cipherArgLen; to->u.ssl2.keyBits = from->u.ssl2.keyBits; to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits; PORT_Memcpy(to->u.ssl2.sessionID, from->u.ssl2.sessionID, sizeof from->u.ssl2.sessionID); PORT_Memcpy(to->u.ssl2.masterKey.data, from->u.ssl2.masterKey, from->u.ssl2.masterKeyLen); SSL_TRC(8, ("%d: SSL: ConvertToSID: masterKeyLen=%d cipherArgLen=%d " "time=%d addr=0x%08x%08x%08x%08x cipherType=%d", myPid, to->u.ssl2.masterKey.len, to->u.ssl2.cipherArg.len, to->time, to->addr.pr_s6_addr32[0], to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2], to->addr.pr_s6_addr32[3], to->u.ssl2.cipherType)); } else { /* This is an SSL v3 session */ to->u.ssl3.sessionIDLength = from->u.ssl3.sessionIDLength; to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite; to->u.ssl3.compression = (SSL3CompressionMethod)from->u.ssl3.compression; to->u.ssl3.resumable = from->u.ssl3.resumable; to->u.ssl3.hasFortezza = from->u.ssl3.hasFortezza; to->u.ssl3.keys = from->u.ssl3.keys; to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech; to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType; PORT_Memcpy(to->u.ssl3.sessionID, from->u.ssl3.sessionID, from->u.ssl3.sessionIDLength); /* the portions of the SID that are only restored on the client * are set to invalid values on the server. */ to->u.ssl3.clientWriteKey = NULL; to->u.ssl3.serverWriteKey = NULL; to->u.ssl3.tek = NULL; to->urlSvrName = NULL; to->u.ssl3.masterModuleID = (SECMODModuleID)-1; /* invalid value */ to->u.ssl3.masterSlotID = (CK_SLOT_ID)-1; /* invalid value */ to->u.ssl3.masterWrapIndex = 0; to->u.ssl3.masterWrapSeries = 0; to->u.ssl3.masterValid = PR_FALSE; to->u.ssl3.clAuthModuleID = (SECMODModuleID)-1; /* invalid value */ to->u.ssl3.clAuthSlotID = (CK_SLOT_ID)-1; /* invalid value */ to->u.ssl3.clAuthSeries = 0; to->u.ssl3.clAuthValid = PR_FALSE; to->u.ssl3.clientWriteSaveLen = 0; if (from->u.ssl3.certIndex != -1) { to->peerCert = GetCertFromCache(from, dbHandle); if (to->peerCert == NULL) goto loser; } } to->version = from->u.ssl2.version; to->time = from->time; to->cached = in_server_cache; to->addr = from->addr; to->references = 1; return to; loser: Invalidate(from); if (to) { if (version < SSL_LIBRARY_VERSION_3_0) { if (to->u.ssl2.masterKey.data) PORT_Free(to->u.ssl2.masterKey.data); if (to->u.ssl2.cipherArg.data) PORT_Free(to->u.ssl2.cipherArg.data); } PORT_Free(to); } return NULL;}/* Invalidate a SID cache entry. * Called from CacheCert, ConvertToSid, and ServerSessionIDUncache. */static void Invalidate(SIDCacheEntry *sce){ PRUint32 offset;#ifdef XP_UNIX off_t off; int rv;#endif if (sce == NULL) return; if (sce->u.ssl2.version < SSL_LIBRARY_VERSION_3_0) { offset = Offset(&sce->addr, sce->u.ssl2.sessionID, sizeof sce->u.ssl2.sessionID); } else { offset = Offset(&sce->addr, sce->u.ssl3.sessionID, sce->u.ssl3.sessionIDLength); } sce->u.ssl2.valid = 0; SSL_TRC(7, ("%d: SSL: uncaching session-id at offset %ld", myPid, offset)); GET_SERVER_CACHE_WRITE_LOCK(SIDCacheFD, offset, sizeof *sce);#ifdef XP_UNIX off = lseek(SIDCacheFD, offset, SEEK_SET); if (off != offset) { if (off == -1) nss_MD_unix_map_lseek_error(errno); else PORT_SetError(PR_FILE_SEEK_ERROR); } else { rv = write(SIDCacheFD, sce, sizeof *sce); if (rv != sizeof *sce) { if (rv == -1) nss_MD_unix_map_write_error(errno); else PORT_SetError(PR_IO_ERROR); IOError(rv, "invalidate-write"); } }#else /* WIN32 */ /* Use memory mapped I/O and just memcpy() the data */ CopyMemory(&SIDCacheData[offset], sce, sizeof *sce);#endif /* XP_UNIX */ RELEASE_SERVER_CACHE_LOCK(SIDCacheFD, offset, sizeof *sce);}static void IOError(int rv, char *type){#ifdef XP_UNIX syslog(LOG_ALERT, "SSL: %s error with session-id cache, pid=%d, rv=%d, error='%m'", type, myPid, rv);#else /* XP_WIN32 */#ifdef MC_HTTPD ereport(LOG_FAILURE, "%s error with session-id cache rv=%d\n",type, rv);#endif /* MC_HTTPD */#endif /* XP_UNIX */}static void lock_cache(void){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?