1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19  """ 
 20  L{SFTPServerInterface} is an interface to override for SFTP server support. 
 21  """ 
 22   
 23  import os 
 24   
 25  from paramiko.common import * 
 26  from paramiko.sftp import * 
 27   
 28   
 30      """ 
 31      This class defines an interface for controlling the behavior of paramiko 
 32      when using the L{SFTPServer} subsystem to provide an SFTP server. 
 33   
 34      Methods on this class are called from the SFTP session's thread, so you can 
 35      block as long as necessary without affecting other sessions (even other 
 36      SFTP sessions).  However, raising an exception will usually cause the SFTP 
 37      session to abruptly end, so you will usually want to catch exceptions and 
 38      return an appropriate error code. 
 39       
 40      All paths are in string form instead of unicode because not all SFTP 
 41      clients & servers obey the requirement that paths be encoded in UTF-8. 
 42      """ 
 43       
 44 -    def __init__ (self, server, *largs, **kwargs): 
  45          """ 
 46          Create a new SFTPServerInterface object.  This method does nothing by 
 47          default and is meant to be overridden by subclasses. 
 48           
 49          @param server: the server object associated with this channel and 
 50              SFTP subsystem 
 51          @type server: L{ServerInterface} 
 52          """ 
 53          super(SFTPServerInterface, self).__init__(*largs, **kwargs) 
  54   
 56          """ 
 57          The SFTP server session has just started.  This method is meant to be 
 58          overridden to perform any necessary setup before handling callbacks 
 59          from SFTP operations. 
 60          """ 
 61          pass 
  62   
 64          """ 
 65          The SFTP server session has just ended, either cleanly or via an 
 66          exception.  This method is meant to be overridden to perform any 
 67          necessary cleanup before this C{SFTPServerInterface} object is 
 68          destroyed. 
 69          """ 
 70          pass 
  71   
 72 -    def open(self, path, flags, attr): 
  73          """ 
 74          Open a file on the server and create a handle for future operations 
 75          on that file.  On success, a new object subclassed from L{SFTPHandle} 
 76          should be returned.  This handle will be used for future operations 
 77          on the file (read, write, etc).  On failure, an error code such as 
 78          L{SFTP_PERMISSION_DENIED} should be returned. 
 79   
 80          C{flags} contains the requested mode for opening (read-only, 
 81          write-append, etc) as a bitset of flags from the C{os} module: 
 82              - C{os.O_RDONLY} 
 83              - C{os.O_WRONLY} 
 84              - C{os.O_RDWR} 
 85              - C{os.O_APPEND} 
 86              - C{os.O_CREAT} 
 87              - C{os.O_TRUNC} 
 88              - C{os.O_EXCL} 
 89          (One of C{os.O_RDONLY}, C{os.O_WRONLY}, or C{os.O_RDWR} will always 
 90          be set.) 
 91   
 92          The C{attr} object contains requested attributes of the file if it 
 93          has to be created.  Some or all attribute fields may be missing if 
 94          the client didn't specify them. 
 95           
 96          @note: The SFTP protocol defines all files to be in "binary" mode. 
 97              There is no equivalent to python's "text" mode. 
 98   
 99          @param path: the requested path (relative or absolute) of the file 
100              to be opened. 
101          @type path: str 
102          @param flags: flags or'd together from the C{os} module indicating the 
103              requested mode for opening the file. 
104          @type flags: int 
105          @param attr: requested attributes of the file if it is newly created. 
106          @type attr: L{SFTPAttributes} 
107          @return: a new L{SFTPHandle} I{or error code}. 
108          @rtype L{SFTPHandle} 
109          """ 
110          return SFTP_OP_UNSUPPORTED 
 111   
113          """ 
114          Return a list of files within a given folder.  The C{path} will use 
115          posix notation (C{"/"} separates folder names) and may be an absolute 
116          or relative path. 
117   
118          The list of files is expected to be a list of L{SFTPAttributes} 
119          objects, which are similar in structure to the objects returned by 
120          C{os.stat}.  In addition, each object should have its C{filename} 
121          field filled in, since this is important to a directory listing and 
122          not normally present in C{os.stat} results.  The method 
123          L{SFTPAttributes.from_stat} will usually do what you want. 
124   
125          In case of an error, you should return one of the C{SFTP_*} error 
126          codes, such as L{SFTP_PERMISSION_DENIED}. 
127   
128          @param path: the requested path (relative or absolute) to be listed. 
129          @type path: str 
130          @return: a list of the files in the given folder, using 
131              L{SFTPAttributes} objects. 
132          @rtype: list of L{SFTPAttributes} I{or error code} 
133           
134          @note: You should normalize the given C{path} first (see the 
135          C{os.path} module) and check appropriate permissions before returning 
136          the list of files.  Be careful of malicious clients attempting to use 
137          relative paths to escape restricted folders, if you're doing a direct 
138          translation from the SFTP server path to your local filesystem. 
139          """ 
140          return SFTP_OP_UNSUPPORTED 
 141   
142 -    def stat(self, path): 
 143          """ 
144          Return an L{SFTPAttributes} object for a path on the server, or an 
145          error code.  If your server supports symbolic links (also known as 
146          "aliases"), you should follow them.  (L{lstat} is the corresponding 
147          call that doesn't follow symlinks/aliases.) 
148   
149          @param path: the requested path (relative or absolute) to fetch 
150              file statistics for. 
151          @type path: str 
152          @return: an attributes object for the given file, or an SFTP error 
153              code (like L{SFTP_PERMISSION_DENIED}). 
154          @rtype: L{SFTPAttributes} I{or error code} 
155          """ 
156          return SFTP_OP_UNSUPPORTED 
 157   
