/* Try to make progress on an SSL handshake by attempting to read the ** next handshake from the peer, and sending any responses. ** For non-blocking sockets, returns PR_ERROR_WOULD_BLOCK if it cannot ** read the next handshake from the underlying socket. ** For SSLv2, returns when handshake is complete or fatal error occurs. ** For SSLv3, returns when handshake is complete, or application data has ** arrived that must be taken by application before handshake can continue, ** or a fatal error occurs. ** Application should use handshake completion callback to tell which. */ SECStatus SSL_ForceHandshake(PRFileDesc *fd) { sslSocket *ss; SECStatus rv = SECFailure; ss = ssl_FindSocket(fd); if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in ForceHandshake", SSL_GETPID(), fd)); return rv; } /* Don't waste my time */ if (!ss->opt.useSecurity) return SECSuccess; if (!ssl_SocketIsBlocking(ss)) { ssl_GetXmitBufLock(ss); if (ss->pendingBuf.len != 0) { int sent = ssl_SendSavedWriteData(ss); if ((sent < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) { ssl_ReleaseXmitBufLock(ss); return SECFailure; } } ssl_ReleaseXmitBufLock(ss); } ssl_Get1stHandshakeLock(ss); if (ss->version >= SSL_LIBRARY_VERSION_3_0) { int gatherResult; ssl_GetRecvBufLock(ss); gatherResult = ssl3_GatherCompleteHandshake(ss, 0); ssl_ReleaseRecvBufLock(ss); if (gatherResult > 0) { rv = SECSuccess; } else if (gatherResult == 0) { PORT_SetError(PR_END_OF_FILE_ERROR); } else if (gatherResult == SECWouldBlock) { PORT_SetError(PR_WOULD_BLOCK_ERROR); } } else if (!ss->firstHsDone) { rv = ssl_Do1stHandshake(ss); } else { /* tried to force handshake on an SSL 2 socket that has ** already completed the handshake. */ rv = SECSuccess; /* just pretend we did it. */ } ssl_Release1stHandshakeLock(ss); return rv; }
int ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags) { int rv = 0; if (ss->shutdownHow & ssl_SHUTDOWN_RCV) { PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR); return PR_FAILURE; } if (flags & ~PR_MSG_PEEK) { PORT_SetError(PR_INVALID_ARGUMENT_ERROR); return PR_FAILURE; } if (!ssl_SocketIsBlocking(ss) && !ss->opt.fdx) { ssl_GetXmitBufLock(ss); if (ss->pendingBuf.len != 0) { rv = ssl_SendSavedWriteData(ss); if ((rv < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) { ssl_ReleaseXmitBufLock(ss); return SECFailure; } } ssl_ReleaseXmitBufLock(ss); } rv = 0; if (!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.bufferedEarlyData)) { PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); return tls13_Read0RttData(ss, buf, len); } /* If any of these is non-zero, the initial handshake is not done. */ if (!ss->firstHsDone) { ssl_Get1stHandshakeLock(ss); if (ss->handshake) { rv = ssl_Do1stHandshake(ss); } ssl_Release1stHandshakeLock(ss); } if (rv < 0) { return rv; } if (len == 0) return 0; rv = DoRecv(ss, (unsigned char *)buf, len, flags); SSL_TRC(2, ("%d: SSL[%d]: recving %d bytes securely (errno=%d)", SSL_GETPID(), ss->fd, rv, PORT_GetError())); return rv; }
int ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags) { sslSecurityInfo *sec; int rv = 0; sec = &ss->sec; if (ss->shutdownHow & ssl_SHUTDOWN_RCV) { PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR); return PR_FAILURE; } if (flags & ~PR_MSG_PEEK) { PORT_SetError(PR_INVALID_ARGUMENT_ERROR); return PR_FAILURE; } if (!ssl_SocketIsBlocking(ss) && !ss->opt.fdx) { ssl_GetXmitBufLock(ss); if (ss->pendingBuf.len != 0) { rv = ssl_SendSavedWriteData(ss); if ((rv < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) { ssl_ReleaseXmitBufLock(ss); return SECFailure; } /* XXX short write? */ } ssl_ReleaseXmitBufLock(ss); } rv = 0; /* If any of these is non-zero, the initial handshake is not done. */ if (!ss->firstHsDone) { ssl_Get1stHandshakeLock(ss); if (ss->handshake || ss->nextHandshake || ss->securityHandshake) { rv = ssl_Do1stHandshake(ss); } ssl_Release1stHandshakeLock(ss); } if (rv < 0) { return rv; } if (len == 0) return 0; rv = DoRecv(ss, (unsigned char*) buf, len, flags); SSL_TRC(2, ("%d: SSL[%d]: recving %d bytes securely (errno=%d)", SSL_GETPID(), ss->fd, rv, PORT_GetError())); return rv; }