1. the sslSecurityInfo and sslGather structs are now part of the sslSocket

rather than being pointed to by the sslSocket.  This reduces the number
of malloc/free calls, and greatly reduces pointer fetches, and null
pointer checks.  sslGather and sslSecurityInfo are separately initialized.
2. SSL_ResetHandshake no longer deallocates and reallocates the sslSecurityInfo and all its subcomponents.
3. Many places that formerly did not check for memory allocation failures
now do check, and do the right thing when allocation failed.
This commit is contained in:
nelsonb%netscape.com 2002-02-27 04:40:17 +00:00
Родитель a16c8ebd6f
Коммит 03a3ae9da0
11 изменённых файлов: 1016 добавлений и 1216 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -32,7 +32,7 @@
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: ssl3gthr.c,v 1.3 2000-12-02 00:53:59 nelsonb%netscape.com Exp $
* $Id: ssl3gthr.c,v 1.4 2002-02-27 04:40:15 nelsonb%netscape.com Exp $
*/
#include "cert.h"
@ -183,32 +183,31 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags)
int
ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
{
sslGather * gs = ss->gather;
SSL3Ciphertext cText;
int rv;
PORT_Assert( ssl_HaveRecvBufLock(ss) );
do {
/* bring in the next sslv3 record. */
rv = ssl3_GatherData(ss, gs, flags);
rv = ssl3_GatherData(ss, &ss->gs, flags);
if (rv <= 0) {
return rv;
}
/* decipher it, and handle it if it's a handshake.
* If it's application data, gs->buf will not be empty upon return.
* If it's application data, ss->gs.buf will not be empty upon return.
*/
cText.type = (SSL3ContentType)gs->hdr[0];
cText.version = (gs->hdr[1] << 8) | gs->hdr[2];
cText.buf = &gs->inbuf;
rv = ssl3_HandleRecord(ss, &cText, &gs->buf);
cText.type = (SSL3ContentType)ss->gs.hdr[0];
cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
cText.buf = &ss->gs.inbuf;
rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
if (rv < 0) {
return ss->recvdCloseNotify ? 0 : rv;
}
} while (ss->ssl3->hs.ws != idle_handshake && gs->buf.len == 0);
} while (ss->ssl3->hs.ws != idle_handshake && ss->gs.buf.len == 0);
gs->readOffset = 0;
gs->writeOffset = gs->buf.len;
ss->gs.readOffset = 0;
ss->gs.writeOffset = ss->gs.buf.len;
return 1;
}
@ -226,13 +225,12 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
int
ssl3_GatherAppDataRecord(sslSocket *ss, int flags)
{
sslGather * gs = ss->gather;
int rv;
PORT_Assert( ssl_HaveRecvBufLock(ss) );
do {
rv = ssl3_GatherCompleteHandshake(ss, flags);
} while (rv > 0 && gs->buf.len == 0);
} while (rv > 0 && ss->gs.buf.len == 0);
return rv;
}

Просмотреть файл

