예제 #1
0
 def __init__(self, host=None, sock=None, announcing=False):
     # pylint: disable=bad-super-call
     super(BMProto, self).__init__(sock=sock)
     self.verackReceived = True
     self.verackSent = True
     # .. todo:: sort out streams
     self.streams = [1]
     self.fullyEstablished = True
     self.connectedAt = 0
     self.skipUntil = 0
     if sock is None:
         if host is None:
             host = ''
         self.create_socket(
             socket.AF_INET6 if ":" in host else socket.AF_INET,
             socket.SOCK_DGRAM)
         self.set_socket_reuse()
         logger.info("Binding UDP socket to %s:%i", host, self.port)
         self.socket.bind((host, self.port))
     else:
         self.socket = sock
         self.set_socket_reuse()
     self.listening = Peer(*self.socket.getsockname())
     self.destination = Peer(*self.socket.getsockname())
     ObjectTracker.__init__(self)
     self.connecting = False
     self.connected = True
     self.announcing = announcing
     self.set_state("bm_header", expectBytes=protocol.Header.size)
예제 #2
0
 def bm_command_addr(self):
     addresses = self._decode_addr()
     # only allow peer discovery from private IPs in order to avoid
     # attacks from random IPs on the internet
     if not self.local:
         return True
     remoteport = False
     for seenTime, stream, _, ip, port in addresses:
         decodedIP = protocol.checkIPAddress(str(ip))
         if stream not in state.streamsInWhichIAmParticipating:
             continue
         if (seenTime < time.time() - self.maxTimeOffset
                 or seenTime > time.time() + self.maxTimeOffset):
             continue
         if decodedIP is False:
             # if the address isn't local, interpret it as
             # the host's own announcement
             remoteport = port
     if remoteport is False:
         return True
     logger.debug("received peer discovery from %s:%i (port %i):",
                  self.destination.host, self.destination.port, remoteport)
     if self.local:
         state.discoveredPeers[Peer(self.destination.host, remoteport)] = \
             time.time()
     return True
예제 #3
0
    def handle_accept(self):
        """Incoming connection callback"""
        try:
            sock = self.accept()[0]
        except (TypeError, IndexError):
            return

        state.ownAddresses[Peer(*sock.getsockname())] = True
        if (
            len(connectionpool.BMConnectionPool())
            > BMConfigParser().safeGetInt(
                'bitmessagesettings', 'maxtotalconnections')
                + BMConfigParser().safeGetInt(
                    'bitmessagesettings', 'maxbootstrapconnections') + 10
        ):
            # 10 is a sort of buffer, in between it will go through
            # the version handshake and return an error to the peer
            logger.warning("Server full, dropping connection")
            sock.close()
            return
        try:
            connectionpool.BMConnectionPool().addConnection(
                TCPConnection(sock=sock))
        except socket.error:
            pass
예제 #4
0
 def announceSelf():
     """Announce our presence"""
     for connection in BMConnectionPool().udpSockets.values():
         if not connection.announcing:
             continue
         for stream in state.streamsInWhichIAmParticipating:
             addr = (
                 stream,
                 Peer(
                     '127.0.0.1',
                     BMConfigParser().safeGetInt(
                         'bitmessagesettings', 'port')),
                 time.time())
             connection.append_write_buf(assemble_addr([addr]))
예제 #5
0
    def handle_read(self):
        try:
            (recdata, addr) = self.socket.recvfrom(self._buf_len)
        except socket.error as e:
            logger.error("socket error: %s", e)
            return

        self.destination = Peer(*addr)
        encodedAddr = protocol.encodeHost(addr[0])
        self.local = bool(protocol.checkIPAddress(encodedAddr, True))
        # overwrite the old buffer to avoid mixing data and so that
        # self.local works correctly
        self.read_buf[0:] = recdata
        self.bm_proto_reset()
        receiveDataQueue.put(self.listening)
