Beispiel #1
0
class ftp_server:
    def __init__(self):
        authorizer = DummyAuthorizer()
        authorizer.add_user('user', '12345', 'collected/', perm='elradfmwMT')
        authorizer.add_anonymous("collected/", perm='elradfmwMT')
        self.handler = MyHandler
        self.handler.authorizer = authorizer
        self.obj = ThreadedFTPServer(("0.0.0.0", 21), self.handler)
        self.filename = ""
        # set a limit for connections
        #self.max_cons = 256
        #self.max_cons_per_ip = 5

    def get_filename(self):
        global filename
        return filename

    def _run_server(self):
        self.obj.serve_forever()

    def start(self):
        srv = threading.Thread(target=self._run_server)
        srv.deamon = True
        srv.start()

    def stop(self):
        self.obj.close_all()
Beispiel #2
0
def ftpserver():
    """Provide a ftp server with virtual files"""
    handler = FTPTestHandler
    handler.abstracted_fs = MyTestFS
    authorizer = MyDummyAuthorizer()
    home = os.curdir
    authorizer.add_user('user', '12345', home, perm='elrmwM')
    handler.authorizer = authorizer
    server = ThreadedFTPServer(('localhost', 12345), handler)

    createThread('FTP', server.serve_forever)
    yield handler
    server.close_all()
Beispiel #3
0
class FTPService():
    def __init__(self, *args, **kwargs):
        self.ftp_root = kodi.vfs.translate_path(
            kodi.get_setting('root_directory'))
        self.ftp_log = kodi.vfs.join(kodi.get_profile(), "pyftpd.log")
        self.cert_file = vfs.join(kodi.get_profile(), "pyftpd.pem")
        if not vfs.exists(self.cert_file):
            vfs.cp(vfs.join(kodi.get_path(), "pyftpd.pem"), self.cert_file)

    def start(self):
        class Monitor(xbmc.Monitor):
            def onSettingsChanged(self):
                pass

        monitor = Monitor()
        kodi.log("Service Starting...")
        authorizer = DummyAuthorizer()
        authorizer.add_user(kodi.get_setting('ftp_user'),
                            kodi.get_setting('ftp_pass'),
                            self.ftp_root,
                            perm='elradfmwMT')
        if kodi.get_setting('use_ssl') == 'true':
            from pyftpdlib.handlers import TLS_FTPHandler as handler
            handler.certfile = self.cert_file
        else:
            from pyftpdlib.handlers import FTPHandler as handler

        handler.banner = "PyFTPd ready."
        handler.authorizer = authorizer
        address = ('', kodi.get_setting('server_port'))
        import logging
        logging.basicConfig(filename=self.ftp_log, level=logging.INFO)
        self.ftpd = ThreadedFTPServer(address, handler)
        self.ftpd.max_cons = 256
        self.ftpd.max_cons_per_ip = 5
        self.server = Thread(target=self.ftpd.serve_forever)
        self.server.start()

        if is_depricated:
            while not xbmc.abortRequested:
                xbmc.sleep(1000)
        else:
            while not monitor.abortRequested():
                xbmc.sleep(1000)

        self.shutdown()

    def shutdown(self):
        kodi.log("Service Stopping...")
        self.ftpd.close_all()
        self.server.join()
Beispiel #4
0
class PyFtpServer(Thread):
    def __init__(self, path, user, pwd, port):
        super(PyFtpServer, self).__init__(name="PyFtpServer")
        self._stop_event = threading.Event()

        self._path = path
        self._user = user
        self._pwd = pwd
        self._port = port

        self._server = None

        self._lock = Lock()

    def run(self):
        with self._lock:
            # Instantiate a dummy authorizer for managing 'virtual' users
            authorizer = DummyAuthorizer()

            # Define a new user having full r/w permissions and a read-only anonymous user
            authorizer.add_user(self._user, self._pwd, self._path, perm='elradfmwMT')

            # Instantiate FTP handler class
            handler = FTPHandler
            handler.authorizer = authorizer

            # Define a customized banner (string returned when client connects)
            handler.banner = "pyftpdlib based ftpd ready."

            # Instantiate FTP server class and listen on 0.0.0.0:self._port
            address = ('0.0.0.0', int(self._port))
            try:
                self._server = ThreadedFTPServer(address, handler)
            except Exception as e:
                logging.error(f"Exception while start PyFtpServer: {e}")

        if self._server is not None:
            # set a limit for connections
            self._server.max_cons = 256
            self._server.max_cons_per_ip = 5

            # start ftp server
            self._server.serve_forever()

    def terminate(self):
        self._server.close_all()

    def success(self):
        with self._lock:
            return self._server is not None
Beispiel #5
0
class FTPServerWrapper(object):
    class TestHandler(FTPHandler):
        def on_incomplete_file_received(self, file):
            pass
            print('on_incomplete_file_received({})'.format(file))
            # TODO: delete incomplete file, mark job as unfinished

    class FTPServerRunner(Thread):
        def __init__(self, server):
            self.server = server
            super(FTPServerWrapper.FTPServerRunner, self).__init__()

        def run(self):
            self.server.serve_forever()

    def __init__(self, port=('', FTP_SERVER_PORT)):
        self.auth = DummyAuthorizer()
        self.handler = FTPServerWrapper.TestHandler
        self.handler.authorizer = self.auth
        self.server = ThreadedFTPServer(port, self.handler)

        self.port = port

        self.users = []
        self.t = FTPServerWrapper.FTPServerRunner(self.server)
        self.t.start()

    def __del__(self):
        self.server.close_all()
        self.server.close()
        del self.server

    def add_user(self, name, r_dir, w_dir):
        logging.info('adding ftp user {}'.format(name))
        self.users.append(name)
        self.auth.add_user('r-' + str(name), name, r_dir, perm='rl')
        self.auth.add_user('w-' + str(name), name, w_dir, perm='wl')

    def rem_user(self, name):
        logging.info('removing ftp user {}'.format(name))
        try:
            self.users.remove(name)
            self.auth.remove_user('r-' + str(name))
            self.auth.remove_user('w-' + str(name))
        except ValueError:
            pass
