Beispiel #1
0
 def test_handle_accept_typeerror(self):
     # https://github.com/giampaolo/pyftpdlib/issues/91
     ac = Acceptor()
     with mock.patch.object(ac, "accept", side_effect=TypeError) as m:
         ac.handle_accept()
         assert m.called
         self.assertIsNone(ac.socket)
Beispiel #2
0
    def __init__(self, address, handler, ioloop=None):
        """Initiate the FTP server opening listening on address.

         - (tuple) address: the host:port pair on which the command
           channel will listen.

         - (classobj) handler: the handler class to use.
        """
        Acceptor.__init__(self, ioloop=ioloop)
        self.handler = handler
        self.ip_map = []
        host, port = address
        # in case of FTPS class not properly configured we want errors
        # to be raised here rather than later, when client connects
        if hasattr(handler, 'get_ssl_context'):
            handler.get_ssl_context()

        # AF_INET or AF_INET6 socket
        # Get the correct address family for our host (allows IPv6 addresses)
        try:
            self._af = self.bind_af_unspecified((host, port))
        except socket.gaierror:
            # Probably a DNS issue. Assume IPv4.
            self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
            self.set_reuse_addr()
            self.bind((host, port))
            self._af = socket.AF_INET
        self.listen(5)
Beispiel #3
0
    def __init__(self, address, handler, ioloop=None):
        """Initiate the FTP server opening listening on address.

         - (tuple) address: the host:port pair on which the command
           channel will listen.

         - (classobj) handler: the handler class to use.
        """
        Acceptor.__init__(self, ioloop=ioloop)
        self.handler = handler
        self.ip_map = []
        host, port = address
        # in case of FTPS class not properly configured we want errors
        # to be raised here rather than later, when client connects
        if hasattr(handler, "get_ssl_context"):
            handler.get_ssl_context()

        # AF_INET or AF_INET6 socket
        # Get the correct address family for our host (allows IPv6 addresses)
        try:
            self._af = self.bind_af_unspecified((host, port))
        except socket.gaierror:
            # Probably a DNS issue. Assume IPv4.
            self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
            self.set_reuse_addr()
            self.bind((host, port))
            self._af = socket.AF_INET
        self.listen(5)
Beispiel #4
0
 def test_handle_accept_typeerror(self):
     # https://github.com/giampaolo/pyftpdlib/issues/91
     ac = Acceptor()
     with mock.patch.object(ac, "accept", side_effect=TypeError) as m:
         ac.handle_accept()
         assert m.called
         self.assertIsNone(ac.socket)
Beispiel #5
0
 def test_handle_accept_econnacorted(self):
     # https://github.com/giampaolo/pyftpdlib/issues/105
     ac = Acceptor()
     with mock.patch.object(
             ac, "accept",
             side_effect=socket.error(errno.ECONNABORTED, "")) as m:
         ac.handle_accept()
         assert m.called
         self.assertIsNone(ac.socket)
Beispiel #6
0
 def test_handle_accept_econnacorted(self):
     # https://github.com/giampaolo/pyftpdlib/issues/105
     ac = Acceptor()
     with mock.patch.object(ac,
                            "accept",
                            side_effect=socket.error(
                                errno.ECONNABORTED, "")) as m:
         ac.handle_accept()
         assert m.called
         self.assertIsNone(ac.socket)
Beispiel #7
0
 def test_bind_af_unspecified_err(self):
     ac = Acceptor()
     with mock.patch.object(ac,
                            "bind",
                            side_effect=socket.error(errno.EBADF, "")) as m:
         self.assertRaises(socket.error, ac.bind_af_unspecified,
                           ("localhost", 0))
         assert m.called
         self.assertIsNone(ac.socket)
