def test_appe(self): self.client_init() _data_1 = "This is just a test!\n" _data_2 = "This is another test\n" _file_name = "ftp_appe_test.txt" with self.vfs.open(_file_name, mode="w") as _server_file: _server_file.write(_data_1) try: with NamedTemporaryFile(mode="w+") as _temp: _temp.write(_data_2) _temp.flush() with open(_temp.name, mode="rb+") as _source: self.client.storbinary(f"appe {_file_name}", _source) with self.vfs.open(_file_name, mode="r") as _server_file: _file_contents = _server_file.read() self.assertEqual(_file_contents, _data_1 + _data_2) finally: self.vfs.remove(_file_name) _data_fs_file = sanitize_file_name( _file_name, self.client.sock.getsockname()[0], self.client.sock.getsockname()[1], ) self.data_fs.remove(_data_fs_file)
def end(self): logger.debug("In TFTPContextServer.end - closing socket and files.") self.sock.close() if self.fileobj is not None and not self.fileobj.closed: logger.debug("self.fileobj is open - closing") self.fileobj.close() if not self.state and (not self._already_uploaded): if self.file_path: # Return None only when transfer is complete! logger.info("TFTP : Transfer Complete!") _file_path = ( self.file_path if isinstance(self.file_path, str) else self.file_path.decode() ) _data_fs_filename = sanitize_file_name( "".join(_file_path.split("/")[-1:]), self.host, self.port ) logger.info("Opening {} for data_fs writing.".format(_data_fs_filename)) with self.vfs.open(_file_path, "rb") as _vfs_file: with self.data_fs.open(_data_fs_filename, "wb") as _data_file: content = _vfs_file.read() _data_file.write(content) self._already_uploaded = True self.metrics.end_time = time.time() logger.debug("Set metrics.end_time to %s", self.metrics.end_time) self.metrics.compute()
def test_stor(self): # let us test by uploading a file called ftp_testing.txt self.client.connect(host='127.0.0.1', port=self.ftp_server.server.server_port) self.client.login(user='******', passwd='nobody') _path = os.path.join(''.join(conpot.__path__), 'tests', 'data', 'test_data_fs', 'ftp') with open(_path + '/ftp_testing.txt', mode='rb') as _file: self.client.storbinary("stor ftp_testing_stor.txt", _file) self.assertIn('ftp_testing_stor.txt', self.ftp_server.handler.config.vfs.listdir('/')) _vfs, _data_fs = conpot_core.get_vfs('ftp') _vfs.remove('ftp_testing_stor.txt') _data_fs_file = sanitize_file_name('ftp_testing_stor.txt', self.client.sock.getsockname()[0], self.client.sock.getsockname()[1]) _data_fs.remove(_data_fs_file)
def test_stor(self): # let us test by uploading a file called ftp_testing.txt self.client_init() _path = os.path.join("".join(conpot.__path__), "tests", "data", "test_data_fs", "ftp") with open(_path + "/ftp_testing.txt", mode="rb") as _file: self.client.storbinary("stor ftp_testing_stor.txt", _file) self.assertIn("ftp_testing_stor.txt", self.ftp_server.handler.config.vfs.listdir("/")) self.vfs.remove("ftp_testing_stor.txt") _data_fs_file = sanitize_file_name( "ftp_testing_stor.txt", self.client.sock.getsockname()[0], self.client.sock.getsockname()[1], ) self.data_fs.remove(_data_fs_file)
def test_stor(self): # let us test by uploading a file called ftp_testing.txt self.client.connect(host="127.0.0.1", port=self.ftp_server.server.server_port) self.client.login(user="******", passwd="nobody") _path = os.path.join("".join(conpot.__path__), "tests", "data", "test_data_fs", "ftp") with open(_path + "/ftp_testing.txt", mode="rb") as _file: self.client.storbinary("stor ftp_testing_stor.txt", _file) self.assertIn("ftp_testing_stor.txt", self.ftp_server.handler.config.vfs.listdir("/")) _vfs, _data_fs = conpot_core.get_vfs("ftp") _vfs.remove("ftp_testing_stor.txt") _data_fs_file = sanitize_file_name( "ftp_testing_stor.txt", self.client.sock.getsockname()[0], self.client.sock.getsockname()[1], ) _data_fs.remove(_data_fs_file)
def end(self): logger.debug("In TFTPContextServer.end - closing socket and files.") self.sock.close() if self.fileobj is not None and not self.fileobj.closed: logger.debug("self.fileobj is open - closing") self.fileobj.close() if not self.state and (not self._already_uploaded): if self.file_path: # Return None only when transfer is complete! logger.info('TFTP : Transfer Complete!') _file_path = self.file_path if isinstance(self.file_path, str) else self.file_path.decode() _data_fs_filename = sanitize_file_name(''.join(_file_path.split('/')[-1:]), self.host, self.port) logger.info('Opening {} for data_fs writing.'.format(_data_fs_filename)) with self.vfs.open(_file_path, "rb") as _vfs_file: with self.data_fs.open(_data_fs_filename, "wb") as _data_file: content = _vfs_file.read() _data_file.write(content) self._already_uploaded = True self.metrics.end_time = time.time() logger.debug("Set metrics.end_time to %s", self.metrics.end_time) self.metrics.compute()
def recv_file(self, _file, _file_pos=0, cmd="STOR"): """ Receive a file - to be used with STOR, REST and APPE. A copy would be made on the _data_fs. :param _file: File Name to the file that would be written to fs. :param _file_pos: Seek file to position before receiving. :param cmd: Command used for receiving file. """ # FIXME: acquire lock to files - both data_fs and vfs. with self.config.vfs.lock(): self.start_data_channel(send_recv="recv") recv_err = None logger.info("Receiving data from {}:{}".format( self.cli_ip, self.cli_port)) _data_fs_file = sanitize_file_name(_file, self.client_address[0], str(self.client_address[1])) _data_fs_d = None _file_d = None # wait till all transfer has finished. self._data_channel_recv.wait() try: # we are blocking on queue for 10 seconds to wait for incoming data. # If there is no data in the queue. We assume that transfer has been completed. _data = self._data_channel_input_q.get() _data_fs_d = self.config.data_fs.open(path=_data_fs_file, mode="wb") if _file_pos == 0 and cmd == "STOR": # overwrite file or create a new one. # we don't need to seek at all. Normal write process by STOR _file_d = self.config.vfs.open(path=_file, mode="wb") else: assert _file_pos != 0 # must seek file. This is done in append or rest(resume transfer) command. # in that case, we should create a duplicate copy of this file till that seek position. with self.config.vfs.open(path=_file, mode="rb") as _file_d: _data_fs_d.write(_file_d.read(_file_pos)) # finally we should let the file to be written as requested. if cmd == "APPE": _file_d = self.config.vfs.open(path=_file, mode="ab") else: # cmd is REST _file_d = self.config.vfs.open(path=_file, mode="rb+") _file_d.seek(_file_pos) _file_d.write(_data) _data_fs_d.write(_data) while not self._data_channel_input_q.empty(): _data = self._data_channel_input_q.get() _file_d.write(_data) _data_fs_d.write(_data) logger.info( "Files {} and {} written successfully to disk".format( _file, _data_fs_file)) except ( AssertionError, IOError, fs.errors.FSError, FilesystemError, FTPPrivilegeException, ) as fe: recv_err = fe self.stop_data_channel(abort=True, reason=str(fe)) self.respond("554 {} command failed.".format(cmd)) finally: if _file_d and _file_d.fileno() != -1: _file_d.close() if _data_fs_d and _data_fs_d.fileno() != -1: _data_fs_d.close() if not recv_err: self.config.vfs.chmod(_file, self.config.file_default_perms) if cmd == "STOR": self.config.vfs.chown(_file, uid=self._uid, gid=self.config.get_gid( self._uid)) self.config.vfs.settimes(_file, accessed=datetime.now(), modified=datetime.now()) self.respond(b"226 Transfer complete.")
def recv_file(self, _file, _file_pos=0, cmd='STOR'): """ Receive a file - to be used with STOR, REST and APPE. A copy would be made on the _data_fs. :param _file: File Name to the file that would be written to fs. :param _file_pos: Seek file to position before receiving. :param cmd: Command used for receiving file. """ # FIXME: acquire lock to files - both data_fs and vfs. with self.config.vfs.lock(): self.start_data_channel(send_recv='recv') recv_err = None logger.info('Receiving data from {}:{}'.format(self.cli_ip, self.cli_port)) _data_fs_file = sanitize_file_name(_file, self.client_address[0], str(self.client_address[1])) _data_fs_d = None _file_d = None # wait till all transfer has finished. self._data_channel_recv.wait() try: # we are blocking on queue for 10 seconds to wait for incoming data. # If there is no data in the queue. We assume that transfer has been completed. _data = self._data_channel_input_q.get() _data_fs_d = self.config.data_fs.open(path=_data_fs_file, mode='wb') if _file_pos == 0 and cmd == 'STOR': # overwrite file or create a new one. # we don't need to seek at all. Normal write process by STOR _file_d = self.config.vfs.open(path=_file, mode='wb') else: assert _file_pos != 0 # must seek file. This is done in append or rest(resume transfer) command. # in that case, we should create a duplicate copy of this file till that seek position. with self.config.vfs.open(path=_file, mode='rb') as _file_d: _data_fs_d.write(_file_d.read(_file_pos)) # finally we should let the file to be written as requested. if cmd == 'APPE': _file_d = self.config.vfs.open(path=_file, mode='ab') else: # cmd is REST _file_d = self.config.vfs.open(path=_file, mode='rb+') _file_d.seek(_file_pos) _file_d.write(_data) _data_fs_d.write(_data) while not self._data_channel_input_q.empty(): _data = self._data_channel_input_q.get() _file_d.write(_data) _data_fs_d.write(_data) logger.info('Files {} and {} written successfully to disk'.format(_file, _data_fs_file)) except (AssertionError, IOError, fs.errors.FSError, FilesystemError, FTPPrivilegeException) as fe: recv_err = fe self.stop_data_channel(abort=True, reason=str(fe)) self.respond('554 {} command failed.'.format(cmd)) finally: if _file_d and _file_d.fileno() != -1: _file_d.close() if _data_fs_d and _data_fs_d.fileno() != -1: _data_fs_d.close() if not recv_err: self.config.vfs.chmod(_file, self.config.file_default_perms) if cmd == 'STOR': self.config.vfs.chown(_file, uid=self._uid, gid=self.config.get_gid(self._uid)) self.config.vfs.settimes(_file, accessed=datetime.now(), modified=datetime.now()) self.respond(b'226 Transfer complete.')