📄 sslconn.c
字号:
while (conn->m_sockStat == NULL || conn->m_sockStat->m_cipherName == NULL) { SSM_DEBUG("Oops, the security status has not been updated. " "Waiting...\n"); SSM_WaitResource(SSMRESOURCE(conn), PR_INTERVAL_NO_TIMEOUT); } /* XXX is this really necessary? */ if (conn->m_sockStat == NULL) { SSM_DEBUG("No socket status on dead socket.\n"); SSM_UnlockResource(SSMRESOURCE(conn)); goto loser; } /* it's probably OK to unlock it here */ SSM_UnlockResource(SSMRESOURCE(conn)); /* we have a socket status object. */ rv = SSMSSLSocketStatus_Pickle(&conn->m_sockStat->super, len, blob); if (rv != PR_SUCCESS) { SSM_DEBUG("Failed to pickle the socket status.\n"); goto loser; } /* get the security level */ *securityLevel = conn->m_sockStat->m_level; return rv; loser: if (rv == PR_SUCCESS) { rv = PR_FAILURE; } return rv;}/* * Function: SSMStatus SSMSSLDataConnection_FormSubmitHandler() * Purpose: handles any UI form submission that has an SSMSSLDataConnection * object as target * Expected request: * - command: "formsubmit_handler" * - baseRef: "formsubmit_dosubmit_js" * - target: an SSMSSLDataConnection object * - formName: "cert_selection" | "bad_server_cert" * Arguments and return values * - res: SSMSSLDataConnection object * - req: the HTTPRequest object to be processed * - returns: SSM_SUCCESS if successful; error otherwise * * Note: add more handling helper functions if there are other form * submission scenarios */SSMStatus SSMSSLDataConnection_FormSubmitHandler(SSMResource* res, HTTPRequest* req){ SSMStatus rv; char* tmpStr = NULL; SSMSSLDataConnection* conn; conn = (SSMSSLDataConnection*)res; /* make sure you got the right baseRef */ rv = SSM_HTTPParamValue(req, "baseRef", &tmpStr); if (rv != SSM_SUCCESS || PL_strcmp(tmpStr, "windowclose_doclose_js") != 0) { goto loser; } /* differentiate among different form submission events by looking up * formName, and dispatch the request to the appropriate handler */ /* cleaning up (unlocking monitors, etc.) is handled by individual * handlers, so just go to done */ if (res->m_formName == NULL) { goto loser; } if (PL_strcmp(res->m_formName, "cert_selection") == 0) { rv = SSM_ClientAuthCertSelectionButtonHandler(req); goto done; } else if (PL_strcmp(res->m_formName, "bad_server_cert") == 0) { /* server auth failure other than unknown issuer case */ rv = SSM_ServerAuthFailureButtonHandler(req); goto done; } else { /* unknown form name; abort */ SSM_DEBUG("don't know how to handle this form.\n"); goto loser; }loser: if (rv == SSM_SUCCESS) { rv = SSM_FAILURE; } SSM_LockResource(req->target); conn->m_UIInfo.chosen = -1; conn->m_UIInfo.trustBadServerCert = BSCA_NO; conn->m_UIInfo.UICompleted = PR_TRUE; SSM_NotifyResource(req->target); SSM_UnlockResource(req->target);done: return rv;}void SSMSSLDataConnection_InitializeUIInfo(SSMSSLUIInfo* info){ info->UICompleted = PR_FALSE; info->numFilteredCerts = 0; info->certNicknames = NULL; info->chosen = -1; /* negative value denotes no cert was chosen */ info->trustBadServerCert = BSCA_NO;}void SSMSSLDataConnection_DestroyUIInfo(SSMSSLUIInfo* info){ int i; if (info->numFilteredCerts != 0) { for (i = 0; i < info->numFilteredCerts; i++) { PR_FREEIF(info->certNicknames[i]); } PR_FREEIF(info->certNicknames); }}SSMStatus SSMSSLDataConnection_UpdateSecurityStatus(SSMSSLDataConnection* conn){ SSMStatus rv = PR_SUCCESS; PR_ASSERT(conn != NULL); SSM_LockResource(SSMRESOURCE(conn)); if (conn->m_sockStat == NULL) { /* socket status has not been created. The security status will * be properly populated by creating the socket status. */ SSMResourceID statRID; SSM_CreateResource(SSM_RESTYPE_SSL_SOCKET_STATUS, conn->socketSSL, SSMRESOURCE(conn)->m_connection, &statRID, (SSMResource**)&conn->m_sockStat); conn->m_sockStat->m_error = conn->m_sslServerError; } else { /* just update the values */ rv = SSMSSLSocketStatus_UpdateSecurityStatus(conn->m_sockStat, conn->socketSSL); if (rv != PR_SUCCESS) { goto loser; } }loser: /* in case we fail to update the security status, we still notify * because we don't want to quit just because this failed... */ SSM_NotifyResource(SSMRESOURCE(conn)); /* notify SSMSSLDataConnection_GetAttr() for the socket RID */ SSM_UnlockResource(SSMRESOURCE(conn)); return rv;}/* updates the error code in case of an exception: returns the current * error code (0 if no error) */static SSMStatus SSMSSLDataConnection_UpdateErrorCode(SSMSSLDataConnection* conn){ PR_ASSERT(conn != NULL); SSM_LockResource(SSMRESOURCE(conn)); if (conn->m_error == 0) { /* update the error code only if it is not already set: * otherwise preserve the initial error code */ PRInt32 rv; rv = PR_GetError(); if (rv != SEC_ERROR_LIBRARY_FAILURE) { /* XXX sometimes NSS reports this error even when connection * terminates normally: will escape this error here so that * this is not reported erroneously */ conn->m_error = rv; } } SSM_UnlockResource(SSMRESOURCE(conn)); return conn->m_error;}/* functions for setting up and configuring SSL connection */SECStatus SSM_SetupSSLSocket(PRFileDesc* socket, PRFileDesc** sslsocket, CERTCertDBHandle* handle, char* hostname, void* wincx){ SECStatus rv = SECFailure; /* check arguments */ if ((socket == NULL) || (sslsocket == NULL) || (handle == NULL) || (hostname == NULL) || (wincx == NULL)) { goto loser; } *sslsocket = NULL; /* import the socket into SSL layer */ *sslsocket = SSL_ImportFD(NULL, socket); if (*sslsocket == NULL) { goto loser; } /* set some SSL settings for the socket */ rv = SSL_Enable(*sslsocket, SSL_SECURITY, PR_TRUE); if (rv != SECSuccess) { goto loser; } rv = SSL_Enable(*sslsocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); if (rv != SECSuccess) { goto loser; } rv = SSL_Enable(*sslsocket, SSL_ENABLE_FDX, PR_TRUE); if (rv != SECSuccess) { goto loser; } /* set callbacks */ /* client authentication */ rv = SSL_GetClientAuthDataHook(*sslsocket, (SSLGetClientAuthData)SSM_SSLGetClientAuthData, NULL) == 0 ? SECSuccess : SECFailure; if (rv != SECSuccess) { goto loser; } /* server cert authentication */ rv = SSL_AuthCertificateHook(*sslsocket, (SSLAuthCertificate)SSM_SSLAuthCertificate, (void*)handle) == 0 ? SECSuccess : SECFailure; if (rv != SECSuccess) { goto loser; } rv = SSL_BadCertHook(*sslsocket, (SSLBadCertHandler)SSM_SSLBadCertHandler, wincx) == 0 ? SECSuccess : SECFailure; if (rv != SECSuccess) { goto loser; } rv = SSL_HandshakeCallback(*sslsocket, (SSLHandshakeCallback)SSM_SSLHandshakeCallback, wincx) == 0 ? SECSuccess : SECFailure; if (rv != SECSuccess) { goto loser; } SSM_DEBUG("setting PKCS11 pin arg.\n"); rv = SSL_SetPKCS11PinArg(*sslsocket, wincx) == 0 ? SECSuccess : SECFailure; if (rv != SECSuccess) { goto loser; } /* prepare against man-in-the-middle attacks */ rv = SSL_SetURL(*sslsocket, hostname) == 0 ? SECSuccess : SECFailure; if (rv != SECSuccess) { goto loser; } return rv;loser: if (*sslsocket == NULL) { /* aborted before SSL_ImportFD() */ if (socket != NULL) { PR_Close(socket); } } else { PR_Close(*sslsocket); *sslsocket = NULL; } return rv;}SSMStatus SSM_GetSSLSocket(SSMSSLDataConnection* conn){ SECStatus secstatus = SECSuccess; PRStatus prstatus = PR_SUCCESS; PRFileDesc* socket = NULL; PRSocketOptionData sockdata; SSMControlConnection* ctrlconn; PRNetAddr addr; PRHostEnt hostentry; char buffer[256]; SSM_DEBUG("SSM_GetSSLSocket entered.\n"); /* check argument first */ if (conn == NULL) { return PR_FAILURE; } /* Enter SSL lock. We will release once connection is set up. * If GetSecurityStatus request comes in before we are done, it'll spin * on the SSL lock. (This lock is not used anyplace else.) */ /*PR_EnterMonitor(conn->sslLock);*/ /* set up SSL secure socket */ SSM_DEBUG("setting up secure socket.\n"); socket = PR_NewTCPSocket(); if (socket == NULL) { goto loser; } /* make the socket blocking - default on some platforms is non-blocking */ sockdata.option = PR_SockOpt_Nonblocking; sockdata.value.non_blocking = PR_FALSE; if (PR_SetSocketOption(socket, &sockdata) != PR_SUCCESS) { goto loser; } if (conn->isTLS != PR_TRUE) { /* set up SSL secure socket */ SSM_DEBUG("setting up secure socket.\n"); ctrlconn = SSMCONTROLCONNECTION(conn); secstatus = SSM_SetupSSLSocket(socket, &conn->socketSSL, ctrlconn->m_certdb, conn->hostName, (void*)conn); if (secstatus != SECSuccess) { goto loser; } } else { /* do not need to create a secure socket here */ conn->socketSSL = socket; } /* prepare and setup network connection */ SSM_DEBUG("preparing and setting up network connection.\n"); 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 == PR_FALSE) && (conn->forceHandshake == PR_TRUE)) { /* 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. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -