|
@@ -396,12 +396,14 @@ command_process_versions_cell(cell_t *cell, or_connection_t *conn)
|
|
|
int highest_supported_version = 0;
|
|
|
const char *cp, *end;
|
|
|
if (conn->link_proto != 0 ||
|
|
|
- conn->_base.state != OR_CONN_STATE_WAITING_FOR_VERSIONS) {
|
|
|
+ conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING ||
|
|
|
+ (conn->handshake_state && conn->handshake_state->received_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);
|
|
|
return;
|
|
|
}
|
|
|
+ tor_assert(conn->handshake_state);
|
|
|
versionslen = ntohs(get_uint16(cell->payload));
|
|
|
end = cell->payload + 2 + versionslen;
|
|
|
if (end > cell->payload + CELL_PAYLOAD_SIZE)
|
|
@@ -416,12 +418,12 @@ command_process_versions_cell(cell_t *cell, or_connection_t *conn)
|
|
|
if (!highest_supported_version) {
|
|
|
log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
|
|
"Couldn't find a version in common; defaulting to v1.");
|
|
|
-
|
|
|
+
|
|
|
conn->link_proto = 1;
|
|
|
return;
|
|
|
}
|
|
|
conn->link_proto = highest_supported_version;
|
|
|
- conn->_base.state = OR_CONN_STATE_OPEN;
|
|
|
+ conn->handshake_state->received_versions = 1;
|
|
|
|
|
|
if (highest_supported_version >= 2)
|
|
|
connection_or_send_netinfo(conn);
|
|
@@ -438,46 +440,42 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
|
|
|
const char *cp, *end;
|
|
|
uint8_t n_other_addrs;
|
|
|
time_t now = time(NULL);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (conn->link_proto < 2 || conn->_base.state != OR_CONN_STATE_OPEN) {
|
|
|
+ if (conn->link_proto < 2) {
|
|
|
log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
|
|
"Received a NETINFO cell on %s connection; dropping.",
|
|
|
conn->link_proto == 0 ? "non-versioned" : "a v1");
|
|
|
return;
|
|
|
}
|
|
|
+ if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING) {
|
|
|
+ log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
|
|
+ "Received a NETINFO cell on a non-handshaking; dropping.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ tor_assert(conn->handshake_state &&
|
|
|
+ conn->handshake_state->received_versions);
|
|
|
+ if (conn->handshake_state->received_netinfo) {
|
|
|
+ log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
|
|
+ "Received a duplicate NETINFO cell; dropping.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
timestamp = ntohl(get_uint32(cell->payload));
|
|
|
+ if (abs(now - conn->handshake_state->sent_versions_at) < 180) {
|
|
|
+ conn->handshake_state->apparent_skew = now - timestamp;
|
|
|
+ }
|
|
|
+
|
|
|
my_addr_type = (uint8_t) cell->payload[4];
|
|
|
my_addr_len = (uint8_t) cell->payload[5];
|
|
|
my_addr_ptr = cell->payload + 6;
|
|
|
-
|
|
|
end = cell->payload + CELL_PAYLOAD_SIZE;
|
|
|
cp = cell->payload + 6 + my_addr_len;
|
|
|
if (cp >= end) {
|
|
|
log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
|
|
"Address too long in netinfo cell; dropping.");
|
|
|
+
|
|
|
return;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (abs(timestamp - now) > 3600 &&
|
|
|
- router_get_by_digest(conn->identity_digest)) {
|
|
|
- long delta = now - timestamp;
|
|
|
- char dbuf[64];
|
|
|
-
|
|
|
- format_time_interval(dbuf, sizeof(dbuf), delta);
|
|
|
- log_fn(LOG_WARN, LD_HTTP, "Received NETINFO cell with skewed time from "
|
|
|
- "server at %s:%d. It seems that our clock is %s by %s, or "
|
|
|
- "that theirs is %s. Tor requires an accurate clock to work: "
|
|
|
- "please check your time and date settings.",
|
|
|
- conn->_base.address, (int)conn->_base.port,
|
|
|
- delta>0 ? "ahead" : "behind", dbuf,
|
|
|
- delta>0 ? "behind" : "ahead");
|
|
|
- control_event_general_status(LOG_WARN,
|
|
|
- "CLOCK_SKEW SKEW=%ld SOURCE=OR:%s:%d",
|
|
|
- delta, conn->_base.address, conn->_base.port);
|
|
|
+ } else if (my_addr_type == RESOLVED_TYPE_IPV4 && my_addr_len == 4) {
|
|
|
+ conn->handshake_state->my_apparent_addr = ntohl(get_uint32(my_addr_ptr));
|
|
|
}
|
|
|
|
|
|
n_other_addrs = (uint8_t) *cp++;
|
|
@@ -491,12 +489,50 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
|
|
|
if (other_addr_type == RESOLVED_TYPE_IPV4 && other_addr_len == 4) {
|
|
|
uint32_t addr = ntohl(get_uint32(cp));
|
|
|
if (addr == conn->real_addr) {
|
|
|
- conn->is_canonical = 1;
|
|
|
+ conn->handshake_state->apparently_canonical = 1;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
cp += other_addr_len;
|
|
|
--n_other_addrs;
|
|
|
}
|
|
|
+
|
|
|
+ conn->handshake_state->received_netinfo = 1;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * learned in netinfo. */
|
|
|
+void
|
|
|
+connection_or_act_on_netinfo(or_connection_t *conn)
|
|
|
+{
|
|
|
+ long delta;
|
|
|
+ if (!conn->handshake_state)
|
|
|
+ return;
|
|
|
+
|
|
|
+ tor_assert(conn->handshake_state->authenticated != 0);
|
|
|
+
|
|
|
+ delta = conn->handshake_state->apparent_skew;
|
|
|
+
|
|
|
+ if (abs(delta) > 3600 &&
|
|
|
+ router_get_by_digest(conn->identity_digest)) {
|
|
|
+ char dbuf[64];
|
|
|
+
|
|
|
+ format_time_interval(dbuf, sizeof(dbuf), delta);
|
|
|
+ log_fn(LOG_WARN, LD_HTTP, "Received NETINFO cell with skewed time from "
|
|
|
+ "server at %s:%d. It seems that our clock is %s by %s, or "
|
|
|
+ "that theirs is %s. Tor requires an accurate clock to work: "
|
|
|
+ "please check your time and date settings.",
|
|
|
+ conn->_base.address, (int)conn->_base.port,
|
|
|
+ delta>0 ? "ahead" : "behind", dbuf,
|
|
|
+ delta>0 ? "behind" : "ahead");
|
|
|
+ control_event_general_status(LOG_WARN,
|
|
|
+ "CLOCK_SKEW SKEW=%ld SOURCE=OR:%s:%d",
|
|
|
+ delta, conn->_base.address, conn->_base.port);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (conn->handshake_state->apparently_canonical) {
|
|
|
+ conn->is_canonical = 1;
|
|
|
+ }
|
|
|
+}
|