diff --git a/src/or/connection.c b/src/or/connection.c index b627dcae16..09b45e03c9 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1240,6 +1240,7 @@ connection_init_accepted_conn(connection_t *conn, case CONN_TYPE_AP: TO_EDGE_CONN(conn)->isolation_flags = listener->isolation_flags; TO_EDGE_CONN(conn)->session_group = listener->session_group; + TO_EDGE_CONN(conn)->nym_epoch = get_signewnym_epoch(); switch (TO_CONN(listener)->type) { case CONN_TYPE_AP_LISTENER: conn->state = AP_CONN_STATE_SOCKS_WAIT; diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 426c342852..ce555ed5e2 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -3296,6 +3296,8 @@ connection_edge_streams_are_compatible(const edge_connection_t *a, return 0; if ((iso & ISO_SESSIONGRP) && a->session_group != b->session_group) return 0; + if ((iso & ISO_NYM_EPOCH) && a->nym_epoch != b->nym_epoch) + return 0; return 1; } @@ -3348,6 +3350,8 @@ connection_edge_compatible_with_circuit(const edge_connection_t *conn, return 0; if ((iso & ISO_SESSIONGRP) && conn->session_group != circ->session_group) return 0; + if ((iso & ISO_NYM_EPOCH) && conn->nym_epoch != circ->nym_epoch) + return 0; return 1; } @@ -3374,6 +3378,7 @@ connection_edge_update_circuit_isolation(const edge_connection_t *conn, circ->client_proto_socksver = conn->socks_request->socks_version; tor_addr_copy(&circ->client_addr, &TO_CONN(conn)->addr); circ->session_group = conn->session_group; + circ->nym_epoch = conn->nym_epoch; /* XXXX023 auth too, once #1666 is in. */ circ->isolation_values_set = 1; @@ -3394,6 +3399,8 @@ connection_edge_update_circuit_isolation(const edge_connection_t *conn, mixed |= ISO_CLIENTADDR; if (conn->session_group != circ->session_group) mixed |= ISO_SESSIONGRP; + if (conn->nym_epoch != circ->nym_epoch) + mixed |= ISO_NYM_EPOCH; if (dry_run) return mixed; diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c index b1316ecc6a..8612b4850f 100644 --- a/src/or/dnsserv.c +++ b/src/or/dnsserv.c @@ -134,6 +134,7 @@ evdns_server_callback(struct evdns_server_request *req, void *data_) conn->dns_server_request = req; conn->isolation_flags = listener->isolation_flags; conn->session_group = listener->session_group; + conn->nym_epoch = get_signewnym_epoch(); if (connection_add(TO_CONN(conn)) < 0) { log_warn(LD_APP, "Couldn't register dummy connection for DNS request"); diff --git a/src/or/main.c b/src/or/main.c index 16d4f0e7aa..54e6451e6a 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -114,6 +114,8 @@ static time_t time_to_check_for_correct_dns = 0; static time_t time_of_last_signewnym = 0; /** Is there a signewnym request we're currently waiting to handle? */ static int signewnym_is_pending = 0; +/** How many times have we called newnym? */ +static unsigned newnym_epoch = 0; /** Smartlist of all open connections. */ static smartlist_t *connection_array = NULL; @@ -1038,9 +1040,18 @@ signewnym_impl(time_t now) time_of_last_signewnym = now; signewnym_is_pending = 0; + ++newnym_epoch; + control_event_signal(SIGNEWNYM); } +/** Return the number of times that signewnym has been called. */ +unsigned +get_signewnym_epoch(void) +{ + return newnym_epoch; +} + /** Perform regular maintenance tasks. This function gets run once per * second by second_elapsed_callback(). */ diff --git a/src/or/main.h b/src/or/main.h index db251356fd..c8903642de 100644 --- a/src/or/main.h +++ b/src/or/main.h @@ -52,6 +52,7 @@ void ip_address_changed(int at_interface); void dns_servers_relaunch_checks(void); long get_uptime(void); +unsigned get_signewnym_epoch(void); void handle_signals(int is_parent); void process_signal(uintptr_t sig); diff --git a/src/or/or.h b/src/or/or.h index c5e5793720..9cf508c2de 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1212,6 +1212,8 @@ typedef struct edge_connection_t { uint8_t isolation_flags; /** AP only: what session group is this stream in? */ int session_group; + /** AP only: The newnym epoch in which we created this connection. */ + unsigned nym_epoch; /* Other fields to isolate on already exist. The ClientAddr is addr. The ClientProtocol is a combination of type and socks_request-> socks_version. SocksAuth will be added to socks_request by ticket @@ -2482,6 +2484,7 @@ typedef struct origin_circuit_t { tor_addr_t client_addr; char *dest_address; int session_group; + unsigned nym_epoch; /* XXXX023 do auth once #1666 is merged */ /**@}*/ @@ -2621,10 +2624,12 @@ typedef enum invalid_router_usage_t { #define ISO_CLIENTADDR (1u<<4) /** Isolate based on session group (always on). */ #define ISO_SESSIONGRP (1u<<5) +/** Isolate based on newnym epoch (always on). */ +#define ISO_NYM_EPOCH (1u<<6) /**@}*/ /** Default isolation level for ports. */ -#define ISO_DEFAULT (ISO_CLIENTADDR|ISO_SOCKSAUTH|ISO_SESSIONGRP) +#define ISO_DEFAULT (ISO_CLIENTADDR|ISO_SOCKSAUTH|ISO_SESSIONGRP|ISO_NYM_EPOCH) /** Configuration for a single port that we're listening on. */ typedef struct port_cfg_t {