예제 #6
0
 def __init__(self, address=None, sock=None):
     BMProto.__init__(self, address=address, sock=sock)
     self.verackReceived = False
     self.verackSent = False
     self.streams = [0]
     self.fullyEstablished = False
     self.connectedAt = 0
     self.skipUntil = 0
     if address is None and sock is not None:
         self.destination = Peer(*sock.getpeername())
         self.isOutbound = False
         TLSDispatcher.__init__(self, sock, server_side=True)
         self.connectedAt = time.time()
         logger.debug(
             'Received connection from %s:%i',
             self.destination.host, self.destination.port)
         self.nodeid = randomBytes(8)
     elif address is not None and sock is not None:
         TLSDispatcher.__init__(self, sock, server_side=False)
         self.isOutbound = True
         logger.debug(
             'Outbound proxy connection to %s:%i',
             self.destination.host, self.destination.port)
     else:
         self.destination = address
         self.isOutbound = True
         self.create_socket(
             socket.AF_INET6 if ":" in address.host else socket.AF_INET,
             socket.SOCK_STREAM)
         self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
         TLSDispatcher.__init__(self, sock, server_side=False)
         self.connect(self.destination)
         logger.debug(
             'Connecting to %s:%i',
             self.destination.host, self.destination.port)
     try:
         self.local = (
             protocol.checkIPAddress(
                 protocol.encodeHost(self.destination.host), True)
             and not protocol.checkSocksIP(self.destination.host)
         )
     except socket.error:
         # it's probably a hostname
         pass
     self.network_group = protocol.network_group(self.destination.host)
     ObjectTracker.__init__(self)  # pylint: disable=non-parent-init-called
     self.bm_proto_reset()
     self.set_state("bm_header", expectBytes=protocol.Header.size)
예제 #7
0
 def removeConnection(self, connection):
     """Remove a connection from our internal dict"""
     if isinstance(connection, UDPSocket):
         del self.udpSockets[connection.listening.host]
     elif isinstance(connection, TCPServer):
         del self.listeningSockets[Peer(connection.destination.host,
                                        connection.destination.port)]
     elif connection.isOutbound:
         try:
             del self.outboundConnections[connection.destination]
         except KeyError:
             pass
     else:
         try:
             del self.inboundConnections[connection.destination]
         except KeyError:
             try:
                 del self.inboundConnections[connection.destination.host]
             except KeyError:
                 pass
     connection.handle_close()
예제 #8
0
    def bm_command_addr(self):
        """Incoming addresses, process them"""
        # pylint: disable=redefined-outer-name
        addresses = self._decode_addr()
        for seenTime, stream, _, ip, port in addresses:
            decodedIP = protocol.checkIPAddress(str(ip))
            if stream not in state.streamsInWhichIAmParticipating:
                continue
            if (decodedIP and time.time() - seenTime > 0
                    and seenTime > time.time() - ADDRESS_ALIVE and port > 0):
                peer = Peer(decodedIP, port)

                with knownnodes.knownNodesLock:
                    # isnew =
                    knownnodes.addKnownNode(stream, peer, seenTime)

                # since we don't track peers outside of knownnodes,
                # only spread if in knownnodes to prevent flood
                # DISABLED TO WORKAROUND FLOOD/LEAK
                # if isnew:
                #     addrQueue.put((
                #         stream, peer, seenTime, self.destination))
        return True
예제 #9
0
    def __init__(self):
        asyncore.set_rates(
            BMConfigParser().safeGetInt("bitmessagesettings",
                                        "maxdownloadrate"),
            BMConfigParser().safeGetInt("bitmessagesettings", "maxuploadrate"))
        self.outboundConnections = {}
        self.inboundConnections = {}
        self.listeningSockets = {}
        self.udpSockets = {}
        self.streams = []
        self._lastSpawned = 0
        self._spawnWait = 2
        self._bootstrapped = False

        trustedPeer = BMConfigParser().safeGet('bitmessagesettings',
                                               'trustedpeer')
        try:
            if trustedPeer:
                host, port = trustedPeer.split(':')
                self.trustedPeer = Peer(host, int(port))
        except ValueError:
            sys.exit('Bad trustedpeer config setting! It should be set as'
                     ' trustedpeer=<hostname>:<portnumber>')
예제 #10
0
 def __init__(self, host='127.0.0.1', port=8444):
     if not hasattr(self, '_map'):
         AdvancedDispatcher.__init__(self)
     self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
     self.set_reuse_addr()
     for attempt in range(50):
         try:
             if attempt > 0:
                 logger.warning('Failed to bind on port %s', port)
                 port = random.randint(32767, 65535)
             self.bind((host, port))
         except socket.error as e:
             if e.errno in (asyncore.EADDRINUSE, asyncore.WSAEADDRINUSE):
                 continue
         else:
             if attempt > 0:
                 logger.warning('Setting port to %s', port)
                 BMConfigParser().set(
                     'bitmessagesettings', 'port', str(port))
                 BMConfigParser().save()
             break
     self.destination = Peer(host, port)
     self.bound = True
     self.listen(5)