@ -30,7 +30,7 @@
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: sslauth.c,v 1.7 2001-11-09 05:39:36 nelsonb%netscape.com Exp $
* $Id: sslauth.c,v 1.8 2002-02-27 04:40:15 nelsonb%netscape.com Exp $
*/
#include "cert.h"
#include "secitem.h"
@ -44,7 +44,6 @@ CERTCertificate *
SSL_PeerCertificate(PRFileDesc *fd)
{
sslSocket *ss;
sslSecurityInfo *sec;
ss = ssl_FindSocket(fd);
if (!ss) {
@ -52,9 +51,8 @@ SSL_PeerCertificate(PRFileDesc *fd)
SSL_GETPID(), fd));
return 0;
}
sec = ss->sec;
if (ss->useSecurity && sec && sec->peerCert) {
return CERT_DupCertificate(sec->peerCert);
if (ss->useSecurity && ss->sec.peerCert) {
return CERT_DupCertificate(ss->sec.peerCert);
}
return 0;
}
@ -64,7 +62,6 @@ CERTCertificate *
SSL_LocalCertificate(PRFileDesc *fd)
{
sslSocket *ss;
sslSecurityInfo *sec;
ss = ssl_FindSocket(fd);
if (!ss) {
@ -72,13 +69,12 @@ SSL_LocalCertificate(PRFileDesc *fd)
SSL_GETPID(), fd));
return NULL;
}
sec = ss->sec;
if (ss->useSecurity && sec ) {
if (sec->localCert) {
return CERT_DupCertificate(sec->localCert);
if (ss->useSecurity) {
if (ss->sec.localCert) {
return CERT_DupCertificate(ss->sec.localCert);
}
if (sec->ci.sid && sec->ci.sid->localCert) {
return CERT_DupCertificate(sec->ci.sid->localCert);
if (ss->sec.ci.sid && ss->sec.ci.sid->localCert) {
return CERT_DupCertificate(ss->sec.ci.sid->localCert);
}
}
return NULL;
@ -92,7 +88,6 @@ SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
char **ip, char **sp)
{
sslSocket *ss;
sslSecurityInfo *sec;
const char *cipherName;
PRBool isDes = PR_FALSE;
@ -113,13 +108,11 @@ SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
}
if (ss->useSecurity && ss->firstHsDone) {
PORT_Assert(ss->sec != 0);
sec = ss->sec;
if (ss->version < SSL_LIBRARY_VERSION_3_0) {
cipherName = ssl_cipherName[sec->cipherType];
cipherName = ssl_cipherName[ss->sec.cipherType];
} else {
cipherName = ssl3_cipherName[sec->cipherType];
cipherName = ssl3_cipherName[ss->sec.cipherType];
}
if (cipherName && PORT_Strstr(cipherName, "DES")) isDes = PR_TRUE;
/* do same key stuff for fortezza */
@ -129,17 +122,17 @@ SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
}
if (kp0) {
*kp0 = sec->keyBits;
*kp0 = ss->sec.keyBits;
if (isDes) *kp0 = (*kp0 * 7) / 8;
}
if (kp1) {
*kp1 = sec->secretKeyBits;
*kp1 = ss->sec.secretKeyBits;
if (isDes) *kp1 = (*kp1 * 7) / 8;
}
if (op) {
if (sec->keyBits == 0) {
if (ss->sec.keyBits == 0) {
*op = SSL_SECURITY_STATUS_OFF;
} else if (sec->secretKeyBits < 90) {
} else if (ss->sec.secretKeyBits < 90) {
*op = SSL_SECURITY_STATUS_ON_LOW;
} else {
@ -150,7 +143,7 @@ SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
if (ip || sp) {
CERTCertificate *cert;
cert = sec->peerCert;
cert = ss->sec.peerCert;
if (cert) {
if (ip) {
*ip = CERT_NameToAscii(&cert->issuer);
@ -188,9 +181,6 @@ SSL_AuthCertificateHook(PRFileDesc *s, SSLAuthCertificate func, void *arg)
return SECFailure;
}
if ((rv = ssl_CreateSecurityInfo(ss)) != 0) {
return rv;
}
ss->authCertificate = func;
ss->authCertificateArg = arg;
@ -212,9 +202,6 @@ SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
return SECFailure;
}
if ((rv = ssl_CreateSecurityInfo(ss)) != 0) {
return rv;
}
ss->getClientAuthData = func;
ss->getClientAuthDataArg = arg;
return SECSuccess;
@ -234,9 +221,6 @@ SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
return SECFailure;
}
if ((rv = ssl_CreateSecurityInfo(ss)) != 0) {
return rv;
}
ss->pkcs11PinArg = arg;
return SECSuccess;
}
@ -266,7 +250,7 @@ SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
/* this may seem backwards, but isn't. */
certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
rv = CERT_VerifyCertNow(handle, ss->sec->peerCert, checkSig, certUsage,
rv = CERT_VerifyCertNow(handle, ss->sec.peerCert, checkSig, certUsage,
ss->pkcs11PinArg);
if ( rv != SECSuccess || isServer )
@ -278,7 +262,7 @@ SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
*/
hostname = ss->url;
if (hostname && hostname[0])
rv = CERT_VerifyCertName(ss->sec->peerCert, hostname);
rv = CERT_VerifyCertName(ss->sec.peerCert, hostname);
else
rv = SECFailure;
if (rv != SECSuccess)

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -32,7 +32,7 @@
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: sslgathr.c,v 1.3 2001-03-16 23:26:04 nelsonb%netscape.com Exp $
* $Id: sslgathr.c,v 1.4 2002-02-27 04:40:16 nelsonb%netscape.com Exp $
*/
#include "cert.h"
#include "ssl.h"
@ -47,7 +47,7 @@ static SECStatus ssl2_HandleV3HandshakeRecord(sslSocket *ss);
** first gathers the header (2 or 3 bytes long depending on the value of
** the most significant bit in the first byte) then gathers up the data
** for the record into gs->buf. This code handles non-blocking I/O
** and is to be called multiple times until sec->recordLen != 0.
** and is to be called multiple times until ss->sec.recordLen != 0.
** This function decrypts the gathered record in place, in gs_buf.
*
* Caller must hold RecvBufLock.
@ -83,7 +83,6 @@ static SECStatus ssl2_HandleV3HandshakeRecord(sslSocket *ss);
int
ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
{
sslSecurityInfo *sec = ss->sec;
unsigned char * bp;
unsigned char * pBuf;
int nb, err, rv;
@ -104,7 +103,7 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
gs->readOffset = 0;
}
if (gs->encrypted) {
PORT_Assert(sec != 0);
PORT_Assert(ss->sec.hash != 0);
}
pBuf = gs->buf.buf;
@ -221,7 +220,7 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
if (gs->encrypted) {
gs->state = GS_MAC;
gs->recordLen = gs->count - gs->recordPadding
- sec->hash->length;
- ss->sec.hash->length;
} else {
gs->state = GS_DATA;
gs->recordLen = gs->count;
@ -250,11 +249,11 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
* If this is a block cipher, this will detect records
* that are not a multiple of the blocksize in length.
*/
if (gs->count & (sec->blockSize - 1)) {
if (gs->count & (ss->sec.blockSize - 1)) {
/* This is an error. Sender is misbehaving */
SSL_DBG(("%d: SSL[%d]: sender, count=%d blockSize=%d",
SSL_GETPID(), ss->fd, gs->count,
sec->blockSize));
ss->sec.blockSize));
PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING);
rv = SECFailure;
goto spec_locked_done;
@ -269,7 +268,7 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
/* Decrypt the portion of data that we just recieved.
** Decrypt it in place.
*/
rv = (*sec->dec)(sec->readcx, pBuf, &nout, gs->offset,
rv = (*ss->sec.dec)(ss->sec.readcx, pBuf, &nout, gs->offset,
pBuf, gs->offset);
if (rv != SECSuccess) {
goto spec_locked_done;
@ -280,9 +279,9 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
**
** Prepare MAC by resetting it and feeding it the shared secret
*/
macLen = sec->hash->length;
macLen = ss->sec.hash->length;
if (gs->offset >= macLen) {
uint32 sequenceNumber = sec->rcvSequence++;
uint32 sequenceNumber = ss->sec.rcvSequence++;
unsigned char seq[4];
seq[0] = (unsigned char) (sequenceNumber >> 24);
@ -290,23 +289,23 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
seq[2] = (unsigned char) (sequenceNumber >> 8);
seq[3] = (unsigned char) (sequenceNumber);
(*sec->hash->begin)(sec->hashcx);
(*sec->hash->update)(sec->hashcx, sec->rcvSecret.data,
sec->rcvSecret.len);
(*sec->hash->update)(sec->hashcx, pBuf + macLen,
gs->offset - macLen);
(*sec->hash->update)(sec->hashcx, seq, 4);
(*sec->hash->end)(sec->hashcx, mac, &macLen, macLen);
(*ss->sec.hash->begin)(ss->sec.hashcx);
(*ss->sec.hash->update)(ss->sec.hashcx, ss->sec.rcvSecret.data,
ss->sec.rcvSecret.len);
(*ss->sec.hash->update)(ss->sec.hashcx, pBuf + macLen,
gs->offset - macLen);
(*ss->sec.hash->update)(ss->sec.hashcx, seq, 4);
(*ss->sec.hash->end)(ss->sec.hashcx, mac, &macLen, macLen);
}
PORT_Assert(macLen == sec->hash->length);
PORT_Assert(macLen == ss->sec.hash->length);
ssl_ReleaseSpecReadLock(ss); /******************************/
if (PORT_Memcmp(mac, pBuf, macLen) != 0) {
/* MAC's didn't match... */
SSL_DBG(("%d: SSL[%d]: mac check failed, seq=%d",
SSL_GETPID(), ss->fd, sec->rcvSequence));
SSL_GETPID(), ss->fd, ss->sec.rcvSequence));
PRINT_BUF(1, (ss, "computed mac:", mac, macLen));
PRINT_BUF(1, (ss, "received mac:", pBuf, macLen));
PORT_SetError(SSL_ERROR_BAD_MAC_READ);
@ -358,7 +357,7 @@ spec_locked_done:
gs->recordPadding = 0;
gs->state = GS_INIT;
++sec->rcvSequence;
++ss->sec.rcvSequence;
PRINT_BUF(50, (ss, "recv clear record:",
pBuf + gs->recordOffset, gs->recordLen));
@ -374,7 +373,7 @@ spec_locked_done:
** first gathers the header (2 or 3 bytes long depending on the value of
** the most significant bit in the first byte) then gathers up the data
** for the record into the readBuf. This code handles non-blocking I/O
** and is to be called multiple times until sec->recordLen != 0.
** and is to be called multiple times until ss->sec.recordLen != 0.
*
* Returns +1 when it has gathered a complete SSLV2 record.
* Returns 0 if it hits EOF.
@ -388,7 +387,7 @@ spec_locked_done:
int
ssl2_GatherRecord(sslSocket *ss, int flags)
{
return ssl2_GatherData(ss, ss->gather, flags);
return ssl2_GatherData(ss, &ss->gs, flags);
}
/*
@ -420,16 +419,16 @@ ssl2_StartGatherBytes(sslSocket *ss, sslGather *gs, unsigned int count)
}
/* Caller should hold RecvBufLock. */
sslGather *
ssl_NewGather(void)
SECStatus
ssl_InitGather(sslGather *gs)
{
sslGather *gs;
SECStatus status;
gs = (sslGather*) PORT_ZAlloc(sizeof(sslGather));
if (gs) {
gs->state = GS_INIT;
}
return gs;
gs->state = GS_INIT;
gs->writeOffset = 0;
gs->readOffset = 0;
status = sslBuffer_Grow(&gs->buf, 4096);
return status;
}
/* Caller must hold RecvBufLock. */
@ -439,7 +438,6 @@ ssl_DestroyGather(sslGather *gs)
if (gs) { /* the PORT_*Free functions check for NULL pointers. */
PORT_ZFree(gs->buf.buf, gs->buf.space);
PORT_Free(gs->inbuf.buf);
PORT_Free(gs);
}
}
@ -447,16 +445,15 @@ ssl_DestroyGather(sslGather *gs)
static SECStatus
ssl2_HandleV3HandshakeRecord(sslSocket *ss)
{
sslGather * gs = ss->gather;
SECStatus rv;
SSL3ProtocolVersion version = (gs->hdr[1] << 8) | gs->hdr[2];
SSL3ProtocolVersion version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
PORT_Assert( ssl_HaveRecvBufLock(ss) );
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
/* We've read in 3 bytes, there are 2 more to go in an ssl3 header. */
gs->remainder = 2;
gs->count = 0;
ss->gs.remainder = 2;
ss->gs.count = 0;
/* Clearing these handshake pointers ensures that
* ssl_Do1stHandshake won't call ssl2_HandleMessage when we return.
@ -473,7 +470,7 @@ ssl2_HandleV3HandshakeRecord(sslSocket *ss)
return rv;
}
ss->sec->send = ssl3_SendApplicationData;
ss->sec.send = ssl3_SendApplicationData;
return SECSuccess;
}

Просмотреть файл

@ -34,7 +34,7 @@
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: sslimpl.h,v 1.22 2002-02-22 04:23:24 wtc%netscape.com Exp $
* $Id: sslimpl.h,v 1.23 2002-02-27 04:40:16 nelsonb%netscape.com Exp $
*/
#ifndef __sslimpl_h_
@ -285,130 +285,6 @@ typedef struct sslServerCertsStr {
unsigned int serverKeyBits;
} sslServerCerts;
/*
** SSL Socket struct
**
** Protection: XXX
*/
struct sslSocketStr {
PRFileDesc * fd;
/* Pointer to operations vector for this socket */
const sslSocketOps * ops;
/* State flags */
unsigned int useSocks : 1;
unsigned int useSecurity : 1;
unsigned int requestCertificate : 1;
unsigned int requireCertificate : 2;
unsigned int handshakeAsClient : 1;
unsigned int handshakeAsServer : 1;
unsigned int enableSSL2 : 1;
unsigned int enableSSL3 : 1;
unsigned int enableTLS : 1;
unsigned int clientAuthRequested: 1;
unsigned int noCache : 1;
unsigned int fdx : 1; /* simultaneous R/W threads */
unsigned int v2CompatibleHello : 1; /* Send v3+ client hello in v2 format */
unsigned int detectRollBack : 1; /* Detect rollback to SSL v3 */
unsigned int firstHsDone : 1; /* first handshake is complete. */
unsigned int recvdCloseNotify : 1; /* received SSL EOF. */
unsigned int lastWriteBlocked : 1;
unsigned int TCPconnected : 1;
unsigned int handshakeBegun : 1;
unsigned int delayDisabled : 1; /* Nagle delay disabled */
/* version of the protocol to use */
SSL3ProtocolVersion version;
SSL3ProtocolVersion clientHelloVersion; /* version sent in client hello. */
/* Non-zero if security is enabled */
sslSecurityInfo *sec;
/* protected by firstHandshakeLock AND (in ssl3) ssl3HandshakeLock. */
const char *url; /* ssl 2 & 3 */
/* Gather object used for gathering data */
sslGather * gather; /*recvBufLock*/
sslHandshakeFunc handshake; /*firstHandshakeLock*/
sslHandshakeFunc nextHandshake; /*firstHandshakeLock*/
sslHandshakeFunc securityHandshake; /*firstHandshakeLock*/
sslBuffer saveBuf; /*xmitBufLock*/
sslBuffer pendingBuf; /*xmitBufLock*/
/* the following variable is only used with socks or other proxies. */
char * peerID; /* String uniquely identifies target server. */
ssl3State * ssl3;
unsigned char * cipherSpecs;
unsigned int sizeCipherSpecs;
const unsigned char * preferredCipher;
/* Configuration state for server sockets */
/* server cert and key for each KEA type */
sslServerCerts serverCerts[kt_kea_size];
ssl3KeyPair * stepDownKeyPair; /* RSA step down keys */
/* Callbacks */
SSLAuthCertificate authCertificate;
void *authCertificateArg;
SSLGetClientAuthData getClientAuthData;
void *getClientAuthDataArg;
SSLBadCertHandler handleBadCert;
void *badCertArg;
SSLHandshakeCallback handshakeCallback;
void *handshakeCallbackData;
void *pkcs11PinArg;
PRIntervalTime rTimeout; /* timeout for NSPR I/O */
PRIntervalTime wTimeout; /* timeout for NSPR I/O */
PRIntervalTime cTimeout; /* timeout for NSPR I/O */
PZLock * recvLock; /* lock against multiple reader threads. */
PZLock * sendLock; /* lock against multiple sender threads. */
PZMonitor * recvBufLock; /* locks low level recv buffers. */
PZMonitor * xmitBufLock; /* locks low level xmit buffers. */
/* Only one thread may operate on the socket until the initial handshake
** is complete. This Monitor ensures that. Since SSL2 handshake is
** only done once, this is also effectively the SSL2 handshake lock.
*/
PZMonitor * firstHandshakeLock;
/* This monitor protects the ssl3 handshake state machine data.
** Only one thread (reader or writer) may be in the ssl3 handshake state
** machine at any time. */
PZMonitor * ssl3HandshakeLock;
/* reader/writer lock, protects the secret data needed to encrypt and MAC
** outgoing records, and to decrypt and MAC check incoming ciphertext
** records. */
NSSRWLock * specLock;
/* handle to perm cert db (and implicitly to the temp cert db) used
** with this socket.
*/
CERTCertDBHandle * dbHandle;
PRThread * writerThread; /* thread holds SSL_LOCK_WRITER lock */
PRUint16 shutdownHow; /* See ssl_SHUTDOWN defines below. */
PRUint16 allowedByPolicy; /* copy of global policy bits. */
PRUint16 maybeAllowedByPolicy; /* copy of global policy bits. */
PRUint16 chosenPreference; /* SSL2 cipher preferences. */
sslHandshakingType handshaking;
ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED];
};
#define SSL_LOCK_RANK_SPEC 255
#define SSL_LOCK_RANK_GLOBAL NSS_RWLOCK_RANK_NONE
@ -510,124 +386,6 @@ typedef SECStatus (*SSLCipher)(void * context,
typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit);
/*
* SSL2 buffers used in SSL3.
* writeBuf in the SecurityInfo maintained by sslsecur.c is used
* to hold the data just about to be passed to the kernel
* sendBuf in the ConnectInfo maintained by sslcon.c is used
* to hold handshake messages as they are accumulated
*/
/*
** This is "ci", as in "ss->sec->ci".
**
** Protection: All the variables in here are protected by
** firstHandshakeLock AND (in ssl3) ssl3HandshakeLock
*/
struct sslConnectInfoStr {
/* outgoing handshakes appended to this. */
sslBuffer sendBuf; /*xmitBufLock*/ /* ssl 2 & 3 */
PRIPv6Addr peer; /* ssl 2 & 3 */
unsigned short port; /* ssl 2 & 3 */
sslSessionID *sid; /* ssl 2 & 3 */
/* see CIS_HAVE defines below for the bit values in *elements. */
char elements; /* ssl2 only */
char requiredElements; /* ssl2 only */
char sentElements; /* ssl2 only */
char sentFinished; /* ssl2 only */
/* Length of server challenge. Used by client when saving challenge */
int serverChallengeLen; /* ssl2 only */
/* type of authentication requested by server */
unsigned char authType; /* ssl2 only */
/* Challenge sent by client to server in client-hello message */
/* SSL3 gets a copy of this. See ssl3_StartHandshakeHash(). */
unsigned char clientChallenge[SSL_MAX_CHALLENGE_BYTES]; /* ssl 2 & 3 */
/* Connection-id sent by server to client in server-hello message */
unsigned char connectionID[SSL_CONNECTIONID_BYTES]; /* ssl2 only */
/* Challenge sent by server to client in request-certificate message */
unsigned char serverChallenge[SSL_MAX_CHALLENGE_BYTES]; /* ssl2 only */
/* Information kept to handle a request-certificate message */
unsigned char readKey[SSL_MAX_MASTER_KEY_BYTES]; /* ssl2 only */
unsigned char writeKey[SSL_MAX_MASTER_KEY_BYTES]; /* ssl2 only */
unsigned keySize; /* ssl2 only */
};
/* bit values for ci->elements, ci->requiredElements, sentElements. */
#define CIS_HAVE_MASTER_KEY 0x01
#define CIS_HAVE_CERTIFICATE 0x02
#define CIS_HAVE_FINISHED 0x04
#define CIS_HAVE_VERIFY 0x08
/* Note: The entire content of this struct and whatever it points to gets
* blown away by SSL_ResetHandshake(). This is "sec" as in "ss->sec".
*
* Unless otherwise specified below, the contents of this struct are
* protected by firstHandshakeLock AND (in ssl3) ssl3HandshakeLock.
*/
struct sslSecurityInfoStr {
sslSendFunc send; /*xmitBufLock*/ /* ssl 2 & 3 */
int isServer; /* Spec Lock?*/ /* ssl 2 & 3 */
sslBuffer writeBuf; /*xmitBufLock*/ /* ssl 2 & 3 */
int cipherType; /* ssl 2 & 3 */
int keyBits; /* ssl 2 & 3 */
int secretKeyBits; /* ssl 2 & 3 */
CERTCertificate *localCert; /* ssl 2 & 3 */
CERTCertificate *peerCert; /* ssl 2 & 3 */
SECKEYPublicKey *peerKey; /* ssl3 only */
SSLSignType authAlgorithm;
PRUint32 authKeyBits;
SSLKEAType keaType;
PRUint32 keaKeyBits;
/*
** Procs used for SID cache (nonce) management.
** Different implementations exist for clients/servers
** The lookup proc is only used for servers. Baloney!
*/
sslSessionIDCacheFunc cache; /* ssl 2 & 3 */
sslSessionIDUncacheFunc uncache; /* ssl 2 & 3 */
/*
** everything below here is for ssl2 only.
** This stuff is equivalent to SSL3's "spec", and is protected by the
** same "Spec Lock" as used for SSL3's specs.
*/
uint32 sendSequence; /*xmitBufLock*/ /* ssl2 only */
uint32 rcvSequence; /*recvBufLock*/ /* ssl2 only */
/* Hash information; used for one-way-hash functions (MD2, MD5, etc.) */
const SECHashObject *hash; /* Spec Lock */ /* ssl2 only */
void *hashcx; /* Spec Lock */ /* ssl2 only */
SECItem sendSecret; /* Spec Lock */ /* ssl2 only */
SECItem rcvSecret; /* Spec Lock */ /* ssl2 only */
/* Session cypher contexts; one for each direction */
void *readcx; /* Spec Lock */ /* ssl2 only */
void *writecx; /* Spec Lock */ /* ssl2 only */
SSLCipher enc; /* Spec Lock */ /* ssl2 only */
SSLCipher dec; /* Spec Lock */ /* ssl2 only */
void (*destroy)(void *, PRBool); /* Spec Lock */ /* ssl2 only */
/* Blocking information for the session cypher */
int blockShift; /* Spec Lock */ /* ssl2 only */
int blockSize; /* Spec Lock */ /* ssl2 only */
/* These are used during a connection handshake */
sslConnectInfo ci; /* ssl 2 & 3 */
};
/*
** ssl3State and CipherSpec structs
@ -963,6 +721,261 @@ typedef struct SSLWrappedSymWrappingKeyStr {
PRUint16 wrapIVLen;
} SSLWrappedSymWrappingKey;
/*
* SSL2 buffers used in SSL3.
* writeBuf in the SecurityInfo maintained by sslsecur.c is used
* to hold the data just about to be passed to the kernel
* sendBuf in the ConnectInfo maintained by sslcon.c is used
* to hold handshake messages as they are accumulated
*/
/*
** This is "ci", as in "ss->sec->ci".
**
** Protection: All the variables in here are protected by
** firstHandshakeLock AND (in ssl3) ssl3HandshakeLock
*/
struct sslConnectInfoStr {
/* outgoing handshakes appended to this. */
sslBuffer sendBuf; /*xmitBufLock*/ /* ssl 2 & 3 */
PRIPv6Addr peer; /* ssl 2 & 3 */
unsigned short port; /* ssl 2 & 3 */
sslSessionID *sid; /* ssl 2 & 3 */
/* see CIS_HAVE defines below for the bit values in *elements. */
char elements; /* ssl2 only */
char requiredElements; /* ssl2 only */
char sentElements; /* ssl2 only */
char sentFinished; /* ssl2 only */
/* Length of server challenge. Used by client when saving challenge */
int serverChallengeLen; /* ssl2 only */
/* type of authentication requested by server */
unsigned char authType; /* ssl2 only */
/* Challenge sent by client to server in client-hello message */
/* SSL3 gets a copy of this. See ssl3_StartHandshakeHash(). */
unsigned char clientChallenge[SSL_MAX_CHALLENGE_BYTES]; /* ssl 2 & 3 */
/* Connection-id sent by server to client in server-hello message */
unsigned char connectionID[SSL_CONNECTIONID_BYTES]; /* ssl2 only */
/* Challenge sent by server to client in request-certificate message */
unsigned char serverChallenge[SSL_MAX_CHALLENGE_BYTES]; /* ssl2 only */
/* Information kept to handle a request-certificate message */
unsigned char readKey[SSL_MAX_MASTER_KEY_BYTES]; /* ssl2 only */
unsigned char writeKey[SSL_MAX_MASTER_KEY_BYTES]; /* ssl2 only */
unsigned keySize; /* ssl2 only */
};
/* bit values for ci->elements, ci->requiredElements, sentElements. */
#define CIS_HAVE_MASTER_KEY 0x01
#define CIS_HAVE_CERTIFICATE 0x02
#define CIS_HAVE_FINISHED 0x04
#define CIS_HAVE_VERIFY 0x08
/* Note: The entire content of this struct and whatever it points to gets
* blown away by SSL_ResetHandshake(). This is "sec" as in "ss->sec".
*
* Unless otherwise specified below, the contents of this struct are
* protected by firstHandshakeLock AND (in ssl3) ssl3HandshakeLock.
*/
struct sslSecurityInfoStr {
sslSendFunc send; /*xmitBufLock*/ /* ssl 2 & 3 */
int isServer; /* Spec Lock?*/ /* ssl 2 & 3 */
sslBuffer writeBuf; /*xmitBufLock*/ /* ssl 2 & 3 */
int cipherType; /* ssl 2 & 3 */
int keyBits; /* ssl 2 & 3 */
int secretKeyBits; /* ssl 2 & 3 */
CERTCertificate *localCert; /* ssl 2 & 3 */
CERTCertificate *peerCert; /* ssl 2 & 3 */
SECKEYPublicKey *peerKey; /* ssl3 only */
SSLSignType authAlgorithm;
PRUint32 authKeyBits;
SSLKEAType keaType;
PRUint32 keaKeyBits;
/*
** Procs used for SID cache (nonce) management.
** Different implementations exist for clients/servers
** The lookup proc is only used for servers. Baloney!
*/
sslSessionIDCacheFunc cache; /* ssl 2 & 3 */
sslSessionIDUncacheFunc uncache; /* ssl 2 & 3 */
/*
** everything below here is for ssl2 only.
** This stuff is equivalent to SSL3's "spec", and is protected by the
** same "Spec Lock" as used for SSL3's specs.
*/
uint32 sendSequence; /*xmitBufLock*/ /* ssl2 only */
uint32 rcvSequence; /*recvBufLock*/ /* ssl2 only */
/* Hash information; used for one-way-hash functions (MD2, MD5, etc.) */
const SECHashObject *hash; /* Spec Lock */ /* ssl2 only */
void *hashcx; /* Spec Lock */ /* ssl2 only */
SECItem sendSecret; /* Spec Lock */ /* ssl2 only */
SECItem rcvSecret; /* Spec Lock */ /* ssl2 only */
/* Session cypher contexts; one for each direction */
void *readcx; /* Spec Lock */ /* ssl2 only */
void *writecx; /* Spec Lock */ /* ssl2 only */
SSLCipher enc; /* Spec Lock */ /* ssl2 only */
SSLCipher dec; /* Spec Lock */ /* ssl2 only */
void (*destroy)(void *, PRBool); /* Spec Lock */ /* ssl2 only */
/* Blocking information for the session cypher */
int blockShift; /* Spec Lock */ /* ssl2 only */
int blockSize; /* Spec Lock */ /* ssl2 only */
/* These are used during a connection handshake */
sslConnectInfo ci; /* ssl 2 & 3 */
};
/*
** SSL Socket struct
**
** Protection: XXX
*/
struct sslSocketStr {
PRFileDesc * fd;
/* Pointer to operations vector for this socket */
const sslSocketOps * ops;
/* State flags */
unsigned int useSocks : 1;
unsigned int useSecurity : 1;
unsigned int requestCertificate : 1;
unsigned int requireCertificate : 2;
unsigned int handshakeAsClient : 1;
unsigned int handshakeAsServer : 1;
unsigned int enableSSL2 : 1;
unsigned int enableSSL3 : 1;
unsigned int enableTLS : 1;
unsigned int clientAuthRequested: 1;
unsigned int noCache : 1;
unsigned int fdx : 1; /* simultaneous R/W threads */
unsigned int v2CompatibleHello : 1; /* Send v3+ client hello in v2 format */
unsigned int detectRollBack : 1; /* Detect rollback to SSL v3 */
unsigned int firstHsDone : 1; /* first handshake is complete. */
unsigned int recvdCloseNotify : 1; /* received SSL EOF. */
unsigned int lastWriteBlocked : 1;
unsigned int TCPconnected : 1;
unsigned int handshakeBegun : 1;
unsigned int delayDisabled : 1; /* Nagle delay disabled */
/* version of the protocol to use */
SSL3ProtocolVersion version;
SSL3ProtocolVersion clientHelloVersion; /* version sent in client hello. */
sslSecurityInfo sec; /* not a pointer any more */
/* protected by firstHandshakeLock AND (in ssl3) ssl3HandshakeLock. */
const char *url; /* ssl 2 & 3 */
/* Gather object used for gathering data */
sslGather gs; /*recvBufLock*/
sslHandshakeFunc handshake; /*firstHandshakeLock*/
sslHandshakeFunc nextHandshake; /*firstHandshakeLock*/
sslHandshakeFunc securityHandshake; /*firstHandshakeLock*/
sslBuffer saveBuf; /*xmitBufLock*/
sslBuffer pendingBuf; /*xmitBufLock*/
/* the following variable is only used with socks or other proxies. */
char * peerID; /* String uniquely identifies target server. */
ssl3State * ssl3;
unsigned char * cipherSpecs;
unsigned int sizeCipherSpecs;
const unsigned char * preferredCipher;
/* Configuration state for server sockets */
/* server cert and key for each KEA type */
sslServerCerts serverCerts[kt_kea_size];
ssl3KeyPair * stepDownKeyPair; /* RSA step down keys */
/* Callbacks */
SSLAuthCertificate authCertificate;
void *authCertificateArg;
SSLGetClientAuthData getClientAuthData;
void *getClientAuthDataArg;
SSLBadCertHandler handleBadCert;
void *badCertArg;
SSLHandshakeCallback handshakeCallback;
void *handshakeCallbackData;
void *pkcs11PinArg;
PRIntervalTime rTimeout; /* timeout for NSPR I/O */
PRIntervalTime wTimeout; /* timeout for NSPR I/O */
PRIntervalTime cTimeout; /* timeout for NSPR I/O */
PZLock * recvLock; /* lock against multiple reader threads. */
PZLock * sendLock; /* lock against multiple sender threads. */
PZMonitor * recvBufLock; /* locks low level recv buffers. */
PZMonitor * xmitBufLock; /* locks low level xmit buffers. */
/* Only one thread may operate on the socket until the initial handshake
** is complete. This Monitor ensures that. Since SSL2 handshake is
** only done once, this is also effectively the SSL2 handshake lock.
*/
PZMonitor * firstHandshakeLock;
/* This monitor protects the ssl3 handshake state machine data.
** Only one thread (reader or writer) may be in the ssl3 handshake state
** machine at any time. */
PZMonitor * ssl3HandshakeLock;
/* reader/writer lock, protects the secret data needed to encrypt and MAC
** outgoing records, and to decrypt and MAC check incoming ciphertext
** records. */
NSSRWLock * specLock;
/* handle to perm cert db (and implicitly to the temp cert db) used
** with this socket.
*/
CERTCertDBHandle * dbHandle;
PRThread * writerThread; /* thread holds SSL_LOCK_WRITER lock */
PRUint16 shutdownHow; /* See ssl_SHUTDOWN defines below. */
PRUint16 allowedByPolicy; /* copy of global policy bits. */
PRUint16 maybeAllowedByPolicy; /* copy of global policy bits. */
PRUint16 chosenPreference; /* SSL2 cipher preferences. */
sslHandshakingType handshaking;
ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED];
};
/* All the global data items declared here should be protected using the
** ssl_global_data_lock, which is a reader/writer lock.
*/
@ -1035,6 +1048,7 @@ extern PRFileDesc *ssl_FindTop(sslSocket *ss);
/* Gather funcs. */
extern sslGather * ssl_NewGather(void);
extern SECStatus ssl_InitGather(sslGather *gs);
extern void ssl_DestroyGather(sslGather *gs);
extern int ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags);
extern int ssl2_GatherRecord(sslSocket *ss, int flags);
@ -1047,6 +1061,7 @@ extern int ssl2_StartGatherBytes(sslSocket *ss, sslGather *gs,
extern SECStatus ssl_CreateSecurityInfo(sslSocket *ss);
extern SECStatus ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os);
extern void ssl_ResetSecurityInfo(sslSecurityInfo *sec);
extern void ssl_DestroySecurityInfo(sslSecurityInfo *sec);
extern sslSocket * ssl_DupSocket(sslSocket *old);

Просмотреть файл

@ -30,7 +30,7 @@
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: sslinfo.c,v 1.2 2001-11-02 04:24:21 nelsonb%netscape.com Exp $
* $Id: sslinfo.c,v 1.3 2002-02-27 04:40:17 nelsonb%netscape.com Exp $
*/
#include "ssl.h"
#include "sslimpl.h"
@ -40,7 +40,6 @@ SECStatus
SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
{
sslSocket * ss;
sslSecurityInfo *sec;
SSLChannelInfo inf;
sslSessionID * sid;
@ -58,14 +57,13 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
memset(&inf, 0, sizeof inf);
inf.length = PR_MIN(sizeof inf, len);
sec = ss->sec;
if (ss->useSecurity && ss->firstHsDone && sec) {
sid = sec->ci.sid;
if (ss->useSecurity && ss->firstHsDone) {
sid = ss->sec.ci.sid;
inf.protocolVersion = ss->version;
inf.authKeyBits = ss->sec->authKeyBits;
inf.keaKeyBits = ss->sec->keaKeyBits;
inf.authKeyBits = ss->sec.authKeyBits;
inf.keaKeyBits = ss->sec.keaKeyBits;
if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */
inf.cipherSuite = ss->sec->cipherType | 0xff00;
inf.cipherSuite = ss->sec.cipherType | 0xff00;
} else if (ss->ssl3) { /* SSL3 and TLS */
/* XXX These should come from crSpec */

Просмотреть файл

@ -32,7 +32,7 @@
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: sslnonce.c,v 1.10 2002-02-22 04:23:24 wtc%netscape.com Exp $
* $Id: sslnonce.c,v 1.11 2002-02-27 04:40:17 nelsonb%netscape.com Exp $
*/
#include "nssrenam.h"
@ -209,7 +209,7 @@ ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID,
/*
** Add an sid to the cache or return a previously cached entry to the cache.
** Although this is static, it is called via ss->sec->cache().
** Although this is static, it is called via ss->sec.cache().
*/
static void
CacheSID(sslSessionID *sid)
@ -309,7 +309,7 @@ UncacheSID(sslSessionID *zap)
/* If sid "zap" is in the cache,
* removes sid from cache, and decrements reference count.
* Although this function is static, it is called externally via
* ss->sec->uncache().
* ss->sec.uncache().
*/
static void
LockAndUncacheSID(sslSessionID *zap)

Просмотреть файл

@ -32,7 +32,7 @@
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: sslreveal.c,v 1.1 2000-03-31 19:35:30 relyea%netscape.com Exp $
* $Id: sslreveal.c,v 1.2 2002-02-27 04:40:17 nelsonb%netscape.com Exp $
*/
#include "cert.h"
@ -54,8 +54,8 @@ SSL_RevealCert(PRFileDesc * fd)
/* CERT_DupCertificate increases reference count and returns pointer to
* the same cert
*/
if (sslsocket && sslsocket->sec)
cert = CERT_DupCertificate(sslsocket->sec->peerCert);
if (sslsocket && sslsocket->sec.peerCert)
cert = CERT_DupCertificate(sslsocket->sec.peerCert);
return cert;
}

Просмотреть файл

@ -32,7 +32,7 @@
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: sslsecur.c,v 1.15 2002-02-22 04:23:25 wtc%netscape.com Exp $
* $Id: sslsecur.c,v 1.16 2002-02-27 04:40:17 nelsonb%netscape.com Exp $
*/
#include "cert.h"
#include "secitem.h"
@ -117,8 +117,6 @@ ssl_Do1stHandshake(sslSocket *ss)
int rv = SECSuccess;
int loopCount = 0;
PORT_Assert(ss->gather != 0);
do {
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( !ssl_HaveRecvBufLock(ss) );
@ -136,23 +134,22 @@ ssl_Do1stHandshake(sslSocket *ss)
}
if (ss->handshake == 0) {
ssl_GetRecvBufLock(ss);
ss->gather->recordLen = 0;
ss->gs.recordLen = 0;
ssl_ReleaseRecvBufLock(ss);
SSL_TRC(3, ("%d: SSL[%d]: handshake is completed",
SSL_GETPID(), ss->fd));
/* call handshake callback for ssl v2 */
/* for v3 this is done in ssl3_HandleFinished() */
if ((ss->sec != NULL) && /* used SSL */
(ss->handshakeCallback != NULL) && /* has callback */
if ((ss->handshakeCallback != NULL) && /* has callback */
(!ss->firstHsDone) && /* only first time */
(ss->version < SSL_LIBRARY_VERSION_3_0)) { /* not ssl3 */
ss->firstHsDone = PR_TRUE;
(ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
}
ss->firstHsDone = PR_TRUE;
ss->gather->writeOffset = 0;
ss->gather->readOffset = 0;
ss->gs.writeOffset = 0;
ss->gs.readOffset = 0;
break;
}
rv = (*ss->handshake)(ss);
@ -201,7 +198,7 @@ SECStatus
SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
{
sslSocket *ss;
SECStatus rv;
SECStatus status;
PRNetAddr addr;
ss = ssl_FindSocket(s);
@ -233,21 +230,16 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
ss->securityHandshake = 0;
ssl_GetRecvBufLock(ss);
ss->gather->state = GS_INIT;
ss->gather->writeOffset = 0;
ss->gather->readOffset = 0;
status = ssl_InitGather(&ss->gs);
ssl_ReleaseRecvBufLock(ss);
/*
** Blow away old security state and get a fresh setup. This way if
** ssl was used to connect to the first point in communication, ssl
** can be used for the next layer.
** Blow away old security state and get a fresh setup.
*/
if (ss->sec) {
ssl_DestroySecurityInfo(ss->sec);
ss->sec = 0;
}
rv = ssl_CreateSecurityInfo(ss);
ssl_GetXmitBufLock(ss);
ssl_ResetSecurityInfo(&ss->sec);
status = ssl_CreateSecurityInfo(ss);
ssl_ReleaseXmitBufLock(ss);
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss);
@ -258,7 +250,7 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
SSL_UNLOCK_WRITER(ss);
SSL_UNLOCK_READER(ss);
return rv;
return status;
}
/* For SSLv2, does nothing but return an error.
@ -328,7 +320,6 @@ SSL_HandshakeCallback(PRFileDesc *fd, SSLHandshakeCallback cb,
ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss);
PORT_Assert(ss->sec);
ss->handshakeCallback = cb;
ss->handshakeCallbackData = client_data;
@ -500,16 +491,13 @@ ssl_SendSavedWriteData(sslSocket *ss, sslBuffer *buf, sslSendFunc send)
static int
DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
{
sslGather * gs;
int rv;
int amount;
int available;
ssl_GetRecvBufLock(ss);
PORT_Assert((ss->sec != 0) && (ss->gather != 0));
gs = ss->gather;
available = gs->writeOffset - gs->readOffset;
available = ss->gs.writeOffset - ss->gs.readOffset;
if (available == 0) {
/* Get some more data */
if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
@ -541,7 +529,7 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
}
/* See if any clear data is now available */
available = gs->writeOffset - gs->readOffset;
available = ss->gs.writeOffset - ss->gs.readOffset;
if (available == 0) {
/*
** No partial data is available. Force error code to
@ -560,9 +548,9 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
/* Dole out clear data to reader */
amount = PR_MIN(len, available);
PORT_Memcpy(out, gs->buf.buf + gs->readOffset, amount);
PORT_Memcpy(out, ss->gs.buf.buf + ss->gs.readOffset, amount);
if (!(flags & MSG_PEEK)) {
gs->readOffset += amount;
ss->gs.readOffset += amount;
}
rv = amount;
@ -620,7 +608,6 @@ SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
{
SECStatus rv;
sslSocket *ss;
sslSecurityInfo *sec;
sslServerCerts *sc;
ss = ssl_FindSocket(fd);
@ -628,16 +615,6 @@ SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
return SECFailure;
}
if ((rv = ssl_CreateSecurityInfo(ss)) != SECSuccess) {
return rv;
}
sec = ss->sec;
if (sec == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* Both key and cert must have a value or be NULL */
/* Passing a value of NULL will turn off key exchange algorithms that were
* previously turned on */
@ -735,120 +712,72 @@ loser:
SECStatus
ssl_CreateSecurityInfo(sslSocket *ss)
{
sslSecurityInfo * sec = (sslSecurityInfo *)0;
sslGather * gs = (sslGather * )0;
int rv;
unsigned char padbuf[MAX_BLOCK_CYPHER_SIZE];
if (ss->sec) {
return SECSuccess;
}
/* Force the global RNG to generate some random data that we never use */
PK11_GenerateRandom(padbuf, sizeof padbuf);
ss->sec = sec = (sslSecurityInfo*) PORT_ZAlloc(sizeof(sslSecurityInfo));
if (!sec) {
goto loser;
}
SECStatus status;
/* initialize sslv2 socket to send data in the clear. */
ssl2_UseClearSendFunc(ss);
sec->blockSize = 1;
sec->blockShift = 0;
ss->sec.blockSize = 1;
ss->sec.blockShift = 0;
ssl_GetRecvBufLock(ss);
if ((gs = ss->gather) == 0) {
ss->gather = gs = ssl_NewGather();
if (!gs) {
goto loser;
}
}
ssl_GetXmitBufLock(ss);
status = sslBuffer_Grow(&ss->sec.writeBuf, 4096);
ssl_ReleaseXmitBufLock(ss);
rv = sslBuffer_Grow(&gs->buf, 4096);
if (rv) {
goto loser;
}
ssl_ReleaseRecvBufLock(ss);
ssl_GetXmitBufLock(ss);
rv = sslBuffer_Grow(&sec->writeBuf, 4096);
if (rv) {
goto loser;
}
ssl_ReleaseXmitBufLock(ss);
SSL_TRC(5, ("%d: SSL[%d]: security info created", SSL_GETPID(), ss->fd));
return SECSuccess;
loser:
if (sec) {
PORT_Free(sec);
ss->sec = sec = (sslSecurityInfo *)0;
}
if (gs) {
ssl_DestroyGather(gs);
ss->gather = gs = (sslGather *)0;
}
return SECFailure;
return status;
}
/* XXX We should handle errors better in this function. */
/* This function assumes that none of the pointers in ss need to be
** freed.
*/
SECStatus
ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os)
{
sslSecurityInfo *sec, *osec;
int rv;
rv = ssl_CreateSecurityInfo(ss);
if (rv < 0) {
goto loser;
}
sec = ss->sec;
osec = os->sec;
ss->sec.send = os->sec.send;
ss->sec.isServer = os->sec.isServer;
ss->sec.keyBits = os->sec.keyBits;
ss->sec.secretKeyBits = os->sec.secretKeyBits;
sec->send = osec->send;
sec->isServer = osec->isServer;
sec->keyBits = osec->keyBits;
sec->secretKeyBits = osec->secretKeyBits;
ss->sec.peerCert = CERT_DupCertificate(os->sec.peerCert);
if (os->sec.peerCert && !ss->sec.peerCert)
goto loser;
sec->peerCert = CERT_DupCertificate(osec->peerCert);
sec->cache = osec->cache;
sec->uncache = osec->uncache;
ss->sec.cache = os->sec.cache;
ss->sec.uncache = os->sec.uncache;
/* we don't dup the connection info. */
sec->sendSequence = osec->sendSequence;
sec->rcvSequence = osec->rcvSequence;
ss->sec.sendSequence = os->sec.sendSequence;
ss->sec.rcvSequence = os->sec.rcvSequence;
if (osec->hash && osec->hashcx) {
sec->hash = osec->hash;
sec->hashcx = osec->hash->clone(osec->hashcx);
if (os->sec.hash && os->sec.hashcx) {
ss->sec.hash = os->sec.hash;
ss->sec.hashcx = os->sec.hash->clone(os->sec.hashcx);
if (os->sec.hashcx && !ss->sec.hashcx)
goto loser;
} else {
sec->hash = NULL;
sec->hashcx = NULL;
ss->sec.hash = NULL;
ss->sec.hashcx = NULL;
}
SECITEM_CopyItem(0, &sec->sendSecret, &osec->sendSecret);
SECITEM_CopyItem(0, &sec->rcvSecret, &osec->rcvSecret);
SECITEM_CopyItem(0, &ss->sec.sendSecret, &os->sec.sendSecret);
if (os->sec.sendSecret.data && !ss->sec.sendSecret.data)
goto loser;
SECITEM_CopyItem(0, &ss->sec.rcvSecret, &os->sec.rcvSecret);
if (os->sec.rcvSecret.data && !ss->sec.rcvSecret.data)
goto loser;
PORT_Assert(osec->readcx == 0);
sec->readcx = osec->readcx; /* XXX wrong if readcx != 0 */
PORT_Assert(osec->writecx == 0);
sec->writecx = osec->writecx; /* XXX wrong if writecx != 0 */
sec->destroy = 0; /* XXX wrong if either cx != 0*/
/* XXX following code is wrong if either cx != 0 */
PORT_Assert(os->sec.readcx == 0);
PORT_Assert(os->sec.writecx == 0);
ss->sec.readcx = os->sec.readcx;
ss->sec.writecx = os->sec.writecx;
ss->sec.destroy = 0;
sec->enc = osec->enc;
sec->dec = osec->dec;
ss->sec.enc = os->sec.enc;
ss->sec.dec = os->sec.dec;
sec->blockShift = osec->blockShift;
sec->blockSize = osec->blockSize;
ss->sec.blockShift = os->sec.blockShift;
ss->sec.blockSize = os->sec.blockSize;
return SECSuccess;
@ -856,57 +785,69 @@ loser:
return SECFailure;
}
/* Reset sec back to its initial state.
** Caller holds any relevant locks.
*/
void
ssl_ResetSecurityInfo(sslSecurityInfo *sec)
{
/* Destroy MAC */
if (sec->hash && sec->hashcx) {
(*sec->hash->destroy)(sec->hashcx, PR_TRUE);
sec->hashcx = NULL;
sec->hash = NULL;
}
SECITEM_ZfreeItem(&sec->sendSecret, PR_FALSE);
SECITEM_ZfreeItem(&sec->rcvSecret, PR_FALSE);
/* Destroy ciphers */
if (sec->destroy) {
(*sec->destroy)(sec->readcx, PR_TRUE);
(*sec->destroy)(sec->writecx, PR_TRUE);
sec->readcx = NULL;
sec->writecx = NULL;
} else {
PORT_Assert(sec->readcx == 0);
PORT_Assert(sec->writecx == 0);
}
sec->readcx = 0;
sec->writecx = 0;
if (sec->localCert) {
CERT_DestroyCertificate(sec->localCert);
sec->localCert = NULL;
}
if (sec->peerCert) {
CERT_DestroyCertificate(sec->peerCert);
sec->peerCert = NULL;
}
if (sec->peerKey) {
SECKEY_DestroyPublicKey(sec->peerKey);
sec->peerKey = NULL;
}
/* cleanup the ci */
if (sec->ci.sid != NULL) {
ssl_FreeSID(sec->ci.sid);
}
PORT_ZFree(sec->ci.sendBuf.buf, sec->ci.sendBuf.space);
memset(&sec->ci, 0, sizeof sec->ci);
}
/*
** Called from SSL_ResetHandshake (above), and
** from ssl_FreeSocket in sslsock.c
** Caller should hold relevant locks (e.g. XmitBufLock)
*/
void
ssl_DestroySecurityInfo(sslSecurityInfo *sec)
{
if (sec != 0) {
/* Destroy MAC */
if (sec->hash && sec->hashcx) {
(*sec->hash->destroy)(sec->hashcx, PR_TRUE);
sec->hashcx = 0;
}
SECITEM_ZfreeItem(&sec->sendSecret, PR_FALSE);
SECITEM_ZfreeItem(&sec->rcvSecret, PR_FALSE);
ssl_ResetSecurityInfo(sec);
/* Destroy ciphers */
if (sec->destroy) {
(*sec->destroy)(sec->readcx, PR_TRUE);
(*sec->destroy)(sec->writecx, PR_TRUE);
} else {
PORT_Assert(sec->readcx == 0);
PORT_Assert(sec->writecx == 0);
}
sec->readcx = 0;
sec->writecx = 0;
PORT_ZFree(sec->writeBuf.buf, sec->writeBuf.space);
sec->writeBuf.buf = 0;
/* etc. */
PORT_ZFree(sec->writeBuf.buf, sec->writeBuf.space);
sec->writeBuf.buf = 0;
if (sec->localCert) {
CERT_DestroyCertificate(sec->localCert);
sec->localCert = NULL;
}
if (sec->peerCert) {
CERT_DestroyCertificate(sec->peerCert);
sec->peerCert = NULL;
}
if (sec->peerKey) {
SECKEY_DestroyPublicKey(sec->peerKey);
sec->peerKey = NULL;
}
PORT_ZFree(sec->ci.sendBuf.buf, sec->ci.sendBuf.space);
if (sec->ci.sid != NULL) {
ssl_FreeSID(sec->ci.sid);
}
PORT_ZFree(sec, sizeof *sec);
}
memset(sec, 0, sizeof *sec);
}
/************************************************************************/
@ -917,8 +858,6 @@ ssl_SecureConnect(sslSocket *ss, const PRNetAddr *sa)
PRFileDesc *osfd = ss->fd->lower;
int rv;
PORT_Assert(ss->sec != 0);
if ( ss->handshakeAsServer ) {
ss->securityHandshake = ssl2_BeginServerHandshake;
ss->handshaking = sslHandshakingAsServer;
@ -1007,8 +946,7 @@ ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
sslSecurityInfo *sec;
int rv = 0;
PORT_Assert(ss->sec != 0);
sec = ss->sec;
sec = &ss->sec;
if (ss->shutdownHow & ssl_SHUTDOWN_RCV) {
PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
@ -1063,12 +1001,8 @@ ssl_SecureRead(sslSocket *ss, unsigned char *buf, int len)
int
ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
{
sslSecurityInfo *sec;
int rv = 0;
PORT_Assert(ss->sec != 0);
sec = ss->sec;
if (ss->shutdownHow & ssl_SHUTDOWN_SEND) {
PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
return PR_FAILURE;
@ -1124,7 +1058,7 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
* ssl3_SendApplicationData
*/
ssl_GetXmitBufLock(ss);
rv = (*sec->send)(ss, buf, len, flags);
rv = (*ss->sec.send)(ss, buf, len, flags);
ssl_ReleaseXmitBufLock(ss);
ss->writerThread = NULL;
return rv;
@ -1149,9 +1083,6 @@ SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, void *arg)
return SECFailure;
}
if ((rv = ssl_CreateSecurityInfo(ss)) != 0) {
return rv;
}
ss->handleBadCert = f;
ss->badCertArg = arg;
@ -1208,13 +1139,9 @@ SSL_DataPending(PRFileDesc *fd)
ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss);
/* Create ss->sec if it doesn't already exist. */
rv = ssl_CreateSecurityInfo(ss);
if (rv == SECSuccess) {
ssl_GetRecvBufLock(ss);
rv = ss->gather->writeOffset - ss->gather->readOffset;
ssl_ReleaseRecvBufLock(ss);
}
ssl_GetRecvBufLock(ss);
rv = ss->gs.writeOffset - ss->gs.readOffset;
ssl_ReleaseRecvBufLock(ss);
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss);
@ -1233,8 +1160,8 @@ SSL_InvalidateSession(PRFileDesc *fd)
ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss);
if (ss->sec && ss->sec->ci.sid) {
ss->sec->uncache(ss->sec->ci.sid);
if (ss->sec.ci.sid) {
ss->sec.uncache(ss->sec.ci.sid);
rv = SECSuccess;
}
@ -1249,24 +1176,25 @@ SSL_GetSessionID(PRFileDesc *fd)
{
sslSocket * ss;
SECItem * item = NULL;
sslSessionID * sid;
ss = ssl_FindSocket(fd);
if (ss) {
ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss);
if (ss->useSecurity && ss->firstHsDone && ss->sec && ss->sec->ci.sid) {
sid = ss->sec->ci.sid;
if (ss->useSecurity && ss->firstHsDone && ss->sec.ci.sid) {
item = (SECItem *)PORT_Alloc(sizeof(SECItem));
if (sid->version < SSL_LIBRARY_VERSION_3_0) {
item->len = SSL2_SESSIONID_BYTES;
item->data = (unsigned char*)PORT_Alloc(item->len);
PORT_Memcpy(item->data, sid->u.ssl2.sessionID, item->len);
} else {
item->len = sid->u.ssl3.sessionIDLength;
item->data = (unsigned char*)PORT_Alloc(item->len);
PORT_Memcpy(item->data, sid->u.ssl3.sessionID, item->len);
if (item) {
sslSessionID * sid = ss->sec.ci.sid;
if (sid->version < SSL_LIBRARY_VERSION_3_0) {
item->len = SSL2_SESSIONID_BYTES;
item->data = (unsigned char*)PORT_Alloc(item->len);
PORT_Memcpy(item->data, sid->u.ssl2.sessionID, item->len);
} else {
item->len = sid->u.ssl3.sessionIDLength;
item->data = (unsigned char*)PORT_Alloc(item->len);
PORT_Memcpy(item->data, sid->u.ssl3.sessionID, item->len);
}
}
}

Просмотреть файл

@ -35,7 +35,7 @@
* may use your version of this file under either the MPL or the
* GPL.
*
* $Id: sslsock.c,v 1.25 2002-02-26 00:28:15 nelsonb%netscape.com Exp $
* $Id: sslsock.c,v 1.26 2002-02-27 04:40:17 nelsonb%netscape.com Exp $
*/
#include "seccomon.h"
#include "cert.h"
@ -305,19 +305,94 @@ loser:
return NULL;
}
/*
* free an sslSocket struct, and all the stuff that hangs off of it
*/
void
ssl_FreeSocket(sslSocket *ss)
static void
ssl_DestroyLocks(sslSocket *ss)
{
/* Destroy locks. */
if (ss->firstHandshakeLock) {
PZ_DestroyMonitor(ss->firstHandshakeLock);
ss->firstHandshakeLock = NULL;
}
if (ss->ssl3HandshakeLock) {
PZ_DestroyMonitor(ss->ssl3HandshakeLock);
ss->ssl3HandshakeLock = NULL;
}
if (ss->specLock) {
NSSRWLock_Destroy(ss->specLock);
ss->specLock = NULL;
}
if (ss->recvLock) {
PZ_DestroyLock(ss->recvLock);
ss->recvLock = NULL;
}
if (ss->sendLock) {
PZ_DestroyLock(ss->sendLock);
ss->sendLock = NULL;
}
if (ss->xmitBufLock) {
PZ_DestroyMonitor(ss->xmitBufLock);
ss->xmitBufLock = NULL;
}
if (ss->recvBufLock) {
PZ_DestroyMonitor(ss->recvBufLock);
ss->recvBufLock = NULL;
}
}
/* Caller holds any relevant locks */
static void
ssl_DestroySocketContents(sslSocket *ss)
{
/* "i" should be of type SSLKEAType, but CC on IRIX complains during
* the for loop.
*/
int i;
sslSocket *fs;
/* Free up socket */
ssl_DestroySecurityInfo(&ss->sec);
ssl3_DestroySSL3Info(ss->ssl3);
PORT_Free(ss->saveBuf.buf);
PORT_Free(ss->pendingBuf.buf);
ssl_DestroyGather(&ss->gs);
if (ss->peerID != NULL)
PORT_Free(ss->peerID);
if (ss->url != NULL)
PORT_Free((void *)ss->url); /* CONST */
if (ss->cipherSpecs) {
PORT_Free(ss->cipherSpecs);
ss->cipherSpecs = NULL;
ss->sizeCipherSpecs = 0;
}
/* Clean up server configuration */
for (i=kt_null; i < kt_kea_size; i++) {
sslServerCerts * sc = ss->serverCerts + i;
if (sc->serverCert != NULL)
CERT_DestroyCertificate(sc->serverCert);
if (sc->serverCertChain != NULL)
CERT_DestroyCertificateList(sc->serverCertChain);
if (sc->serverKey != NULL)
SECKEY_DestroyPrivateKey(sc->serverKey);
}
if (ss->stepDownKeyPair) {
ssl3_FreeKeyPair(ss->stepDownKeyPair);
ss->stepDownKeyPair = NULL;
}
}
/*
* free an sslSocket struct, and all the stuff that hangs off of it
*/
void
ssl_FreeSocket(sslSocket *ss)
{
#ifdef DEBUG
sslSocket *fs;
sslSocket lSock;
#endif
@ -337,37 +412,10 @@ ssl_FreeSocket(sslSocket *ss)
*fs = *ss; /* Copy the old socket structure, */
PORT_Memset(ss, 0x1f, sizeof *ss); /* then blast the old struct ASAP. */
#else
fs = ss;
#define fs ss
#endif
/* Free up socket */
ssl_DestroySecurityInfo(fs->sec);
ssl3_DestroySSL3Info(fs->ssl3);
PORT_Free(fs->saveBuf.buf);
PORT_Free(fs->pendingBuf.buf);
if (fs->gather) {
ssl_DestroyGather(fs->gather);
}
if (fs->peerID != NULL)
PORT_Free(fs->peerID);
if (fs->url != NULL)
PORT_Free((void *)fs->url); /* CONST */
/* Clean up server configuration */
for (i=kt_null; i < kt_kea_size; i++) {
sslServerCerts * sc = fs->serverCerts + i;
if (sc->serverCert != NULL)
CERT_DestroyCertificate(sc->serverCert);
if (sc->serverCertChain != NULL)
CERT_DestroyCertificateList(sc->serverCertChain);
if (sc->serverKey != NULL)
SECKEY_DestroyPrivateKey(sc->serverKey);
}
if (fs->stepDownKeyPair) {
ssl3_FreeKeyPair(fs->stepDownKeyPair);
fs->stepDownKeyPair = NULL;
}
ssl_DestroySocketContents(fs);
/* Release all the locks acquired above. */
SSL_UNLOCK_READER(fs);
@ -378,45 +426,12 @@ ssl_FreeSocket(sslSocket *ss)
ssl_ReleaseXmitBufLock(fs);
ssl_ReleaseSpecWriteLock(fs);
/* Destroy locks. */
if (fs->firstHandshakeLock) {
PZ_DestroyMonitor(fs->firstHandshakeLock);
fs->firstHandshakeLock = NULL;
}
if (fs->ssl3HandshakeLock) {
PZ_DestroyMonitor(fs->ssl3HandshakeLock);
fs->ssl3HandshakeLock = NULL;
}
if (fs->specLock) {
NSSRWLock_Destroy(fs->specLock);
fs->specLock = NULL;
}
if (fs->recvLock) {
PZ_DestroyLock(fs->recvLock);
fs->recvLock = NULL;
}
if (fs->sendLock) {
PZ_DestroyLock(fs->sendLock);
fs->sendLock = NULL;
}
if (fs->xmitBufLock) {
PZ_DestroyMonitor(fs->xmitBufLock);
fs->xmitBufLock = NULL;
}
if (fs->recvBufLock) {
PZ_DestroyMonitor(fs->recvBufLock);
fs->recvBufLock = NULL;
}
if (fs->cipherSpecs) {
PORT_Free(fs->cipherSpecs);
fs->cipherSpecs = NULL;
fs->sizeCipherSpecs = 0;
}
ssl_DestroyLocks(fs);
PORT_Free(ss); /* free the caller's copy, not ours. */
return;
}
#undef fs
/************************************************************************/
SECStatus
@ -446,13 +461,6 @@ PrepareSocket(sslSocket *ss)
{
SECStatus rv = SECSuccess;
if (ss->useSecurity) {
rv = ssl_CreateSecurityInfo(ss);
if (rv != SECSuccess) {
return rv;
}
}
ssl_ChooseOps(ss);
return rv;
}
@ -1272,15 +1280,11 @@ ssl_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
SECStatus
ssl_GetPeerInfo(sslSocket *ss)
{
sslConnectInfo * ci;
PRNetAddr sin;
int rv;
PRFileDesc * osfd;
PORT_Assert((ss->sec != 0));
int rv;
PRNetAddr sin;
osfd = ss->fd->lower;
ci = &ss->sec->ci;
PORT_Memset(&sin, 0, sizeof(sin));
rv = osfd->methods->getpeername(osfd, &sin);
@ -1289,11 +1293,11 @@ ssl_GetPeerInfo(sslSocket *ss)
}
ss->TCPconnected = 1;
if (sin.inet.family == PR_AF_INET) {
PR_ConvertIPv4AddrToIPv6(sin.inet.ip, &ci->peer);
ci->port = sin.inet.port;
PR_ConvertIPv4AddrToIPv6(sin.inet.ip, &ss->sec.ci.peer);
ss->sec.ci.port = sin.inet.port;
} else if (sin.ipv6.family == PR_AF_INET6) {
ci->peer = sin.ipv6.ip;
ci->port = sin.ipv6.port;
ss->sec.ci.peer = sin.ipv6.ip;
ss->sec.ci.port = sin.ipv6.port;
} else {
PORT_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR);
return SECFailure;
@ -1796,15 +1800,12 @@ static sslSocket *
ssl_NewSocket(void)
{
sslSocket *ss;
#ifdef DEBUG
static int firsttime = 1;
#endif
#ifdef DEBUG
#if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS)
static int firsttime = 1;
if (firsttime) {
firsttime = 0;
{
char *ev = getenv("SSLDEBUG");
if (ev && ev[0]) {
@ -1832,6 +1833,7 @@ ssl_NewSocket(void)
* complains during the for loop.
*/
int i;
SECStatus status;
ss->useSecurity = ssl_defaults.useSecurity;
ss->useSocks = PR_FALSE;
@ -1878,14 +1880,31 @@ ssl_NewSocket(void)
ssl3_InitSocketPolicy(ss);
ss->firstHandshakeLock = PZ_NewMonitor(nssILockSSL);
if (!ss->firstHandshakeLock) goto loser;
ss->ssl3HandshakeLock = PZ_NewMonitor(nssILockSSL);
if (!ss->ssl3HandshakeLock) goto loser;
ss->specLock = NSSRWLock_New(SSL_LOCK_RANK_SPEC, NULL);
if (!ss->specLock) goto loser;
ss->recvBufLock = PZ_NewMonitor(nssILockSSL);
if (!ss->recvBufLock) goto loser;
ss->xmitBufLock = PZ_NewMonitor(nssILockSSL);
if (!ss->xmitBufLock) goto loser;
ss->writerThread = NULL;
if (ssl_lock_readers) {
ss->recvLock = PZ_NewLock(nssILockSSL);
if (!ss->recvLock) goto loser;
ss->sendLock = PZ_NewLock(nssILockSSL);
if (!ss->sendLock) goto loser;
}
status = ssl_CreateSecurityInfo(ss);
if (status != SECSuccess) goto loser;
status = ssl_InitGather(&ss->gs);
if (status != SECSuccess) {
loser:
ssl_DestroySocketContents(ss);
ssl_DestroyLocks(ss);
PORT_Free(ss);
ss = NULL;
}
}
return ss;