Beispiel #6
0
class Example(QtWidgets.QMainWindow):
    def __init__(self):
        super(Example, self).__init__()
        uic.loadUi('gui.ui', self)
        self.pushButtonStart.clicked.connect(self.onClick)
        self.pushButtonStop.clicked.connect(self.onStop)

        self.authorizer = DummyAuthorizer()
        self.authorizer.add_anonymous(os.getcwd())

        self.handler = FTPHandler
        self.handler.authorizer = self.authorizer
        self.handler.banner = "pyftpdlib based ftpd ready."

        # set a limit for connections
        self.max_cons = 256
        self.max_cons_per_ip = 5

    def onClick(self):
        print('start')

        user = self.lineEditUser.text()
        passw = self.lineEditPassword.text()

        self.authorizer.add_user(user, passw, '.', perm='elrw')
        self.address = ('127.0.0.1', 2100)
        self.server = ThreadedFTPServer(self.address, self.handler)

        QMessageBox.information(self, "FTP Server started",
                                "FTP Server started")
        self.start()

    def _run_server(self):
        self.server.serve_forever()

    def start(self):
        srv = threading.Thread(target=self._run_server)
        srv.deamon = True
        srv.start()

    def onStop(self):
        print('stop')
        self.server.close_all()
        QMessageBox.information(self, "FTP Server stopped",
                                "FTP Server stopped")
Beispiel #7
0
class FTPThread(Thread):
    def __init__(self):
        super().__init__()
        authorizer = DummyAuthorizer()
        authorizer.add_user("ons", "ons", "./ftp", perm="elradfmw")

        handler = FTPHandler
        handler.authorizer = authorizer
        handler.abstracted_fs = UnixFilesystem
        self.server = ThreadedFTPServer(
            (settings.FTP_HOST, str(settings.FTP_PORT)), handler)

    def run(self):
        logger.debug("Calling enter")
        try:
            self.server.serve_forever()
        except OSError:
            logger.debug("Thrown during shut down")
            exit()

    def stop(self):
        logger.debug("Calling exit")
        self.server.close_all()
Beispiel #8
0
class FTPListener(object):

    def taste(self, data, dport):

        # See RFC5797 for full command list. Many of these commands are not likely
        # to be used but are included in case malware uses FTP in unexpected ways
        base_ftp_commands = [
            'abor', 'acct', 'allo', 'appe', 'cwd', 'dele', 'help', 'list', 'mode', 
            'nlst', 'noop', 'pass', 'pasv', 'port', 'quit', 'rein', 'rest', 'retr',
            'rnfr', 'rnto', 'site', 'stat', 'stor', 'stru', 'type', 'user'
        ]
        opt_ftp_commands = [
            'cdup', 'mkd', 'pwd', 'rmd', 'smnt', 'stou', 'syst'
        ]

        confidence = 1 if dport == 21 else 0 

        data = data.lstrip().lower()
        for command in base_ftp_commands + opt_ftp_commands:
            if data.startswith(command):
                return confidence + 1

        return confidence

    def __init__(self,
            config,
            name='FTPListener',
            logging_level=logging.INFO,
            running_listeners=None,
            diverter=None
            ):

        self.logger = logging.getLogger(name)
        self.logger.setLevel(logging_level)

        self.config = config
        self.name = name
        self.local_ip = config.get('ipaddr')
        self.server = None
        self.running_listeners = running_listeners
        self.diverter = diverter
        self.name = 'FTP'
        self.port = self.config.get('port', 21)

        self.logger.debug('Starting...')

        self.logger.debug('Initialized with config:')
        for key, value in config.iteritems():
            self.logger.debug('  %10s: %s', key, value)

        # Initialize ftproot directory
        path = self.config.get('ftproot','defaultFiles')
        self.ftproot_path = ListenerBase.abs_config_path(path)
        if self.ftproot_path is None:
            self.logger.error('Could not locate ftproot directory: %s', path)
            sys.exit(1)

    def expand_ports(self, ports_list):
        ports = []
        for i in ports_list.split(','):
            if '-' not in i:
                ports.append(int(i))
            else:
                l,h = map(int, i.split('-'))
                ports+= range(l,h+1)
        return ports

    def start(self):

        self.authorizer = DummyAuthorizer()


        if self.config.get('usessl') == 'Yes':
            self.logger.debug('Using SSL socket.')

            keyfile_path = 'listeners/ssl_utils/privkey.pem'
            keyfile_path = ListenerBase.abs_config_path(keyfile_path)
            if keyfile_path is None:
                self.logger.error('Could not locate %s', keyfile_path)
                sys.exit(1)

            self.handler = TLS_FakeFTPHandler
            self.handler.certfile = keyfile_path

        else:
            self.handler = FakeFTPHandler

        self.handler.banner = self.genBanner()

        self.handler.ftproot_path = self.ftproot_path
        self.handler.abstracted_fs = FakeFS

        self.handler.authorizer = self.authorizer
        self.handler.passive_ports = self.expand_ports(self.config.get('pasvports', '60000-60010'))


        self.server = ThreadedFTPServer((self.local_ip, int(self.config['port'])), self.handler)

        # Override pyftpdlib logger name
        logging.getLogger('pyftpdlib').name = self.name


        self.server_thread = threading.Thread(target=self.server.serve_forever)
        self.server_thread.daemon = True
        self.server_thread.start()

    def stop(self):
        self.logger.debug('Stopping...')
        if self.server:
            self.server.close_all()

    def genBanner(self):
        bannerfactory = BannerFactory.BannerFactory()
        return bannerfactory.genBanner(self.config, BANNERS)
