def start_subsystem(self, name, transport, channel): self.sock = channel self._log(DEBUG, 'Started sftp server on channel %s' % repr(channel)) self._send_server_version() self.server.session_started() while True: try: t, data = self._read_packet() except EOFError: self._log(DEBUG, 'EOF -- end of session') return except Exception as e: self._log(DEBUG, 'Exception on channel: ' + str(e)) self._log(DEBUG, util.tb_strings()) return msg = Message(data) request_number = msg.get_int() try: self._process(t, request_number, msg) except Exception as e: self._log(DEBUG, 'Exception in server processing: ' + str(e)) self._log(DEBUG, util.tb_strings()) # send some kind of failure message, at least try: self._send_status(request_number, SFTP_FAILURE) except: pass
def start_subsystem(self, name, transport, channel): self.sock = channel self._log(DEBUG, 'Started sftp server on channel %s' % repr(channel)) self._send_server_version() self.server.session_started() while True: try: t, data = self._read_packet() except EOFError: self._log(DEBUG, 'EOF -- end of session') return except Exception as e: self._log(ERROR, 'Exception on channel: ' + str(e)) return msg = Message(data) request_number = msg.get_int() try: self._process(t, request_number, msg) except Exception as e: self._log(ERROR, 'Exception in server processing: ' + str(e)) # send some kind of failure message, at least try: self._send_status(request_number, SFTP_FAILURE) except: pass
def _check_file(self, request_number, msg): # this extension actually comes from v6 protocol, but since it's an # extension, i feel like we can reasonably support it backported. # it's very useful for verifying uploaded files or checking for # rsync-like differences between local and remote files. handle = msg.get_binary() alg_list = msg.get_list() start = msg.get_int64() length = msg.get_int64() block_size = msg.get_int() if handle not in self.file_table: self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle') return f = self.file_table[handle] for x in alg_list: if x in _hash_class: algname = x alg = _hash_class[x] break else: self._send_status(request_number, SFTP_FAILURE, 'No supported hash types found') return if length == 0: st = f.stat() if not issubclass(type(st), SFTPAttributes): self._send_status(request_number, st, 'Unable to stat file') return length = st.st_size - start if block_size == 0: block_size = length if block_size < 256: self._send_status(request_number, SFTP_FAILURE, 'Block size too small') return sum_out = bytes() offset = start while offset < start + length: blocklen = min(block_size, start + length - offset) # don't try to read more than about 64KB at a time chunklen = min(blocklen, 65536) count = 0 hash_obj = alg.new() while count < blocklen: data = f.read(offset, chunklen) if not isinstance(data, bytes_types): self._send_status(request_number, data, 'Unable to hash file') return hash_obj.update(data) count += len(data) offset += count sum_out += hash_obj.digest() msg = Message() msg.add_int(request_number) msg.add_string('check-file') msg.add_string(algname) msg.add_bytes(sum_out) self._send_packet(CMD_EXTENDED_REPLY, msg)
def _check_file(self, request_number, msg): # this extension actually comes from v6 protocol, but since it's an # extension, i feel like we can reasonably support it backported. # it's very useful for verifying uploaded files or checking for # rsync-like differences between local and remote files. handle = msg.get_binary() alg_list = msg.get_list() start = msg.get_int64() length = msg.get_int64() block_size = msg.get_int() if handle not in self.file_table: self._send_status(request_number, SFTP_BAD_MESSAGE, 'Invalid handle') return f = self.file_table[handle] for x in alg_list: if x in _hash_class: algname = x alg = _hash_class[x] break else: self._send_status(request_number, SFTP_FAILURE, 'No supported hash types found') return if length == 0: st = f.stat() if not issubclass(type(st), SFTPAttributes): self._send_status(request_number, st, 'Unable to stat file') return length = st.st_size - start if block_size == 0: block_size = length if block_size < 256: self._send_status(request_number, SFTP_FAILURE, 'Block size too small') return sum_out = bytes() offset = start while offset < start + length: blocklen = min(block_size, start + length - offset) # don't try to read more than about 64KB at a time chunklen = min(blocklen, 65536) count = 0 hash_obj = alg() while count < blocklen: data = f.read(offset, chunklen) if not isinstance(data, bytes_types): self._send_status(request_number, data, 'Unable to hash file') return hash_obj.update(data) count += len(data) offset += count sum_out += hash_obj.digest() msg = Message() msg.add_int(request_number) msg.add_string('check-file') msg.add_string(algname) msg.add_bytes(sum_out) self._send_packet(CMD_EXTENDED_REPLY, msg)
def _read_folder(self, request_number, folder): flist = folder._get_next_files() if len(flist) == 0: self._send_status(request_number, SFTP_EOF) return msg = Message() msg.add_int(request_number) msg.add_int(len(flist)) for attr in flist: msg.add_string(attr.filename) msg.add_string(attr) attr._pack(msg) self._send_packet(CMD_NAME, msg)
def _response(self, request_number, t, *arg): msg = Message() msg.add_int(request_number) for item in arg: if isinstance(item, long): msg.add_int64(item) elif isinstance(item, int): msg.add_int(item) elif isinstance(item, (string_types, bytes_types)): msg.add_string(item) elif type(item) is SFTPAttributes: item._pack(msg) else: raise Exception('unknown type for ' + repr(item) + ' type ' + repr(type(item))) self._send_packet(t, msg)