Beispiel #8
0
    def __init__(self, address_or_socket, handler, ioloop=None, backlog=100):
        """Creates a socket listening on 'address' dispatching
        connections to a 'handler'.

         - (tuple) address_or_socket: the (host, port) pair on which
           the command channel will listen for incoming connections or
           an existent socket object.

         - (instance) handler: the handler class to use.

         - (instance) ioloop: a pyftpdlib.ioloop.IOLoop instance

         - (int) backlog: the maximum number of queued connections
           passed to listen(). If a connection request arrives when
           the queue is full the client may raise ECONNRESET.
           Defaults to 5.
        """
        Acceptor.__init__(self, ioloop=ioloop)
        self.handler = handler
        self.backlog = backlog
        self.ip_map = []
        # in case of FTPS class not properly configured we want errors
        # to be raised here rather than later, when client connects
        if hasattr(handler, 'get_ssl_context'):
            handler.get_ssl_context()
        if callable(getattr(address_or_socket, 'listen', None)):
            sock = address_or_socket
            sock.setblocking(0)
            self.set_socket(sock)
            if hasattr(sock, 'family'):
                self._af = sock.family
            else:
                # python 2.4
                ip, port = self.socket.getsockname()[:2]
                self._af = socket.getaddrinfo(ip, port, socket.AF_UNSPEC,
                                              socket.SOCK_STREAM)[0][0]
        else:
            self._af = self.bind_af_unspecified(address_or_socket)
        self.listen(backlog)
    def __init__(self, cmd_channel, extmode=False):
        """Initialize the passive data server.

         - (instance) cmd_channel: the command channel class instance.
         - (bool) extmode: wheter use extended passive mode response type.
        """
        self.cmd_channel = cmd_channel
        self.log = cmd_channel.log
        self.log_exception = cmd_channel.log_exception
        self._closed = False
        self._idler = None
        Acceptor.__init__(self, ioloop=cmd_channel.ioloop)

        local_ip = self.cmd_channel.socket.getsockname()[0]
        if local_ip in self.cmd_channel.masquerade_address_map:
            masqueraded_ip = self.cmd_channel.masquerade_address_map[local_ip]
        elif self.cmd_channel.masquerade_address:
            masqueraded_ip = self.cmd_channel.masquerade_address
        else:
            masqueraded_ip = None

        if self.cmd_channel.server._af != socket.AF_INET:
            # dual stack IPv4/IPv6 support
            af = self.bind_af_unspecified((local_ip, 0))
            self.socket.close()
        else:
            af = self.cmd_channel._af

        self.create_socket(af, socket.SOCK_STREAM)

        if self.cmd_channel.passive_ports is None:
            # By using 0 as port number value we let kernel choose a
            # free unprivileged random port.
            self.bind((local_ip, 0))
        else:
            ports = list(self.cmd_channel.passive_ports)
            while ports:
                port = ports.pop(random.randint(0, len(ports) - 1))
                self.set_reuse_addr()
                try:
                    self.bind((local_ip, port))
                except socket.error:
                    err = sys.exc_info()[1]
                    if err.args[0] == errno.EADDRINUSE:  # port already in use
                        if ports:
                            continue
                        # If cannot use one of the ports in the configured
                        # range we'll use a kernel-assigned port, and log
                        # a message reporting the issue.
                        # By using 0 as port number value we let kernel
                        # choose a free unprivileged random port.
                        else:
                            self.bind((local_ip, 0))
                            self.cmd_channel.log(
                                "Can't find a valid passive port in the "
                                "configured range. A random kernel-assigned "
                                "port will be used.",
                                logfun=logger.warning)
                    else:
                        raise
                else:
                    break
        self.listen(self.backlog or self.cmd_channel.server.backlog)

        port = self.socket.getsockname()[1]
        if not extmode:
            ip = masqueraded_ip or local_ip
            if ip.startswith('::ffff:'):
                # In this scenario, the server has an IPv6 socket, but
                # the remote client is using IPv4 and its address is
                # represented as an IPv4-mapped IPv6 address which
                # looks like this ::ffff:151.12.5.65, see:
                # http://en.wikipedia.org/wiki/IPv6#IPv4-mapped_addresses
                # http://tools.ietf.org/html/rfc3493.html#section-3.7
                # We truncate the first bytes to make it look like a
                # common IPv4 address.
                ip = ip[7:]
            # The format of 227 response in not standardized.
            # This is the most expected:
            self.cmd_channel.respond(
                '227 Entering passive mode (%s,%d,%d).' %
                (ip.replace('.', ','), port // 256, port % 256))
        else:
            self.cmd_channel.respond('229 Entering extended passive mode '
                                     '(|||%d|).' % port)
        if self.timeout:
            self._idler = self.ioloop.call_later(self.timeout,
                                                 self.handle_timeout,
                                                 _errback=self.handle_error)
 def close(self):
     if not self._closed:
         self._closed = True
         Acceptor.close(self)
         if self._idler is not None and not self._idler.cancelled:
             self._idler.cancel()