Пример #1
0
@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));
}
Пример #2
0
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;
}
Пример #3
0
extern "C" int32_t CryptoNative_IsSslRenegotiatePending(SSL* ssl)
{
    return SSL_renegotiate_pending(ssl) != 0;
}
Пример #4
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);
}
Пример #5
0
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;
}