sslsock.c

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

C
1,856
字号
    opt.value.non_blocking = PR_FALSE;    status = PR_GetSocketOption(fd, &opt);    if (status != PR_SUCCESS)	return PR_FALSE;    return (PRBool)!opt.value.non_blocking;}PRBoolssl_SocketIsBlocking(sslSocket *ss){    return ssl_FdIsBlocking(ss->fd);}PRInt32  sslFirstBufSize = 8 * 1024;PRInt32  sslCopyLimit    = 1024;static PRInt32 PR_CALLBACKssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors,            PRIntervalTime timeout){    PRInt32            bufLen;    PRInt32            left;    PRInt32            rv;    PRInt32            sent      =  0;    const PRInt32      first_len = sslFirstBufSize;    const PRInt32      limit     = sslCopyLimit;    PRBool             blocking;    PRIOVec            myIov	 = { 0, 0 };    char               buf[MAX_FRAGMENT_LENGTH];    if (vectors > PR_MAX_IOVECTOR_SIZE) {    	PORT_SetError(PR_BUFFER_OVERFLOW_ERROR);	return -1;    }    blocking = ssl_FdIsBlocking(fd);#define K16 sizeof(buf)#define KILL_VECTORS while (vectors && !iov->iov_len) { ++iov; --vectors; }#define GET_VECTOR   do { myIov = *iov++; --vectors; KILL_VECTORS } while (0)#define HANDLE_ERR(rv, len) \    if (rv != len) { \	if (rv < 0) { \	    if (blocking \		&& (PR_GetError() == PR_WOULD_BLOCK_ERROR) \		&& (sent > 0)) { \		return sent; \	    } else { \		return -1; \	    } \	} \	/* Only a nonblocking socket can have partial sends */ \	PR_ASSERT(blocking); \	return sent; \    } #define SEND(bfr, len) \    do { \	rv = ssl_Send(fd, bfr, len, 0, timeout); \	HANDLE_ERR(rv, len) \	sent += len; \    } while (0)    /* Make sure the first write is at least 8 KB, if possible. */    KILL_VECTORS    if (!vectors)	return 0;    GET_VECTOR;    if (!vectors) {	return ssl_Send(fd, myIov.iov_base, myIov.iov_len, 0, timeout);    }    if (myIov.iov_len < first_len) {	PORT_Memcpy(buf, myIov.iov_base, myIov.iov_len);	bufLen = myIov.iov_len;	left = first_len - bufLen;	while (vectors && left) {	    int toCopy;	    GET_VECTOR;	    toCopy = PR_MIN(left, myIov.iov_len);	    PORT_Memcpy(buf + bufLen, myIov.iov_base, toCopy);	    bufLen         += toCopy;	    left           -= toCopy;	    myIov.iov_base += toCopy;	    myIov.iov_len  -= toCopy;	}	SEND( buf, bufLen );    }    while (vectors || myIov.iov_len) {	PRInt32   addLen;	if (!myIov.iov_len) {	    GET_VECTOR;	}	while (myIov.iov_len >= K16) {	    SEND(myIov.iov_base, K16);	    myIov.iov_base += K16;	    myIov.iov_len  -= K16;	}	if (!myIov.iov_len)	    continue;	if (!vectors || myIov.iov_len > limit) {	    addLen = 0;	} else if ((addLen = iov->iov_len % K16) + myIov.iov_len <= limit) {	    /* Addlen is already computed. */;	} else if (vectors > 1 && 	     iov[1].iov_len % K16 + addLen + myIov.iov_len <= 2 * limit) {	     addLen = limit - myIov.iov_len;	} else 	    addLen = 0;	if (!addLen) {	    SEND( myIov.iov_base, myIov.iov_len );	    myIov.iov_len = 0;	    continue;	}	PORT_Memcpy(buf, myIov.iov_base, myIov.iov_len);	bufLen = myIov.iov_len;	do {	    GET_VECTOR;	    PORT_Memcpy(buf + bufLen, myIov.iov_base, addLen);	    myIov.iov_base += addLen;	    myIov.iov_len  -= addLen;	    bufLen         += addLen;	    left = PR_MIN( limit, K16 - bufLen);	    if (!vectors 		/* no more left */	    ||  myIov.iov_len > 0	/* we didn't use that one all up */	    ||  bufLen >= K16		/* it's full. */	    ) {		addLen = 0;	    } else if ((addLen = iov->iov_len % K16) <= left) {		/* Addlen is already computed. */;	    } else if (vectors > 1 && 		 iov[1].iov_len % K16 + addLen <= left + limit) {		 addLen = left;	    } else 		addLen = 0;	} while (addLen);	SEND( buf, bufLen );    }     return sent;}/* * These functions aren't implemented. */static PRInt32 PR_CALLBACKssl_Available(PRFileDesc *fd){    PORT_Assert(0);    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);    return SECFailure;}static PRInt64 PR_CALLBACKssl_Available64(PRFileDesc *fd){    PRInt64 res;    PORT_Assert(0);    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);    LL_I2L(res, -1L);    return res;}static PRStatus PR_CALLBACKssl_FSync(PRFileDesc *fd){    PORT_Assert(0);    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);    return PR_FAILURE;}static PRInt32 PR_CALLBACKssl_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence how) {    PORT_Assert(0);    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);    return SECFailure;}static PRInt64 PR_CALLBACKssl_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence how) {    PRInt64 res;    PORT_Assert(0);    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);    LL_I2L(res, -1L);    return res;}static PRStatus PR_CALLBACKssl_FileInfo(PRFileDesc *fd, PRFileInfo *info){    PORT_Assert(0);    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);    return PR_FAILURE;}static PRStatus PR_CALLBACKssl_FileInfo64(PRFileDesc *fd, PRFileInfo64 *info){    PORT_Assert(0);    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);    return PR_FAILURE;}static PRInt32 PR_CALLBACKssl_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,	     PRNetAddr *addr, PRIntervalTime timeout){    PORT_Assert(0);    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);    return SECFailure;}static PRInt32 PR_CALLBACKssl_SendTo(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,	   const PRNetAddr *addr, PRIntervalTime timeout){    PORT_Assert(0);    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);    return SECFailure;}static const PRIOMethods ssl_methods = {    PR_DESC_LAYERED,    ssl_Close,           	/* close        */    ssl_Read,            	/* read         */    ssl_Write,           	/* write        */    ssl_Available,       	/* available    */    ssl_Available64,     	/* available64  */    ssl_FSync,           	/* fsync        */    ssl_Seek,            	/* seek         */    ssl_Seek64,          	/* seek64       */    ssl_FileInfo,        	/* fileInfo     */    ssl_FileInfo64,      	/* fileInfo64   */    ssl_WriteV,          	/* writev       */    ssl_Connect,         	/* connect      */    ssl_Accept,          	/* accept       */    ssl_Bind,            	/* bind         */    ssl_Listen,          	/* listen       */    ssl_Shutdown,        	/* shutdown     */    ssl_Recv,            	/* recv         */    ssl_Send,            	/* send         */    ssl_RecvFrom,        	/* recvfrom     */    ssl_SendTo,          	/* sendto       */    ssl_Poll,            	/* poll         */    ssl_EmulateAcceptRead,      /* acceptread   */    ssl_EmulateTransmitFile,    /* transmitfile */    ssl_GetSockName,     	/* getsockname  */    ssl_GetPeerName,     	/* getpeername  */    NULL,                	/* getsockopt   OBSOLETE */    NULL,                	/* setsockopt   OBSOLETE */    NULL,                	/* getsocketoption   */    NULL,                	/* setsocketoption   */    ssl_EmulateSendFile, 	/* Send a (partial) file with header/trailer*/    NULL,                	/* reserved for future use */    NULL,                	/* reserved for future use */    NULL,                	/* reserved for future use */    NULL,                	/* reserved for future use */    NULL                 	/* reserved for future use */};static PRIOMethods combined_methods;static voidssl_SetupIOMethods(void){          PRIOMethods *new_methods  = &combined_methods;    const PRIOMethods *nspr_methods = PR_GetDefaultIOMethods();    const PRIOMethods *my_methods   = &ssl_methods;    *new_methods = *nspr_methods;    new_methods->file_type         = my_methods->file_type;    new_methods->close             = my_methods->close;    new_methods->read              = my_methods->read;    new_methods->write             = my_methods->write;    new_methods->available         = my_methods->available;    new_methods->available64       = my_methods->available64;    new_methods->fsync             = my_methods->fsync;    new_methods->seek              = my_methods->seek;    new_methods->seek64            = my_methods->seek64;    new_methods->fileInfo          = my_methods->fileInfo;    new_methods->fileInfo64        = my_methods->fileInfo64;    new_methods->writev            = my_methods->writev;    new_methods->connect           = my_methods->connect;    new_methods->accept            = my_methods->accept;    new_methods->bind              = my_methods->bind;    new_methods->listen            = my_methods->listen;    new_methods->shutdown          = my_methods->shutdown;    new_methods->recv              = my_methods->recv;    new_methods->send              = my_methods->send;    new_methods->recvfrom          = my_methods->recvfrom;    new_methods->sendto            = my_methods->sendto;    new_methods->poll              = my_methods->poll;    new_methods->acceptread        = my_methods->acceptread;    new_methods->transmitfile      = my_methods->transmitfile;    new_methods->getsockname       = my_methods->getsockname;    new_methods->getpeername       = my_methods->getpeername;/*  new_methods->getsocketoption   = my_methods->getsocketoption;	*//*  new_methods->setsocketoption   = my_methods->setsocketoption;	*/    new_methods->sendfile          = my_methods->sendfile;}static PRCallOnceType initIoLayerOnce;static PRStatus  ssl_InitIOLayer(void){    ssl_layer_id = PR_GetUniqueIdentity("SSL");    ssl_SetupIOMethods();    ssl_inited = PR_TRUE;    return PR_SUCCESS;}static PRStatusssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack, PRDescIdentity id){    PRFileDesc *layer	= NULL;    PRStatus    status;    if (!ssl_inited) {	PR_CallOnce(&initIoLayerOnce, &ssl_InitIOLayer);    }    if (ns == NULL)	goto loser;    layer = PR_CreateIOLayerStub(ssl_layer_id, &combined_methods);    if (layer == NULL)	goto loser;    layer->secret = (PRFilePrivate *)ns;    /* Here, "stack" points to the PRFileDesc on the top of the stack.    ** "layer" points to a new FD that is to be inserted into the stack.    ** If layer is being pushed onto the top of the stack, then     ** PR_PushIOLayer switches the contents of stack and layer, and then    ** puts stack on top of layer, so that after it is done, the top of     ** stack is the same "stack" as it was before, and layer is now the     ** FD for the former top of stack.    ** After this call, stack always points to the top PRFD on the stack.    ** If this function fails, the contents of stack and layer are as     ** they were before the call.    */    status = PR_PushIOLayer(stack, id, layer);    if (status != PR_SUCCESS)	goto loser;    ns->fd = (id == PR_TOP_IO_LAYER) ? stack : layer;    return PR_SUCCESS;loser:    if (layer) {	layer->dtor(layer); /* free layer */    }    return PR_FAILURE;}/*** Create a newsocket structure for a file descriptor.*/static sslSocket *ssl_NewSocket(void){    sslSocket *ss;#ifdef DEBUG    static int firsttime = 1;#endif#ifdef DEBUG#if defined(XP_UNIX) || defined(XP_WIN32)    if (firsttime) {	firsttime = 0;	{	    char *ev = getenv("SSLDEBUG");	    if (ev && ev[0]) {		ssl_debug = atoi(ev);		SSL_TRACE(("SSL: debugging set to %d", ssl_debug));	    }	}#ifdef TRACE	{	    char *ev = getenv("SSLTRACE");	    if (ev && ev[0]) {		ssl_trace = atoi(ev);		SSL_TRACE(("SSL: tracing set to %d", ssl_trace));	    }	}#endif /* TRACE */    }#endif /* XP_UNIX || XP_WIN32 */#endif /* DEBUG */    /* Make a new socket and get it ready */    ss = (sslSocket*) PORT_ZAlloc(sizeof(sslSocket));    if (ss) {        /* This should be of type SSLKEAType, but CC on IRIX	 * complains during the for loop.	 */	int i; 	ss->useSecurity        = ssl_defaults.useSecurity;	ss->useSocks           = ssl_defaults.useSocks;	ss->requestCertificate = ssl_defaults.requestCertificate;	ss->requireCertificate = ssl_defaults.requireCertificate;	ss->handshakeAsClient  = ssl_defaults.handshakeAsClient;	ss->handshakeAsServer  = ssl_defaults.handshakeAsServer;	ss->enableSSL2         = ssl_defaults.enableSSL2;	ss->enableSSL3         = ssl_defaults.enableSSL3;	ss->enableTLS          = ssl_defaults.enableTLS ;	ss->fdx                = ssl_defaults.fdx;	ss->v2CompatibleHello  = ssl_defaults.v2CompatibleHello;	ss->detectRollBack     = ssl_defaults.detectRollBack;	memset(&ss->peer, 0, sizeof(ss->peer));	ss->port               = 0;	ss->noCache            = ssl_defaults.noCache;	ss->peerID             = NULL;	ss->rTimeout	       = PR_INTERVAL_NO_TIMEOUT;	ss->wTimeout	       = PR_INTERVAL_NO_TIMEOUT;	ss->cTimeout	       = PR_INTERVAL_NO_TIMEOUT;	ss->cipherSpecs        = NULL;        ss->sizeCipherSpecs    = 0;  /* produced lazily */        ss->preferredCipher    = NULL;        ss->url                = NULL;	for (i=kt_null; i < kt_kea_size; i++) {	    ss->serverCert[i]      = NULL;	    ss->serverCertChain[i] = NULL;	    ss->serverKey[i]       = NULL;	}	ss->stepDownKeyPair    = NULL;	ss->dbHandle           = CERT_GetDefaultCertDB();	/* Provide default implementation of hooks */	ss->authCertificate    = SSL_AuthCertificate;	ss->authCertificateArg = (void *)ss->dbHandle;	ss->getClientAuthData  = NULL;	ss->handleBadCert      = NULL;	ss->badCertArg         = NULL;	ss->pkcs11PinArg       = NULL;	ssl_ChooseOps(ss);	ssl2_InitSocketPolicy(ss);	ssl3_InitSocketPolicy(ss);	ss->firstHandshakeLock = PR_NewMonitor();	ss->ssl3HandshakeLock  = PR_NewMonitor();	ss->specLock           = NSSRWLock_New(SSL_LOCK_RANK_SPEC, NULL);	ss->recvBufLock        = PR_NewMonitor();	ss->xmitBufLock        = PR_NewMonitor();	if (ssl_lock_readers) {	    ss->recvLock       = PR_NewLock();	    ss->sendLock       = PR_NewLock();	}    }    return ss;}

⌨️ 快捷键说明

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