Esempio n. 1
0
    def process_inbound_message(self, msg):
        """
    First stage for handling an inbound message: check that it's a known
    message type, and that the number of arguments is correct; extract
    sequence numbers, send an ack if its required, if the message is a reply,
    retrieve any state that was stored when we sent the previous message.
    Actual functional message handling is organised by .determine_response()
    """

        self.debug_note("Processing inbound %s" % msg, seriousness=-2)
        # All Switzerland messages should be lists
        if type(msg) != types.ListType or type(msg[0]) != types.StringType or \
          msg[0] not in self.in_messages:
            self.protocol_error("Invalid message object " +
                                util.screensafe(str))

        # Message is a list of: msg_type, [reply_seq_no,] [seq_no,] arguments
        msg_type = msg[0]
        m = self.in_messages[msg_type]
        if len(msg) != m.length:
            self.protocol_error("Invalid message length %d for %s:\n " % \
            (len(msg), util.screensafe(msg)))

        args = []
        offset = 1
        seq_no = reply_seq_no = None
        if m.is_reply:
            reply_seq_no = int(msg[offset])
            offset += 1
            # semi-magically arrange for the reply data stored at our end to be passed
            # to the handler as if it was sent by the other party
            try:
                reply_data = self.reply_data_table[reply_seq_no]
            except:
                raise
            del self.reply_data_table[reply_seq_no]
            args.append(reply_data)
        if m.expects_ack or m.expects_reply:
            seq_no = int(msg[offset])
            offset += 1

        args += msg[offset:]

        # The rest depends on the specific message
        if not self.determine_response(msg_type, args, seq_no, reply_seq_no):
            sys.stderr.write(
                "Bug in %s.determine_response(), can't handle message %s\n" %
                ( ` self.__class__ `, `
                  (msg_type, args, seq_no, reply_seq_no) `))
            sys.exit(1)

        # Ack at the end to ensure it isn't over-confident
        if m.expects_ack:
            self.send_message("ack", [seq_no])
Esempio n. 2
0
  def process_inbound_message(self, msg):
    """
    First stage for handling an inbound message: check that it's a known
    message type, and that the number of arguments is correct; extract
    sequence numbers, send an ack if its required, if the message is a reply,
    retrieve any state that was stored when we sent the previous message.
    Actual functional message handling is organised by .determine_response()
    """
    
    self.debug_note("Processing inbound %s" % msg, seriousness=-2) 
    # All Switzerland messages should be lists
    if type(msg) != types.ListType or type(msg[0]) != types.StringType or \
      msg[0] not in self.in_messages:
      self.protocol_error("Invalid message object " + util.screensafe(str))

    # Message is a list of: msg_type, [reply_seq_no,] [seq_no,] arguments
    msg_type = msg[0]
    m = self.in_messages[msg_type]
    if len(msg) != m.length:
      self.protocol_error("Invalid message length %d for %s:\n " % \
      (len(msg), util.screensafe(msg)))

    args = []
    offset = 1 
    seq_no = reply_seq_no = None
    if m.is_reply:
      reply_seq_no = int(msg[offset])
      offset += 1
      # semi-magically arrange for the reply data stored at our end to be passed
      # to the handler as if it was sent by the other party
      try:
        reply_data = self.reply_data_table[reply_seq_no]
      except:
        raise
      del self.reply_data_table[reply_seq_no]
      args.append(reply_data)
    if m.expects_ack or m.expects_reply:
      seq_no = int(msg[offset])
      offset += 1

    args += msg[offset:]

    # The rest depends on the specific message
    if not self.determine_response(msg_type, args, seq_no, reply_seq_no):
      sys.stderr.write(
          "Bug in %s.determine_response(), can't handle message %s\n" %
          (`self.__class__`, `(msg_type, args, seq_no, reply_seq_no)`))
      sys.exit(1)

    # Ack at the end to ensure it isn't over-confident
    if m.expects_ack:
      self.send_message("ack", [seq_no])
  def handle_myip(self, args, reply_seq_no):
    "The other side has told us their opinion of their own IP address"
    peers_public_host, peer_port = self.peer
    peers_public_host = s.gethostbyname(peers_public_host)
    ips = args[0]
    try:
      self.peers_private_ip = s.gethostbyname(ips[0])
    except:
      self.protocol_error("Invalid peer host:\n %s" % util.screensafe(args[0]))

    if len(ips) == 2 and self.parent.config.allow_fake_ips: 
      # alice may specify a public ip she wishes to assume
      peer_host = ips[1]
      self.parent.faking_ip(self, peer_host)
      self.fake_ip(peer_host)
      self.alice_firewalled = ips[0] != ips[1]
    else: 
      if len(ips) == 2:
        # Fake IPs are intended for testing.  Perhaps in the future we'll
        # allow them for clients coming in through Tor, but there are security
        # issues to consider with that
        log.error("DENYING REQUEST FOR A FAKE IP!")
        self.send_message("error-cont", ["Denying request for a fake IP"])
      # but by default, she'll believe switzerland
      peer_host = s.gethostbyname(peers_public_host)
      self.alice_firewalled = peer_host != self.peers_private_ip

    self.send_message("public-ip", [peer_host], reply_seq_no=reply_seq_no)

    # XXX the simultaneous use of fake IPs and Alice's filter_packets=True
    # will break this next message
    self.send_message("new-members", [self.parent.peers_of(self.peer[0])])
    self.parent.joining_circle(self)
    self.now_ready()