class FTPListener():

    def __init__(self, config, name = 'FTPListener', logging_level = logging.INFO):
        self.logger = logging.getLogger(name)
        self.logger.setLevel(logging_level)
            
        self.config = config
        self.name = name
        self.local_ip = '0.0.0.0'
        self.server = None

        self.logger.info('Starting...')

        self.logger.debug('Initialized with config:')
        for key, value in config.iteritems():
            self.logger.debug('  %10s: %s', key, value)

        # Initialize webroot directory
        self.ftproot_path = self.config.get('ftproot','defaultFiles')

    def expand_ports(self, ports_list):
        ports = []
        for i in ports_list.split(','):
            if '-' not in i:
                ports.append(int(i))
            else:
                l,h = map(int, i.split('-'))
                ports+= range(l,h+1)
        return ports

    def start(self):

        self.authorizer = DummyAuthorizer()


        if self.config.get('usessl') == 'Yes':
            self.logger.debug('Using SSL socket.')

            keyfile_path = 'privkey.pem'
            self.handler = TLS_FakeFTPHandler
            self.handler.certfile = keyfile_path

        else:
            self.handler = FakeFTPHandler



        self.handler.ftproot_path = self.ftproot_path
        self.handler.abstracted_fs = FakeFS


        self.handler.authorizer = self.authorizer
        self.handler.passive_ports = self.expand_ports(self.config.get('pasvports', '60000-60010'))


        self.server = ThreadedFTPServer((self.local_ip, int(self.config['port'])), self.handler)

        # Override pyftpdlib logger name
        logging.getLogger('pyftpdlib').name = self.name


        self.server_thread = threading.Thread(target=self.server.serve_forever)
        self.server_thread.daemon = True
        self.server_thread.start()

    def stop(self):
        self.logger.debug('Stopping...')
        if self.server:
            self.server.close_all()