예제 #11
0
 def __init__(self, host, port):
     self._connection_base.__init__(self, Peer(host, port))
     self.close_reason = self._succeed = False
예제 #12
0
 def __init__(self):
     super(BMStringParser, self).__init__()
     self.destination = Peer('127.0.0.1', 8444)
     self.payload = None
     ObjectTracker.__init__(self)
예제 #13
0
    def peerValidityChecks(self):
        """Check the validity of the peer"""
        if self.remoteProtocolVersion < 3:
            self.append_write_buf(
                protocol.assembleErrorMessage(
                    errorText=
                    "Your is using an old protocol. Closing connection.",
                    fatal=2))
            logger.debug(
                'Closing connection to old protocol version %s, node: %s',
                self.remoteProtocolVersion, self.destination)
            return False
        if self.timeOffset > MAX_TIME_OFFSET:
            self.append_write_buf(
                protocol.assembleErrorMessage(
                    errorText="Your time is too far in the future"
                    " compared to mine. Closing connection.",
                    fatal=2))
            logger.info(
                "%s's time is too far in the future (%s seconds)."
                " Closing connection to it.", self.destination,
                self.timeOffset)
            BMProto.timeOffsetWrongCount += 1
            return False
        elif self.timeOffset < -MAX_TIME_OFFSET:
            self.append_write_buf(
                protocol.assembleErrorMessage(
                    errorText=
                    "Your time is too far in the past compared to mine."
                    " Closing connection.",
                    fatal=2))
            logger.info(
                "%s's time is too far in the past (timeOffset %s seconds)."
                " Closing connection to it.", self.destination,
                self.timeOffset)
            BMProto.timeOffsetWrongCount += 1
            return False
        else:
            BMProto.timeOffsetWrongCount = 0
        if not self.streams:
            self.append_write_buf(
                protocol.assembleErrorMessage(
                    errorText="We don't have shared stream interests."
                    " Closing connection.",
                    fatal=2))
            logger.debug(
                'Closed connection to %s because there is no overlapping'
                ' interest in streams.', self.destination)
            return False
        if self.destination in connectionpool.BMConnectionPool(
        ).inboundConnections:
            try:
                if not protocol.checkSocksIP(self.destination.host):
                    self.append_write_buf(
                        protocol.assembleErrorMessage(
                            errorText="Too many connections from your IP."
                            " Closing connection.",
                            fatal=2))
                    logger.debug(
                        'Closed connection to %s because we are already'
                        ' connected to that IP.', self.destination)
                    return False
            except Exception:
                pass
        if not self.isOutbound:
            # incoming from a peer we're connected to as outbound,
            # or server full report the same error to counter deanonymisation
            if (Peer(self.destination.host, self.peerNode.port)
                    in connectionpool.BMConnectionPool().inboundConnections
                    or len(connectionpool.BMConnectionPool()) >
                    BMConfigParser().safeGetInt('bitmessagesettings',
                                                'maxtotalconnections') +
                    BMConfigParser().safeGetInt('bitmessagesettings',
                                                'maxbootstrapconnections')):
                self.append_write_buf(
                    protocol.assembleErrorMessage(
                        errorText="Server full, please try again later.",
                        fatal=2))
                logger.debug(
                    'Closed connection to %s due to server full'
                    ' or duplicate inbound/outbound.', self.destination)
                return False
        if connectionpool.BMConnectionPool().isAlreadyConnected(self.nonce):
            self.append_write_buf(
                protocol.assembleErrorMessage(
                    errorText="I'm connected to myself. Closing connection.",
                    fatal=2))
            logger.debug(
                "Closed connection to %s because I'm connected to myself.",
                self.destination)
            return False

        return True
예제 #14
0
 def bm_command_portcheck(self):
     """Incoming port check request, queue it."""
     portCheckerQueue.put(Peer(self.destination, self.peerNode.port))
     return True