sslconn.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,048 行 · 第 1/5 页
C
2,048 行
if (PR_StringToNetAddr(conn->hostIP, &addr) != PR_SUCCESS) { PRIntn hostIndex; prstatus = PR_GetHostByName(conn->hostName, buffer, 256, &hostentry); if (prstatus != PR_SUCCESS) { goto loser; } SSM_DEBUG("SSL server port: %d / host: %s \n", conn->port, conn->hostName); do { hostIndex = PR_EnumerateHostEnt(0, &hostentry, (PRUint16) conn->port, &addr); if (hostIndex < 0) { goto loser; } } while (PR_Connect(conn->socketSSL, &addr, PR_INTERVAL_NO_TIMEOUT) != PR_SUCCESS && hostIndex > 0); SSM_DEBUG("Connected to target.\n"); } else { if (PR_InitializeNetAddr(PR_IpAddrNull, (PRUint16)conn->port, &addr) != PR_SUCCESS) { goto loser; } if (PR_Connect(conn->socketSSL, &addr, PR_INTERVAL_NO_TIMEOUT) != PR_SUCCESS) { goto loser; } SSM_DEBUG("SSL server port: %d / host: %s\n", conn->port, conn->hostName); SSM_DEBUG("connected using hostIP: %s\n", conn->hostIP); }#ifdef _HACK_ /* ### mwelch Fix for NSPR20 connect problem under 95/NT. */ PR_Sleep(PR_INTERVAL_NO_WAIT);#endif /* established SSL connection, ready to send data */ if (!conn->isTLS && conn->forceHandshake) { /* if the client wants a forced handshake (e.g. SSL/IMAP), * do it here */ SSM_DEBUG("forcing handshake.\n"); secstatus = (SSL_ForceHandshake(conn->socketSSL) == 0)? SECSuccess:SECFailure; if (secstatus != SECSuccess) { goto loser; } } /* if (conn->m_sockStat) { SSM_FreeResource(&conn->m_sockStat->super); } SSM_CreateResource(SSM_RESTYPE_SSL_SOCKET_STATUS, conn->socketSSL, SSMRESOURCE(conn)->m_connection, &statRID, (SSMResource**)&conn->m_sockStat); */ /* check everything is hunky-dorey */ /* SSMSSLSocketStatus_Invariant(conn->m_sockStat); */ /* end of the block */ /* release SSL lock. SSL connection is established. */ /*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;}/* * Function: PRStatus SSMSSLDataConnection_TLSStepUp() * Purpose: "step up" the connection and set up an SSL socket for the * underlying TCP socket * Arguments and return values: * - conn: TLS connection object to be manipulated * - returns: PR_SUCCESS if successful; PR_FAILURE otherwise * * Notes: SSL handshakes are not done here; it is performed when the first * read/write operation is done on the secure socket * This function must be called while the underlying resource is * locked */static 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) { /* SSL/SMTP connections usually require a large outbound buffer */ 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 Nova-specific: Nova 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, Nova 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) { SSM_DEBUG("Couldn't send all data to the target socket (sent: %d read: %d)\n", 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");#if 0 SSM_DumpBuffer(inbound, read);#endif 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. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?