Beispiel #10
0
class CrestronDevice(object):
    
    def __init__(self, args):
        self.args = args
        self.console_prompt = ""
        self.device_ip_address = self.args.ip_address
        self.dry_run = self.args.dry_run
        self.forcessh = self.args.force_ssh
        self.ftp_output_path = self.args.ftp_dir
        self.ftp_server = None
        self.ftp_server_ip_address = self.args.ftp_server
        self.local_path = self.args.ftp_dir
        
        self.sshclient = None
        self.sock = None
        
    def start_ftp_server(self):
        if not self.dry_run and self.args.local_ftp_server:
            self.ftp_server = None
            try:
                handler = FTPHandler
                authorizer = DummyAuthorizer()
                
                if(self.args.ftp_username and self.args.ftp_username != ""):
                    authorizer.add_user(self.args.ftp_username, self.args.ftp_password, self.ftp_output_path, perm='elradfmwMT')
                else:
                    authorizer.add_anonymous(self.ftp_output_path, perm='elradfmwMT')
                
                handler.authorizer = authorizer
                self.ftp_server = ThreadedFTPServer((self.args.local_ftp_interface, self.args.local_ftp_port), handler)
                self.ftp_server.serve_forever(blocking=False)
                
                if self.args.local_ftp_interface == "":
                    print("Started local FTP server: ::%s" % (self.args.local_ftp_port))
                else:
                    print("Started local FTP server: %s:%s" % (self.args.local_ftp_interface, self.args.local_ftp_port))
                    
            except:
                if self.args.local_ftp_interface == "":
                    print("Failed to start local FTP server on: ::%s" % (self.args.local_ftp_port))
                else:
                    print("Failed to start local FTP server on: %s:%s" % (self.args.local_ftp_interface, self.args.local_ftp_port))
                exit()
                
    def stop_ftp_server(self):
        if self.ftp_server:
            print("[*] Stopping local FTP server...")
            try:
                self.ftp_server.close_all()
                print("[+] Local FTP server stopped.")
            except:
                print("[-] Failed to stop local FTP server.")
                pass
            
    def open_device_connection(self):
        if self.forcessh:
            print("[*] Establishing Paramiko SSH session with %s:%s ..." % (self.device_ip_address, SSH_PORT))
            self.sshclient = paramiko.client.SSHClient()
            try:
                self.sshclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                self.sshclient.load_system_host_keys()
                self.sshclient.connect(self.device_ip_address, port=22, username=self.args.username, password=self.args.password, timeout=SOCKET_TIMEOUT)
                print("[+] Successfully established Paramiko SSH session.")
                return True
            except:
                self.sshclient = None
                print("[-] Error: Unable to establish Paramiko SSH session with device.")
                return False
                
        else:
            print("[*] Establishing CTP session with %s:%s ..." % (self.device_ip_address, CTP_PORT))
            try:
                self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.sock.settimeout(SOCKET_TIMEOUT)
                self.sock.connect((self.device_ip_address, CTP_PORT))
                print("[+] Successfully established CTP session.")
                return True
            except:
                self.sock = None
                print("[-] Error: Unable to establish CTP session with device.")
                return False

    def close_device_connection(self):
        print("[*] Shutting down device connections...")
        if self.sshclient:
            try:
                self.sshclient.close()
                print("[+] Closed Paramiko SSH session.")
            except:
                print("[-] Failed to close Paramiko SSH session.")
                pass
        
        if self.sock:
            try:
                self.sock.close()
                print("[+] Closed CTP session.")
            except:
                print("[-] Failed to close CTP session.")
                pass
            
            
    def get_console_prompt(self):
        """
        Determine the device console prompt
        """
        data = ""
        for _unused in range(0, MAX_RETRIES):
            if self.sshclient:
                stdin,stdout,stderr=self.sshclient.exec_command("ver")
                data = str(stdout.readlines())
                search = re.findall("([\w-]{3,30})\ ", data, re.MULTILINE)
            else:
                self.sock.sendall(CR+CR)
                data += self.sock.recv(BUFF_SIZE)
                search = re.findall("[\n\r]([\w-]{3,30})>", data, re.MULTILINE)
            
            sleep(GLOBAL_SLEEP_VALUE)
            if search:
                self.console_prompt = search[0]
                print("[!] Console prompt is: %s" % (self.console_prompt))
                
                if self.console_prompt == "MERCURY":
                    print("[-] Mercury currently unsupported due to Crestron engin.err.uity (I guess...).")
                    return False
                
                self.ftp_output_path = os.path.join(self.local_path, ("Crestron_Device_%s" % (self.console_prompt)))
                if not os.path.isdir(self.ftp_output_path) and not self.dry_run and self.args.local_ftp_server:
                    try:
                        os.makedirs(self.ftp_output_path)
                    except:
                        self.ftp_output_path = os.path.join(self.local_path, ("Crestron_Device_%s" % (self.device_ip_address)))
                        try:
                            os.makedirs(self.ftp_output_path)
                        except:
                            self.ftp_output_path = self.local_path
                
                print("[+] Crestron local FTP working directory set to:\r\n\t%s\r\n" % (self.ftp_output_path))
                
                return True
        print("[-] Console prompt not found on device.")
        return False

    def find_console_prompt(self, data, key_value="", minimum_next_prompt_location=0, maximum_next_prompt_location=0, return_position=False, reverse=False):
        """
        Description:    Monolithic function for locating and verifying the presence of a supplied key value.
        Parameters:     data - the string value to check for the key_value.
                        key_value - either a string to look for or an empty string.
                            If a non-empty string is supplied, data is checked for the supplied value.
                            If an empty string is supplied, data is checked for the presence of the console_prompt.
                        minimum_next_prompt_location - the position to start searching for the key_value.
                            Default value of 0 means the whole string is checked.
                        maximum_next_prompt_location - the position to stop searching for the key_value.
                            Default value of 0 means everything past the minimum_next_prompt_location is checked.
                        return_position - returns the position of the key_value instead of a bool.
                        reverse - use rfind instead of find, to find the highest index of key_value.
        Output:         Returns True if the key_value is found in data, at the minimum_next_prompt_location supplied.
        """
        # If the minimum_next_prompt_location specifies a location outside of the data string, return -1 if looking for a position or
        #   return False, signifying that the key_value was not found.
        if minimum_next_prompt_location >= len(data) or minimum_next_prompt_location < 0:
            if return_position:
                return -1
            else:
                return False
                
        # If the maximum_next_prompt_location comes before the minimum_next_prompt_location or is less than 0, set it to the length of the data.
        if maximum_next_prompt_location <= minimum_next_prompt_location or maximum_next_prompt_location < 0:
            # Purposefully overshooting the end of the string in case minimum_next_prompt_location is or is near the end of the string.
            # Doesn't really matter if this value is larger than the actual data value.
            maximum_next_prompt_location = len(data)
            
        # If no key_value supplied, use the console prompt as the key_value.
        if not key_value or key_value == "":
            key_value = ("%s>" % (self.console_prompt))
            
        if return_position:
            if reverse:
                return data.rfind(key_value, minimum_next_prompt_location, maximum_next_prompt_location)
            else:
                return data.find(key_value, minimum_next_prompt_location, maximum_next_prompt_location)
        else:
            return data.find(key_value, minimum_next_prompt_location, maximum_next_prompt_location) != -1
    
    def remove_prompt(self, data, char_limit=0):
        """
        Remove the console prompt from the text within the specified character limit.
        """
        # If 0, remove the first occurrence of the prompt.
        if char_limit == 0:
            return data.replace(self.console_prompt+">", "", 1)
            
        # If less than 0, remove all instances of the prompt.
        elif char_limit <= 0:
            return data.replace(self.console_prompt+">", "")

        # Else if the first console prompt is found within the first char_limit characters, remove it.
        elif data.find(self.console_prompt+">") < char_limit:
            return data.replace(self.console_prompt+">", "", 1)
        
        return data

    def send_command_wait_prompt(self, command, minimum_next_prompt_location=0, done_string=""):
        """
        Send a command and wait for the following console prompt or done_string to appear.
        """
        if self.sshclient:
            stdin,stdout,stderr=self.sshclient.exec_command(command)
            data = stdout.readlines()
            data = "".join(data)
        else:
            data = ""
            is_checking_for_data = False
            
            wait_count = 0
            
            self.sock.sendall((CR+command+CR))
            sleep(GLOBAL_SLEEP_VALUE)
            
            data = (self.sock.recv(BUFF_SIZE)).replace((CR+command+CR), "")
            sleep(GLOBAL_SLEEP_VALUE)
            
            last_data_length = len(data)
            data_check_count = 0
            if done_string and done_string != "":
                is_checking_for_data = (not self.find_console_prompt(data, done_string))
            else:
                is_checking_for_data = (not self.find_console_prompt(data, minimum_next_prompt_location=minimum_next_prompt_location))
            
            while is_checking_for_data:
                # "Deal with newer firmware that executes commands / doesn't return a prompt instead of printing help"
                #   I'm not entirely sure what this means or looks like. It seems we're waiting for data that may or may not show up.
                #   If the recv errors, we send a return, though we also send a return every 5 iterations, regardless...
                #   We were also stuck in this while loop, waiting for a string that may never appear in the received data...
                
                try:
                    data += self.sock.recv(BUFF_SIZE)
                except:
                    self.sock.sendall(CR)
                sleep(GLOBAL_SLEEP_VALUE)
                
                wait_count += 1
                if wait_count == 5:
                    self.sock.sendall(CR)
                    sleep(GLOBAL_SLEEP_VALUE)
                    wait_count = 0
                    
                    # A shitty attempt at breaking the while loop.
                    # Every 5 loops, this segment execs, checking if the size of data has changed since the last 5 loops.
                    # If the size of the data hasn't changed in the last 15 loops, break out of the while loop.
                    # Results will vary.
                    data_check_count += 1
                    if data_check_count > 3 and last_data_length == len(data):
                        break
                    elif last_data_length != len(data):
                        data_check_count = 0
                    last_data_length = len(data)
                
                if done_string and done_string != "":
                    is_checking_for_data = (not self.find_console_prompt(data, done_string))
                else:
                    is_checking_for_data = (not self.find_console_prompt(data, minimum_next_prompt_location=minimum_next_prompt_location))
        return data
        
    def get_dir_listing(self, path=''):
        """
        Get a directory list for the supplied path. If no path supplied, lists out the root.
        """
        if path == '':
            path = '\\'
        data = self.send_command_wait_prompt(("dir %s" % (path)), 40)
        if not self.sshclient:
            return self.remove_prompt(data)
        else:
            return data.strip()
        
    def get_file(self, ftp_path, remote_path):
        """
        Get a file from the device using the FPUTfile command. This tells the device to FTP the file at remote_path
            to the supplied FTP server, at the ftp_path.
        """
        ftp_url = "ftp://%s%s" % (self.ftp_server_ip_address, urllib.quote(ftp_path))
        
        command = "FPUTfile %s \"%s\"" % (ftp_url, remote_path)
        
        if remote_path.find(" ") >= 0:
            command = "%s \"%s\"" % (command, remote_path)
        else:
            command = "%s %s" % (command, remote_path)
        
        if(self.args.ftp_username and self.args.ftp_username != ""):
            command = "%s %s:%s" % (command, self.args.ftp_username, self.args.ftp_password)
            
        print(command)
        
        if not self.dry_run:
            data = self.send_command_wait_prompt(command, done_string="End Progress")
        
    def replicate_filesystem(self, current_path=''):
        """
        Replicate the device's filesystem. Recursively lists and gets files from the device using get_dir_listing and get_file.
            Creates any necessary local directories, along the way.
        """
        if not os.path.isdir(self.ftp_output_path+current_path) and not self.dry_run and self.args.local_ftp_server:
            os.makedirs(self.ftp_output_path+current_path)
        
        data = self.get_dir_listing(current_path)
        directory_re = "\[DIR\]\s+\d+-\d+-\d+ \d+:\d+:\d+ (?P<directory_name>.+?)\r\n"
        file_re = "\d+\s+\d+-\d+-\d+ \d+:\d+:\d+ (?P<file_name>.+?)\r\n"
        
        for directory_name in re.findall(directory_re, data, re.MULTILINE):
            remote_directory_path = '\\'.join([current_path,directory_name])
            self.replicate_filesystem(remote_directory_path)
        
        for file_name in re.findall(file_re, data, re.MULTILINE):
            remote_file_path = '\\'.join([current_path,file_name])
            ftp_path = '/'.join([current_path.replace('\\','/'),file_name])
            data = self.get_file(ftp_path, remote_file_path)
