sslsnce.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,927 行 · 第 1/4 页

C
1,927
字号
    PR_Lock(cacheLock);}static void unlock_cache(void){    PR_Unlock(cacheLock);}/*** Perform some mumbo jumbo on the ip-address and the session-id value to** compute a hash value.*/static PRUint32 Offset(const PRIPv6Addr *addr, unsigned char *s, unsigned nl){    PRUint32 rv;    rv = addr->pr_s6_addr32[3] ^ (((PRUint32)s[0] << 24) | ((PRUint32)s[1] << 16)		 | (s[2] << 8) | s[nl-1]);    return (rv % numSIDCacheEntries) * sizeof(SIDCacheEntry);}/*** Look something up in the cache. This will invalidate old entries** in the process. Caller has locked the cache!** Returns PR_TRUE if found a valid match.  PR_FALSE otherwise.*/static PRBool FindSID(const PRIPv6Addr *addr, unsigned char *sessionID,	unsigned sessionIDLength, SIDCacheEntry *sce){    PRUint32      offset;    PRUint32      now;    int           rv;#ifdef XP_UNIX    off_t         off;#endif    /* Read in cache entry after hashing ip address and session-id value */    offset = Offset(addr, sessionID, sessionIDLength);     now = ssl_Time();    GET_SERVER_CACHE_READ_LOCK(SIDCacheFD, offset, sizeof *sce);#ifdef XP_UNIX    off = lseek(SIDCacheFD, 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(SIDCacheFD, sce, sizeof *sce);	if (rv != sizeof *sce) {	    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(sce, &SIDCacheData[offset], sizeof *sce);    rv = sizeof *sce;#endif /* XP_WIN32 */    RELEASE_SERVER_CACHE_LOCK(SIDCacheFD, offset, sizeof *sce);    if (rv != sizeof *sce) {	IOError(rv, "server sid cache read");	return PR_FALSE;    }    if (!sce->u.ssl2.valid) {	/* Entry is not valid */	PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND);	return PR_FALSE;    }    if (((sce->u.ssl2.version < SSL_LIBRARY_VERSION_3_0) &&	 (now > sce->time + ssl_sid_timeout)) ||	((sce->u.ssl2.version >= SSL_LIBRARY_VERSION_3_0) &&	 (now > sce->time + ssl3_sid_timeout))) {	/* SessionID has timed out. Invalidate the entry. */	SSL_TRC(7, ("%d: timed out sid entry addr=%08x%08x%08x%08x now=%x time+=%x",		    myPid, sce->addr.pr_s6_addr32[0],		    sce->addr.pr_s6_addr32[1], sce->addr.pr_s6_addr32[2],		    sce->addr.pr_s6_addr32[3], now, 		    sce->time + ssl_sid_timeout));	sce->u.ssl2.valid = 0;	GET_SERVER_CACHE_WRITE_LOCK(SIDCacheFD, offset, sizeof *sce);#ifdef XP_UNIX	off = lseek(SIDCacheFD, offset, SEEK_SET);	rv = -1;	if (off != offset) {	    if (off == -1) 		nss_MD_unix_map_lseek_error(errno);	    else	    	PORT_SetError(PR_IO_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, "timeout-write");	    }	}#else /* WIN32 */	/* Use memory mapped I/O and just memcpy() the data */	CopyMemory(&SIDCacheData[offset], sce, sizeof *sce);	rv = sizeof *sce;#endif /* XP_UNIX */	RELEASE_SERVER_CACHE_LOCK(SIDCacheFD, offset, sizeof *sce);	if (rv == sizeof *sce)	    PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND);	return PR_FALSE;    }    /*    ** Finally, examine specific session-id/addr data to see if the cache    ** entry matches our addr+session-id value    */    if (!memcmp(&sce->addr, addr, sizeof(PRIPv6Addr)) &&	(PORT_Memcmp(sce->u.ssl2.sessionID, sessionID, sessionIDLength) == 0)) {	/* Found it */	return PR_TRUE;    }    PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND);    return PR_FALSE;}/************************************************************************//* This is the primary function for finding entries in the server's sid cache. * Although it is static, this function is called via the global function  * pointer ssl_sid_lookup. */static sslSessionID *ServerSessionIDLookup(	const PRIPv6Addr  *addr,			unsigned char *sessionID,			unsigned int   sessionIDLength,                        CERTCertDBHandle * dbHandle){    SIDCacheEntry sce;    sslSessionID *sid;    sid = 0;    lock_cache();    if (FindSID(addr, sessionID, sessionIDLength, &sce)) {	/* Found it. Convert file format to internal format */	sid = ConvertToSID(&sce, dbHandle);    }    unlock_cache();    return sid;}/*** Place an sid into the cache, if it isn't already there. Note that if** some other server process has replaced a session-id cache entry that has** the same cache index as this sid, then all is ok. Somebody has to lose** when this condition occurs, so it might as well be this sid.*/static void ServerSessionIDCache(sslSessionID *sid){    SIDCacheEntry sce;    PRUint32      offset;#ifdef XP_UNIX    off_t         off;    int           rv;#endif    uint16 version = sid->version;    if ((version >= SSL_LIBRARY_VERSION_3_0) &&	(sid->u.ssl3.sessionIDLength == 0)) {	return;    }    if (sid->cached == never_cached || sid->cached == invalid_cache) {	lock_cache();	sid->time = ssl_Time();	if (version < SSL_LIBRARY_VERSION_3_0) {	    SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "			"cipher=%d", myPid, sid->cached, 			sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],			sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],			sid->time, sid->u.ssl2.cipherType));	    PRINT_BUF(8, (0, "sessionID:", sid->u.ssl2.sessionID,			  sizeof(sid->u.ssl2.sessionID)));	    PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,			  sid->u.ssl2.masterKey.len));	    PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,			  sid->u.ssl2.cipherArg.len));	    /* Write out new cache entry */	    offset = Offset(&sid->addr, sid->u.ssl2.sessionID,			    sizeof(sid->u.ssl2.sessionID)); 	} else {	    SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "			"cipherSuite=%d", myPid, sid->cached, 			sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],			sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3], 			sid->time, sid->u.ssl3.cipherSuite));	    PRINT_BUF(8, (0, "sessionID:", sid->u.ssl3.sessionID,			  sid->u.ssl3.sessionIDLength));	    offset = Offset(&sid->addr, sid->u.ssl3.sessionID,			    sid->u.ssl3.sessionIDLength);	    	}	ConvertFromSID(&sce, sid);	if (version >= SSL_LIBRARY_VERSION_3_0) {	    if (sid->peerCert == NULL) {		sce.u.ssl3.certIndex = -1;	    } else {		sce.u.ssl3.certIndex = (int16)		    ((offset / sizeof(SIDCacheEntry)) % numCertCacheEntries);	    }	}		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_IO_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, "update-write");	    }	}#else /* WIN32 */	CopyMemory(&SIDCacheData[offset], &sce, sizeof sce);#endif /* XP_UNIX */	RELEASE_SERVER_CACHE_LOCK(SIDCacheFD, offset, sizeof sce);	if ((version >= SSL_LIBRARY_VERSION_3_0) && 	    (sid->peerCert != NULL)) {	    CacheCert(sid->peerCert, &sce);	}	sid->cached = in_server_cache;	unlock_cache();    }}static void ServerSessionIDUncache(sslSessionID *sid){    SIDCacheEntry sce;    PRErrorCode   err;    int rv;    if (sid == NULL) return;        /* Uncaching a SID should never change the error code.     ** So save it here and restore it before exiting.    */    err = PR_GetError();    lock_cache();    if (sid->version < SSL_LIBRARY_VERSION_3_0) {	SSL_TRC(8, ("%d: SSL: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "		    "cipher=%d", myPid, sid->cached, 		    sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],		    sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3], 		    sid->time, sid->u.ssl2.cipherType));	PRINT_BUF(8, (0, "sessionID:", sid->u.ssl2.sessionID,		      sizeof(sid->u.ssl2.sessionID)));	PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,		      sid->u.ssl2.masterKey.len));	PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,		      sid->u.ssl2.cipherArg.len));	rv = FindSID(&sid->addr, sid->u.ssl2.sessionID,		     sizeof(sid->u.ssl2.sessionID), &sce);    } else {	SSL_TRC(8, ("%d: SSL3: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "		    "cipherSuite=%d", myPid, sid->cached, 		    sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],		    sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3], 		    sid->time, sid->u.ssl3.cipherSuite));	PRINT_BUF(8, (0, "sessionID:", sid->u.ssl3.sessionID,		      sid->u.ssl3.sessionIDLength));	rv = FindSID(&sid->addr, sid->u.ssl3.sessionID,		     sid->u.ssl3.sessionIDLength, &sce);    }        if (rv) {	Invalidate(&sce);    }    sid->cached = invalid_cache;    unlock_cache();    PORT_SetError(err);}static SECStatusInitSessionIDCache(int maxCacheEntries, PRUint32 timeout,		   PRUint32 ssl3_timeout, const char *directory){    char *cfn;#ifdef XP_UNIX    int rv;    if (SIDCacheFD >= 0) {	/* Already done */	return SECSuccess;    }#else /* WIN32 */	if(SIDCacheFDMAP != INVALID_HANDLE_VALUE) {	/* Already done */	return SECSuccess;	}#endif /* XP_UNIX */    if (maxCacheEntries) {	numSIDCacheEntries = maxCacheEntries;    }    sidCacheWrapOffset = numSIDCacheEntries * sizeof(SIDCacheEntry);    sidCacheFileSize = sidCacheWrapOffset +         (kt_kea_size * SSL_NUM_WRAP_MECHS * sizeof(SSLWrappedSymWrappingKey));    /* Create file names */    cfn = (char*) PORT_Alloc(PORT_Strlen(directory) + 100);    if (!cfn) {	return SECFailure;    }#ifdef XP_UNIX    sprintf(cfn, "%s/.sslsidc.%d", directory, getpid());#else /* XP_WIN32 */	sprintf(cfn, "%s\\ssl.sidc.%d.%d", directory,			GetCurrentProcessId(), GetCurrentThreadId());#endif /* XP_WIN32 */    /* Create session-id cache file */#ifdef XP_UNIX    do {	(void) unlink(cfn);	SIDCacheFD = open(cfn, O_EXCL|O_CREAT|O_RDWR, 0600);    } while (SIDCacheFD < 0 && errno == EEXIST);    if (SIDCacheFD < 0) {	nss_MD_unix_map_open_error(errno);	IOError(SIDCacheFD, "create");	goto loser;    }    rv = unlink(cfn);    if (rv < 0) {	nss_MD_unix_map_unlink_error(errno);	IOError(rv, "unlink");	goto loser;    }#else  /* WIN32 */    SIDCacheFDMAP =     	CreateFileMapping(INVALID_HANDLE_VALUE, /* allocate in swap file */			  &sidCacheFDMapAttributes, /* inheritable. */			  PAGE_READWRITE,			  0,                    /* size, high word. */			  sidCacheFileSize,     /* size, low  word. */			  NULL);		/* no map name in FS */    if(! SIDCacheFDMAP) {	nss_MD_win32_map_default_error(GetLastError());	goto loser;    }    SIDCacheData = (char *)MapViewOfFile(SIDCacheFDMAP,                                          FILE_MAP_ALL_ACCESS, 	/* R/W    */					 0, 0, 			/* offset */				         sidCacheFileSize);	/* size   */    if (! SIDCacheData) {	nss_MD_win32_map_default_error(GetLastError());	goto loser;    }#endif /* XP_UNIX */    if (!cacheLock)	nss_InitLock(&cacheLock);    if (!cacheLock) {	SET_ERROR_CODE	goto loser;    }#ifdef _WIN32    if (isMultiProcess  && (SECSuccess != createServerCacheSemaphore())) {	SET_ERROR_CODE	goto loser;    }#endif    if (timeout) {   	if (timeout > 100) {	    timeout = 100;	}	if (timeout < 5) {	    timeout = 5;	}	ssl_sid_timeout = timeout;    }    if (ssl3_timeout) {   	if (ssl3_timeout > 86400L) {	    ssl3_timeout = 86400L;	}	if (ssl3_timeout < 5) {	    ssl3_timeout = 5;	}	ssl3_sid_timeout = ssl3_timeout;    }    GET_SERVER_CACHE_WRITE_LOCK(SIDCacheFD, 0, sidCacheFileSize);#ifdef XP_UNIX    /* Initialize the files */    if (ZeroFile(SIDCacheFD, sidCacheFileSize)) {	/* Bummer */	close(SIDCacheFD);	SIDCacheFD = -1;	goto loser;    }#else /* XP_WIN32 */    ZeroMemory(SIDCacheData, sidCacheFileSize);#endif /* XP_UNIX */    RELEASE_SERVER_CACHE_LOCK(SIDCacheFD, 0, sidCacheFileSize);    PORT_Free(cfn);    return SECSuccess;  loser:#ifdef _WIN32    if (svrCacheSem)	destroyServerCacheSemaphore();#endif    if (cacheLock) {	PR_DestroyLock(cacheLock);	cacheLock = NULL;    }    PORT_Free(cfn);    return SECFailure;}static SECStatus InitCertCache(const char *directory){    char *cfn;#ifdef XP_UNIX    int rv;    if (certCacheFD >= 0) {	/* Already done */	return SECSuccess;    }#else /* WIN32 */    if(certCacheFDMAP != INVALID_HANDLE_VALUE) {	/* Already done */	return SECSuccess;    }#endif /* XP_UNIX */    numCertCacheEntries = sidCacheFileSize / sizeof(CertCacheEntry);    if (numCertCacheEntries < MIN_CERT_CACHE_ENTRIES)    	numCertCacheEntries = MIN_CERT_CACHE_ENTRIES;    certCacheFileSize = numCertCacheEntries * sizeof(CertCacheEntry);    /* Create file names */    cfn = (char*) PORT_Alloc(PORT_Strlen(directory) + 100);    if (!cfn) {	return SECFailure;    }#ifdef XP_UNIX    sprintf(cfn, "%s/.sslcertc.%d", directory, getpid());#else /* XP_WIN32 */    sprintf(cfn, "%s\\ssl.certc.%d.%d", directory,	    GetCurrentProcessId(), GetCurrentThreadId());#endif /* XP_WIN32 */    /* Create certificate cache file */#ifdef XP_UNIX

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?