aboutsummaryrefslogtreecommitdiff
path: root/src/or/connection_or.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/connection_or.c')
-rw-r--r--src/or/connection_or.c384
1 files changed, 220 insertions, 164 deletions
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index d402563fb..ed174c922 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -11,6 +11,22 @@
**/
#include "or.h"
+#include "buffers.h"
+#include "circuitbuild.h"
+#include "command.h"
+#include "config.h"
+#include "connection.h"
+#include "connection_or.h"
+#include "control.h"
+#include "dirserv.h"
+#include "geoip.h"
+#include "main.h"
+#include "networkstatus.h"
+#include "reasons.h"
+#include "relay.h"
+#include "rephist.h"
+#include "router.h"
+#include "routerlist.h"
static int connection_tls_finish_handshake(or_connection_t *conn);
static int connection_or_process_cells_from_inbuf(or_connection_t *conn);
@@ -80,10 +96,8 @@ connection_or_clear_identity_map(void)
}
});
- if (orconn_identity_map) {
- digestmap_free(orconn_identity_map, NULL);
- orconn_identity_map = NULL;
- }
+ digestmap_free(orconn_identity_map, NULL);
+ orconn_identity_map = NULL;
}
/** Change conn->identity_digest to digest, and add conn into
@@ -133,7 +147,7 @@ void
cell_pack(packed_cell_t *dst, const cell_t *src)
{
char *dest = dst->body;
- *(uint16_t*)dest = htons(src->circ_id);
+ set_uint16(dest, htons(src->circ_id));
*(uint8_t*)(dest+2) = src->command;
memcpy(dest+3, src->payload, CELL_PAYLOAD_SIZE);
}
@@ -144,7 +158,7 @@ cell_pack(packed_cell_t *dst, const cell_t *src)
static void
cell_unpack(cell_t *dest, const char *src)
{
- dest->circ_id = ntohs(*(uint16_t*)(src));
+ dest->circ_id = ntohs(get_uint16(src));
dest->command = *(uint8_t*)(src+2);
memcpy(dest->payload, src+3, CELL_PAYLOAD_SIZE);
}
@@ -187,66 +201,6 @@ connection_or_reached_eof(or_connection_t *conn)
return 0;
}
-/** Read conn's inbuf. If the http response from the proxy is all
- * here, make sure it's good news, and begin the tls handshake. If
- * it's bad news, close the connection and return -1. Else return 0
- * and hope for better luck next time.
- */
-static int
-connection_or_read_proxy_response(or_connection_t *or_conn)
-{
- char *headers;
- char *reason=NULL;
- int status_code;
- time_t date_header;
- connection_t *conn = TO_CONN(or_conn);
-
- switch (fetch_from_buf_http(conn->inbuf,
- &headers, MAX_HEADERS_SIZE,
- NULL, NULL, 10000, 0)) {
- case -1: /* overflow */
- log_warn(LD_PROTOCOL,
- "Your https proxy sent back an oversized response. Closing.");
- return -1;
- case 0:
- log_info(LD_OR,"https proxy response not all here yet. Waiting.");
- return 0;
- /* case 1, fall through */
- }
-
- if (parse_http_response(headers, &status_code, &date_header,
- NULL, &reason) < 0) {
- log_warn(LD_OR,
- "Unparseable headers from proxy (connecting to '%s'). Closing.",
- conn->address);
- tor_free(headers);
- return -1;
- }
- if (!reason) reason = tor_strdup("[no reason given]");
-
- if (status_code == 200) {
- log_info(LD_OR,
- "HTTPS connect to '%s' successful! (200 %s) Starting TLS.",
- conn->address, escaped(reason));
- tor_free(reason);
- if (connection_tls_start_handshake(or_conn, 0) < 0) {
- /* TLS handshaking error of some kind. */
- connection_mark_for_close(conn);
-
- return -1;
- }
- return 0;
- }
- /* else, bad news on the status code */
- log_warn(LD_OR,
- "The https proxy sent back an unexpected status code %d (%s). "
- "Closing.",
- status_code, escaped(reason));
- tor_free(reason);
- connection_mark_for_close(conn);
- return -1;
-}
-
/** Handle any new bytes that have come in on connection <b>conn</b>.
* If conn is in 'open' state, hand it to
* connection_or_process_cells_from_inbuf()
@@ -255,11 +209,24 @@ connection_or_read_proxy_response(or_connection_t *or_conn)
int
connection_or_process_inbuf(or_connection_t *conn)
{
+ int ret;
tor_assert(conn);
switch (conn->_base.state) {
- case OR_CONN_STATE_PROXY_READING:
- return connection_or_read_proxy_response(conn);
+ case OR_CONN_STATE_PROXY_HANDSHAKING:
+ ret = connection_read_proxy_handshake(TO_CONN(conn));
+
+ /* start TLS after handshake completion, or deal with error */
+ if (ret == 1) {
+ tor_assert(TO_CONN(conn)->proxy_state == PROXY_CONNECTED);
+ if (connection_tls_start_handshake(conn, 0) < 0)
+ ret = -1;
+ }
+ if (ret < 0) {
+ connection_mark_for_close(TO_CONN(conn));
+ }
+
+ return ret;
case OR_CONN_STATE_OPEN:
case OR_CONN_STATE_OR_HANDSHAKING:
return connection_or_process_cells_from_inbuf(conn);
@@ -285,8 +252,7 @@ connection_or_flushed_some(or_connection_t *conn)
/* If we're under the low water mark, add cells until we're just over the
* high water mark. */
if (datalen < OR_CONN_LOWWATER) {
- ssize_t n = (OR_CONN_HIGHWATER - datalen + CELL_NETWORK_SIZE-1)
- / CELL_NETWORK_SIZE;
+ ssize_t n = CEIL_DIV(OR_CONN_HIGHWATER - datalen, CELL_NETWORK_SIZE);
time_t now = approx_time();
while (conn->active_circuits && n > 0) {
int flushed;
@@ -312,11 +278,7 @@ connection_or_finished_flushing(or_connection_t *conn)
assert_connection_ok(TO_CONN(conn),0);
switch (conn->_base.state) {
- case OR_CONN_STATE_PROXY_FLUSHING:
- log_debug(LD_OR,"finished sending CONNECT to proxy.");
- conn->_base.state = OR_CONN_STATE_PROXY_READING;
- connection_stop_writing(TO_CONN(conn));
- break;
+ case OR_CONN_STATE_PROXY_HANDSHAKING:
case OR_CONN_STATE_OPEN:
case OR_CONN_STATE_OR_HANDSHAKING:
connection_stop_writing(TO_CONN(conn));
@@ -334,37 +296,34 @@ connection_or_finished_flushing(or_connection_t *conn)
int
connection_or_finished_connecting(or_connection_t *or_conn)
{
+ int proxy_type;
connection_t *conn;
tor_assert(or_conn);
conn = TO_CONN(or_conn);
tor_assert(conn->state == OR_CONN_STATE_CONNECTING);
- log_debug(LD_OR,"OR connect() to router at %s:%u finished.",
+ log_debug(LD_HANDSHAKE,"OR connect() to router at %s:%u finished.",
conn->address,conn->port);
control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0);
- if (get_options()->HttpsProxy) {
- char buf[1024];
- char *base64_authenticator=NULL;
- const char *authenticator = get_options()->HttpsProxyAuthenticator;
+ proxy_type = PROXY_NONE;
- if (authenticator) {
- base64_authenticator = alloc_http_authenticator(authenticator);
- if (!base64_authenticator)
- log_warn(LD_OR, "Encoding https authenticator failed");
- }
- if (base64_authenticator) {
- tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1\r\n"
- "Proxy-Authorization: Basic %s\r\n\r\n",
- fmt_addr(&conn->addr),
- conn->port, base64_authenticator);
- tor_free(base64_authenticator);
- } else {
- tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n\r\n",
- fmt_addr(&conn->addr), conn->port);
+ if (get_options()->HTTPSProxy)
+ proxy_type = PROXY_CONNECT;
+ else if (get_options()->Socks4Proxy)
+ proxy_type = PROXY_SOCKS4;
+ else if (get_options()->Socks5Proxy)
+ proxy_type = PROXY_SOCKS5;
+
+ if (proxy_type != PROXY_NONE) {
+ /* start proxy handshake */
+ if (connection_proxy_connect(conn, proxy_type) < 0) {
+ connection_mark_for_close(conn);
+ return -1;
}
- connection_write_to_buf(buf, strlen(buf), conn);
- conn->state = OR_CONN_STATE_PROXY_FLUSHING;
+
+ connection_start_reading(conn);
+ conn->state = OR_CONN_STATE_PROXY_HANDSHAKING;
return 0;
}
@@ -376,6 +335,78 @@ connection_or_finished_connecting(or_connection_t *or_conn)
return 0;
}
+/** Return 1 if identity digest <b>id_digest</b> is known to be a
+ * currently or recently running relay. Otherwise return 0. */
+int
+connection_or_digest_is_known_relay(const char *id_digest)
+{
+ if (router_get_consensus_status_by_id(id_digest))
+ return 1; /* It's in the consensus: "yes" */
+ if (router_get_by_digest(id_digest))
+ return 1; /* Not in the consensus, but we have a descriptor for
+ * it. Probably it was in a recent consensus. "Yes". */
+ return 0;
+}
+
+/** Set the per-conn read and write limits for <b>conn</b>. If it's a known
+ * relay, we will rely on the global read and write buckets, so give it
+ * per-conn limits that are big enough they'll never matter. But if it's
+ * not a known relay, first check if we set PerConnBwRate/Burst, then
+ * check if the consensus sets them, else default to 'big enough'.
+ *
+ * If <b>reset</b> is true, set the bucket to be full. Otherwise, just
+ * clip the bucket if it happens to be <em>too</em> full.
+ */
+static void
+connection_or_update_token_buckets_helper(or_connection_t *conn, int reset,
+ or_options_t *options)
+{
+ int rate, burst; /* per-connection rate limiting params */
+ if (connection_or_digest_is_known_relay(conn->identity_digest)) {
+ /* It's in the consensus, or we have a descriptor for it meaning it
+ * was probably in a recent consensus. It's a recognized relay:
+ * give it full bandwidth. */
+ rate = (int)options->BandwidthRate;
+ burst = (int)options->BandwidthBurst;
+ } else {
+ /* Not a recognized relay. Squeeze it down based on the suggested
+ * bandwidth parameters in the consensus, but allow local config
+ * options to override. */
+ rate = options->PerConnBWRate ? (int)options->PerConnBWRate :
+ networkstatus_get_param(NULL, "perconnbwrate",
+ (int)options->BandwidthRate, 1, INT32_MAX);
+ burst = options->PerConnBWBurst ? (int)options->PerConnBWBurst :
+ networkstatus_get_param(NULL, "perconnbwburst",
+ (int)options->BandwidthBurst, 1, INT32_MAX);
+ }
+
+ conn->bandwidthrate = rate;
+ conn->bandwidthburst = burst;
+ if (reset) { /* set up the token buckets to be full */
+ conn->read_bucket = conn->write_bucket = burst;
+ return;
+ }
+ /* If the new token bucket is smaller, take out the extra tokens.
+ * (If it's larger, don't -- the buckets can grow to reach the cap.) */
+ if (conn->read_bucket > burst)
+ conn->read_bucket = burst;
+ if (conn->write_bucket > burst)
+ conn->write_bucket = burst;
+}
+
+/** Either our set of relays or our per-conn rate limits have changed.
+ * Go through all the OR connections and update their token buckets to make
+ * sure they don't exceed their maximum values. */
+void
+connection_or_update_token_buckets(smartlist_t *conns, or_options_t *options)
+{
+ SMARTLIST_FOREACH(conns, connection_t *, conn,
+ {
+ if (connection_speaks_cells(conn))
+ connection_or_update_token_buckets_helper(TO_OR_CONN(conn), 0, options);
+ });
+}
+
/** If we don't necessarily know the router we're connecting to, but we
* have an addr/port/id_digest, then fill in as much as we can. Start
* by checking to see if this describes a router we know. */
@@ -385,11 +416,9 @@ connection_or_init_conn_from_address(or_connection_t *conn,
const char *id_digest,
int started_here)
{
- or_options_t *options = get_options();
routerinfo_t *r = router_get_by_digest(id_digest);
- conn->bandwidthrate = (int)options->BandwidthRate;
- conn->read_bucket = conn->bandwidthburst = (int)options->BandwidthBurst;
connection_or_set_identity_digest(conn, id_digest);
+ connection_or_update_token_buckets_helper(conn, 1, get_options());
conn->_base.port = port;
tor_addr_copy(&conn->_base.addr, addr);
@@ -442,7 +471,7 @@ connection_or_init_conn_from_address(or_connection_t *conn,
* Requires that both input connections are open; not is_bad_for_new_circs,
* and not impossibly non-canonical.
*
- * If </b>forgive_new_connections</b> is true, then we do not call
+ * If <b>forgive_new_connections</b> is true, then we do not call
* <b>a</b>better than <b>b</b> simply because b has no circuits,
* unless b is also relatively old.
*/
@@ -581,11 +610,24 @@ connection_or_get_for_extend(const char *digest,
#define TIME_BEFORE_OR_CONN_IS_TOO_OLD (60*60*24*7)
/** Given the head of the linked list for all the or_connections with a given
- * identity, set elements of that list as is_bad_for_new_circs() as
- * appropriate. Helper for connection_or_set_bad_connections().
+ * identity, set elements of that list as is_bad_for_new_circs as
+ * appropriate. Helper for connection_or_set_bad_connections().
+ *
+ * Specifically, we set the is_bad_for_new_circs flag on:
+ * - all connections if <b>force</b> is true.
+ * - all connections that are too old.
+ * - all open non-canonical connections for which a canonical connection
+ * exists to the same router.
+ * - all open canonical connections for which a 'better' canonical
+ * connection exists to the same router.
+ * - all open non-canonical connections for which a 'better' non-canonical
+ * connection exists to the same router at the same address.
+ *
+ * See connection_or_is_better() for our idea of what makes one OR connection
+ * better than another.
*/
static void
-connection_or_group_set_badness(or_connection_t *head)
+connection_or_group_set_badness(or_connection_t *head, int force)
{
or_connection_t *or_conn = NULL, *best = NULL;
int n_old = 0, n_inprogress = 0, n_canonical = 0, n_other = 0;
@@ -597,8 +639,9 @@ connection_or_group_set_badness(or_connection_t *head)
if (or_conn->_base.marked_for_close ||
or_conn->is_bad_for_new_circs)
continue;
- if (or_conn->_base.timestamp_created + TIME_BEFORE_OR_CONN_IS_TOO_OLD
- < now) {
+ if (force ||
+ or_conn->_base.timestamp_created + TIME_BEFORE_OR_CONN_IS_TOO_OLD
+ < now) {
log_info(LD_OR,
"Marking OR conn to %s:%d as too old for new circuits "
"(fd %d, %d secs old).",
@@ -631,7 +674,7 @@ connection_or_group_set_badness(or_connection_t *head)
/* We have at least one open canonical connection to this router,
* and this one is open but not canonical. Mark it bad. */
log_info(LD_OR,
- "Marking OR conn to %s:%d as too old for new circuits: "
+ "Marking OR conn to %s:%d as unsuitable for new circuits: "
"(fd %d, %d secs old). It is not canonical, and we have "
"another connection to that OR that is.",
or_conn->_base.address, or_conn->_base.port, or_conn->_base.s,
@@ -671,7 +714,7 @@ connection_or_group_set_badness(or_connection_t *head)
even when we're being forgiving. */
if (best->is_canonical) {
log_info(LD_OR,
- "Marking OR conn to %s:%d as too old for new circuits: "
+ "Marking OR conn to %s:%d as unsuitable for new circuits: "
"(fd %d, %d secs old). We have a better canonical one "
"(fd %d; %d secs old).",
or_conn->_base.address, or_conn->_base.port, or_conn->_base.s,
@@ -681,9 +724,9 @@ connection_or_group_set_badness(or_connection_t *head)
} else if (!tor_addr_compare(&or_conn->real_addr,
&best->real_addr, CMP_EXACT)) {
log_info(LD_OR,
- "Marking OR conn to %s:%d as too old for new circuits: "
- "(fd %d, %d secs old). We have a better one "
- "(fd %d; %d secs old).",
+ "Marking OR conn to %s:%d as unsuitable for new circuits: "
+ "(fd %d, %d secs old). We have a better one with the "
+ "same address (fd %d; %d secs old).",
or_conn->_base.address, or_conn->_base.port, or_conn->_base.s,
(int)(now - or_conn->_base.timestamp_created),
best->_base.s, (int)(now - best->_base.timestamp_created));
@@ -693,27 +736,20 @@ connection_or_group_set_badness(or_connection_t *head)
}
}
-/** Go through all the OR connections, and set the is_bad_for_new_circs
- * flag on:
- * - all connections that are too old.
- * - all open non-canonical connections for which a canonical connection
- * exists to the same router.
- * - all open canonical connections for which a 'better' canonical
- * connection exists to the same router.
- * - all open non-canonical connections for which a 'better' non-canonical
- * connection exists to the same router at the same address.
- *
- * See connection_or_is_better() for our idea of what makes one OR connection
- * better than another.
+/** Go through all the OR connections (or if <b>digest</b> is non-NULL, just
+ * the OR connections with that digest), and set the is_bad_for_new_circs
+ * flag based on the rules in connection_or_group_set_badness() (or just
+ * always set it if <b>force</b> is true).
*/
void
-connection_or_set_bad_connections(void)
+connection_or_set_bad_connections(const char *digest, int force)
{
if (!orconn_identity_map)
return;
DIGESTMAP_FOREACH(orconn_identity_map, identity, or_connection_t *, conn) {
- connection_or_group_set_badness(conn);
+ if (!digest || tor_memeq(digest, conn->identity_digest, DIGEST_LEN))
+ connection_or_group_set_badness(conn, force);
} DIGESTMAP_FOREACH_END;
}
@@ -753,6 +789,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
or_connection_t *conn;
or_options_t *options = get_options();
int socket_error = 0;
+ int using_proxy = 0;
tor_addr_t addr;
tor_assert(_addr);
@@ -771,19 +808,27 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
conn->_base.state = OR_CONN_STATE_CONNECTING;
control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED, 0);
- if (options->HttpsProxy) {
- /* we shouldn't connect directly. use the https proxy instead. */
- tor_addr_from_ipv4h(&addr, options->HttpsProxyAddr);
- port = options->HttpsProxyPort;
+ /* use a proxy server if available */
+ if (options->HTTPSProxy) {
+ using_proxy = 1;
+ tor_addr_copy(&addr, &options->HTTPSProxyAddr);
+ port = options->HTTPSProxyPort;
+ } else if (options->Socks4Proxy) {
+ using_proxy = 1;
+ tor_addr_copy(&addr, &options->Socks4ProxyAddr);
+ port = options->Socks4ProxyPort;
+ } else if (options->Socks5Proxy) {
+ using_proxy = 1;
+ tor_addr_copy(&addr, &options->Socks5ProxyAddr);
+ port = options->Socks5ProxyPort;
}
switch (connection_connect(TO_CONN(conn), conn->_base.address,
&addr, port, &socket_error)) {
case -1:
/* If the connection failed immediately, and we're using
- * an https proxy, our https proxy is down. Don't blame the
- * Tor server. */
- if (!options->HttpsProxy)
+ * a proxy, our proxy is down. Don't blame the Tor server. */
+ if (!using_proxy)
entry_guard_register_connect_status(conn->identity_digest,
0, 1, time(NULL));
connection_or_connect_failed(conn,
@@ -792,7 +837,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
connection_free(TO_CONN(conn));
return NULL;
case 0:
- connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
+ connection_watch_events(TO_CONN(conn), READ_EVENT | WRITE_EVENT);
/* writable indicates finish, readable indicates broken link,
error indicates broken link on windows */
return conn;
@@ -819,13 +864,14 @@ connection_tls_start_handshake(or_connection_t *conn, int receiving)
{
conn->_base.state = OR_CONN_STATE_TLS_HANDSHAKING;
conn->tls = tor_tls_new(conn->_base.s, receiving);
- tor_tls_set_logged_address(conn->tls, escaped_safe_str(conn->_base.address));
+ tor_tls_set_logged_address(conn->tls, // XXX client and relay?
+ escaped_safe_str(conn->_base.address));
if (!conn->tls) {
log_warn(LD_BUG,"tor_tls_new failed. Closing.");
return -1;
}
connection_start_reading(TO_CONN(conn));
- log_debug(LD_OR,"starting TLS handshake on fd %d", conn->_base.s);
+ log_debug(LD_HANDSHAKE,"starting TLS handshake on fd %d", conn->_base.s);
note_crypto_pk_op(receiving ? TLS_HANDSHAKE_S : TLS_HANDSHAKE_C);
if (connection_tls_continue_handshake(conn) < 0) {
@@ -932,23 +978,26 @@ connection_or_nonopen_was_started_here(or_connection_t *conn)
* return -1 if he is lying, broken, or otherwise something is wrong.
*
* If we initiated this connection (<b>started_here</b> is true), make sure
- * the other side sent sent a correctly formed certificate. If I initiated the
+ * the other side sent a correctly formed certificate. If I initiated the
* connection, make sure it's the right guy.
*
* Otherwise (if we _didn't_ initiate this connection), it's okay for
* the certificate to be weird or absent.
*
* If we return 0, and the certificate is as expected, write a hash of the
- * identity key into digest_rcvd, which must have DIGEST_LEN space in it. (If
- * we return -1 this buffer is undefined.) If the certificate is invalid
- * or missing on an incoming connection, we return 0 and set digest_rcvd to
- * DIGEST_LEN 0 bytes.
+ * identity key into <b>digest_rcvd_out</b>, which must have DIGEST_LEN
+ * space in it.
+ * If the certificate is invalid or missing on an incoming connection,
+ * we return 0 and set <b>digest_rcvd_out</b> to DIGEST_LEN NUL bytes.
+ * (If we return -1, the contents of this buffer are undefined.)
*
* As side effects,
* 1) Set conn->circ_id_type according to tor-spec.txt.
* 2) If we're an authdirserver and we initiated the connection: drop all
* descriptors that claim to be on that IP/port but that aren't
* this guy; and note that this guy is reachable.
+ * 3) If this is a bridge and we didn't configure its identity
+ * fingerprint, remember the keyid we just learned.
*/
static int
connection_or_check_valid_tls_handshake(or_connection_t *conn,
@@ -959,19 +1008,23 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
or_options_t *options = get_options();
int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN;
const char *safe_address =
- started_here ? conn->_base.address : safe_str(conn->_base.address);
+ started_here ? conn->_base.address :
+ safe_str_client(conn->_base.address);
const char *conn_type = started_here ? "outgoing" : "incoming";
+ crypto_pk_env_t *our_identity =
+ started_here ? get_tlsclient_identity_key() :
+ get_server_identity_key();
int has_cert = 0, has_identity=0;
check_no_tls_errors();
has_cert = tor_tls_peer_has_cert(conn->tls);
if (started_here && !has_cert) {
- log_info(LD_PROTOCOL,"Tried connecting to router at %s:%d, but it didn't "
+ log_info(LD_HANDSHAKE,"Tried connecting to router at %s:%d, but it didn't "
"send a cert! Closing.",
safe_address, conn->_base.port);
return -1;
} else if (!has_cert) {
- log_debug(LD_PROTOCOL,"Got incoming connection with no certificate. "
+ log_debug(LD_HANDSHAKE,"Got incoming connection with no certificate. "
"That's ok.");
}
check_no_tls_errors();
@@ -980,15 +1033,16 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
int v = tor_tls_verify(started_here?severity:LOG_INFO,
conn->tls, &identity_rcvd);
if (started_here && v<0) {
- log_fn(severity,LD_OR,"Tried connecting to router at %s:%d: It"
+ log_fn(severity,LD_HANDSHAKE,"Tried connecting to router at %s:%d: It"
" has a cert but it's invalid. Closing.",
safe_address, conn->_base.port);
return -1;
} else if (v<0) {
- log_info(LD_PROTOCOL,"Incoming connection gave us an invalid cert "
+ log_info(LD_HANDSHAKE,"Incoming connection gave us an invalid cert "
"chain; ignoring.");
} else {
- log_debug(LD_OR,"The certificate seems to be valid on %s connection "
+ log_debug(LD_HANDSHAKE,
+ "The certificate seems to be valid on %s connection "
"with %s:%d", conn_type, safe_address, conn->_base.port);
}
check_no_tls_errors();
@@ -997,7 +1051,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
if (identity_rcvd) {
has_identity = 1;
crypto_pk_get_digest(identity_rcvd, digest_rcvd_out);
- if (crypto_pk_cmp_keys(get_identity_key(), identity_rcvd)<0) {
+ if (crypto_pk_cmp_keys(our_identity, identity_rcvd)<0) {
conn->circ_id_type = CIRC_ID_TYPE_LOWER;
} else {
conn->circ_id_type = CIRC_ID_TYPE_HIGHER;
@@ -1015,9 +1069,13 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
conn->nickname[0] = '$';
base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1,
conn->identity_digest, DIGEST_LEN);
- log_info(LD_OR, "Connected to router %s at %s:%d without knowing "
+ log_info(LD_HANDSHAKE, "Connected to router %s at %s:%d without knowing "
"its key. Hoping for the best.",
conn->nickname, conn->_base.address, conn->_base.port);
+ /* if it's a bridge and we didn't know its identity fingerprint, now
+ * we do -- remember it for future attempts. */
+ learned_router_identity(&conn->_base.addr, conn->_base.port,
+ digest_rcvd_out);
}
if (started_here) {
@@ -1031,7 +1089,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
base16_encode(seen, sizeof(seen), digest_rcvd_out, DIGEST_LEN);
base16_encode(expected, sizeof(expected), conn->identity_digest,
DIGEST_LEN);
- log_fn(severity, LD_OR,
+ log_fn(severity, LD_HANDSHAKE,
"Tried connecting to router at %s:%d, but identity key was not "
"as expected: wanted %s but got %s.",
conn->_base.address, conn->_base.port, expected, seen);
@@ -1044,9 +1102,6 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
as_advertised = 0;
}
if (authdir_mode_tests_reachability(options)) {
- /* We initiated this connection to address:port. Drop all routers
- * with the same address:port and a different key.
- */
dirserv_orconn_tls_done(conn->_base.address, conn->_base.port,
digest_rcvd_out, as_advertised);
}
@@ -1073,8 +1128,8 @@ connection_tls_finish_handshake(or_connection_t *conn)
char digest_rcvd[DIGEST_LEN];
int started_here = connection_or_nonopen_was_started_here(conn);
- log_debug(LD_OR,"tls handshake with %s done. verifying.",
- safe_str(conn->_base.address));
+ log_debug(LD_HANDSHAKE,"tls handshake with %s done. verifying.",
+ safe_str_client(conn->_base.address));
directory_set_dirty();
@@ -1082,6 +1137,8 @@ connection_tls_finish_handshake(or_connection_t *conn)
digest_rcvd) < 0)
return -1;
+ circuit_build_times_network_is_live(&circ_times);
+
if (tor_tls_used_v1_handshake(conn->tls)) {
conn->link_proto = 1;
if (!started_here) {
@@ -1117,7 +1174,8 @@ connection_init_or_handshake_state(or_connection_t *conn, int started_here)
void
or_handshake_state_free(or_handshake_state_t *state)
{
- tor_assert(state);
+ if (!state)
+ return;
memset(state, 0xBE, sizeof(or_handshake_state_t));
tor_free(state);
}
@@ -1134,6 +1192,7 @@ connection_or_set_state_open(or_connection_t *conn)
control_event_or_conn_status(conn, OR_CONN_EVENT_CONNECTED, 0);
if (started_here) {
+ circuit_build_times_network_is_live(&circ_times);
rep_hist_note_connect_succeeded(conn->identity_digest, now);
if (entry_guard_register_connect_status(conn->identity_digest,
1, 0, now) < 0) {
@@ -1158,10 +1217,10 @@ connection_or_set_state_open(or_connection_t *conn)
}
}
}
- if (conn->handshake_state) {
- or_handshake_state_free(conn->handshake_state);
- conn->handshake_state = NULL;
- }
+
+ or_handshake_state_free(conn->handshake_state);
+ conn->handshake_state = NULL;
+
connection_start_reading(TO_CONN(conn));
circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
@@ -1235,6 +1294,7 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
if (connection_fetch_var_cell_from_buf(conn, &var_cell)) {
if (!var_cell)
return 0; /* not yet. */
+ circuit_build_times_network_is_live(&circ_times);
command_process_var_cell(var_cell, conn);
var_cell_free(var_cell);
} else {
@@ -1244,6 +1304,7 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
available? */
return 0; /* not yet */
+ circuit_build_times_network_is_live(&circ_times);
connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, TO_CONN(conn));
/* retrieve cell info from buf (create the host-order struct from the
@@ -1274,10 +1335,6 @@ connection_or_send_destroy(circid_t circ_id, or_connection_t *conn, int reason)
cell.payload[0] = (uint8_t) reason;
log_debug(LD_OR,"Sending destroy (circID %d).", circ_id);
- /* XXXX It's possible that under some circumstances, we want the destroy
- * to take precedence over other data waiting on the circuit's cell queue.
- */
-
connection_or_write_cell_to_buf(&cell, conn);
return 0;
}
@@ -1357,9 +1414,8 @@ connection_or_send_netinfo(or_connection_t *conn)
len = append_address_to_payload(out, &my_addr);
if (len < 0)
return -1;
- out += len;
} else {
- *out++ = 0;
+ *out = 0;
}
connection_or_write_cell_to_buf(&cell, conn);