Browse Source

wip! single-pass circuit creation

Chelsea H. Komlo 4 years ago
parent
commit
73b75d2089
2 changed files with 67 additions and 3 deletions
  1. 46 3
      client.py
  2. 21 0
      relay.py

+ 46 - 3
client.py

@@ -261,7 +261,8 @@ class ClientChannelManager(relay.ChannelManager):
 
     def new_circuit_telescoping(self):
         """Create a new circuit from this client. (Telescoping Walking Onions
-        version)"""
+        version). If an error occurs and the circuit is deleted from the guard
+        channel, return None, otherwise, return the circuit handler."""
 
         # Get our channel to the guard
         guardchannel = self.get_channel_to(self.guardaddr)
@@ -291,6 +292,42 @@ class ClientChannelManager(relay.ChannelManager):
 
         return circhandler
 
+    def new_circuit_singlepass(self):
+        """Create a new circuit from this client. (Single-Pass Walking Onions
+        version). If an error occurs and the circuit is deleted from the guard
+        channel, return None, otherwise, return the circuit handler."""
+
+        # Get our channel to the guard
+        guardchannel = self.get_channel_to(self.guardaddr)
+
+        # Allocate a new circuit id on it
+        circid, circhandler = guardchannel.new_circuit()
+
+        # first, create the path-selection key used for Sphinx
+        client_key = nacl.public.PrivateKey.generate()
+
+        # Construct the SinglePassCreateCircuitMsg
+        ntor = relay.NTor(self.perfstats)
+        ntor_request = ntor.request()
+        circcreatemsg = relay.SinglePassCreateCircuitMsg(circid, ntor_request,
+                client_key.public_key)
+
+        # Send the message
+        guardchannel.send_msg(circcreatemsg)
+
+        # Check to make sure the circuit is open before sending it- if there
+        # was an error when establishing it, the circuit could already be
+        # closed.
+        if not guardchannel.is_circuit_open(circid):
+            print("ERR: Circuit was already closed, not sending bytes. circid: " + str(circid))
+            return None
+
+        #TODO validate the Sphinx keys on reply
+        print("WARNING: Unimplemented! The client should validate the NTOR handshake using Sphinx operations here.")
+
+        return circhandler
+
+
     def new_circuit(self):
         """Create a new circuit from this client."""
         circhandler = None
@@ -303,7 +340,7 @@ class ClientChannelManager(relay.ChannelManager):
             elif network.thenetwork.womode == network.WOMode.TELESCOPING:
                 circhandler = self.new_circuit_telescoping()
             elif network.thenetwork.womode == network.WOMode.SINGLEPASS:
-                sys.exit("NOT YET IMPLEMENTED")
+                circhandler = self.new_circuit_singlepass()
 
         return circhandler
 
@@ -421,13 +458,19 @@ if __name__ == '__main__':
         print("Not a valid network mode: " + network_mode)
         sys.exit(0)
 
+    #TODO Add a command-line switch to set Merkle or Threshold
+
     if network_mode == network.WOMode.VANILLA:
         network.thenetwork.set_wo_style(network.WOMode.VANILLA,
             network.SNIPAuthMode.NONE)
     elif network_mode == network.WOMode.TELESCOPING:
         network.thenetwork.set_wo_style(network.WOMode.TELESCOPING,
             network.SNIPAuthMode.MERKLE)
-    # TODO set single-pass
+    elif network_mode == network.WOMode.SINGLEPASS:
+        network.thenetwork.set_wo_style(network.WOMode.SINGLEPASS,
+            network.SNIPAuthMode.MERKLE)
+    else:
+        sys.exit("Received unsupported network mode, exiting.")
 
     # Start some dirauths
     numdirauths = 9

+ 21 - 0
relay.py

@@ -173,6 +173,23 @@ class TelescopingExtendedCircuitCell(RelayCell):
         self.ntor_reply = ntor_reply
         self.snip = snip
 
+class SinglePassCreateCircuitMsg(RelayNetMsg):
+    """The message for requesting circuit creation in Single Pass Onion
+    Routing."""
+
+    def __init__(self, circid, ntor_request, client_path_selection_key):
+        self.circid = circid
+        self.ntor_request = ntor_request
+        self.client_path_selection_key = client_path_selection_key
+
+class SinglePassCreatedCircuitCell(RelayCell):
+    """The message for responding to circuit creation in Single-Pass Walking
+    Onions."""
+
+    def __init__(self, ntor_reply, circuit_snips):
+        self.ntor_reply = ntor_reply
+        self.circuit_snips = circuit_snips
+
 
 class EncryptedCell(RelayCell):
     """Send a message encrypted with a symmetric key.  In this
@@ -857,6 +874,10 @@ class RelayChannelManager(ChannelManager):
             # Send the ntor reply
             self.send_msg(CircuitCellMsg(msg.circid,
                     TelescopingCreatedCircuitCell(reply)), peeraddr)
+        elif isinstance(msg, SinglePassCreateCircuitMsg):
+            # A new circuit has arrived
+            circhandler = channel.new_circuit_with_circid(msg.circid)
+            sys.exit("have not yet implemented circuit handling for single-pass in relays")
         else:
             return super().received_msg(msg, peeraddr, channel)