Browse Source

Add a new isolation type and field: "nym epoch"

The "nym epoch" of a stream is defined as the number of times that
NEWNYM had been called before the stream was opened.  All streams
are isolated by nym epoch.

This feature should be redundant with existing signewnym stuff, but
it provides a good belt-and-suspenders way for us to avoid ever
letting any circuit type bypass signewnym.
Nick Mathewson 13 years ago
parent
commit
1d3c8c1f74
6 changed files with 27 additions and 1 deletions
  1. 1 0
      src/or/connection.c
  2. 7 0
      src/or/connection_edge.c
  3. 1 0
      src/or/dnsserv.c
  4. 11 0
      src/or/main.c
  5. 1 0
      src/or/main.h
  6. 6 1
      src/or/or.h

+ 1 - 0
src/or/connection.c

@@ -1240,6 +1240,7 @@ connection_init_accepted_conn(connection_t *conn,
     case CONN_TYPE_AP:
     case CONN_TYPE_AP:
       TO_EDGE_CONN(conn)->isolation_flags = listener->isolation_flags;
       TO_EDGE_CONN(conn)->isolation_flags = listener->isolation_flags;
       TO_EDGE_CONN(conn)->session_group = listener->session_group;
       TO_EDGE_CONN(conn)->session_group = listener->session_group;
+      TO_EDGE_CONN(conn)->nym_epoch = get_signewnym_epoch();
       switch (TO_CONN(listener)->type) {
       switch (TO_CONN(listener)->type) {
         case CONN_TYPE_AP_LISTENER:
         case CONN_TYPE_AP_LISTENER:
           conn->state = AP_CONN_STATE_SOCKS_WAIT;
           conn->state = AP_CONN_STATE_SOCKS_WAIT;

+ 7 - 0
src/or/connection_edge.c

@@ -3296,6 +3296,8 @@ connection_edge_streams_are_compatible(const edge_connection_t *a,
     return 0;
     return 0;
   if ((iso & ISO_SESSIONGRP) && a->session_group != b->session_group)
   if ((iso & ISO_SESSIONGRP) && a->session_group != b->session_group)
     return 0;
     return 0;
+  if ((iso & ISO_NYM_EPOCH) && a->nym_epoch != b->nym_epoch)
+    return 0;
 
 
   return 1;
   return 1;
 }
 }
@@ -3348,6 +3350,8 @@ connection_edge_compatible_with_circuit(const edge_connection_t *conn,
     return 0;
     return 0;
   if ((iso & ISO_SESSIONGRP) && conn->session_group != circ->session_group)
   if ((iso & ISO_SESSIONGRP) && conn->session_group != circ->session_group)
     return 0;
     return 0;
+  if ((iso & ISO_NYM_EPOCH) && conn->nym_epoch != circ->nym_epoch)
+    return 0;
 
 
   return 1;
   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;
     circ->client_proto_socksver = conn->socks_request->socks_version;
     tor_addr_copy(&circ->client_addr, &TO_CONN(conn)->addr);
     tor_addr_copy(&circ->client_addr, &TO_CONN(conn)->addr);
     circ->session_group = conn->session_group;
     circ->session_group = conn->session_group;
+    circ->nym_epoch = conn->nym_epoch;
     /* XXXX023 auth too, once #1666 is in. */
     /* XXXX023 auth too, once #1666 is in. */
 
 
     circ->isolation_values_set = 1;
     circ->isolation_values_set = 1;
@@ -3394,6 +3399,8 @@ connection_edge_update_circuit_isolation(const edge_connection_t *conn,
       mixed |= ISO_CLIENTADDR;
       mixed |= ISO_CLIENTADDR;
     if (conn->session_group != circ->session_group)
     if (conn->session_group != circ->session_group)
       mixed |= ISO_SESSIONGRP;
       mixed |= ISO_SESSIONGRP;
+    if (conn->nym_epoch != circ->nym_epoch)
+      mixed |= ISO_NYM_EPOCH;
 
 
     if (dry_run)
     if (dry_run)
       return mixed;
       return mixed;

+ 1 - 0
src/or/dnsserv.c

@@ -134,6 +134,7 @@ evdns_server_callback(struct evdns_server_request *req, void *data_)
   conn->dns_server_request = req;
   conn->dns_server_request = req;
   conn->isolation_flags = listener->isolation_flags;
   conn->isolation_flags = listener->isolation_flags;
   conn->session_group = listener->session_group;
   conn->session_group = listener->session_group;
+  conn->nym_epoch = get_signewnym_epoch();
 
 
   if (connection_add(TO_CONN(conn)) < 0) {
   if (connection_add(TO_CONN(conn)) < 0) {
     log_warn(LD_APP, "Couldn't register dummy connection for DNS request");
     log_warn(LD_APP, "Couldn't register dummy connection for DNS request");

+ 11 - 0
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;
 static time_t time_of_last_signewnym = 0;
 /** Is there a signewnym request we're currently waiting to handle? */
 /** Is there a signewnym request we're currently waiting to handle? */
 static int signewnym_is_pending = 0;
 static int signewnym_is_pending = 0;
+/** How many times have we called newnym? */
+static unsigned newnym_epoch = 0;
 
 
 /** Smartlist of all open connections. */
 /** Smartlist of all open connections. */
 static smartlist_t *connection_array = NULL;
 static smartlist_t *connection_array = NULL;
@@ -1038,9 +1040,18 @@ signewnym_impl(time_t now)
   time_of_last_signewnym = now;
   time_of_last_signewnym = now;
   signewnym_is_pending = 0;
   signewnym_is_pending = 0;
 
 
+  ++newnym_epoch;
+
   control_event_signal(SIGNEWNYM);
   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
 /** Perform regular maintenance tasks.  This function gets run once per
  * second by second_elapsed_callback().
  * second by second_elapsed_callback().
  */
  */

+ 1 - 0
src/or/main.h

@@ -52,6 +52,7 @@ void ip_address_changed(int at_interface);
 void dns_servers_relaunch_checks(void);
 void dns_servers_relaunch_checks(void);
 
 
 long get_uptime(void);
 long get_uptime(void);
+unsigned get_signewnym_epoch(void);
 
 
 void handle_signals(int is_parent);
 void handle_signals(int is_parent);
 void process_signal(uintptr_t sig);
 void process_signal(uintptr_t sig);

+ 6 - 1
src/or/or.h

@@ -1212,6 +1212,8 @@ typedef struct edge_connection_t {
   uint8_t isolation_flags;
   uint8_t isolation_flags;
   /** AP only: what session group is this stream in? */
   /** AP only: what session group is this stream in? */
   int session_group;
   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
   /* Other fields to isolate on already exist.  The ClientAddr is addr.  The
      ClientProtocol is a combination of type and socks_request->
      ClientProtocol is a combination of type and socks_request->
      socks_version.  SocksAuth will be added to socks_request by ticket
      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;
   tor_addr_t client_addr;
   char *dest_address;
   char *dest_address;
   int session_group;
   int session_group;
+  unsigned nym_epoch;
   /* XXXX023 do auth once #1666 is merged */
   /* XXXX023 do auth once #1666 is merged */
   /**@}*/
   /**@}*/
 
 
@@ -2621,10 +2624,12 @@ typedef enum invalid_router_usage_t {
 #define ISO_CLIENTADDR  (1u<<4)
 #define ISO_CLIENTADDR  (1u<<4)
 /** Isolate based on session group (always on). */
 /** Isolate based on session group (always on). */
 #define ISO_SESSIONGRP  (1u<<5)
 #define ISO_SESSIONGRP  (1u<<5)
+/** Isolate based on newnym epoch (always on). */
+#define ISO_NYM_EPOCH   (1u<<6)
 /**@}*/
 /**@}*/
 
 
 /** Default isolation level for ports. */
 /** 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. */
 /** Configuration for a single port that we're listening on. */
 typedef struct port_cfg_t {
 typedef struct port_cfg_t {