@return: Whether there's a renegotiation in progress\n\ "; static PyObject * ssl_Connection_renegotiate_pending(ssl_ConnectionObj *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":renegotiate_pending")) return NULL; return PyLong_FromLong((long)SSL_renegotiate_pending(self->ssl)); }
bool sslLoop(SSL *ssl, int fd, bool isserver, bool verify, bool waitforpeer) { char inbuffer[NBYTES+1]; // Want to null terminate char netbuffer[NBYTES]; size_t insize = 0, instart = 0; bool read_wantwrite = false; // set if last read return want_write bool write_wantread = false; // set if last write returned want_read bool closed = false; // stdin has closed terminated = false; // global flag set by signal handler while (!terminated || SSL_renegotiate_pending(ssl)) { bool write_pending = insize > 0; fd_set rfds, wfds; FD_ZERO(&rfds); FD_ZERO(&wfds); // Suppress ingest of data if we are renegotiating & we are the server if (!closed && !write_pending && (!isserver || !SSL_renegotiate_pending(ssl))) { FD_SET(0, &rfds); } if (write_pending) { if (write_wantread) { FD_SET(fd, &rfds); } else { FD_SET(fd, &wfds); } } else if (!read_wantwrite) { FD_SET(fd, &rfds); } else { FD_SET(fd, &wfds); } { int ret = select(fd+1,&rfds,&wfds,NULL,NULL); if (ret < 0 && errno == EINTR) continue; // Recheck loop condition select_count++; CHECK(ret >= 0); } if (FD_ISSET(0, &rfds)) { size_t ret = read(0, inbuffer,NBYTES); if (debuglevel > 4) fprintf(stderr,"Read %zd bytes from 0\n", ret); CHECK(ret >= 0); if (ret <= 0) { closed = true; if (!waitforpeer) return true; } else { inbuffer[ret] = 0; if (strcmp(inbuffer, "r\n") == 0) { if (!renegotiatefull(ssl,isserver)) return false; } else { insize = ret; instart = 0; } } } bool gotsslevent = FD_ISSET(fd, &rfds) || FD_ISSET(fd, &wfds); // If we aren't waiting to complete a write we must be waiting to read. // If we are waiting to complete a write, we mustn't read as the // OpenSSL state machine cannae take it. if (!write_pending && gotsslevent) { while (true) { int ret = SSL_read(ssl, netbuffer, NBYTES); int err = SSL_get_error(ssl,ret); if (ret == 0) { return err == SSL_ERROR_ZERO_RETURN; } else if (ret > 0) { CHECK(err == SSL_ERROR_NONE); if (debuglevel > 4) fprintf(stderr,"Read %d bytes from SSL\n", ret); read_ok_count++; nread += ret; if (!noecho) CHECK(write(1,netbuffer,ret) > 0); if (verify) { // On first read from client, do client verification assert(isserver); verify = false; if (debuglevel > 2) fprintf(stderr,"Verifying client\n"); SSL_set_verify(ssl, SSL_VERIFY_PEER | //SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyCallback); if (!renegotiatefull(ssl,isserver)) return false; if (debuglevel > 2) fprintf(stderr,"Client verified\n"); } } else { if (err == SSL_ERROR_WANT_READ) { read_wantread_count++; read_wantwrite = false; } else if (err == SSL_ERROR_WANT_WRITE) { read_wantwrite_count++; read_wantwrite = true; } else if (err == SSL_ERROR_SYSCALL && errno == EAGAIN) { // Don't do anything here, go round again. // This seems to be a new "feature". } else { fprintf(stderr, "SSL_read: err %d\n", err); CHECK(0); } break; // On error return } } } // We might have done some reads or writes to the socket in // the calls to SSL_read, so it's not clear that the various // flags are still valid at this point. So just // call SSL_write unconditionally & keep the logic simple (if we // didn't do a read, then we must have got the flags for write, if // we did, then the state might have changed), and if we didn't get // signalled on the SSL fd at all, we must have got something in // from stdin. // However, if write_pending is true, then we won't have tried // to read & it's only worth trying a write if we really got an // event on the SSL socket. I think. if (insize > 0 && !(write_pending && !gotsslevent)) { int ret = SSL_write(ssl, inbuffer+instart, insize); if (ret == 0) { return true; } else if (ret > 0) { if (debuglevel > 4) fprintf(stderr,"Write %d bytes to SSL\n", ret); // Allow for partial writes insize -= ret; instart += ret; nwritten += ret; write_wantread = false; write_ok_count++; } else { int err = SSL_get_error(ssl,ret); if (err == SSL_ERROR_WANT_READ) { write_wantread = true; write_wantread_count++; } else if (err == SSL_ERROR_WANT_WRITE) { write_wantread = false; write_wantwrite_count++; } else { fprintf(stderr,"SSL_write: err %d\n", err); CHECK(0); } } } // Now maybe start a random renegotiation if (!verify && insize == 0 && rfactor > 0 && rand()%rfactor == 0) { renegotiate_count++; if (!renegotiate(ssl,isserver)) return false; } } return true; }
extern "C" int32_t CryptoNative_IsSslRenegotiatePending(SSL* ssl) { return SSL_renegotiate_pending(ssl) != 0; }
static int openssl_ssl_renegotiate_pending(lua_State*L) { SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl"); int ret = SSL_renegotiate_pending(s); return openssl_ssl_pushresult(L, s, ret); }
static void do_reneg_setup_step(const SSL_TEST_CTX *test_ctx, PEER *peer) { int ret; char buf; TEST_check(peer->status == PEER_RETRY); TEST_check(test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER || test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT); /* Check if we are the peer that is going to initiate */ if ((test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER && SSL_is_server(peer->ssl)) || (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT && !SSL_is_server(peer->ssl))) { /* * If we already asked for a renegotiation then fall through to the * SSL_read() below. */ if (!SSL_renegotiate_pending(peer->ssl)) { /* * If we are the client we will always attempt to resume the * session. The server may or may not resume dependant on the * setting of SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION */ if (SSL_is_server(peer->ssl)) ret = SSL_renegotiate(peer->ssl); else ret = SSL_renegotiate_abbreviated(peer->ssl); if (!ret) { peer->status = PEER_ERROR; return; } do_handshake_step(peer); /* * If status is PEER_RETRY it means we're waiting on the peer to * continue the handshake. As far as setting up the renegotiation is * concerned that is a success. The next step will continue the * handshake to its conclusion. * * If status is PEER_SUCCESS then we are the server and we have * successfully sent the HelloRequest. We need to continue to wait * until the handshake arrives from the client. */ if (peer->status == PEER_RETRY) peer->status = PEER_SUCCESS; else if (peer->status == PEER_SUCCESS) peer->status = PEER_RETRY; return; } } /* * The SSL object is still expecting app data, even though it's going to * get a handshake message. We try to read, and it should fail - after which * we should be in a handshake */ ret = SSL_read(peer->ssl, &buf, sizeof(buf)); if (ret >= 0) { /* * We're not actually expecting data - we're expecting a reneg to * start */ peer->status = PEER_ERROR; return; } else { int error = SSL_get_error(peer->ssl, ret); if (error != SSL_ERROR_WANT_READ) { peer->status = PEER_ERROR; return; } /* If we're no in init yet then we're not done with setup yet */ if (!SSL_in_init(peer->ssl)) return; } peer->status = PEER_SUCCESS; }