⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sslconn.c

📁 安全开发库。含客户端建立ssl连接、签名、证书验证、证书发布和撤销等。编译用到nss
💻 C
📖 第 1 页 / 共 5 页
字号:
    /*PR_Notify(conn->sslLock);      PR_ExitMonitor(conn->sslLock);*/    SSM_DEBUG("returning OK.\n");    return prstatus;loser:    (void)SSMSSLDataConnection_UpdateErrorCode(conn);    SSM_LockResource(SSMRESOURCE(conn));    SSM_DEBUG("error %d (%s), exiting abnormally.\n", conn->m_error,               SSL_Strerror(conn->m_error));    SSM_UnlockResource(SSMRESOURCE(conn));    return PR_FAILURE;}PRStatus SSMSSLDataConnection_TLSStepUp(SSMSSLDataConnection* conn){    PRFileDesc* socket = conn->socketSSL;    PRFileDesc* sslsocket = NULL;    PR_ASSERT(conn->isTLS == PR_TRUE);    if (conn->isSecure == PR_TRUE) {        /* socket is already secure */        return PR_SUCCESS;    }    SSM_DEBUG("Setting up secure socket for this TLS connection.\n");    if (SSM_SetupSSLSocket(socket, &sslsocket,                           SSMCONTROLCONNECTION(conn)->m_certdb,                           conn->hostName, (void*)conn) !=        SECSuccess) {        goto loser;    }    SSM_DEBUG("Resetting handshake.\n");    if (SSL_ResetHandshake(sslsocket, PR_FALSE) != SECSuccess) {        goto loser;    }    /* XXX it is important that the SSL handshake does not take place here     *     because that would create a deadlock on this thread     */    SSM_DEBUG("We now have a secure socket.\n");    /* secure socket is established */    conn->socketSSL = sslsocket;    conn->isSecure = PR_TRUE;    return PR_SUCCESS;loser:    (void)SSMSSLDataConnection_UpdateErrorCode(conn);    if (sslsocket == NULL) {        if (socket != NULL) {            PR_Close(socket);        }    }    else {        PR_Close(sslsocket);    }    return PR_FAILURE;}/* thread function *//* SSL connection is serviced by the data service thread that works on * the client data socket and the SSL socket. *  * Our poll descriptor array contains the client data socket and the SSL  * target socket in this order. */#define SSL_PDS 3#define READSSL_CHUNKSIZE 16384void SSM_SSLDataServiceThread(void* arg){    SSMStatus rv = PR_SUCCESS;    SSMSSLDataConnection* conn = NULL;    PRPollDesc pds[SSL_PDS];    PRIntn nSockets = 0;    PRInt32 nReady;    int i;    PRIntn read = 0;    PRIntn sent = 0;    char **outbound = NULL;    char **inbound = NULL;    PRIntn oBufSize;        SSM_RegisterNewThread("ssl data", (SSMResource *) arg);    conn = (SSMSSLDataConnection*)arg;    SSM_DEBUG("initializing.\n");    if (arg == NULL) {        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);        goto loser;    }    SSMDATACONNECTION(conn)->m_dataServiceThread = PR_GetCurrentThread();	/* initialize xfer buffers */	outbound = (char **) PR_CALLOC(READSSL_CHUNKSIZE+1);	if (outbound == NULL)		goto loser;	inbound = (char **) PR_CALLOC(READSSL_CHUNKSIZE+1);	if (inbound == NULL)		goto loser;    /* initialize the poll descriptors */    for (i = 0; i < SSL_PDS; i++) {        pds[i].fd = NULL;    }    /* set up sockets */    /* set up the client data socket */    rv = SSMDataConnection_SetupClientSocket(SSMDATACONNECTION(conn));    if (rv != PR_SUCCESS) {        goto loser;    }    /* save the client data socket in the array */    pds[0].fd = SSMDATACONNECTION(conn)->m_clientSocket;    pds[0].in_flags = PR_POLL_READ;    nSockets++;    /* set up the SSL socket */    rv = SSM_GetSSLSocket(conn);    if (rv != PR_SUCCESS) {        goto loser;    }    /* save the SSL socket in the array */    pds[1].fd = conn->socketSSL;    pds[1].in_flags = PR_POLL_READ;    nSockets++;    if (conn->isTLS == PR_TRUE) {        /* have large outbound buffer size because this is (most likely)         * an SSL/SMTP connection         */        oBufSize = READSSL_CHUNKSIZE;        /* Add step-up FD to the list of FDs until we've been asked to           encrypt */        pds[2].fd = conn->stepUpFD;        pds[2].in_flags = PR_POLL_READ;        nSockets++;    }    else {        oBufSize = LINESIZE;    }    /* spinning mode.  Exchange data between the client socket and the SSL     * socket.     */    while ((nSockets > 0) &&            (SSM_Count(SSMDATACONNECTION(conn)->m_shutdownQ) == 0)) {        /* XXX The old client does not handle active close from the         *     server properly in case of keep-alive connections: what         *     happens is that although we perform a shutdown on the client         *     socket, the client never sends us a close.  If the SSL socket          *     is removed, we might as well close the client socket by hand.         */        /* if the outbound connection is shut down and there is no data         * pending in the client socket, perhaps the client is acting up         */        if (pds[1].fd == NULL) {            /* don't block in polling */            nReady = PR_Poll(pds, SSL_PDS, PR_INTERVAL_NO_WAIT);            if (nReady <= 0) {                /* either error or the client socket is blocked.  Bail. */                rv = SSMSSLDataConnection_UpdateErrorCode(conn);                if (SSMDATACONNECTION(conn)->m_clientSocket != NULL) {                    PR_Shutdown(SSMDATACONNECTION(conn)->m_clientSocket,                                PR_SHUTDOWN_SEND);                }                nSockets--;                if (nSockets > 1)                    {                        /*                            We were waiting for notification to step up,                           but that notification won't happen. So,                           remove stepUpFD from the list as well.                        */                        pds[2].fd = NULL;                        nSockets = 1;                    }                break;    /* go to loser; */            }        }        SSM_DEBUG("Polling sockets for pending data.\n");        /* poll sockets for pending data */#if 0        if (conn->isTLS == PR_TRUE) {            /* we require the lock for this operation and do a non-blocking             * poll in case of TLS because we want to yield to the step-up              * operation             */            SSM_LockResource(SSMRESOURCE(conn));            nReady = PR_Poll(pds, SSL_PDS, PR_INTERVAL_NO_WAIT);            SSM_UnlockResource(SSMRESOURCE(conn));            if (nReady == 0) {                continue;            }        }        else {#endif            /* Poll for however many sockets we're interested in. */            nReady = PR_Poll(pds, nSockets, PR_INTERVAL_NO_TIMEOUT);#if 0        }#endif        if (nReady < 0) {            rv = SSMSSLDataConnection_UpdateErrorCode(conn);            goto loser;        }        /* Wind down from SSL_PDS because the pollable event           takes priority over the I/O sockets. */        for (i = (SSL_PDS-1); i >= 0; i--) {            if (pds[i].fd == NULL) {                continue;            }            /* check sockets for data */            if (pds[i].out_flags & (PR_POLL_READ | PR_POLL_EXCEPT)) {                if (pds[i].fd == SSMDATACONNECTION(conn)->m_clientSocket) {                    /* got data at the client socket */                    SSM_DEBUG("Attempting to read %ld bytes from client "                              "socket.\n", oBufSize);                    read = PR_Recv(SSMDATACONNECTION(conn)->m_clientSocket,                                   outbound, oBufSize, 0,                                   PR_INTERVAL_NO_TIMEOUT);                                        if (read <= 0) {                        if (read < 0) {                            /* Got an error */                            rv = SSMSSLDataConnection_UpdateErrorCode(conn);                            SSM_DEBUG("Error receiving data over client "                                      "socket, status == %ld\n", (long)rv);                        }                        else {                            /* We got an EOF */                            SSM_DEBUG("Got EOF at client socket.\n");                            rv = PR_SUCCESS;                        }                        if (conn->socketSSL != NULL) {                            SSM_DEBUG("Shutting down the target socket.\n");                            PR_Shutdown(conn->socketSSL, PR_SHUTDOWN_SEND);                        }                        /* remove the socket from the array */                        pds[i].fd = NULL;                        nSockets--;                    }                    else {                        SSM_DEBUG("data: <%s>\n" "Send the data to the "                                  "target.\n", outbound);                        sent = PR_Send(conn->socketSSL, outbound, read, 0,                                       PR_INTERVAL_NO_TIMEOUT);                        if (sent != read) {                            rv = SSMSSLDataConnection_UpdateErrorCode(conn);                                                        if (SSMDATACONNECTION(conn)->m_clientSocket != 				NULL) {                                SSM_DEBUG("Shutting down the client socket.\n");                                PR_Shutdown(SSMDATACONNECTION(conn)->m_clientSocket, 					    PR_SHUTDOWN_SEND);                            }                            /* remove the socket from the array */                            pds[i].fd = NULL;                            nSockets--;                        }                    }                }                else if (pds[i].fd == conn->socketSSL) {                    /* got data at the SSL socket */                    SSM_DEBUG("Reading data from target socket.\n");                    read = PR_Recv(conn->socketSSL, inbound, READSSL_CHUNKSIZE,                                   0, PR_INTERVAL_NO_TIMEOUT);                    if (read <= 0) {                        if (read < 0) {                            /* Got error */                            rv = SSMSSLDataConnection_UpdateErrorCode(conn);                            SSM_DEBUG("Error receiving data from target "                                      "socket, status = %ld\n", rv);                        }                        else {                            /* We got an EOF */                            SSM_DEBUG("Got EOF at target socket.\n");                            rv = PR_SUCCESS;                        }                        if (SSMDATACONNECTION(conn)->m_clientSocket != NULL) {			    SSM_DEBUG("Shutting down the client socket.\n");                            PR_Shutdown(SSMDATACONNECTION(conn)->m_clientSocket,                                         PR_SHUTDOWN_SEND);                        }                        /* remove the socket from the array */                        pds[i].fd = NULL;                        nSockets--;                    }                    else {                        /* Got data, write it to the client socket */                        SSM_DEBUG("Writing to client socket.\n");                        sent = PR_Send(SSMDATACONNECTION(conn)->m_clientSocket,                                       inbound, read, 0,                                        PR_INTERVAL_NO_TIMEOUT);                        if (sent != read) {                            rv = SSMSSLDataConnection_UpdateErrorCode(conn);                            if (conn->socketSSL != NULL) {			        SSM_DEBUG("Shutting down the target socket.\n");                                PR_Shutdown(conn->socketSSL, PR_SHUTDOWN_SEND);                            }                            /* remove the socket from the array */                            pds[i].fd = NULL;                            nSockets--;                        }                        SSM_DEBUG("Wrote %ld bytes.\n", sent);                    }                }                else if (pds[i].fd == conn->stepUpFD)                {                    /* We've been told to enable TLS on this connection.                       Clear the event, step up, and reconfigure sockets. */                    PRFileDesc *stepUpFD = conn->stepUpFD;                    /* Make sure the control connection has settled */                    SSM_LockResource(SSMRESOURCE(conn));                    if ((pds[i].out_flags & PR_POLL_READ) != 0)                        /* it's readable, so it should return immediately */                        PR_WaitForPollableEvent(stepUpFD);                    /* Step up to encryption. */                    rv = SSMSSLDataConnection_TLSStepUp(conn);                    conn->m_error = rv; /* tell the control connection */                    /* Remove the step-up fd */                    conn->stepUpFD = NULL;                    pds[i].fd = NULL;                    nSockets--;                    PR_DestroyPollableEvent(stepUpFD);                    /* Notify ourselves to wake up the control connection */                    SSM_NotifyResource(SSMRESOURCE(conn));                    SSM_UnlockResource(SSMRESOURCE(conn));                }            }        }    /* end of for loop */    }    /* end of while loop */loser:    SSM_DEBUG("** Closing, return value %ld. **\n", rv);    if (conn != NULL) {      	SSM_ShutdownResource(SSMRESOURCE(conn), rv);        SSM_FreeResource(SSMRESOURCE(conn));    }    if (outbound != NULL) {        PR_Free(outbound);    }    if (inbound != NULL) {        PR_Free(inbound);    }    SSM_DEBUG("SSL data service thread terminated.\n");}/* callback functions and auxilliary functions *//* * Function: SECStatus SSM_SSLAuthCertificate() * Purpose: this callback function is used to authenticate certificates *			received from the remote end of an SSL connection. * * Arguments and return values * - arg: certDB handle (cannot be NULL) * - socket: SSL socket * - checkSig: whether to check the signature (usually should be PR_TRUE) * - isServer: whether we are an SSL server (expect PR_FALSE since PSM is *			   an SSL client) * - returns: SECSuccess if successful; error code otherwise * * ### sjlee: this is essentially a wrapper over the default SSL callback *			  function.  It provides minimal argument checking to the default *			  callback.  When we're confident that the default will do the *			  job, we might want to drop this... */SECStatus SSM_SSLAuthCertificate(void* arg, PRFileDesc* socket, 								 PRBool checkSig, PRBool isServer){	SSM_DEBUG("checking server cert.\n");	/* check arguments */	if (arg == NULL || socket == NULL || isServer != PR_FALSE) {		return (SECStatus) SEC_ERROR_INVALID_ARGS;	}	/* call the default callback */	return (SECStatus) SSL_AuthCertificate(arg, socket, checkSig, isServer);}/*

⌨️ 快捷键说明

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