Beispiel #11
0
class ftp_server():
    def __init__(self):
        self.root_dir = None
        self.user = None
        self.password = None
        self.port = None
        self.server = None
        self.ftp_server_thread = None
        self.running = False
        self.last_error = None

    def get_root_dir(self):
        return self.root_dir

    def set_root_dir(self, full_path):
        self.root_dir = full_path

    def setup_ftp(self, server_id=1):
        ftp_settings = None
        mc_settings = None
        try:
            ftp_settings = Ftp_Srv.get_by_id(1)
            mc_settings = MC_settings.get_by_id(server_id)

        except Exception as e:
            logging.exception("Error Loading FTP. Traceback:")
            self.last_error = e
            return False

        pemfile = os.path.join(helper.crafty_root, "app", 'web', 'certs',
                               'crafty.pem')

        if not helper.check_file_exists(pemfile):
            helper.create_ftp_pem()

        if ftp_settings is not None and mc_settings is not None:

            self.user = ftp_settings.user
            self.password = ftp_settings.password
            self.port = ftp_settings.port
            self.root_dir = mc_settings.server_path

            logger.info("FTP server is now setup - Port: {}, Dir: {}".format(
                self.port, self.root_dir))

    def _ftp_serve(self, server_id=1):
        self.setup_ftp(server_id)

        authorizer = DummyAuthorizer()
        authorizer.add_user(self.user,
                            self.password,
                            self.root_dir,
                            perm='elradfmwMT')
        handler = TLS_FTPHandler
        crafty_root = os.path.abspath(helper.crafty_root)
        certfile = os.path.join(crafty_root, 'app', 'web', 'certs',
                                'crafty.pem')

        handler.certfile = certfile
        handler.authorizer = authorizer
        self.server = ThreadedFTPServer(('0.0.0.0', self.port), handler)
        self.running = True
        self.server.serve_forever()

    def run_threaded_ftp_server(self, server_id=1):
        self.running = True
        logger.info("Ftp Server Started for server ID: {}".format(server_id))
        self.ftp_server_thread = threading.Thread(target=self._ftp_serve,
                                                  args=[server_id],
                                                  daemon=True)
        self.ftp_server_thread.start()

    def stop_threaded_ftp_server(self):
        self.running = False
        self.server.close_all()

    def check_running(self):
        return self.running