Esempio n. 4
0
  def handle_active_flows(self, link, args):
    "The active_flows message from Alice updates our state of flows."
    new_flows, deleted_flows = args

    # Process deleted flows first, because we might want to delete a flow
    # and recreate it simultaneously if it has been closed and re-SYNed

    try:
      if not self.config.keep_reconciliators:
        self.debug_note("deleting flows: %s" % deleted_flows)
        for f_id in deleted_flows:
          self.mm.delete_flow(link, f_id)
    except:
      link.protocol_error("Problem with flow list: %s\n" % 
                                              util.screensafe(new_flows))
      raise

    # Now the new flows:
    try:
      for flow in new_flows:
        f_id = flow[0]
        assert len(flow[1]) == Protocol.hash_length, \
               "hashlen is not %d in %r" % (Protocol.hash_length, flow)
        if ipids_in_matchmaker:
          opening_hash = flow[1]
        else:
          opening_hash = flow[1][:-2]
        f_tuple = flow[2]
        assert len(f_tuple) == 5
        assert type(opening_hash) == str

        match = self.ponder_flow(link, f_id, f_tuple, opening_hash)
        if match:
          self.debug_note("YES", seriousness=-1)
          self.mm.add_flow(link, f_id, f_tuple, match)
        else:
          self.debug_note("NO", seriousness=-1)
          if not self.config.sloppy:
            self.debug_note("Mysteriously Irrelevant Flow!!!%s" %
                            `(link.peer[0],print_flow_tuple(f_tuple))`)

    except:
      errlog.debug("OH NOES %s", traceback.format_exc())
      link.protocol_error("Problem with flow list: %s\n" % 
                                            util.screensafe(new_flows))
      raise
Esempio n. 5
0
    def handle_myip(self, args, reply_seq_no):
        "The other side has told us their opinion of their own IP address"
        peers_public_host, peer_port = self.peer
        peers_public_host = s.gethostbyname(peers_public_host)
        ips = args[0]
        try:
            self.peers_private_ip = s.gethostbyname(ips[0])
        except:
            self.protocol_error("Invalid peer host:\n %s" %
                                util.screensafe(args[0]))

        if len(ips) == 2 and self.parent.config.allow_fake_ips:
            # alice may specify a public ip she wishes to assume
            peer_host = ips[1]
            self.parent.faking_ip(self, peer_host)
            self.fake_ip(peer_host)
            self.alice_firewalled = ips[0] != ips[1]
        else:
            if len(ips) == 2:
                # Fake IPs are intended for testing.  Perhaps in the future we'll
                # allow them for clients coming in through Tor, but there are security
                # issues to consider with that
                log.error("DENYING REQUEST FOR A FAKE IP!")
                self.send_message("error-cont",
                                  ["Denying request for a fake IP"])
            # but by default, she'll believe switzerland
            peer_host = s.gethostbyname(peers_public_host)
            self.alice_firewalled = peer_host != self.peers_private_ip

        self.send_message("public-ip", [peer_host], reply_seq_no=reply_seq_no)

        # XXX the simultaneous use of fake IPs and Alice's filter_packets=True
        # will break this next message
        self.send_message("new-members", [self.parent.peers_of(self.peer[0])])
        self.parent.joining_circle(self)
        self.now_ready()