sslsock.c

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

C
1,856
字号
    for (policy = ssl_ciphers; policy->cipher != 0; ++policy) {	status = SSL_SetPolicy(policy->cipher, policy->export);	if (status != SECSuccess)	    break;    }    return status;}SECStatusNSS_SetFrancePolicy(void){    SECStatus      status = SECSuccess;    cipherPolicy * policy;    for (policy = ssl_ciphers; policy->cipher != 0; ++policy) {	status = SSL_SetPolicy(policy->cipher, policy->france);	if (status != SECSuccess)	    break;    }    return status;}/* LOCKS ??? XXX */PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd){    sslSocket * ns = NULL;    PRStatus    rv;    if (model == NULL) {	/* Just create a default socket if we're given NULL for the model */	ns = ssl_NewSocket();    } else {	sslSocket * ss = ssl_FindSocket(model);	if (ss == NULL) {	    SSL_DBG(("%d: SSL[%d]: bad model socket in ssl_ImportFD", 	    	      SSL_GETPID(), model));	    SET_ERROR_CODE	    return NULL;	}	ns = ssl_DupSocket(ss);    }    if (ns == NULL)    	return NULL;    rv = ssl_PushIOLayer(ns, fd, PR_TOP_IO_LAYER);    if (rv != PR_SUCCESS) {	ssl_FreeSocket(ns);	SET_ERROR_CODE	return NULL;    }#ifdef _WIN32    PR_Sleep(PR_INTERVAL_NO_WAIT);     /* workaround NT winsock connect bug. */#endif    return fd;}/************************************************************************//* The following functions are the TOP LEVEL SSL functions.** They all get called through the NSPRIOMethods table below.*/static PRFileDesc * PR_CALLBACKssl_Accept(PRFileDesc *fd, PRNetAddr *sockaddr, PRIntervalTime timeout){    sslSocket  *ss;    sslSocket  *ns 	= NULL;    PRFileDesc *newfd 	= NULL;    PRFileDesc *osfd;    PRStatus    status;    ss = ssl_GetPrivate(fd);    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in accept", SSL_GETPID(), fd));	return NULL;    }    /* IF this is a listen socket, there shouldn't be any I/O going on */    SSL_LOCK_READER(ss);    SSL_LOCK_WRITER(ss);    ssl_Get1stHandshakeLock(ss);    ssl_GetSSL3HandshakeLock(ss);    ss->cTimeout = timeout;    osfd = ss->fd->lower;    /* First accept connection */    newfd = osfd->methods->accept(osfd, sockaddr, timeout);    if (newfd == NULL) {	SSL_DBG(("%d: SSL[%d]: accept failed, errno=%d",		 SSL_GETPID(), ss->fd, PORT_GetError()));    } else {	/* Create ssl module */	ns = ssl_DupSocket(ss);    }    ssl_ReleaseSSL3HandshakeLock(ss);    ssl_Release1stHandshakeLock(ss);    SSL_UNLOCK_WRITER(ss);    SSL_UNLOCK_READER(ss);			/* ss isn't used below here. */    if (ns == NULL)	goto loser;    /* push ssl module onto the new socket */    status = ssl_PushIOLayer(ns, newfd, PR_TOP_IO_LAYER);    if (status != PR_SUCCESS)	goto loser;    /* Now start server connection handshake with client.    ** Don't need locks here because nobody else has a reference to ns yet.    */    if ( ns->useSecurity ) {	if ( ns->handshakeAsClient ) {	    ns->handshake = ssl2_BeginClientHandshake;	} else {	    ns->handshake = ssl2_BeginServerHandshake;	}    }    return newfd;loser:    if (ns != NULL)	ssl_FreeSocket(ns);    if (newfd != NULL)	PR_Close(newfd);    return NULL;}static PRStatus PR_CALLBACKssl_Connect(PRFileDesc *fd, const PRNetAddr *sockaddr, PRIntervalTime timeout){    sslSocket *ss;    PRStatus   rv;    ss = ssl_GetPrivate(fd);    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in connect", SSL_GETPID(), fd));	return PR_FAILURE;    }    /* IF this is a listen socket, there shouldn't be any I/O going on */    SSL_LOCK_READER(ss);    SSL_LOCK_WRITER(ss);    ss->cTimeout = timeout;    rv = (PRStatus)(*ss->ops->connect)(ss, sockaddr);#ifdef _WIN32    PR_Sleep(PR_INTERVAL_NO_WAIT);     /* workaround NT winsock connect bug. */#endif    SSL_UNLOCK_WRITER(ss);    SSL_UNLOCK_READER(ss);    return rv;}static PRStatus PR_CALLBACKssl_Bind(PRFileDesc *fd, const PRNetAddr *addr){    sslSocket * ss = ssl_GetPrivate(fd);    PRStatus    rv;    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in bind", SSL_GETPID(), fd));	return PR_FAILURE;    }    SSL_LOCK_READER(ss);    SSL_LOCK_WRITER(ss);    rv = (PRStatus)(*ss->ops->bind)(ss, addr);    SSL_UNLOCK_WRITER(ss);    SSL_UNLOCK_READER(ss);    return rv;}static PRStatus PR_CALLBACKssl_Listen(PRFileDesc *fd, PRIntn backlog){    sslSocket * ss = ssl_GetPrivate(fd);    PRStatus    rv;    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in listen", SSL_GETPID(), fd));	return PR_FAILURE;    }    SSL_LOCK_READER(ss);    SSL_LOCK_WRITER(ss);    rv = (PRStatus)(*ss->ops->listen)(ss, backlog);    SSL_UNLOCK_WRITER(ss);    SSL_UNLOCK_READER(ss);    return rv;}static PRStatus PR_CALLBACKssl_Shutdown(PRFileDesc *fd, PRIntn how){    sslSocket * ss = ssl_GetPrivate(fd);    PRStatus    rv;    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in shutdown", SSL_GETPID(), fd));	return PR_FAILURE;    }    if (how == PR_SHUTDOWN_RCV || how == PR_SHUTDOWN_BOTH) {    	SSL_LOCK_READER(ss);    }    if (how == PR_SHUTDOWN_SEND || how == PR_SHUTDOWN_BOTH) {    	SSL_LOCK_WRITER(ss);    }    rv = (PRStatus)(*ss->ops->shutdown)(ss, how);    if (how == PR_SHUTDOWN_SEND || how == PR_SHUTDOWN_BOTH) {    	SSL_UNLOCK_WRITER(ss);    }    if (how == PR_SHUTDOWN_RCV || how == PR_SHUTDOWN_BOTH) {    	SSL_UNLOCK_READER(ss);    }    return rv;}static PRStatus PR_CALLBACKssl_Close(PRFileDesc *fd){    sslSocket *ss;    PRStatus   rv;    ss = ssl_GetPrivate(fd);    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in close", SSL_GETPID(), fd));	return PR_FAILURE;    }    /* There must not be any I/O going on */    SSL_LOCK_READER(ss);    SSL_LOCK_WRITER(ss);    /* By the time this function returns,     ** ss is an invalid pointer, and the locks to which it points have     ** been unlocked and freed.  So, this is the ONE PLACE in all of SSL    ** where the LOCK calls and the corresponding UNLOCK calls are not in    ** the same function scope.  The unlock calls are in ssl_FreeSocket().    */    rv = (PRStatus)(*ss->ops->close)(ss);    return rv;}static int PR_CALLBACKssl_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,	 PRIntervalTime timeout){    sslSocket *ss;    int        rv;    ss = ssl_GetPrivate(fd);    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in recv", SSL_GETPID(), fd));	return SECFailure;    }    SSL_LOCK_READER(ss);    ss->rTimeout = timeout;    rv = (*ss->ops->recv)(ss, (unsigned char*)buf, len, flags);    SSL_UNLOCK_READER(ss);    return rv;}static int PR_CALLBACKssl_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,	 PRIntervalTime timeout){    sslSocket *ss;    int        rv;    ss = ssl_GetPrivate(fd);    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in send", SSL_GETPID(), fd));	return SECFailure;    }    SSL_LOCK_WRITER(ss);    ss->wTimeout = timeout;    rv = (*ss->ops->send)(ss, (const unsigned char*)buf, len, flags);    SSL_UNLOCK_WRITER(ss);    return rv;}static int PR_CALLBACKssl_Read(PRFileDesc *fd, void *buf, PRInt32 len){    sslSocket *ss;    int        rv;    ss = ssl_GetPrivate(fd);    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in read", SSL_GETPID(), fd));	return SECFailure;    }    SSL_LOCK_READER(ss);    ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;    rv = (*ss->ops->read)(ss, (unsigned char*)buf, len);    SSL_UNLOCK_READER(ss);    return rv;}static int PR_CALLBACKssl_Write(PRFileDesc *fd, const void *buf, PRInt32 len){    sslSocket *ss;    int        rv;    ss = ssl_GetPrivate(fd);    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in write", SSL_GETPID(), fd));	return SECFailure;    }    SSL_LOCK_WRITER(ss);    ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;    rv = (*ss->ops->write)(ss, (const unsigned char*)buf, len);    SSL_UNLOCK_WRITER(ss);    return rv;}static PRStatus PR_CALLBACKssl_GetPeerName(PRFileDesc *fd, PRNetAddr *addr){    sslSocket *ss;    ss = ssl_GetPrivate(fd);    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in getpeername", SSL_GETPID(), fd));	return PR_FAILURE;    }    return (PRStatus)(*ss->ops->getpeername)(ss, addr);}/*** XXX this code doesn't work properly inside a Socks server.*/SECStatusssl_GetPeerInfo(sslSocket *ss){    sslConnectInfo *  ci;    PRNetAddr         sin;    int               rv;    PRFileDesc *      osfd;    PORT_Assert((ss->sec != 0));    osfd = ss->fd->lower;    ci   = &ss->sec->ci;    /* If ssl_SocksConnect() has previously recorded the peer's IP & port,     * use that.     */    if ((ss->port != 0) &&	((ss->peer.pr_s6_addr32[0] != 0) || (ss->peer.pr_s6_addr32[1] != 0) ||	 (ss->peer.pr_s6_addr32[2] != 0) || (ss->peer.pr_s6_addr32[3] != 0))) {	/* SOCKS code has already recorded the peer's IP addr and port.	 * (NOT the proxy's addr and port) in ss->peer & port.	 */	ci->peer = ss->peer;	ci->port = ss->port;	return SECSuccess;    }    PORT_Memset(&sin, 0, sizeof(sin));    rv = osfd->methods->getpeername(osfd, &sin);    if (rv < 0) {	return SECFailure;    }    /* we have to mask off the high byte because AIX is lame */    if ((sin.inet.family & 0xff) == PR_AF_INET) {        PR_ConvertIPv4AddrToIPv6(sin.inet.ip, &ci->peer);	ci->port = sin.inet.port;    } else {        PORT_Assert(sin.ipv6.family == PR_AF_INET6);	ci->peer = sin.ipv6.ip;	ci->port = sin.ipv6.port;    }    return SECSuccess;}static PRStatus PR_CALLBACKssl_GetSockName(PRFileDesc *fd, PRNetAddr *name){    sslSocket *ss;    ss = ssl_GetPrivate(fd);    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in getsockname", SSL_GETPID(), fd));	return PR_FAILURE;    }    return (PRStatus)(*ss->ops->getsockname)(ss, name);}int PR_CALLBACKSSL_SetSockPeerID(PRFileDesc *fd, char *peerID){    sslSocket *ss;    ss = ssl_GetPrivate(fd);    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetCacheIndex",		 SSL_GETPID(), fd));	return SECFailure;    }    ss->peerID = PORT_Strdup(peerID);    return 0;}static PRInt16 PR_CALLBACKssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *out_flags){    sslSocket *ss;    PRInt16    ret_flags = how_flags;	/* should select on these flags. */    *out_flags = 0;    ss = ssl_GetPrivate(fd);    if (!ss) {	SSL_DBG(("%d: SSL[%d]: bad socket in SSL_Poll",		 SSL_GETPID(), fd));	return 0;	/* don't poll on this socket */    }    if ((ret_flags & PR_POLL_WRITE) &&         ( (ss->useSocks && ss->handshake) || 	  (ss->useSecurity && !ss->connected && 	   /* XXX There needs to be a better test than the following. */	   /* Don't check ss->securityHandshake. */	   (ss->handshake || ss->nextHandshake)))) {    	/* The user is trying to write, but the handshake is blocked waiting	 * to read, so tell NSPR NOT to poll on write.	 */	ret_flags ^=  PR_POLL_WRITE;	/* don't select on write. */	ret_flags |=  PR_POLL_READ;	/* do    select on read. */    }    if ((ret_flags & PR_POLL_READ) && (SSL_DataPending(fd) > 0)) {	*out_flags = PR_POLL_READ;	/* it's ready already. */    } else if (ret_flags && (fd->lower->methods->poll != NULL)) {        ret_flags = fd->lower->methods->poll(fd->lower, ret_flags, out_flags);    }    return ret_flags;}PRBoolssl_FdIsBlocking(PRFileDesc *fd){    PRSocketOptionData opt;    PRStatus           status;    opt.option             = PR_SockOpt_Nonblocking;

⌨️ 快捷键说明

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