class TestCapture(unittest.TestCase):
    def setUp(self) -> None:

        self.fake = Faker()
        self.fake.add_provider(FakeCamera)

        self.temp_folder = tempfile.mkdtemp()
        self.temp_upload_file_path = None

        self.ftp_auth = DummyAuthorizer()
        self.ftp_auth.add_user('test', 'test', self.temp_folder, 'elrmw')
        self.ftp_handler = FTPHandler
        self.ftp_handler.authorizer = self.ftp_auth
        self.ftp_server = None
        while not self.ftp_server:
            self.ftp_port = random.randint(50000, 60000)
            try:
                self.ftp_server = ThreadedFTPServer(
                    ('localhost', self.ftp_port), self.ftp_handler)
            except Exception as exc:
                print('{} error creating FTP server: {}; retrying...'.format(
                    type(exc), exc))
                self.ftp_server = None
        self.ftp_thread = Thread(target=self.ftp_server.serve_forever)
        self.ftp_thread.start()

        logging.getLogger('').setLevel(logging.DEBUG)

    def tearDown(self) -> None:

        self.ftp_server.close_all()
        shutil.rmtree(self.temp_folder)
        if self.temp_upload_file_path:
            os.unlink(self.temp_upload_file_path)

    def test_capture_upload(self):
        frame_jpg = image_to_jpeg(self.fake.random_image(640, 480))  # pylint: disable=no-member
        self.temp_upload_file_path = tempfile.mktemp(suffix='.jpg')
        with open(self.temp_upload_file_path, 'wb') as temp_file:
            temp_file.write(frame_jpg)

        nowdate = datetime.now()
        nowstamp = nowdate.strftime('%Y-%m-%d-%H-%M-%S-%f')
        ftp_path = 'ftp://*****:*****@localhost:{}/dev/%date%'.format(
            self.ftp_port)
        print(ftp_path)
        capturer_args = {'path': ftp_path}
        capturer = CaptureWriter('test_capture', nowstamp, 640, 480,
                                 **capturer_args)
        capturer.upload_ftp(self.temp_upload_file_path)

        # Verify file was uploaded correctly.
        upload_local_dest = os.path.join(
            self.temp_folder, 'dev', nowdate.strftime('%Y-%m-%d'),
            os.path.basename(self.temp_upload_file_path))
        self.assertTrue(os.path.exists(upload_local_dest))
        local_stat = os.stat(self.temp_upload_file_path)
        remote_stat = os.stat(upload_local_dest)
        self.assertEqual(local_stat.st_size, remote_stat.st_size)

    def test_capture_photo(self):

        with self.fake.directory() as capture_path:  # pylint: disable=no-member

            config = {
                'enable': 'true',
                'backuppath': capture_path,
                'path': capture_path,
                'multiproc': 'false',
                'camera': 'test'
            }

            capturer = PhotoCapture('test_capture', **config)

            for i in range(10):
                frame = None
                frame = self.fake.random_image(640, 480)  # pylint: disable=no-member
                capturer.handle_motion_frame(frame)

            capturer.finalize_motion(None)

            self.assertEqual(len(os.listdir(capture_path)), 10)

    @memunit.assert_lt_mb(300)
    def test_capture_video(self):

        with self.fake.directory() as capture_path:  # pylint: disable=no-member

            config = {
                'enable': 'true',
                'graceframes': '10',
                'backuppath': capture_path,
                'path': capture_path,
                'fps': '5.0',
                'fourcc': 'mp4v',
                'container': 'mp4',
                'multiproc': 'false',
                'camera': 'test',
            }

            capturer = VideoCapture('test_capture', **config)

            for i in range(5):
                frame = None
                self.assertEqual(capturer.frames_count, 0)
                fc_check = 0
                for j in range(0, 200):
                    frame = self.fake.random_image(640, 480)  # pylint: disable=no-member
                    capturer.handle_motion_frame(frame)
                    fc_check += 1
                    if fc_check > 100:
                        fc_check = 0
                    else:
                        self.assertEqual(capturer.frames_count, fc_check)

                capturer.finalize_motion(None)
                self.assertEqual(capturer.frames_count, 0)

            # Verify the video files.
            video_count: int = 0
            for entry in os.scandir(capture_path):
                if entry.name.endswith('.mp4'):
                    width: int = 0
                    height: int = 0
                    sec: int = 0
                    #ms : int = 0
                    video_count += 1
                    filename = os.path.join(capture_path, entry.name)
                    parser = createParser(filename)
                    metadata = extractMetadata(parser)
                    text = metadata.exportPlaintext()
                    for line in text:
                        match = RE_DURATION.match(line)
                        if match:
                            sec = int(match.group('sec'))
                            #ms = int( match.group('ms') )
                            continue

                        match = RE_WIDTH.match(line)
                        if match:
                            width = int(match.group('width'))
                            continue

                        match = RE_HEIGHT.match(line)
                        if match:
                            height = int(match.group('height'))

                    self.assertEqual(width, 640)
                    self.assertEqual(height, 480)
                    self.assertIn(sec, [19, 20])
                    #self.assertEqual( ms, 190 )

            self.assertEqual(video_count, 10)
Beispiel #13
0
class FTPListener():

    def __init__(self, config, name = 'FTPListener', logging_level = logging.INFO):
        self.logger = logging.getLogger(name)
        self.logger.setLevel(logging_level)
            
        self.config = config
        self.name = name
        self.local_ip = '0.0.0.0'
        self.server = None

        self.logger.info('Starting...')

        self.logger.debug('Initialized with config:')
        for key, value in config.iteritems():
            self.logger.debug('  %10s: %s', key, value)

        # Initialize webroot directory
        self.ftproot_path = self.config.get('ftproot','defaultFiles')

    def expand_ports(self, ports_list):
        ports = []
        for i in ports_list.split(','):
            if '-' not in i:
                ports.append(int(i))
            else:
                l,h = map(int, i.split('-'))
                ports+= range(l,h+1)
        return ports

    def start(self):

        self.authorizer = DummyAuthorizer()


        if self.config.get('usessl') == 'Yes':
            self.logger.debug('Using SSL socket.')

            keyfile_path = 'privkey.pem'
            self.handler = TLS_FakeFTPHandler
            self.handler.certfile = keyfile_path

        else:
            self.handler = FakeFTPHandler



        self.handler.ftproot_path = self.ftproot_path
        self.handler.abstracted_fs = FakeFS


        self.handler.authorizer = self.authorizer
        self.handler.passive_ports = self.expand_ports(self.config.get('pasvports', '60000-60010'))


        self.server = ThreadedFTPServer((self.local_ip, int(self.config['port'])), self.handler)

        # Override pyftpdlib logger name
        logging.getLogger('pyftpdlib').name = self.name


        self.server_thread = threading.Thread(target=self.server.serve_forever)
        self.server_thread.daemon = True
        self.server_thread.start()

    def stop(self):
        self.logger.debug('Stopping...')
        if self.server:
            self.server.close_all()
