Browse Source

In telescoping WO, be sure to not pick the guard as the exit

The guard and middle will already reject attempts to pick themselves as
the hop right after them, so we just have to watch out for
guard-middle-guard circuits.
Ian Goldberg 4 years ago
parent
commit
8e7b52b98d
1 changed files with 18 additions and 2 deletions
  1. 18 2
      client.py

+ 18 - 2
client.py

@@ -140,14 +140,16 @@ class TelescopingExtendedHandler:
             return
 
         nexthopidx = None
+        guardrange = circhandler.circuit_descs[0].snipdict["range"]
         while nexthopidx is None:
             # Relays make sure that when the extend to a relay, they are not
             # extending to themselves. So here, we just need to make sure that
             # this ID is not the same as the guard ID, to protect against the
             # guard and exit being the same relay
-            print("WARNING: Unimplemented! Need to check that sampled ID is not the same as the guard.")
             nexthopidx = self.channelmgr.relaypicker.pick_weighted_relay_index()
-            logging.warning("Unimplemented! Need to check if this idx is in the list of circhandlers idxs")
+            if guardrange[0] <= nexthopidx and nexthopidx < guardrange[1]:
+                # We've picked this relay already.  Try again.
+                nexthopidx = None
 
         # Construct the VanillaExtendCircuitCell
         ntor = relay.NTor(self.channelmgr.perfstats)
@@ -309,6 +311,20 @@ class ClientChannelManager(relay.ChannelManager):
             logging.debug("Circuit was already closed, not sending bytes. circid: " + str(circid))
             return None
 
+        # In Telescoping Walking Onions, it should never happen that the
+        # guard and exit are the same node, as the
+        # TelescopingExtendedHandler takes care to not pick an index for
+        # the exit that matches the guard's range.  So this test should
+        # never trigger.  In Single-Pass Walking Onions, however, the
+        # equivalent test is needed here (but should just log a debug,
+        # not an error, since the client cannot control the index value
+        # selected for the exit.
+        if circhandler.circuit_descs[0].snipdict["addr"] == \
+                circhandler.circuit_descs[2].snipdict["addr"]:
+            logging.error("CIRCUIT IN A LOOP")
+            circhandler.close()
+            circhandler = None
+
         return circhandler
 
     def new_circuit_singlepass(self):