Actually call connection_tls_finish_handshake() with bufferevents

First start of a fix for bug2001, but my test network still isn't
working: the client and the server send each other VERSIONS cells,
but never notice that they got them.
This commit is contained in:
Nick Mathewson 2010-10-11 13:45:27 -04:00
parent c1c74c51d4
commit a9172c87be
3 changed files with 51 additions and 4 deletions

View File

@ -127,6 +127,8 @@ struct tor_tls_t {
* one certificate). */ * one certificate). */
/** True iff we should call negotiated_callback when we're done reading. */ /** True iff we should call negotiated_callback when we're done reading. */
unsigned int got_renegotiate:1; unsigned int got_renegotiate:1;
/** Incremented every time we start the server side of a handshake. */
uint8_t server_handshake_count;
size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last
* time. */ * time. */
/** Last values retrieved from BIO_number_read()/write(); see /** Last values retrieved from BIO_number_read()/write(); see
@ -841,6 +843,8 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val)
/* Check whether we're watching for renegotiates. If so, this is one! */ /* Check whether we're watching for renegotiates. If so, this is one! */
if (tls->negotiated_callback) if (tls->negotiated_callback)
tls->got_renegotiate = 1; tls->got_renegotiate = 1;
if (tls->server_handshake_count < 127) /*avoid any overflow possibility*/
++tls->server_handshake_count;
} else { } else {
log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!"); log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
} }
@ -1658,6 +1662,22 @@ tor_tls_used_v1_handshake(tor_tls_t *tls)
return 1; return 1;
} }
/** Return the number of server handshakes that we've noticed doing on
* <b>tls</b>. */
int
tor_tls_get_num_server_handshakes(tor_tls_t *tls)
{
return tls->server_handshake_count;
}
/** Return true iff the server TLS connection <b>tls</b> got the renegotiation
* request it was waiting for. */
int
tor_tls_server_got_renegotiate(tor_tls_t *tls)
{
return tls->got_renegotiate;
}
/** Examine the amount of memory used and available for buffers in <b>tls</b>. /** Examine the amount of memory used and available for buffers in <b>tls</b>.
* Set *<b>rbuf_capacity</b> to the amount of storage allocated for the read * Set *<b>rbuf_capacity</b> to the amount of storage allocated for the read
* buffer and *<b>rbuf_bytes</b> to the amount actually used. * buffer and *<b>rbuf_bytes</b> to the amount actually used.

View File

@ -80,6 +80,8 @@ void tor_tls_get_buffer_sizes(tor_tls_t *tls,
size_t *wbuf_capacity, size_t *wbuf_bytes); size_t *wbuf_capacity, size_t *wbuf_bytes);
int tor_tls_used_v1_handshake(tor_tls_t *tls); int tor_tls_used_v1_handshake(tor_tls_t *tls);
int tor_tls_get_num_server_handshakes(tor_tls_t *tls);
int tor_tls_server_got_renegotiate(tor_tls_t *tls);
/* Log and abort if there are unhandled TLS errors in OpenSSL's error stack. /* Log and abort if there are unhandled TLS errors in OpenSSL's error stack.
*/ */

View File

@ -41,6 +41,8 @@ static int connection_or_check_valid_tls_handshake(or_connection_t *conn,
int started_here, int started_here,
char *digest_rcvd_out); char *digest_rcvd_out);
static void connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn);
#ifdef USE_BUFFEREVENTS #ifdef USE_BUFFEREVENTS
static void connection_or_handle_event_cb(struct bufferevent *bufev, static void connection_or_handle_event_cb(struct bufferevent *bufev,
short event, void *arg); short event, void *arg);
@ -237,6 +239,12 @@ connection_or_process_inbuf(or_connection_t *conn)
} }
return ret; return ret;
case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
if (tor_tls_server_got_renegotiate(conn->tls))
connection_or_tls_renegotiated_cb(conn->tls, conn);
if (conn->_base.marked_for_close)
return 0;
/* fall through. */
case OR_CONN_STATE_OPEN: case OR_CONN_STATE_OPEN:
case OR_CONN_STATE_OR_HANDSHAKING: case OR_CONN_STATE_OR_HANDSHAKING:
return connection_or_process_cells_from_inbuf(conn); return connection_or_process_cells_from_inbuf(conn);
@ -1034,14 +1042,29 @@ connection_or_handle_event_cb(struct bufferevent *bufev, short event,
tor_tls_unblock_renegotiation(conn->tls); tor_tls_unblock_renegotiation(conn->tls);
return; /* ???? */ return; /* ???? */
} }
} else { } else if (tor_tls_get_num_server_handshakes(conn->tls) == 1) {
/* improved handshake, but not a client. */ /* improved handshake, as a server. Only got one handshake, so
* wait for the next one. */
tor_tls_set_renegotiate_callback(conn->tls, tor_tls_set_renegotiate_callback(conn->tls,
connection_or_tls_renegotiated_cb, connection_or_tls_renegotiated_cb,
conn); conn);
conn->_base.state = OR_CONN_STATE_TLS_SERVER_RENEGOTIATING; conn->_base.state = OR_CONN_STATE_TLS_SERVER_RENEGOTIATING;
/* return 0; */ /* return 0; */
return; /* ???? */ return; /* ???? */
} else {
const int handshakes = tor_tls_get_num_server_handshakes(conn->tls);
tor_assert(handshakes >= 2);
if (handshakes == 2) {
/* improved handshake, as a server. Two handshakes happened already,
* so we treat renegotiation as done.
*/
connection_or_tls_renegotiated_cb(conn->tls, conn);
} else {
log_warn(LD_OR, "More than two handshakes done on connection. "
"Closing.");
connection_mark_for_close(TO_CONN(conn));
}
return;
} }
} }
connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT); connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
@ -1230,7 +1253,9 @@ connection_tls_finish_handshake(or_connection_t *conn)
char digest_rcvd[DIGEST_LEN]; char digest_rcvd[DIGEST_LEN];
int started_here = connection_or_nonopen_was_started_here(conn); int started_here = connection_or_nonopen_was_started_here(conn);
log_debug(LD_HANDSHAKE,"tls handshake with %s done. verifying.", log_debug(LD_HANDSHAKE,"%s tls handshake on %p with %s done. verifying.",
started_here?"outgoing":"incoming",
conn,
safe_str_client(conn->_base.address)); safe_str_client(conn->_base.address));
directory_set_dirty(); directory_set_dirty();