Beispiel #14
0
class DeployAgent(object):
    def __init__(self, ftpaddr, ftpport, ftphome, rpcaddr, rpcport):
        self.ftpaddr        = ftpaddr
        self.ftpport        = ftpport
        self.ftphome        = ftphome
        
        self.rpcaddr        = rpcaddr
        self.rpcport        = rpcport
        
        logger.info("--- xagent startup ---")

        XOR.File.mkpath(self.ftphome)
        authorizer = DummyAuthorizer()
        authorizer.add_anonymous(self.ftphome, perm='elradfmwM')
        handler = FTPHandler
        handler.authorizer = authorizer
        handler.banner = "xagent ftp server ready"
        self.ftpserver = ThreadedFTPServer((self.ftpaddr, self.ftpport), handler)

        self.rpcserver = XOR.Net.XMLRPCServer(addr=(self.rpcaddr, self.rpcport), logRequests=True, allow_none=True, encoding="UTF-8")
        self.rpcserver.reg_function(XOR.OS.runex, "os.")
        self.rpcserver.reg_function(XOR.OS.type, "os.")
        self.rpcserver.reg_function(XOR.Zip.extract, "zip.")
        self.rpcserver.reg_function(XOR.File.remove, "file.")
        self.rpcserver.reg_function(self.reg_package)
        self.rpcserver.reg_function(self.shutdown)
        self.rpcserver.reg_function(self.set_logger)
        self.rpcserver.reg_function(self.del_logger)
        self.rpcserver.reg_function(self.get_ftphomedir)
        self.rpcserver.register_introspection_functions()
        self.rpcserver.register_multicall_functions()


    def startup(self):
        self.ftpthread = threading.Thread(target=lambda:self.ftpserver.serve_forever())
        self.ftpthread.daemon = True
        self.ftpthread.start()
        
        self.rpcthread = threading.Thread(target=lambda:self.rpcserver.serve_forever())
        self.rpcthread.daemon = True
        self.rpcthread.start()


    def shutdown(self):
        self.ftpserver.close_all()
        self.rpcserver.shutdown()


    def join(self):
        self.ftpthread.join()
        self.rpcthread.join()


    def set_logger(self, logurl):
        logger.info("set httphandler: %s", logurl)
        if hasattr(self, "httphandler"):
            self.del_logger()
        
        match = re.match("http://(.*:\d{1,5})/(.*)", logurl)
        host = match.group(1)
        path = "/%s" % match.group(2)
        logger.info("log host: %s", host)
        logger.info("log path: %s", path)
        self.httphandler = logging.handlers.HTTPHandler(host, path, "POST")
        self.httphandler.setLevel(logging.DEBUG)
        logger.info("set httphandler: %s", logurl)
        rootlogger.addHandler(self.httphandler)
    
    
    def del_logger(self):
        logger.info("delete logging httphandler: %s" % self.httphandler)
        rootlogger.removeHandler(self.httphandler)
    
    
    def reg_package(self, name, path=[], clss=[]):
        found = imp.find_module( name, path )
        imp.load_module(name, *found)
        self.rpcserver.reg_module(sys.modules[name], clss, "%s." % name)

    
    def get_ftphomedir(self):
        return self.ftphome
    
    @staticmethod
    def parse_args():
        parser = argparse.ArgumentParser(add_help=True)
        parser.add_argument('--host', action='store', default="0.0.0.0")
        parser.add_argument('--rpcport', action='store', type=int, default=3333)
        parser.add_argument('--ftpport', action='store', type=int, default=6121)
        parser.add_argument('--ftpusername', action='store', default="xor")
        parser.add_argument('--ftppassword', action='store', default="xor")
        parser.add_argument('--ftphomedir', action='store', default= os.path.join( os.path.dirname(bindir), "dist" ))
        args = parser.parse_known_args()
        return vars(args[0])
