def create_circuit_hop1(self) -> int: """ The function to setup circuit with the first hop in the circuit. Creates the CREATE/CREATE2 cell and sends it down the socket. It assumes that the open_connection was called on the first node and the socket is connected to the first node :return: Returns a status code. 0 --> Success DH Handshake and -1 --> Means error in processing the cell or the DH Handshake. On error it closes the socket to node 1 """ # First create a CREATE2 Cell. x, x_bytes, gx, gx_bytes = CoreCryptoDH.generate_dh_priv_key() create_cell = Builder.build_create_cell( 'TAP', x_bytes, gx_bytes, self.circ_id, self.node_container[1].onion_key_pub) # Sending a JSON String down the socket self.skt.client_send_data(ComplexStructEncoder.encode(create_cell)) # self.skt.client_send_data(Serialize.obj_to_json(create_cell).encode('utf-8')) # Get the created cell in response and convert it to python Cell Object cell_bytes = self.skt.client_recv_data() created_cell = Parser.parse_encoded_created_cell(cell_bytes) self.session_key01 = Processor.process_created_cell( created_cell, self.circ_id, x_bytes) if self.session_key01 is None: self.skt.close() return -1 return 0
def create_circuit_hop2(self) -> int: """ The function to setup circuit with the second hop in the circuit. Creates the EXTEND/EXTEND2 cell and sends it down the socket. It assumes that the open_connection was called on the first node and the socket is connected to the first node, and that to the second node :return: Returns a status code. 0 --> Success DH Handshake and -1 --> Means error in processing the cell or the DH Handshake. On error it closes the socket to node 2. """ # First create a EXTEND2 Cell. x, x_bytes, gx, gx_bytes = CoreCryptoDH.generate_dh_priv_key() # For hop2 we get its IP:port for LSPEC ==> Link specifier hop2_ip = self.node_container[2].host hop2_port = self.node_container[2].port extend_cell = Builder.build_extend_cell( 'TAP', x_bytes, gx_bytes, self.circ_id, self.node_container[2].onion_key_pub, hop2_ip, hop2_port) print(extend_cell) # Sending a JSON String down the socket self.skt.client_send_data(ComplexStructEncoder.encode(extend_cell)) # Get the extended cell in response and convert it to python Cell Object cell_bytes = self.skt.client_recv_data() extended_cell = Parser.parse_encoded_extended_cell(cell_bytes) self.session_key02 = Processor.process_extended_cell( extended_cell, self.circ_id, x_bytes) if self.session_key02 is None: self.skt.close() return -1 return 0
def handle_relay_begin_cell(self, cell_bytes, direction): begin_cell = Parser.parse_encoded_begin_cell(cell_bytes) recognized, begin_cell = Processor.process_begin_cell( begin_cell, self.session_key) if recognized == 0: print("Recognized the begin cell!") # Getting the IP and port addrport = bytearray(begin_cell.PAYLOAD.Data.ADDRPORT) ip_addr, port = unpack('!IH', addrport) ip_addr = str(IPv4Address(ip_addr)) # Appending the stream ID to this circuit stream_id = begin_cell.PAYLOAD.StreamID self.stream_ids.append(stream_id) # Creating the socket and connecting it to end host! F**k yeah conn = self.stream_skts[stream_id] = HTTPConnection(ip_addr, port) conn.request("GET", "/") res = conn.getresponse() print(res.status, res.reason) if res: # The last parameter for build_relay_connected_cell is supposed to be TTL in secs connected_cell = Builder.build_relay_connected_cell( self.circ_id, stream_id, self.session_key, ip_addr, 360) self.conn.sendall(ComplexStructEncoder.encode(connected_cell)) else: print("Begin cell not for us. Lets pass it on!") self.skt.client_send_data(ComplexStructEncoder.encode(begin_cell))
def handle_relay_extend_cell(self, cell_bytes, direction): if self.is_last_node: extend_cell = Parser.parse_encoded_extend_cell(cell_bytes) addr, port, htype, hlen, hdata = Processor.process_extend_cell( extend_cell, self.node.onion_key_pri) # Connect with next node print(addr, port) err_code = self.skt.client_connect(addr, port) print(err_code) # Successfully connected, register it to the selectors list if err_code == 0: self.sktSelector.register(self.skt.skt, selectors.EVENT_READ, 1) # Create a CREATE2 Cell. create_cell = Builder.build_create_cell_from_extend( self.circ_id, htype, hlen, hdata) # Sending a JSON String down the socket self.skt.client_send_data(ComplexStructEncoder.encode(create_cell)) return 1 else: # Forwarding the cell down the stream self.skt.client_send_data(cell_bytes) return 2
def handle_relay_connected_cell(self, cell_bytes, direction): """ Function for handling the connected cell when it is received by a router :param cell_bytes: The struct received by the router for the connected cell """ parsed_connected_cell = Parser.parse_encoded_connected_cell(cell_bytes) processed_connected_cell = Processor.process_connected_cell_router(parsed_connected_cell, self.session_key) self.conn.sendall(ComplexStructEncoder.encode(processed_connected_cell)) return
def handle_created_cell(self, cell_bytes, direction): created_cell = Parser.parse_encoded_created_cell(cell_bytes) # process created cell hlen, hdata = Processor.process_created_cell_for_extended(created_cell) # Create extended cell extended_cell = Builder.build_extended_cell_from_created_cell(self.circ_id, hlen, hdata) # send extended to conn self.conn.sendall(ComplexStructEncoder.encode(extended_cell)) self.is_last_node = False print("Extended cell sent")
def handle_create_cell(self, cell_bytes, direction): # Call the Parser for create cell create_cell = Parser.parse_encoded_create_cell(cell_bytes) # Process the create cell y, y_bytes, gy, gy_bytes = CoreCryptoDH.generate_dh_priv_key() gx_bytes, kdf_dict = Processor.process_create_cell(create_cell, self.node.onion_key_pri, y_bytes) # After processing the create cell, we make a created cell # and send it down the socket created_cell = Builder.build_created_cell(y_bytes, gy_bytes, self.circ_id, gx_bytes) print(created_cell) self.conn.sendall(ComplexStructEncoder.encode(created_cell)) print("Created cell sent") self.session_key = kdf_dict return 0
def handle_relay_data_cell(self, cell_bytes, direction): """ Function for handling the data cell when received by a router :param cell_bytes: The struct received by the router for the data cell :param direction: :return: """ parsed_relay_data_cell = Parser.parse_encoded_relay_data_cell(cell_bytes) recognized, http_request_payload, relay_data_cell = Processor.process_relay_data_cell(parsed_relay_data_cell, self.session_key) if recognized == 0 and direction == 0: stream_id = relay_data_cell.PAYLOAD.StreamID conn = self.stream_skts[stream_id] conn.request(http_request_payload['method'], http_request_payload['url']) res = conn.getresponse() print(res.status, res.reason) return elif recognized != 0 and direction == 0: print("Not for me! Pass it on") self.skt.client_send_data(ComplexStructEncoder.encode(relay_data_cell)) return else: print("shouldn't reach here at this stage") return
def begin_end_destination_stream(self, ip_addr: str, port: int = 80): addrport = pack('!IH', int(ip_address(ip_addr)), port) flag_dict = { 'IPV6_PREF': 0, 'IPV4_NOT_OK': 0, 'IPV6_OK': 1 } # Need to set the flag according to the spec. But for now its fine # Build a begin cell to send to the exit node begin_cell = Builder.build_begin_cell(addrport, flag_dict, self.circ_id, 0, 1, self.session_key01, self.session_key02, self.session_key03) # Send the begin cell down the first hop # Sending a JSON String down the socket self.skt.client_send_data(ComplexStructEncoder.encode(begin_cell)) # Wait for the relay_connected cell to arrive # Get the relay_connected cell in response and convert it to python Cell Object cell_bytes = self.skt.client_recv_data() relay_connected_cell_parsed = Parser.parse_encoded_connected_cell( cell_bytes) relay_connected_cell = Processor.process_connected_cell_proxy( relay_connected_cell_parsed, self.session_key01, self.session_key02, self.session_key03) print(vars(relay_connected_cell)) print(vars(relay_connected_cell.PAYLOAD)) print(vars(relay_connected_cell.PAYLOAD.Data)) if relay_connected_cell is not None: return 0 else: return -1