sftp.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. # Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com>
  2. #
  3. # This file is part of paramiko.
  4. #
  5. # Paramiko is free software; you can redistribute it and/or modify it under the
  6. # terms of the GNU Lesser General Public License as published by the Free
  7. # Software Foundation; either version 2.1 of the License, or (at your option)
  8. # any later version.
  9. #
  10. # Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY
  11. # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  13. # details.
  14. #
  15. # You should have received a copy of the GNU Lesser General Public License
  16. # along with Paramiko; if not, write to the Free Software Foundation, Inc.,
  17. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. import select
  19. import socket
  20. import struct
  21. from paramiko import util
  22. from paramiko.common import asbytes, DEBUG
  23. from paramiko.message import Message
  24. from paramiko.py3compat import byte_chr, byte_ord
  25. (
  26. CMD_INIT,
  27. CMD_VERSION,
  28. CMD_OPEN,
  29. CMD_CLOSE,
  30. CMD_READ,
  31. CMD_WRITE,
  32. CMD_LSTAT,
  33. CMD_FSTAT,
  34. CMD_SETSTAT,
  35. CMD_FSETSTAT,
  36. CMD_OPENDIR,
  37. CMD_READDIR,
  38. CMD_REMOVE,
  39. CMD_MKDIR,
  40. CMD_RMDIR,
  41. CMD_REALPATH,
  42. CMD_STAT,
  43. CMD_RENAME,
  44. CMD_READLINK,
  45. CMD_SYMLINK,
  46. ) = range(1, 21)
  47. (CMD_STATUS, CMD_HANDLE, CMD_DATA, CMD_NAME, CMD_ATTRS) = range(101, 106)
  48. (CMD_EXTENDED, CMD_EXTENDED_REPLY) = range(200, 202)
  49. SFTP_OK = 0
  50. (
  51. SFTP_EOF,
  52. SFTP_NO_SUCH_FILE,
  53. SFTP_PERMISSION_DENIED,
  54. SFTP_FAILURE,
  55. SFTP_BAD_MESSAGE,
  56. SFTP_NO_CONNECTION,
  57. SFTP_CONNECTION_LOST,
  58. SFTP_OP_UNSUPPORTED,
  59. ) = range(1, 9)
  60. SFTP_DESC = [
  61. "Success",
  62. "End of file",
  63. "No such file",
  64. "Permission denied",
  65. "Failure",
  66. "Bad message",
  67. "No connection",
  68. "Connection lost",
  69. "Operation unsupported",
  70. ]
  71. SFTP_FLAG_READ = 0x1
  72. SFTP_FLAG_WRITE = 0x2
  73. SFTP_FLAG_APPEND = 0x4
  74. SFTP_FLAG_CREATE = 0x8
  75. SFTP_FLAG_TRUNC = 0x10
  76. SFTP_FLAG_EXCL = 0x20
  77. _VERSION = 3
  78. # for debugging
  79. CMD_NAMES = {
  80. CMD_INIT: "init",
  81. CMD_VERSION: "version",
  82. CMD_OPEN: "open",
  83. CMD_CLOSE: "close",
  84. CMD_READ: "read",
  85. CMD_WRITE: "write",
  86. CMD_LSTAT: "lstat",
  87. CMD_FSTAT: "fstat",
  88. CMD_SETSTAT: "setstat",
  89. CMD_FSETSTAT: "fsetstat",
  90. CMD_OPENDIR: "opendir",
  91. CMD_READDIR: "readdir",
  92. CMD_REMOVE: "remove",
  93. CMD_MKDIR: "mkdir",
  94. CMD_RMDIR: "rmdir",
  95. CMD_REALPATH: "realpath",
  96. CMD_STAT: "stat",
  97. CMD_RENAME: "rename",
  98. CMD_READLINK: "readlink",
  99. CMD_SYMLINK: "symlink",
  100. CMD_STATUS: "status",
  101. CMD_HANDLE: "handle",
  102. CMD_DATA: "data",
  103. CMD_NAME: "name",
  104. CMD_ATTRS: "attrs",
  105. CMD_EXTENDED: "extended",
  106. CMD_EXTENDED_REPLY: "extended_reply",
  107. }
  108. class SFTPError(Exception):
  109. pass
  110. class BaseSFTP(object):
  111. def __init__(self):
  112. self.logger = util.get_logger("paramiko.sftp")
  113. self.sock = None
  114. self.ultra_debug = False
  115. # ...internals...
  116. def _send_version(self):
  117. self._send_packet(CMD_INIT, struct.pack(">I", _VERSION))
  118. t, data = self._read_packet()
  119. if t != CMD_VERSION:
  120. raise SFTPError("Incompatible sftp protocol")
  121. version = struct.unpack(">I", data[:4])[0]
  122. # if version != _VERSION:
  123. # raise SFTPError('Incompatible sftp protocol')
  124. return version
  125. def _send_server_version(self):
  126. # winscp will freak out if the server sends version info before the
  127. # client finishes sending INIT.
  128. t, data = self._read_packet()
  129. if t != CMD_INIT:
  130. raise SFTPError("Incompatible sftp protocol")
  131. version = struct.unpack(">I", data[:4])[0]
  132. # advertise that we support "check-file"
  133. extension_pairs = ["check-file", "md5,sha1"]
  134. msg = Message()
  135. msg.add_int(_VERSION)
  136. msg.add(*extension_pairs)
  137. self._send_packet(CMD_VERSION, msg)
  138. return version
  139. def _log(self, level, msg, *args):
  140. self.logger.log(level, msg, *args)
  141. def _write_all(self, out):
  142. while len(out) > 0:
  143. n = self.sock.send(out)
  144. if n <= 0:
  145. raise EOFError()
  146. if n == len(out):
  147. return
  148. out = out[n:]
  149. return
  150. def _read_all(self, n):
  151. out = bytes()
  152. while n > 0:
  153. if isinstance(self.sock, socket.socket):
  154. # sometimes sftp is used directly over a socket instead of
  155. # through a paramiko channel. in this case, check periodically
  156. # if the socket is closed. (for some reason, recv() won't ever
  157. # return or raise an exception, but calling select on a closed
  158. # socket will.)
  159. while True:
  160. read, write, err = select.select([self.sock], [], [], 0.1)
  161. if len(read) > 0:
  162. x = self.sock.recv(n)
  163. break
  164. else:
  165. x = self.sock.recv(n)
  166. if len(x) == 0:
  167. raise EOFError()
  168. out += x
  169. n -= len(x)
  170. return out
  171. def _send_packet(self, t, packet):
  172. packet = asbytes(packet)
  173. out = struct.pack(">I", len(packet) + 1) + byte_chr(t) + packet
  174. if self.ultra_debug:
  175. self._log(DEBUG, util.format_binary(out, "OUT: "))
  176. self._write_all(out)
  177. def _read_packet(self):
  178. x = self._read_all(4)
  179. # most sftp servers won't accept packets larger than about 32k, so
  180. # anything with the high byte set (> 16MB) is just garbage.
  181. if byte_ord(x[0]):
  182. raise SFTPError("Garbage packet received")
  183. size = struct.unpack(">I", x)[0]
  184. data = self._read_all(size)
  185. if self.ultra_debug:
  186. self._log(DEBUG, util.format_binary(data, "IN: "))
  187. if size > 0:
  188. t = byte_ord(data[0])
  189. return t, data[1:]
  190. return 0, bytes()