Beispiel #15
0
class FTPServerApp(tkinter.Frame):
    root_dir = dict()
    root_dir_tree = dict()
    dir_tree_frame = dict()

    def __init__(self, master=None):
        tkinter.Frame.__init__(self, master)
        self.grid(row=0, column=0)

        # Main Frame
        master.minsize(480,640)
        self.local_ip_addr = socket.gethostbyname(socket.getfqdn())
        self.local_port = int(LOWEST_PORT_NO)
        master.title("FTP Server by TP031319 at %s" % (self.local_ip_addr,))

        self.authorizer = DummyAuthorizer()
        self.initialise()

        self.create_server_control_frame(rw=0, cl=0)
        self.create_input_frame(rw=0, cl=3)
        self.create_state_frame(rw=1, cl=0)

        self.create_dir_frame(rw=4, cl=0)
        self.create_dir_tree_frame(rw=7, cl=0, tit="Local")

        self.create_browse_button(rw=5, cl=4)
        self.create_share_button(rw=5, cl=5)

        self.create_stderr_frame(rw=12, cl=0)

        self.handler = FTPHandler
        self.handler.authorizer = self.authorizer
        self.handler.banner = "FTP Server ver %s is ready" % VERSION #does this work in Python3?

    def create_server_control_frame(self, rw, cl):
        # Server Control Frame
        self.server_control_frame = ttk.Frame(self, relief=constants.SOLID, borderwidth=1)
        self.server_control_frame.grid(row=rw, column=cl, columnspan=4, sticky=constants.W,
            pady=4, padx=5)
        ttk.Label(self.server_control_frame, text="Server Control ").grid(row=rw, column=cl)

        self.start_button = ttk.Button(self.server_control_frame, text="Start",
            command=self.start_server)
        self.start_button.grid(row=rw, column=cl+1)

        self.stop_button = ttk.Button(self.server_control_frame, text="Stop", state=['disabled'],
                        command=self.stop_server)
        self.stop_button.grid(row=rw, column=cl+2)

    def create_state_frame(self, rw, cl):
        # State Frame
        state_frame = ttk.Frame(self, relief=constants.SOLID, borderwidth=1)
        state_frame.grid(row=rw, column=cl, columnspan=3, sticky=constants.W, pady=4, padx=5)
        ttk.Label(state_frame, text="Server State").grid(row=rw, column=cl)

        state_value = ttk.Label(state_frame, textvariable=self.current_state, foreground='blue')
        state_value.grid(row=rw, column=cl+1)

    def create_input_frame(self, rw, cl):
        self.input_frame = ttk.Frame(self, relief=constants.SOLID, borderwidth=1)
        self.input_frame.grid(row=rw, column=cl, columnspan=3, sticky=constants.W, pady=4, padx=5)

        port_input_label = ttk.Label(self.input_frame,
            text="Server Port ({0}~{1})".format(LOWEST_PORT_NO, HIGHEST_PORT_NO))
        port_input_label.grid(row=rw, column=cl+1, sticky=constants.W)
        self.listen_port_input = ttk.Entry(self.input_frame, width=8, textvariable=self.listen_port)
        self.listen_port_input.grid(row=rw+1, column=cl+1)

    def create_dir_frame(self, rw, cl):
        self.dir_frame = ttk.Frame(self, relief=constants.SOLID, borderwidth=1)
        self.dir_frame.grid(row=rw, column=cl, columnspan=3, sticky=constants.W, pady=4, padx=5)
        ttk.Label(self.dir_frame, text="Shared Directory").grid(row=rw, column=cl,
            sticky=constants.W)

        self.root_dir_input = ttk.Entry(self.dir_frame, width=64,
            textvariable=self.root_dir['Local'])
        self.root_dir_input.grid(row=rw+1, column=cl)

    def create_browse_button(self, rw, cl):
        self.browse_button = ttk.Button(self.dir_frame, text="Browse",
            command=partial(self.select_dir, self.root_dir_tree['Local']))
        self.browse_button.grid(row=rw, column=cl)

    def create_share_button(self, rw, cl):
        self.share_button = ttk.Button(self.dir_frame, text="Share",
            command=partial(self.share_dir, self.root_dir_tree['Local']))
        self.share_button.grid(row=rw, column=cl)

    def create_dir_tree_frame(self, rw, cl, tit):
        self.dir_tree_frame[tit] = ttk.Frame(self, relief=constants.SOLID, borderwidth=1)
        self.root_dir_tree[tit] = RootTree(self, columns=('fullpath','type','size'),
            displaycolumns='size', root_dir=self.root_dir[tit],
            conn=self.ftp_conn if tit=='Remote' else None)

        self.root_dir_tree[tit].heading('#0', text='Directory', anchor=constants.W)
        self.root_dir_tree[tit].heading('size', text='Size', anchor=constants.W)
        self.root_dir_tree[tit].column('#0', stretch=0, minwidth=200, width=440)
        self.root_dir_tree[tit].column('size', stretch=1, minwidth=40, width=80)

        self.dir_tree_frame[tit].grid(row=rw, column=cl, sticky=constants.W, pady=4, padx=5)
        ttk.Label(self.dir_tree_frame[tit], text=tit).grid(row=rw, column=cl, sticky=constants.W)
        self.root_dir_tree[tit].grid(in_=self.dir_tree_frame[tit], row=rw+1, column=cl,
            sticky=constants.NSEW)

        yScrollBar = ttk.Scrollbar(self.dir_tree_frame[tit], orient=constants.VERTICAL,
            command=self.root_dir_tree[tit].yview)
        xScrollBar = ttk.Scrollbar(self.dir_tree_frame[tit], orient=constants.HORIZONTAL,
            command=self.root_dir_tree[tit].xview)
        self.root_dir_tree[tit]['yscroll'] = yScrollBar.set
        self.root_dir_tree[tit]['xscroll'] = xScrollBar.set

        yScrollBar.grid(row=rw, column=cl+2, rowspan=3, sticky=constants.NS)
        xScrollBar.grid(row=rw+3, column=cl, rowspan=1, sticky=constants.EW)
        # set frame resizing priorities
        self.dir_tree_frame[tit].rowconfigure(0, weight=1)
        self.dir_tree_frame[tit].columnconfigure(0, weight=1)

    def create_stderr_frame(self, rw, cl):
        self.stderr_frame = ttk.Frame(self, relief=constants.SOLID, borderwidth=1)
        self.stderr_frame.grid(row=rw, column=cl)

        self.old_stderr = sys.stderr

        self.err = tkinter.Text(self, width=64, height=12, wrap='none')
        self.err.grid(row=rw+1, column=cl, pady=4, padx=5)
        sys.stderr = StdoutRedirector(self.err)

    def initialise(self):
        # Initial values
        self.username = tkinter.StringVar()
        self.username.set("user")

        self.password = tkinter.StringVar()
        self.password.set("passwd")

        self.listen_ip = tkinter.StringVar()
        self.listen_ip.set(self.local_ip_addr)

        self.listen_port = tkinter.StringVar()
        self.listen_port.set(self.local_port)

        self.root_dir['Local'] = tkinter.StringVar()
        self.root_dir['Local'].set(os.getcwd() + os.sep)

        self.current_state = tkinter.StringVar()
        self.current_state.set("NOT RUNNING")

        self.root_dir['Remote'] = tkinter.StringVar()
        self.root_dir['Remote'].set(os.sep)

        # This can be set up only once and saved in a database
        self.authorizer.add_user(self.username.get(), self.password.get(),
            self.root_dir['Local'].get(), 'elradfmw')

    def start_server(self):
        port_no = 0
        msg = "Please type a port number between 1025 and 65533 inclusive."
        try:
            port_no = int(self.listen_port.get())

            if port_no < LOWEST_PORT_NO or port_no > HIGHEST_PORT_NO:
                msg += " Port {0} is not valid.".format(port_no)
                raise Exception(msg)
        except:
            mbox.showinfo(message=msg)
            return

        self.address = (self.listen_ip.get(), port_no)
        self.server = ThreadedFTPServer(self.address, self.handler)
        self.server.max_cons = 256
        self.server.max_cons_per_ip = 5

        self.share_dir(self.root_dir_tree['Local'])

        self.start_button.state(['disabled'])
        self.stop_button.state(['!disabled'])
        self.share_button.state(['disabled'])
        self.current_state.set("RUNNING")

        threading.Thread(target=self.server.serve_forever).start()

    def stop_server(self):
        self.server.close_all()
        self.start_button.state(['!disabled'])
        self.stop_button.state(['disabled'])
        self.share_button.state(['!disabled'])
        self.current_state.set("NOT RUNNING")

    def select_dir(self, dir_tree_view):
        if isinstance(dir_tree_view, RootTree):
            children = dir_tree_view.get_children('')
            if children:
                dir_tree_view.delete(children)
            old_dir_tree_view_root_dir = dir_tree_view.root_directory.get()
            dir_tree_view.root_directory.set(filedialog.askdirectory().replace("/" , str(os.sep)))
            if not dir_tree_view.root_directory.get():
                dir_tree_view.root_directory.set(old_dir_tree_view_root_dir)

    def share_dir(self, dir_tree_view):
        if isinstance(dir_tree_view, RootTree):
            try:
                os.chdir(self.root_dir['Local'].get())
                dir_tree_view.root_directory = self.root_dir['Local']
                # No need to reconnect because this is only for local dir
                dir_tree_view.populate_parent()
                # Open up the directory for transferring out/receiving in files
                # For use with WindowsAuthorizer or UnixAuthorizer:
                # For simplicity's sake, update the homedir everytime Share button is pressed
                # self.authorizer.override_user(self.username.get(),
                # homedir=self.root_dir['Local'].get())
                # For now the workaround:
                self.authorizer.remove_user(self.username.get())
                self.authorizer.add_user(self.username.get(), self.password.get(),
                    self.root_dir['Local'].get(), 'elradfmw')
            except FileNotFoundError:
                mbox.showinfo(message="Invalid Directory!")