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 + -
显示快捷键?