diff --git a/doc/TODO b/doc/TODO index 30087cbdf6..0187869d31 100644 --- a/doc/TODO +++ b/doc/TODO @@ -43,7 +43,7 @@ Things we'd like to do in 0.2.0.x: - 105 only - Need to get a finished proposal 105 o "Pick a version" function - - Have a 'waiting_for_version' state. + o Have a 'waiting_for_version' state. o Store version in or_connection_t. o Generate netinfo cells o Accept netinfo cells @@ -52,7 +52,7 @@ Things we'd like to do in 0.2.0.x: o Set it when we get a match for a routerinfo we have. - Don't extend a circuit over a noncanonical connection with mismatched address. - - Version negotiation: send a version cell and enter + o Version negotiation: send a version cell and enter waiting-for-version; when version cell arrives, pick version and send netinfo and be "open". o On netinfo, warn if there's skew from a server. diff --git a/src/common/tortls.c b/src/common/tortls.c index 986265da9b..db6d62c4ce 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -888,3 +888,10 @@ _check_no_tls_errors(const char *fname, int line) tls_log_errors(LOG_WARN, NULL); } +/**DOCDOC */ +int +tor_tls_used_v1_handshake(tor_tls_t *tls) +{ + (void)tls; + return 1; +} diff --git a/src/common/tortls.h b/src/common/tortls.h index 7d69f8e6c4..89cbe3be58 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -64,6 +64,8 @@ size_t tor_tls_get_forced_write_size(tor_tls_t *tls); void tor_tls_get_n_raw_bytes(tor_tls_t *tls, size_t *n_read, size_t *n_written); +int tor_tls_used_v1_handshake(tor_tls_t *tls); + /* Log and abort if there are unhandled TLS errors in OpenSSL's error stack. */ #define check_no_tls_errors() _check_no_tls_errors(__FILE__,__LINE__) diff --git a/src/or/command.c b/src/or/command.c index 4fa098d9a7..c449e6c0a0 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -395,7 +395,8 @@ command_process_versions_cell(cell_t *cell, or_connection_t *conn) uint16_t versionslen; int highest_supported_version = 0; const char *cp, *end; - if (conn->link_proto != 0) { + if (conn->link_proto != 0 || + conn->_base.state != OR_CONN_STATE_WAITING_FOR_VERSIONS) { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Received a VERSIONS cell on a connection with its version " "already set to %d; dropping", (int) conn->link_proto); @@ -412,13 +413,18 @@ command_process_versions_cell(cell_t *cell, or_connection_t *conn) highest_supported_version = v; } } - if (!versionslen) { + if (!highest_supported_version) { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Couldn't find a version in common; defaulting to v1."); /*XXXX020 or just break the connection?*/ conn->link_proto = 1; return; } + conn->link_proto = highest_supported_version; + conn->_base.state = OR_CONN_STATE_OPEN; + + if (highest_supported_version >= 2) + connection_or_send_netinfo(conn); } /** Process a 'netinfo' cell. DOCDOC say more. */ @@ -433,9 +439,9 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) uint8_t n_other_addrs; time_t now = time(NULL); - /*XXXX020 reject duplicat netinfos. */ + /*XXXX020 reject duplicate netinfos. */ - if (conn->link_proto < 2) { + if (conn->link_proto < 2 || conn->_base.state != OR_CONN_STATE_OPEN) { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Received a NETINFO cell on %s connection; dropping.", conn->link_proto == 0 ? "non-versioned" : "a v1"); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 1d083e39b3..89e3200b85 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -16,6 +16,7 @@ const char connection_or_c_id[] = static int connection_tls_finish_handshake(or_connection_t *conn); static int connection_or_process_cells_from_inbuf(or_connection_t *conn); +static int connection_or_send_versions(or_connection_t *conn); /**************************************************************/ @@ -732,8 +733,25 @@ connection_tls_finish_handshake(or_connection_t *conn) } directory_set_dirty(); + + if (tor_tls_used_v1_handshake(conn->tls)) { + conn->link_proto = 1; + return connection_or_set_state_open(conn); + } else { + /*XXXX020 actually, we'll need to send some kind of authentication. */ + conn->_base.state = OR_CONN_STATE_WAITING_FOR_VERSIONS; + return connection_or_send_versions(conn); + } +} + +/**DOCDOC*/ +int +connection_or_set_state_open(or_connection_t *conn) +{ + int started_here = connection_or_nonopen_was_started_here(conn); conn->_base.state = OR_CONN_STATE_OPEN; control_event_or_conn_status(conn, OR_CONN_EVENT_CONNECTED, 0); + if (started_here) { rep_hist_note_connect_succeeded(conn->identity_digest, time(NULL)); if (entry_guard_register_connect_status(conn->identity_digest, 1, @@ -746,7 +764,6 @@ connection_tls_finish_handshake(or_connection_t *conn) connection_watch_events(TO_CONN(conn), EV_READ); circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */ - conn->link_proto = 1; /* Version negotiation not yet enabled.XXX020 */ return 0; } @@ -850,10 +867,12 @@ connection_or_send_versions(or_connection_t *conn) } connection_or_write_cell_to_buf(&cell, conn); + + return 0; } /** DOCDOC */ -static int +int connection_or_send_netinfo(or_connection_t *conn) { cell_t cell; @@ -881,7 +900,5 @@ connection_or_send_netinfo(or_connection_t *conn) connection_or_write_cell_to_buf(&cell, conn); - /*XXXX020 remove these once we send netinfo and versions cells. */ - (void) connection_or_send_netinfo; - (void) connection_or_send_versions; + return 0; } diff --git a/src/or/or.h b/src/or/or.h index 20766ac3c4..7b8da74858 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -236,9 +236,12 @@ typedef enum { #define OR_CONN_STATE_PROXY_READING 3 /** State for a connection to an OR: SSL is handshaking, not done yet. */ #define OR_CONN_STATE_HANDSHAKING 4 +/** State for a connection to an OR: We sent a VERSIONS cell and want one back + */ +#define OR_CONN_STATE_WAITING_FOR_VERSIONS 5 /** State for a connection to an OR: Ready to send/receive cells. */ -#define OR_CONN_STATE_OPEN 5 -#define _OR_CONN_STATE_MAX 5 +#define OR_CONN_STATE_OPEN 6 +#define _OR_CONN_STATE_MAX 6 #define _EXIT_CONN_STATE_MIN 1 /** State for an exit connection: waiting for response from dns farm. */ @@ -2717,10 +2720,12 @@ or_connection_t *connection_or_connect(uint32_t addr, uint16_t port, int connection_tls_start_handshake(or_connection_t *conn, int receiving); int connection_tls_continue_handshake(or_connection_t *conn); +int connection_or_set_state_open(or_connection_t *conn); void connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn); int connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn, int reason); +int connection_or_send_netinfo(or_connection_t *conn); void cell_pack(packed_cell_t *dest, const cell_t *src);