diff options
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/buffers.c | 2 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 13 | ||||
-rw-r--r-- | src/or/circuitbuild.h | 2 | ||||
-rw-r--r-- | src/or/command.c | 17 | ||||
-rw-r--r-- | src/or/config.c | 4 | ||||
-rw-r--r-- | src/or/connection_edge.c | 26 | ||||
-rw-r--r-- | src/or/connection_edge.h | 2 | ||||
-rw-r--r-- | src/or/connection_or.c | 5 | ||||
-rw-r--r-- | src/or/control.c | 3 | ||||
-rw-r--r-- | src/or/dirserv.c | 16 | ||||
-rw-r--r-- | src/or/hibernate.c | 28 | ||||
-rw-r--r-- | src/or/main.c | 3 | ||||
-rw-r--r-- | src/or/onion.c | 14 | ||||
-rw-r--r-- | src/or/onion.h | 12 | ||||
-rw-r--r-- | src/or/or.h | 6 | ||||
-rw-r--r-- | src/or/relay.c | 84 | ||||
-rw-r--r-- | src/or/relay.h | 10 | ||||
-rw-r--r-- | src/or/rendclient.c | 13 | ||||
-rw-r--r-- | src/or/rendclient.h | 9 | ||||
-rw-r--r-- | src/or/rendcommon.c | 2 | ||||
-rw-r--r-- | src/or/rendcommon.h | 3 | ||||
-rw-r--r-- | src/or/rendmid.c | 30 | ||||
-rw-r--r-- | src/or/rendmid.h | 8 | ||||
-rw-r--r-- | src/or/rendservice.c | 9 | ||||
-rw-r--r-- | src/or/rendservice.h | 4 | ||||
-rw-r--r-- | src/or/rephist.c | 148 | ||||
-rw-r--r-- | src/or/router.c | 2 |
27 files changed, 298 insertions, 177 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c index 658a924cef..f84fb45c64 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -1048,7 +1048,7 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto) result->circ_id = ntohs(get_uint16(hdr)); buf_remove_from_front(buf, VAR_CELL_HEADER_SIZE); - peek_from_buf(result->payload, length, buf); + peek_from_buf((char*) result->payload, length, buf); buf_remove_from_front(buf, length); check(); diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 473b28e872..2fe750ea5b 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1902,7 +1902,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) * and a DH operation. */ cell_type = CELL_CREATE_FAST; memset(payload, 0, sizeof(payload)); - crypto_rand(circ->cpath->fast_handshake_state, + crypto_rand((char*) circ->cpath->fast_handshake_state, sizeof(circ->cpath->fast_handshake_state)); memcpy(payload, circ->cpath->fast_handshake_state, sizeof(circ->cpath->fast_handshake_state)); @@ -2081,8 +2081,8 @@ circuit_extend(cell_t *cell, circuit_t *circ) n_addr32 = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE)); n_port = ntohs(get_uint16(cell->payload+RELAY_HEADER_SIZE+4)); - onionskin = cell->payload+RELAY_HEADER_SIZE+4+2; - id_digest = cell->payload+RELAY_HEADER_SIZE+4+2+ONIONSKIN_CHALLENGE_LEN; + onionskin = (char*) cell->payload+RELAY_HEADER_SIZE+4+2; + id_digest = (char*) cell->payload+RELAY_HEADER_SIZE+4+2+ONIONSKIN_CHALLENGE_LEN; tor_addr_from_ipv4h(&n_addr, n_addr32); if (!n_port || !n_addr32) { @@ -2220,7 +2220,7 @@ circuit_init_cpath_crypto(crypt_path_t *cpath, const char *key_data, */ int circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, - const char *reply) + const uint8_t *reply) { char keys[CPATH_KEY_MATERIAL_LEN]; crypt_path_t *hop; @@ -2237,7 +2237,7 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, tor_assert(hop->state == CPATH_STATE_AWAITING_KEYS); if (reply_type == CELL_CREATED && hop->dh_handshake_state) { - if (onion_skin_client_handshake(hop->dh_handshake_state, reply, keys, + if (onion_skin_client_handshake(hop->dh_handshake_state, (char*)reply, keys, DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) { log_warn(LD_CIRC,"onion_skin_client_handshake failed."); return -END_CIRC_REASON_TORPROTOCOL; @@ -2245,7 +2245,8 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, /* Remember hash of g^xy */ memcpy(hop->handshake_digest, reply+DH_KEY_LEN, DIGEST_LEN); } else if (reply_type == CELL_CREATED_FAST && !hop->dh_handshake_state) { - if (fast_client_handshake(hop->fast_handshake_state, reply, keys, + if (fast_client_handshake(hop->fast_handshake_state, reply, + (uint8_t*)keys, DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) { log_warn(LD_CIRC,"fast_client_handshake failed."); return -END_CIRC_REASON_TORPROTOCOL; diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index 888bf9d255..a85c410133 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -31,7 +31,7 @@ int circuit_extend(cell_t *cell, circuit_t *circ); int circuit_init_cpath_crypto(crypt_path_t *cpath, const char *key_data, int reverse); int circuit_finish_handshake(origin_circuit_t *circ, uint8_t cell_type, - const char *reply); + const uint8_t *reply); int circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer); int onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload, const char *keys); diff --git a/src/or/command.c b/src/or/command.c index ea0bbea1e5..beb5d09a9d 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -306,7 +306,8 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn) char keys[CPATH_KEY_MATERIAL_LEN]; char reply[DIGEST_LEN*2]; tor_assert(cell->command == CELL_CREATE_FAST); - if (fast_server_handshake(cell->payload, reply, keys, sizeof(keys))<0) { + if (fast_server_handshake(cell->payload, (uint8_t*)reply, + (uint8_t*)keys, sizeof(keys))<0) { log_warn(LD_OR,"Failed to generate key material. Closing."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); return; @@ -353,7 +354,7 @@ command_process_created_cell(cell_t *cell, or_connection_t *conn) int err_reason = 0; log_debug(LD_OR,"at OP. Finishing handshake."); if ((err_reason = circuit_finish_handshake(origin_circ, cell->command, - cell->payload)) < 0) { + cell->payload)) < 0) { log_warn(LD_OR,"circuit_finish_handshake failed."); circuit_mark_for_close(circ, -err_reason); return; @@ -369,7 +370,7 @@ command_process_created_cell(cell_t *cell, or_connection_t *conn) log_debug(LD_OR, "Converting created cell to extended relay cell, sending."); relay_send_command_from_edge(0, circ, RELAY_COMMAND_EXTENDED, - cell->payload, ONIONSKIN_REPLY_LEN, + (char*)cell->payload, ONIONSKIN_REPLY_LEN, NULL); } } @@ -499,7 +500,7 @@ static void command_process_versions_cell(var_cell_t *cell, or_connection_t *conn) { int highest_supported_version = 0; - const char *cp, *end; + const uint8_t *cp, *end; if (conn->link_proto != 0 || conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING || (conn->handshake_state && conn->handshake_state->received_versions)) { @@ -553,8 +554,8 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) time_t timestamp; uint8_t my_addr_type; uint8_t my_addr_len; - const char *my_addr_ptr; - const char *cp, *end; + const uint8_t *my_addr_ptr; + const uint8_t *cp, *end; uint8_t n_other_addrs; time_t now = time(NULL); @@ -582,7 +583,7 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) my_addr_type = (uint8_t) cell->payload[4]; my_addr_len = (uint8_t) cell->payload[5]; - my_addr_ptr = cell->payload + 6; + my_addr_ptr = (uint8_t*) cell->payload + 6; end = cell->payload + CELL_PAYLOAD_SIZE; cp = cell->payload + 6 + my_addr_len; if (cp >= end) { @@ -599,7 +600,7 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) /* Consider all the other addresses; if any matches, this connection is * "canonical." */ tor_addr_t addr; - const char *next = decode_address_from_payload(&addr, cp, (int)(end-cp)); + const uint8_t *next = decode_address_from_payload(&addr, cp, (int)(end-cp)); if (next == NULL) { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Bad address in netinfo cell; closing connection."); diff --git a/src/or/config.c b/src/or/config.c index bd8c45758b..7fea8500b2 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -787,9 +787,9 @@ add_default_trusted_dir_authorities(authority_type_t type) "4A0C CD2D DC79 9508 3D73 F5D6 6710 0C8A 5831 F16D", "ides orport=9090 no-v2 v3ident=27B6B5996C426270A5C95488AA5BCEB6BCC86956 " "216.224.124.114:9030 F397 038A DC51 3361 35E7 B80B D99C A384 4360 292B", - "gabelmoo orport=8080 no-v2 " + "gabelmoo orport=443 no-v2 " "v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 " - "80.190.246.100:8180 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281", + "212.112.245.170:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281", "dannenberg orport=443 no-v2 " "v3ident=585769C78764D58426B8B52B6651A5A71137189A " "193.23.244.244:80 7BE6 83E6 5D48 1413 21C5 ED92 F075 C553 64AC 7123", diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index cc040b1780..2bfa88e6a9 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1492,7 +1492,8 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, tor_snprintf(socks->address, sizeof(socks->address), "REVERSE[%s]", orig_address); connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_HOSTNAME, - strlen(result), result, -1, + strlen(result), (uint8_t*)result, + -1, map_expires); connection_mark_unattached_ap(conn, END_STREAM_REASON_DONE | @@ -1613,7 +1614,8 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, /* remember _what_ is supposed to have been resolved. */ strlcpy(socks->address, orig_address, sizeof(socks->address)); connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4, - (char*)&answer,-1,map_expires); + (uint8_t*)&answer, + -1,map_expires); connection_mark_unattached_ap(conn, END_STREAM_REASON_DONE | END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -2318,7 +2320,7 @@ void connection_ap_handshake_socks_resolved(edge_connection_t *conn, int answer_type, size_t answer_len, - const char *answer, + const uint8_t *answer, int ttl, time_t expires) { @@ -2332,7 +2334,7 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn, client_dns_set_addressmap(conn->socks_request->address, a, conn->chosen_exit_name, ttl); } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) { - char *cp = tor_strndup(answer, answer_len); + char *cp = tor_strndup((char*)answer, answer_len); client_dns_set_reverse_addressmap(conn->socks_request->address, cp, conn->chosen_exit_name, ttl); @@ -2343,14 +2345,14 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn, if (conn->is_dns_request) { if (conn->dns_server_request) { /* We had a request on our DNS port: answer it. */ - dnsserv_resolved(conn, answer_type, answer_len, answer, ttl); + dnsserv_resolved(conn, answer_type, answer_len, (char*)answer, ttl); conn->socks_request->has_finished = 1; return; } else { /* This must be a request from the controller. We already sent * a mapaddress if there's a ttl. */ tell_controller_about_resolved_result(conn, answer_type, answer_len, - answer, ttl, expires); + (char*)answer, ttl, expires); conn->socks_request->has_finished = 1; return; } @@ -2495,6 +2497,8 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) or_circ = TO_OR_CIRCUIT(circ); relay_header_unpack(&rh, cell->payload); + if (rh.length > RELAY_PAYLOAD_SIZE) + return -1; /* Note: we have to use relay_send_command_from_edge here, not * connection_edge_end or connection_edge_send_command, since those require @@ -2518,7 +2522,8 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) END_STREAM_REASON_TORPROTOCOL, NULL); return 0; } - if (parse_addr_port(LOG_PROTOCOL_WARN, cell->payload+RELAY_HEADER_SIZE, + if (parse_addr_port(LOG_PROTOCOL_WARN, + (char*)(cell->payload+RELAY_HEADER_SIZE), &address,NULL,&port)<0) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Unable to parse addr:port in relay begin cell. Closing."); @@ -2683,6 +2688,8 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ) assert_circuit_ok(TO_CIRCUIT(circ)); relay_header_unpack(&rh, cell->payload); + if (rh.length > RELAY_PAYLOAD_SIZE) + return -1; /* This 'dummy_conn' only exists to remember the stream ID * associated with the resolve request; and to make the @@ -2693,8 +2700,9 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ) */ dummy_conn = edge_connection_new(CONN_TYPE_EXIT, AF_INET); dummy_conn->stream_id = rh.stream_id; - dummy_conn->_base.address = tor_strndup(cell->payload+RELAY_HEADER_SIZE, - rh.length); + dummy_conn->_base.address = tor_strndup( + (char*)cell->payload+RELAY_HEADER_SIZE, + rh.length); dummy_conn->_base.port = 0; dummy_conn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED; dummy_conn->_base.purpose = EXIT_PURPOSE_RESOLVE; diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h index 762af5172e..cca82022c3 100644 --- a/src/or/connection_edge.h +++ b/src/or/connection_edge.h @@ -38,7 +38,7 @@ void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply, void connection_ap_handshake_socks_resolved(edge_connection_t *conn, int answer_type, size_t answer_len, - const char *answer, + const uint8_t *answer, int ttl, time_t expires); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 415a48dca3..45266a99b1 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -1259,7 +1259,8 @@ connection_or_write_var_cell_to_buf(const var_cell_t *cell, tor_assert(conn); var_cell_pack_header(cell, hdr); connection_write_to_buf(hdr, sizeof(hdr), TO_CONN(conn)); - connection_write_to_buf(cell->payload, cell->payload_len, TO_CONN(conn)); + connection_write_to_buf((char*)cell->payload, + cell->payload_len, TO_CONN(conn)); if (cell->command != CELL_PADDING) conn->timestamp_last_added_nonpadding = approx_time(); } @@ -1388,7 +1389,7 @@ connection_or_send_netinfo(or_connection_t *conn) time_t now = time(NULL); routerinfo_t *me; int len; - char *out; + uint8_t *out; memset(&cell, 0, sizeof(cell_t)); cell.command = CELL_NETINFO; diff --git a/src/or/control.c b/src/or/control.c index 4d505a98fb..ad316c4ebc 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -2855,9 +2855,10 @@ connection_control_process_inbuf(control_connection_t *conn) && !TOR_ISSPACE(conn->incoming_cmd[cmd_len])) ++cmd_len; - data_len -= cmd_len; conn->incoming_cmd[cmd_len]='\0'; args = conn->incoming_cmd+cmd_len+1; + tor_assert(data_len>(size_t)cmd_len); + data_len -= (cmd_len+1); /* skip the command and NUL we added after it */ while (*args == ' ' || *args == '\t') { ++args; --data_len; diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 42d7d561ce..841c86624b 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -386,13 +386,19 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, strmap_size(fingerprint_list->fp_by_name), digestmap_size(fingerprint_list->status_by_digest)); - /* Tor 0.1.2.x is pretty old, but there are a lot of them running still, - * and there aren't any critical relay-side vulnerabilities. Once more - * of them die off, we should raise this minimum to 0.2.0.x. */ - if (platform && !tor_version_as_new_as(platform,"0.1.2.14")) { + /* Tor 0.2.0.26-rc is the oldest version that currently caches the right + * directory information. Once more of them die off, we should raise this + * minimum. */ + if (platform && !tor_version_as_new_as(platform,"0.2.0.26-rc")) { if (msg) *msg = "Tor version is far too old to work."; return FP_REJECT; + } else if (platform && tor_version_as_new_as(platform,"0.2.1.3-alpha") + && !tor_version_as_new_as(platform, "0.2.1.19")) { + /* These versions mishandled RELAY_EARLY cells on rend circuits. */ + if (msg) + *msg = "Tor version is too buggy to work."; + return FP_REJECT; } result = dirserv_get_name_status(id_digest, nickname); @@ -1160,7 +1166,7 @@ directory_fetches_from_authorities(or_options_t *options) return 0; if (server_mode(options) && router_pick_published_address(options, &addr)<0) return 1; /* we don't know our IP address; ask an authority. */ - refuseunknown = router_my_exit_policy_is_reject_star() && + refuseunknown = ! router_my_exit_policy_is_reject_star() && should_refuse_unknown_exits(options); if (options->DirPort == 0 && !refuseunknown) return 0; diff --git a/src/or/hibernate.c b/src/or/hibernate.c index e9be5930d1..929c1994c3 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -515,7 +515,6 @@ accounting_run_housekeeping(time_t now) static void accounting_set_wakeup_time(void) { - char buf[ISO_TIME_LEN+1]; char digest[DIGEST_LEN]; crypto_digest_env_t *d_env; int time_in_interval; @@ -529,21 +528,26 @@ accounting_set_wakeup_time(void) } } - format_iso_time(buf, interval_start_time); - crypto_pk_get_digest(get_server_identity_key(), digest); + if (server_identity_key_is_set()) { + char buf[ISO_TIME_LEN+1]; + format_iso_time(buf, interval_start_time); - d_env = crypto_new_digest_env(); - crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN); - crypto_digest_add_bytes(d_env, digest, DIGEST_LEN); - crypto_digest_get_digest(d_env, digest, DIGEST_LEN); - crypto_free_digest_env(d_env); + crypto_pk_get_digest(get_server_identity_key(), digest); + + d_env = crypto_new_digest_env(); + crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN); + crypto_digest_add_bytes(d_env, digest, DIGEST_LEN); + crypto_digest_get_digest(d_env, digest, DIGEST_LEN); + crypto_free_digest_env(d_env); + } else { + crypto_rand(digest, DIGEST_LEN); + } if (!expected_bandwidth_usage) { char buf1[ISO_TIME_LEN+1]; char buf2[ISO_TIME_LEN+1]; format_local_iso_time(buf1, interval_start_time); format_local_iso_time(buf2, interval_end_time); - time_to_exhaust_bw = GUESS_TIME_TO_USE_BANDWIDTH; interval_wakeup_time = interval_start_time; log_notice(LD_ACCT, @@ -558,8 +562,8 @@ accounting_set_wakeup_time(void) time_to_exhaust_bw = (get_options()->AccountingMax/expected_bandwidth_usage)*60; - if (time_to_exhaust_bw > TIME_MAX) { - time_to_exhaust_bw = TIME_MAX; + if (time_to_exhaust_bw > INT_MAX) { + time_to_exhaust_bw = INT_MAX; time_to_consider = 0; } else { time_to_consider = time_in_interval - (int)time_to_exhaust_bw; @@ -577,8 +581,6 @@ accounting_set_wakeup_time(void) * to be chosen than the last half. */ interval_wakeup_time = interval_start_time + (get_uint32(digest) % time_to_consider); - - format_iso_time(buf, interval_wakeup_time); } { diff --git a/src/or/main.c b/src/or/main.c index 9bdbbc17a6..e13215bd2e 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -893,6 +893,9 @@ run_scheduled_events(time_t now) signewnym_impl(now); } + /* 0c. If we've deferred log messages for the controller, handle them now */ + flush_pending_log_callbacks(); + /** 1a. Every MIN_ONION_KEY_LIFETIME seconds, rotate the onion keys, * shut down and restart all cpuworkers, and update the directory if * necessary. diff --git a/src/or/onion.c b/src/or/onion.c index fa001656e6..4d14f9095b 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -349,9 +349,9 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state, * Return 0 on success, <0 on failure. **/ int -fast_server_handshake(const char *key_in, /* DIGEST_LEN bytes */ - char *handshake_reply_out, /* DIGEST_LEN*2 bytes */ - char *key_out, +fast_server_handshake(const uint8_t *key_in, /* DIGEST_LEN bytes */ + uint8_t *handshake_reply_out, /* DIGEST_LEN*2 bytes */ + uint8_t *key_out, size_t key_out_len) { char tmp[DIGEST_LEN+DIGEST_LEN]; @@ -359,7 +359,7 @@ fast_server_handshake(const char *key_in, /* DIGEST_LEN bytes */ size_t out_len; int r = -1; - if (crypto_rand(handshake_reply_out, DIGEST_LEN)<0) + if (crypto_rand((char*)handshake_reply_out, DIGEST_LEN)<0) return -1; memcpy(tmp, key_in, DIGEST_LEN); @@ -392,9 +392,9 @@ fast_server_handshake(const char *key_in, /* DIGEST_LEN bytes */ * and protected by TLS). */ int -fast_client_handshake(const char *handshake_state, /* DIGEST_LEN bytes */ - const char *handshake_reply_out, /* DIGEST_LEN*2 bytes */ - char *key_out, +fast_client_handshake(const uint8_t *handshake_state, /* DIGEST_LEN bytes */ + const uint8_t *handshake_reply_out, /* DIGEST_LEN*2 bytes */ + uint8_t *key_out, size_t key_out_len) { char tmp[DIGEST_LEN+DIGEST_LEN]; diff --git a/src/or/onion.h b/src/or/onion.h index e84dbb47be..e097dcdbb3 100644 --- a/src/or/onion.h +++ b/src/or/onion.h @@ -32,14 +32,14 @@ int onion_skin_client_handshake(crypto_dh_env_t *handshake_state, char *key_out, size_t key_out_len); -int fast_server_handshake(const char *key_in, - char *handshake_reply_out, - char *key_out, +int fast_server_handshake(const uint8_t *key_in, + uint8_t *handshake_reply_out, + uint8_t *key_out, size_t key_out_len); -int fast_client_handshake(const char *handshake_state, - const char *handshake_reply_out, - char *key_out, +int fast_client_handshake(const uint8_t *handshake_state, + const uint8_t *handshake_reply_out, + uint8_t *key_out, size_t key_out_len); void clear_pending_onions(void); diff --git a/src/or/or.h b/src/or/or.h index a2cefe2b4a..07b73ec9b7 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -838,7 +838,7 @@ typedef struct cell_t { circid_t circ_id; /**< Circuit which received the cell. */ uint8_t command; /**< Type of the cell: one of CELL_PADDING, CELL_CREATE, * CELL_DESTROY, etc */ - char payload[CELL_PAYLOAD_SIZE]; /**< Cell body. */ + uint8_t payload[CELL_PAYLOAD_SIZE]; /**< Cell body. */ } cell_t; /** Parsed variable-length onion routing cell. */ @@ -846,7 +846,7 @@ typedef struct var_cell_t { uint8_t command; circid_t circ_id; uint16_t payload_len; - char payload[1]; + uint8_t payload[1]; } var_cell_t; /** A cell as packed for writing to the network. */ @@ -1958,7 +1958,7 @@ typedef struct crypt_path_t { * authentication, secrecy, and integrity we need, and we're already * distinguishable from an OR. */ - char fast_handshake_state[DIGEST_LEN]; + uint8_t fast_handshake_state[DIGEST_LEN]; /** Negotiated key material shared with the OR at this step. */ char handshake_digest[DIGEST_LEN];/* KH in tor-spec.txt */ diff --git a/src/or/relay.c b/src/or/relay.c index 467f8847c8..c951cab560 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -97,7 +97,7 @@ relay_set_digest(crypto_digest_env_t *digest, cell_t *cell) char integrity[4]; relay_header_t rh; - crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE); + crypto_digest_add_bytes(digest, (char*)cell->payload, CELL_PAYLOAD_SIZE); crypto_digest_get_digest(digest, integrity, 4); // log_fn(LOG_DEBUG,"Putting digest of %u %u %u %u into relay cell.", // integrity[0], integrity[1], integrity[2], integrity[3]); @@ -130,7 +130,7 @@ relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell) // received_integrity[0], received_integrity[1], // received_integrity[2], received_integrity[3]); - crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE); + crypto_digest_add_bytes(digest, (char*) cell->payload, CELL_PAYLOAD_SIZE); crypto_digest_get_digest(digest, calculated_integrity, 4); if (memcmp(received_integrity, calculated_integrity, 4)) { @@ -156,12 +156,12 @@ relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell) * Return -1 if the crypto fails, else return 0. */ static int -relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in, +relay_crypt_one_payload(crypto_cipher_env_t *cipher, uint8_t *in, int encrypt_mode) { int r; (void)encrypt_mode; - r = crypto_cipher_crypt_inplace(cipher, in, CELL_PAYLOAD_SIZE); + r = crypto_cipher_crypt_inplace(cipher, (char*) in, CELL_PAYLOAD_SIZE); if (r) { log_warn(LD_BUG,"Error during relay encryption"); @@ -476,10 +476,9 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, * about the wire format. */ void -relay_header_pack(char *dest, const relay_header_t *src) +relay_header_pack(uint8_t *dest, const relay_header_t *src) { - *(uint8_t*)(dest) = src->command; - + set_uint8(dest, src->command); set_uint16(dest+1, htons(src->recognized)); set_uint16(dest+3, htons(src->stream_id)); memcpy(dest+5, src->integrity, 4); @@ -490,10 +489,9 @@ relay_header_pack(char *dest, const relay_header_t *src) * relay_header_t structure <b>dest</b>. */ void -relay_header_unpack(relay_header_t *dest, const char *src) +relay_header_unpack(relay_header_t *dest, const uint8_t *src) { - dest->command = *(uint8_t*)(src); - + dest->command = get_uint8(src); dest->recognized = ntohs(get_uint16(src+1)); dest->stream_id = ntohs(get_uint16(src+3)); memcpy(dest->integrity, src+5, 4); @@ -1124,13 +1122,13 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, } stats_n_data_bytes_received += rh.length; - connection_write_to_buf(cell->payload + RELAY_HEADER_SIZE, + connection_write_to_buf((char*)(cell->payload + RELAY_HEADER_SIZE), rh.length, TO_CONN(conn)); connection_edge_consider_sending_sendme(conn); return 0; case RELAY_COMMAND_END: reason = rh.length > 0 ? - *(uint8_t *)(cell->payload+RELAY_HEADER_SIZE) : END_STREAM_REASON_MISC; + get_uint8(cell->payload+RELAY_HEADER_SIZE) : END_STREAM_REASON_MISC; if (!conn) { log_info(domain,"end cell (%s) dropped, unknown stream.", stream_end_reason_to_string(reason)); @@ -1478,10 +1476,11 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, crypt_path_t *layer_hint) { edge_connection_t *conn; - int n_streams, n_streams_left; + int n_packaging_streams, n_streams_left; int packaged_this_round; int cells_on_queue; int cells_per_conn; + edge_connection_t *chosen_stream = NULL; /* How many cells do we have space for? It will be the minimum of * the number needed to exhaust the package window, and the minimum @@ -1496,26 +1495,61 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, if (CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue < max_to_package) max_to_package = CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue; + /* Once we used to start listening on the streams in the order they + * appeared in the linked list. That leads to starvation on the + * streams that appeared later on the list, since the first streams + * would always get to read first. Instead, we just pick a random + * stream on the list, and enable reading for streams starting at that + * point (and wrapping around as if the list were circular). It would + * probably be better to actually remember which streams we've + * serviced in the past, but this is simple and effective. */ + + /* Select a stream uniformly at random from the linked list. We + * don't need cryptographic randomness here. */ + { + int num_streams = 0; + for (conn = first_conn; conn; conn = conn->next_stream) { + num_streams++; + if ((tor_weak_random() % num_streams)==0) + chosen_stream = conn; + /* Invariant: chosen_stream has been chosen uniformly at random from + * among the first num_streams streams on first_conn. */ + } + } + /* Count how many non-marked streams there are that have anything on * their inbuf, and enable reading on all of the connections. */ - n_streams = 0; - for (conn=first_conn; conn; conn=conn->next_stream) { + n_packaging_streams = 0; + /* Activate reading starting from the chosen stream */ + for (conn=chosen_stream; conn; conn = conn->next_stream) { + /* Start reading for the streams starting from here */ + if (conn->_base.marked_for_close || conn->package_window <= 0) + continue; + if (!layer_hint || conn->cpath_layer == layer_hint) { + connection_start_reading(TO_CONN(conn)); + + if (buf_datalen(conn->_base.inbuf) > 0) + ++n_packaging_streams; + } + } + /* Go back and do the ones we skipped, circular-style */ + for (conn = first_conn; conn != chosen_stream; conn = conn->next_stream) { if (conn->_base.marked_for_close || conn->package_window <= 0) continue; if (!layer_hint || conn->cpath_layer == layer_hint) { connection_start_reading(TO_CONN(conn)); if (buf_datalen(conn->_base.inbuf) > 0) - ++n_streams; + ++n_packaging_streams; } } - if (n_streams == 0) /* avoid divide-by-zero */ + if (n_packaging_streams == 0) /* avoid divide-by-zero */ return 0; again: - cells_per_conn = CEIL_DIV(max_to_package, n_streams); + cells_per_conn = CEIL_DIV(max_to_package, n_packaging_streams); packaged_this_round = 0; n_streams_left = 0; @@ -1563,7 +1597,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, if (packaged_this_round && packaged_this_round < max_to_package && n_streams_left) { max_to_package -= packaged_this_round; - n_streams = n_streams_left; + n_packaging_streams = n_streams_left; goto again; } @@ -2427,7 +2461,7 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn, * ADDRESS [length bytes] * Return the number of bytes added, or -1 on error */ int -append_address_to_payload(char *payload_out, const tor_addr_t *addr) +append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr) { uint32_t a; switch (tor_addr_family(addr)) { @@ -2452,13 +2486,13 @@ append_address_to_payload(char *payload_out, const tor_addr_t *addr) * encoded as by append_address_to_payload(), try to decode the address into * *<b>addr_out</b>. Return the next byte in the payload after the address on * success, or NULL on failure. */ -const char * -decode_address_from_payload(tor_addr_t *addr_out, const char *payload, +const uint8_t * +decode_address_from_payload(tor_addr_t *addr_out, const uint8_t *payload, int payload_len) { if (payload_len < 2) return NULL; - if (payload_len < 2+(uint8_t)payload[1]) + if (payload_len < 2+payload[1]) return NULL; switch (payload[0]) { @@ -2470,13 +2504,13 @@ decode_address_from_payload(tor_addr_t *addr_out, const char *payload, case RESOLVED_TYPE_IPV6: if (payload[1] != 16) return NULL; - tor_addr_from_ipv6_bytes(addr_out, payload+2); + tor_addr_from_ipv6_bytes(addr_out, (char*)(payload+2)); break; default: tor_addr_make_unspec(addr_out); break; } - return payload + 2 + (uint8_t)payload[1]; + return payload + 2 + payload[1]; } /** Remove all the cells queued on <b>circ</b> for <b>orconn</b>. */ diff --git a/src/or/relay.h b/src/or/relay.h index 08a1ffe789..8ccf0e2b30 100644 --- a/src/or/relay.h +++ b/src/or/relay.h @@ -18,8 +18,8 @@ extern uint64_t stats_n_relay_cells_delivered; int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, cell_direction_t cell_direction); -void relay_header_pack(char *dest, const relay_header_t *src); -void relay_header_unpack(relay_header_t *dest, const char *src); +void relay_header_pack(uint8_t *dest, const relay_header_t *src); +void relay_header_unpack(relay_header_t *dest, const uint8_t *src); int relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ, uint8_t relay_command, const char *payload, size_t payload_len, crypt_path_t *cpath_layer); @@ -55,9 +55,9 @@ void assert_active_circuits_ok(or_connection_t *orconn); void make_circuit_inactive_on_conn(circuit_t *circ, or_connection_t *conn); void make_circuit_active_on_conn(circuit_t *circ, or_connection_t *conn); -int append_address_to_payload(char *payload_out, const tor_addr_t *addr); -const char *decode_address_from_payload(tor_addr_t *addr_out, - const char *payload, +int append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr); +const uint8_t *decode_address_from_payload(tor_addr_t *addr_out, + const uint8_t *payload, int payload_len); unsigned cell_ewma_get_tick(void); void cell_ewma_set_scale_factor(or_options_t *options, diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 3e1083f694..ab968078e8 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -234,7 +234,7 @@ rend_client_rendcirc_has_opened(origin_circuit_t *circ) */ int rend_client_introduction_acked(origin_circuit_t *circ, - const char *request, size_t request_len) + const uint8_t *request, size_t request_len) { origin_circuit_t *rendcirc; (void) request; // XXXX Use this. @@ -583,7 +583,7 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, * the circuit to C_REND_READY. */ int -rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request, +rend_client_rendezvous_acked(origin_circuit_t *circ, const uint8_t *request, size_t request_len) { (void) request; @@ -609,7 +609,7 @@ rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request, /** Bob sent us a rendezvous cell; join the circuits. */ int -rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request, +rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, size_t request_len) { crypt_path_t *hop; @@ -637,9 +637,10 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request, tor_assert(circ->build_state->pending_final_cpath); hop = circ->build_state->pending_final_cpath; tor_assert(hop->dh_handshake_state); - if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, hop->dh_handshake_state, - request, DH_KEY_LEN, keys, - DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) { + if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, + hop->dh_handshake_state, (char*)request, + DH_KEY_LEN, + keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) { log_warn(LD_GENERAL, "Couldn't complete DH handshake."); goto err; } diff --git a/src/or/rendclient.h b/src/or/rendclient.h index 842fe0b8ce..79d37b2a58 100644 --- a/src/or/rendclient.h +++ b/src/or/rendclient.h @@ -14,14 +14,17 @@ void rend_client_introcirc_has_opened(origin_circuit_t *circ); void rend_client_rendcirc_has_opened(origin_circuit_t *circ); -int rend_client_introduction_acked(origin_circuit_t *circ, const char *request, +int rend_client_introduction_acked(origin_circuit_t *circ, + const uint8_t *request, size_t request_len); void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query); int rend_client_remove_intro_point(extend_info_t *failed_intro, const rend_data_t *rend_query); -int rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request, +int rend_client_rendezvous_acked(origin_circuit_t *circ, + const uint8_t *request, size_t request_len); -int rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request, +int rend_client_receive_rendezvous(origin_circuit_t *circ, + const uint8_t *request, size_t request_len); void rend_client_desc_trynow(const char *query); diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index ec6680b1e6..85d97e0253 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -1358,7 +1358,7 @@ rend_cache_store_v2_desc_as_client(const char *desc, void rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint, int command, size_t length, - const char *payload) + const uint8_t *payload) { or_circuit_t *or_circ = NULL; origin_circuit_t *origin_circ = NULL; diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h index 00705022a2..d3313faf5a 100644 --- a/src/or/rendcommon.h +++ b/src/or/rendcommon.h @@ -22,7 +22,8 @@ rend_data_free(rend_data_t *data) int rend_cmp_service_ids(const char *one, const char *two); void rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint, - int command, size_t length, const char *payload); + int command, size_t length, + const uint8_t *payload); void rend_service_descriptor_free(rend_service_descriptor_t *desc); rend_service_descriptor_t *rend_parse_service_descriptor(const char *str, diff --git a/src/or/rendmid.c b/src/or/rendmid.c index d392f8e53a..bc36a4e117 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -18,7 +18,7 @@ * setting the circuit's purpose and service pk digest. */ int -rend_mid_establish_intro(or_circuit_t *circ, const char *request, +rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, size_t request_len) { crypto_pk_env_t *pk = NULL; @@ -48,7 +48,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request, /* Next asn1len bytes: asn1-encoded key. */ if (request_len < 2+DIGEST_LEN+asn1len) goto truncated; - pk = crypto_pk_asn1_decode(request+2, asn1len); + pk = crypto_pk_asn1_decode((char*)(request+2), asn1len); if (!pk) { reason = END_CIRC_REASON_TORPROTOCOL; log_warn(LD_PROTOCOL, "Couldn't decode public key."); @@ -69,8 +69,8 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request, } /* Rest of body: signature of previous data */ note_crypto_pk_op(REND_MID); - if (crypto_pk_public_checksig_digest(pk, request, 2+asn1len+DIGEST_LEN, - request+2+DIGEST_LEN+asn1len, + if (crypto_pk_public_checksig_digest(pk, (char*)request, 2+asn1len+DIGEST_LEN, + (char*)(request+2+DIGEST_LEN+asn1len), request_len-(2+DIGEST_LEN+asn1len))<0) { log_warn(LD_PROTOCOL, "Incorrect signature on ESTABLISH_INTRO cell; rejecting."); @@ -130,7 +130,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request, * INTRODUCE2 cell. */ int -rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len) +rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, size_t request_len) { or_circuit_t *intro_circ; char serviceid[REND_SERVICE_ID_LEN_BASE32+1]; @@ -159,10 +159,10 @@ rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len) } base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1, - request, REND_SERVICE_ID_LEN); + (char*)request, REND_SERVICE_ID_LEN); /* The first 20 bytes are all we look at: they have a hash of Bob's PK. */ - intro_circ = circuit_get_intro_point(request); + intro_circ = circuit_get_intro_point((char*)request); if (!intro_circ) { log_info(LD_REND, "No intro circ found for INTRODUCE1 cell (%s) from circuit %d; " @@ -180,7 +180,7 @@ rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len) /* Great. Now we just relay the cell down the circuit. */ if (relay_send_command_from_edge(0, TO_CIRCUIT(intro_circ), RELAY_COMMAND_INTRODUCE2, - request, request_len, NULL)) { + (char*)request, request_len, NULL)) { log_warn(LD_GENERAL, "Unable to send INTRODUCE2 cell to Tor client."); goto err; @@ -212,7 +212,7 @@ rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len) * rendezvous cookie. */ int -rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request, +rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, size_t request_len) { char hexid[9]; @@ -232,7 +232,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request, goto err; } - if (circuit_get_rendezvous(request)) { + if (circuit_get_rendezvous((char*)request)) { log_warn(LD_PROTOCOL, "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS."); goto err; @@ -250,7 +250,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request, circ->_base.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING; memcpy(circ->rend_token, request, REND_COOKIE_LEN); - base16_encode(hexid,9,request,4); + base16_encode(hexid,9,(char*)request,4); log_info(LD_REND, "Established rendezvous point on circuit %d for cookie %s", @@ -267,13 +267,13 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request, * connecting the two circuits. */ int -rend_mid_rendezvous(or_circuit_t *circ, const char *request, +rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, size_t request_len) { or_circuit_t *rend_circ; char hexid[9]; int reason = END_CIRC_REASON_INTERNAL; - base16_encode(hexid,9,request,request_len<4?request_len:4); + base16_encode(hexid,9,(char*)request,request_len<4?request_len:4); if (request_len>=4) { log_info(LD_REND, @@ -297,7 +297,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const char *request, goto err; } - rend_circ = circuit_get_rendezvous(request); + rend_circ = circuit_get_rendezvous((char*)request); if (!rend_circ) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.", @@ -309,7 +309,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const char *request, /* Send the RENDEZVOUS2 cell to Alice. */ if (relay_send_command_from_edge(0, TO_CIRCUIT(rend_circ), RELAY_COMMAND_RENDEZVOUS2, - request+REND_COOKIE_LEN, + (char*)(request+REND_COOKIE_LEN), request_len-REND_COOKIE_LEN, NULL)) { log_warn(LD_GENERAL, "Unable to send RENDEZVOUS2 cell to client on circuit %d.", diff --git a/src/or/rendmid.h b/src/or/rendmid.h index 4d08d4c8b9..f06dd3d85e 100644 --- a/src/or/rendmid.h +++ b/src/or/rendmid.h @@ -12,13 +12,13 @@ #ifndef _TOR_RENDMID_H #define _TOR_RENDMID_H -int rend_mid_establish_intro(or_circuit_t *circ, const char *request, +int rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, size_t request_len); -int rend_mid_introduce(or_circuit_t *circ, const char *request, +int rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, size_t request_len); -int rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request, +int rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, size_t request_len); -int rend_mid_rendezvous(or_circuit_t *circ, const char *request, +int rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, size_t request_len); #endif diff --git a/src/or/rendservice.c b/src/or/rendservice.c index b0d791529b..f06c98337a 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -849,7 +849,7 @@ clean_accepted_intros(rend_service_t *service, time_t now) * rendezvous point. */ int -rend_service_introduce(origin_circuit_t *circuit, const char *request, +rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, size_t request_len) { char *ptr, *r_cookie; @@ -913,7 +913,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request, crypto_pk_get_digest(intro_key, intro_key_digest); if (memcmp(intro_key_digest, request, DIGEST_LEN)) { base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1, - request, REND_SERVICE_ID_LEN); + (char*)request, REND_SERVICE_ID_LEN); log_warn(LD_REND, "Got an INTRODUCE2 cell for the wrong service (%s).", escaped(serviceid)); return -1; @@ -928,7 +928,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request, /* Next N bytes is encrypted with service key */ note_crypto_pk_op(REND_SERVER); r = crypto_pk_private_hybrid_decrypt( - intro_key,buf,request+DIGEST_LEN,request_len-DIGEST_LEN, + intro_key,buf,(char*)(request+DIGEST_LEN),request_len-DIGEST_LEN, PK_PKCS1_OAEP_PADDING,1); if (r<0) { log_warn(LD_PROTOCOL, "Couldn't decrypt INTRODUCE2 cell."); @@ -1392,7 +1392,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) * live introduction point, and note that the service descriptor is * now out-of-date.*/ int -rend_service_intro_established(origin_circuit_t *circuit, const char *request, +rend_service_intro_established(origin_circuit_t *circuit, + const uint8_t *request, size_t request_len) { rend_service_t *service; diff --git a/src/or/rendservice.h b/src/or/rendservice.h index 1767714c60..722cec1561 100644 --- a/src/or/rendservice.h +++ b/src/or/rendservice.h @@ -22,10 +22,10 @@ void rend_consider_descriptor_republication(void); void rend_service_intro_has_opened(origin_circuit_t *circuit); int rend_service_intro_established(origin_circuit_t *circuit, - const char *request, + const uint8_t *request, size_t request_len); void rend_service_rendezvous_has_opened(origin_circuit_t *circuit); -int rend_service_introduce(origin_circuit_t *circuit, const char *request, +int rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, size_t request_len); void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc); int rend_service_set_connection_addr_port(edge_connection_t *conn, diff --git a/src/or/rephist.c b/src/or/rephist.c index 22b3ec5217..5a57b954fd 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -1943,9 +1943,8 @@ dump_pk_ops(int severity) #define EXIT_STATS_ROUND_UP_STREAMS 4 /** Number of TCP ports */ #define EXIT_STATS_NUM_PORTS 65536 -/** Reciprocal of threshold (= 0.01%) of total bytes that a port needs to - * see in order to be included in exit stats. */ -#define EXIT_STATS_THRESHOLD_RECIPROCAL 10000 +/** Top n ports that will be included in exit stats. */ +#define EXIT_STATS_TOP_N_PORTS 10 /* The following data structures are arrays and no fancy smartlists or maps, * so that all write operations can be done in constant time. This comes at @@ -1995,15 +1994,23 @@ rep_hist_exit_stats_term(void) tor_free(exit_streams); } +/** Helper for qsort: compare two ints. */ +static int +_compare_int(const void *x, const void *y) { + return (*(int*)x - *(int*)y); +} + /** Return a newly allocated string containing the exit port statistics * until <b>now</b>, or NULL if we're not collecting exit stats. */ char * rep_hist_format_exit_stats(time_t now) { - int i; - uint64_t total_bytes = 0, threshold_bytes, other_read = 0, - other_written = 0; - uint32_t other_streams = 0; + int i, j, top_elements = 0, cur_min_idx = 0, cur_port; + uint64_t top_bytes[EXIT_STATS_TOP_N_PORTS]; + int top_ports[EXIT_STATS_TOP_N_PORTS]; + uint64_t cur_bytes = 0, other_read = 0, other_written = 0, + total_read = 0, total_written = 0; + uint32_t total_streams = 0, other_streams = 0; char *buf; smartlist_t *written_strings, *read_strings, *streams_strings; char *written_string, *read_string, *streams_string; @@ -2013,52 +2020,101 @@ rep_hist_format_exit_stats(time_t now) if (!start_of_exit_stats_interval) return NULL; /* Not initialized. */ - /* Count total number of bytes, so that we can attribute observations - * below or equal to a threshold of 1 / EXIT_STATS_THRESHOLD_RECIPROCAL - * of all bytes to a special port 'other'. */ + /* Go through all ports to find the n ports that saw most written and + * read bytes. + * + * Invariant: at the end of the loop for iteration i, + * total_read is the sum of all exit_bytes_read[0..i] + * total_written is the sum of all exit_bytes_written[0..i] + * total_stream is the sum of all exit_streams[0..i] + * + * top_elements = MAX(EXIT_STATS_TOP_N_PORTS, + * #{j | 0 <= j <= i && volume(i) > 0}) + * + * For all 0 <= j < top_elements, + * top_bytes[j] > 0 + * 0 <= top_ports[j] <= 65535 + * top_bytes[j] = volume(top_ports[j]) + * + * There is no j in 0..i and k in 0..top_elements such that: + * volume(j) > top_bytes[k] AND j is not in top_ports[0..top_elements] + * + * There is no j!=cur_min_idx in 0..top_elements such that: + * top_bytes[j] < top_bytes[cur_min_idx] + * + * where volume(x) == exit_bytes_read[x]+exit_bytes_written[x] + * + * Worst case: O(EXIT_STATS_NUM_PORTS * EXIT_STATS_TOP_N_PORTS) + */ for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { - total_bytes += exit_bytes_read[i]; - total_bytes += exit_bytes_written[i]; + total_read += exit_bytes_read[i]; + total_written += exit_bytes_written[i]; + total_streams += exit_streams[i]; + cur_bytes = exit_bytes_read[i] + exit_bytes_written[i]; + if (cur_bytes == 0) { + continue; + } + if (top_elements < EXIT_STATS_TOP_N_PORTS) { + top_bytes[top_elements] = cur_bytes; + top_ports[top_elements++] = i; + } else if (cur_bytes > top_bytes[cur_min_idx]) { + top_bytes[cur_min_idx] = cur_bytes; + top_ports[cur_min_idx] = i; + } else { + continue; + } + cur_min_idx = 0; + for (j = 1; j < top_elements; j++) { + if (top_bytes[j] < top_bytes[cur_min_idx]) { + cur_min_idx = j; + } + } } - threshold_bytes = total_bytes / EXIT_STATS_THRESHOLD_RECIPROCAL; - /* Add observations of all ports above the threshold to smartlists and - * join them to single strings. Also count bytes and streams of ports - * below or equal to the threshold. */ + /* Add observations of top ports to smartlists. */ written_strings = smartlist_create(); read_strings = smartlist_create(); streams_strings = smartlist_create(); - for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) { - if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) { - if (exit_bytes_written[i] > 0) { - uint64_t num = round_uint64_to_next_multiple_of( - exit_bytes_written[i], EXIT_STATS_ROUND_UP_BYTES); - num /= 1024; - buf = NULL; - tor_asprintf(&buf, "%d="U64_FORMAT, i, U64_PRINTF_ARG(num)); - smartlist_add(written_strings, buf); - } - if (exit_bytes_read[i] > 0) { - uint64_t num = round_uint64_to_next_multiple_of( - exit_bytes_read[i], EXIT_STATS_ROUND_UP_BYTES); - num /= 1024; - buf = NULL; - tor_asprintf(&buf, "%d="U64_FORMAT, i, U64_PRINTF_ARG(num)); - smartlist_add(read_strings, buf); - } - if (exit_streams[i] > 0) { - uint32_t num = round_uint32_to_next_multiple_of(exit_streams[i], - EXIT_STATS_ROUND_UP_STREAMS); - buf = NULL; - tor_asprintf(&buf, "%d=%u", i, num); - smartlist_add(streams_strings, buf); - } - } else { - other_read += exit_bytes_read[i]; - other_written += exit_bytes_written[i]; - other_streams += exit_streams[i]; + other_read = total_read; + other_written = total_written; + other_streams = total_streams; + /* Sort the ports; this puts them out of sync with top_bytes, but we + * won't be using top_bytes again anyway */ + qsort(top_ports, top_elements, sizeof(int), _compare_int); + for (j = 0; j < top_elements; j++) { + cur_port = top_ports[j]; + if (exit_bytes_written[cur_port] > 0) { + uint64_t num = round_uint64_to_next_multiple_of( + exit_bytes_written[cur_port], + EXIT_STATS_ROUND_UP_BYTES); + num /= 1024; + buf = NULL; + tor_asprintf(&buf, "%d="U64_FORMAT, cur_port, U64_PRINTF_ARG(num)); + smartlist_add(written_strings, buf); + other_written -= exit_bytes_written[cur_port]; + } + if (exit_bytes_read[cur_port] > 0) { + uint64_t num = round_uint64_to_next_multiple_of( + exit_bytes_read[cur_port], + EXIT_STATS_ROUND_UP_BYTES); + num /= 1024; + buf = NULL; + tor_asprintf(&buf, "%d="U64_FORMAT, cur_port, U64_PRINTF_ARG(num)); + smartlist_add(read_strings, buf); + other_read -= exit_bytes_read[cur_port]; + } + if (exit_streams[cur_port] > 0) { + uint32_t num = round_uint32_to_next_multiple_of( + exit_streams[cur_port], + EXIT_STATS_ROUND_UP_STREAMS); + buf = NULL; + tor_asprintf(&buf, "%d=%u", cur_port, num); + smartlist_add(streams_strings, buf); + other_streams -= exit_streams[cur_port]; } } + + /* Add observations of other ports in a single element. */ other_written = round_uint64_to_next_multiple_of(other_written, EXIT_STATS_ROUND_UP_BYTES); other_written /= 1024; @@ -2076,6 +2132,8 @@ rep_hist_format_exit_stats(time_t now) buf = NULL; tor_asprintf(&buf, "other=%u", other_streams); smartlist_add(streams_strings, buf); + + /* Join all observations in single strings. */ written_string = smartlist_join_strings(written_strings, ",", 0, NULL); read_string = smartlist_join_strings(read_strings, ",", 0, NULL); streams_string = smartlist_join_strings(streams_strings, ",", 0, NULL); diff --git a/src/or/router.c b/src/or/router.c index 3d4ee70399..66ef8ec52e 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1523,7 +1523,7 @@ router_rebuild_descriptor(int force) /* Let bridges serve their own descriptors unencrypted, so they can * pass reachability testing. (If they want to be harder to notice, * they can always leave the DirPort off). */ - if (!options->BridgeRelay) + if (ei && !options->BridgeRelay) ei->cache_info.send_unencrypted = 1; router_get_router_hash(ri->cache_info.signed_descriptor_body, |