159          """ 
160          Return an L{SFTPAttributes} object for a path on the server, or an 
161          error code.  If your server supports symbolic links (also known as 
162          "aliases"), you should I{not} follow them -- instead, you should 
163          return data on the symlink or alias itself.  (L{stat} is the 
164          corresponding call that follows symlinks/aliases.) 
165   
166          @param path: the requested path (relative or absolute) to fetch 
167              file statistics for. 
168          @type path: str 
169          @return: an attributes object for the given file, or an SFTP error 
170              code (like L{SFTP_PERMISSION_DENIED}). 
171          @rtype: L{SFTPAttributes} I{or error code} 
172          """ 
173          return SFTP_OP_UNSUPPORTED 
 174   
176          """ 
177          Delete a file, if possible. 
178   
179          @param path: the requested path (relative or absolute) of the file 
180              to delete. 
181          @type path: str 
182          @return: an SFTP error code like L{SFTP_OK}. 
183          @rtype: int 
184          """ 
185          return SFTP_OP_UNSUPPORTED 
 186   
187 -    def rename(self, oldpath, newpath): 
 188          """ 
189          Rename (or move) a file.  The SFTP specification implies that this 
190          method can be used to move an existing file into a different folder, 
191          and since there's no other (easy) way to move files via SFTP, it's 
192          probably a good idea to implement "move" in this method too, even for 
193          files that cross disk partition boundaries, if at all possible. 
194           
195          @note: You should return an error if a file with the same name as 
196              C{newpath} already exists.  (The rename operation should be 
197              non-desctructive.) 
198   
199          @param oldpath: the requested path (relative or absolute) of the 
200              existing file. 
201          @type oldpath: str 
202          @param newpath: the requested new path of the file. 
203          @type newpath: str 
204          @return: an SFTP error code like L{SFTP_OK}. 
205          @rtype: int 
206          """ 
207          return SFTP_OP_UNSUPPORTED 
 208   
209 -    def mkdir(self, path, attr): 
 210          """ 
211          Create a new directory with the given attributes.  The C{attr} 
212          object may be considered a "hint" and ignored. 
213   
214          The C{attr} object will contain only those fields provided by the 
215          client in its request, so you should use C{hasattr} to check for 
216          the presense of fields before using them.  In some cases, the C{attr} 
217          object may be completely empty. 
218   
219          @param path: requested path (relative or absolute) of the new 
220              folder. 
221          @type path: str 
222          @param attr: requested attributes of the new folder. 
223          @type attr: L{SFTPAttributes} 
224          @return: an SFTP error code like L{SFTP_OK}. 
225          @rtype: int 
226          """ 
227          return SFTP_OP_UNSUPPORTED 
 228   
230          """ 
231          Remove a directory if it exists.  The C{path} should refer to an 
232          existing, empty folder -- otherwise this method should return an 
233          error. 
234   
235          @param path: requested path (relative or absolute) of the folder 
236              to remove. 
237          @type path: str 
238          @return: an SFTP error code like L{SFTP_OK}. 
239          @rtype: int 
240          """ 
241          return SFTP_OP_UNSUPPORTED 
 242   
243 -    def chattr(self, path, attr): 
 244          """ 
245          Change the attributes of a file.  The C{attr} object will contain 
246          only those fields provided by the client in its request, so you 
247          should check for the presence of fields before using them. 
248   
249          @param path: requested path (relative or absolute) of the file to 
250              change. 
251          @type path: str 
252          @param attr: requested attributes to change on the file. 
253          @type attr: L{SFTPAttributes} 
254          @return: an error code like L{SFTP_OK}. 
255          @rtype: int 
256          """ 
257          return SFTP_OP_UNSUPPORTED 
 258   
260          """ 
261          Return the canonical form of a path on the server.  For example, 
262          if the server's home folder is C{/home/foo}, the path 
263          C{"../betty"} would be canonicalized to C{"/home/betty"}.  Note 
264          the obvious security issues: if you're serving files only from a 
265          specific folder, you probably don't want this method to reveal path 
266          names outside that folder. 
267   
268          You may find the python methods in C{os.path} useful, especially 
269          C{os.path.normpath} and C{os.path.realpath}. 
270   
271          The default implementation returns C{os.path.normpath('/' + path)}. 
272          """ 
273          if os.path.isabs(path): 
274              out = os.path.normpath(path) 
275          else: 
276              out = os.path.normpath('/' + path) 
277          if sys.platform == 'win32': 
278               
279              out = out.replace('\\', '/') 
280          return out 
 281       
283          """ 
284          Return the target of a symbolic link (or shortcut) on the server. 
285          If the specified path doesn't refer to a symbolic link, an error 
286          should be returned. 
287           
288          @param path: path (relative or absolute) of the symbolic link. 
289          @type path: str 
290          @return: the target path of the symbolic link, or an error code like 
291              L{SFTP_NO_SUCH_FILE}. 
292          @rtype: str I{or error code} 
293          """ 
294          return SFTP_OP_UNSUPPORTED 
 295       
296 -    def symlink(self, target_path, path): 
 297          """ 
298          Create a symbolic link on the server, as new pathname C{path}, 
299          with C{target_path} as the target of the link. 
300           
301          @param target_path: path (relative or absolute) of the target for 
302              this new symbolic link. 
303          @type target_path: str 
304          @param path: path (relative or absolute) of the symbolic link to 
305              create. 
306          @type path: str 
307          @return: an error code like C{SFTP_OK}. 
308          @rtype: int 
309          """ 
310          return SFTP_OP_UNSUPPORTED 
  311