[project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-157]
change SubsystemHandler/SFTPServerInterface API change the API of SubsystemHandler to accept a reference to the ServerInstance object during construction. this will break all code that currently creates subsystem handlers (like sftp servers) -- sorry! lots of little doc fixups (mostly indenting).
This commit is contained in:
parent
5d8d1938fa
commit
71a337ee08
|
@ -72,10 +72,10 @@ class ServerInterface (object):
|
||||||
C{OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED}.
|
C{OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED}.
|
||||||
|
|
||||||
@param kind: the kind of channel the client would like to open
|
@param kind: the kind of channel the client would like to open
|
||||||
(usually C{"session"}).
|
(usually C{"session"}).
|
||||||
@type kind: str
|
@type kind: str
|
||||||
@param chanid: ID of the channel, required to create a new L{Channel}
|
@param chanid: ID of the channel, required to create a new L{Channel}
|
||||||
object.
|
object.
|
||||||
@type chanid: int
|
@type chanid: int
|
||||||
@return: a success or failure code (listed above).
|
@return: a success or failure code (listed above).
|
||||||
@rtype: int
|
@rtype: int
|
||||||
|
@ -115,7 +115,7 @@ class ServerInterface (object):
|
||||||
@param username: the username of the client.
|
@param username: the username of the client.
|
||||||
@type username: str
|
@type username: str
|
||||||
@return: L{AUTH_FAILED} if the authentication fails;
|
@return: L{AUTH_FAILED} if the authentication fails;
|
||||||
L{AUTH_SUCCESSFUL} if it succeeds.
|
L{AUTH_SUCCESSFUL} if it succeeds.
|
||||||
@rtype: int
|
@rtype: int
|
||||||
"""
|
"""
|
||||||
return AUTH_FAILED
|
return AUTH_FAILED
|
||||||
|
@ -140,9 +140,9 @@ class ServerInterface (object):
|
||||||
@param password: the password given by the client.
|
@param password: the password given by the client.
|
||||||
@type password: str
|
@type password: str
|
||||||
@return: L{AUTH_FAILED} if the authentication fails;
|
@return: L{AUTH_FAILED} if the authentication fails;
|
||||||
L{AUTH_SUCCESSFUL} if it succeeds;
|
L{AUTH_SUCCESSFUL} if it succeeds;
|
||||||
L{AUTH_PARTIALLY_SUCCESSFUL} if the password auth is
|
L{AUTH_PARTIALLY_SUCCESSFUL} if the password auth is
|
||||||
successful, but authentication must continue.
|
successful, but authentication must continue.
|
||||||
@rtype: int
|
@rtype: int
|
||||||
"""
|
"""
|
||||||
return AUTH_FAILED
|
return AUTH_FAILED
|
||||||
|
@ -173,9 +173,9 @@ class ServerInterface (object):
|
||||||
@param key: the key object provided by the client.
|
@param key: the key object provided by the client.
|
||||||
@type key: L{PKey <pkey.PKey>}
|
@type key: L{PKey <pkey.PKey>}
|
||||||
@return: L{AUTH_FAILED} if the client can't authenticate
|
@return: L{AUTH_FAILED} if the client can't authenticate
|
||||||
with this key; L{AUTH_SUCCESSFUL} if it can;
|
with this key; L{AUTH_SUCCESSFUL} if it can;
|
||||||
L{AUTH_PARTIALLY_SUCCESSFUL} if it can authenticate with
|
L{AUTH_PARTIALLY_SUCCESSFUL} if it can authenticate with
|
||||||
this key but must continue with authentication.
|
this key but must continue with authentication.
|
||||||
@rtype: int
|
@rtype: int
|
||||||
"""
|
"""
|
||||||
return AUTH_FAILED
|
return AUTH_FAILED
|
||||||
|
@ -230,13 +230,13 @@ class ServerInterface (object):
|
||||||
@param height: height of screen in characters.
|
@param height: height of screen in characters.
|
||||||
@type height: int
|
@type height: int
|
||||||
@param pixelwidth: width of screen in pixels, if known (may be C{0} if
|
@param pixelwidth: width of screen in pixels, if known (may be C{0} if
|
||||||
unknown).
|
unknown).
|
||||||
@type pixelwidth: int
|
@type pixelwidth: int
|
||||||
@param pixelheight: height of screen in pixels, if known (may be C{0}
|
@param pixelheight: height of screen in pixels, if known (may be C{0}
|
||||||
if unknown).
|
if unknown).
|
||||||
@type pixelheight: int
|
@type pixelheight: int
|
||||||
@return: C{True} if the psuedo-terminal has been allocated; C{False}
|
@return: C{True} if the psuedo-terminal has been allocated; C{False}
|
||||||
otherwise.
|
otherwise.
|
||||||
@rtype: bool
|
@rtype: bool
|
||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
@ -253,7 +253,7 @@ class ServerInterface (object):
|
||||||
@param channel: the L{Channel} the pty request arrived on.
|
@param channel: the L{Channel} the pty request arrived on.
|
||||||
@type channel: L{Channel}
|
@type channel: L{Channel}
|
||||||
@return: C{True} if this channel is now hooked up to a shell; C{False}
|
@return: C{True} if this channel is now hooked up to a shell; C{False}
|
||||||
if a shell can't or won't be provided.
|
if a shell can't or won't be provided.
|
||||||
@rtype: bool
|
@rtype: bool
|
||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
@ -292,21 +292,21 @@ class ServerInterface (object):
|
||||||
C{True}. Otherwise it returns C{False}.
|
C{True}. Otherwise it returns C{False}.
|
||||||
|
|
||||||
@note: Because the default implementation uses the L{Transport} to
|
@note: Because the default implementation uses the L{Transport} to
|
||||||
identify valid subsystems, you probably won't need to override this
|
identify valid subsystems, you probably won't need to override this
|
||||||
method.
|
method.
|
||||||
|
|
||||||
@param channel: the L{Channel} the pty request arrived on.
|
@param channel: the L{Channel} the pty request arrived on.
|
||||||
@type channel: L{Channel}
|
@type channel: L{Channel}
|
||||||
@param name: name of the requested subsystem.
|
@param name: name of the requested subsystem.
|
||||||
@type name: str
|
@type name: str
|
||||||
@return: C{True} if this channel is now hooked up to the requested
|
@return: C{True} if this channel is now hooked up to the requested
|
||||||
subsystem; C{False} if that subsystem can't or won't be provided.
|
subsystem; C{False} if that subsystem can't or won't be provided.
|
||||||
@rtype: bool
|
@rtype: bool
|
||||||
"""
|
"""
|
||||||
handler_class, larg, kwarg = channel.get_transport()._get_subsystem_handler(name)
|
handler_class, larg, kwarg = channel.get_transport()._get_subsystem_handler(name)
|
||||||
if handler_class is None:
|
if handler_class is None:
|
||||||
return False
|
return False
|
||||||
handler = handler_class(channel, name, *larg, **kwarg)
|
handler = handler_class(channel, name, self, *larg, **kwarg)
|
||||||
handler.start()
|
handler.start()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -324,10 +324,10 @@ class ServerInterface (object):
|
||||||
@param height: height of screen in characters.
|
@param height: height of screen in characters.
|
||||||
@type height: int
|
@type height: int
|
||||||
@param pixelwidth: width of screen in pixels, if known (may be C{0} if
|
@param pixelwidth: width of screen in pixels, if known (may be C{0} if
|
||||||
unknown).
|
unknown).
|
||||||
@type pixelwidth: int
|
@type pixelwidth: int
|
||||||
@param pixelheight: height of screen in pixels, if known (may be C{0}
|
@param pixelheight: height of screen in pixels, if known (may be C{0}
|
||||||
if unknown).
|
if unknown).
|
||||||
@type pixelheight: int
|
@type pixelheight: int
|
||||||
@return: C{True} if the terminal was resized; C{False} if not.
|
@return: C{True} if the terminal was resized; C{False} if not.
|
||||||
@rtype: bool
|
@rtype: bool
|
||||||
|
@ -353,7 +353,7 @@ class SubsystemHandler (threading.Thread):
|
||||||
|
|
||||||
@since: ivysaur
|
@since: ivysaur
|
||||||
"""
|
"""
|
||||||
def __init__(self, channel, name):
|
def __init__(self, channel, name, server):
|
||||||
"""
|
"""
|
||||||
Create a new handler for a channel. This is used by L{ServerInterface}
|
Create a new handler for a channel. This is used by L{ServerInterface}
|
||||||
to start up a new handler when a channel requests this subsystem. You
|
to start up a new handler when a channel requests this subsystem. You
|
||||||
|
@ -365,11 +365,24 @@ class SubsystemHandler (threading.Thread):
|
||||||
@type channel: L{Channel}
|
@type channel: L{Channel}
|
||||||
@param name: name of the requested subsystem.
|
@param name: name of the requested subsystem.
|
||||||
@type name: str
|
@type name: str
|
||||||
|
@param server: the server object for the session that started this
|
||||||
|
subsystem
|
||||||
|
@rtype server: L{ServerInterface}
|
||||||
"""
|
"""
|
||||||
threading.Thread.__init__(self, target=self._run)
|
threading.Thread.__init__(self, target=self._run)
|
||||||
self.__channel = channel
|
self.__channel = channel
|
||||||
self.__transport = channel.get_transport()
|
self.__transport = channel.get_transport()
|
||||||
self.__name = name
|
self.__name = name
|
||||||
|
self.__server = server
|
||||||
|
|
||||||
|
def get_server(self):
|
||||||
|
"""
|
||||||
|
Return the L{ServerInterface} object associated with this channel and
|
||||||
|
subsystem.
|
||||||
|
|
||||||
|
@rtype: L{ServerInterface}
|
||||||
|
"""
|
||||||
|
return self.__server
|
||||||
|
|
||||||
def _run(self):
|
def _run(self):
|
||||||
try:
|
try:
|
||||||
|
@ -396,12 +409,11 @@ class SubsystemHandler (threading.Thread):
|
||||||
corresponds to exactly one L{Channel} on one L{Transport}.
|
corresponds to exactly one L{Channel} on one L{Transport}.
|
||||||
|
|
||||||
@note: It is the responsibility of this method to exit if the
|
@note: It is the responsibility of this method to exit if the
|
||||||
underlying L{Transport} is closed. This can be done by checking
|
underlying L{Transport} is closed. This can be done by checking
|
||||||
L{Transport.is_active <BaseTransport.is_active>} or noticing an EOF
|
L{Transport.is_active <BaseTransport.is_active>} or noticing an EOF
|
||||||
on the L{Channel}.
|
on the L{Channel}. If this method loops forever without checking
|
||||||
If this method loops forever without checking for this case, your
|
for this case, your python interpreter may refuse to exit because
|
||||||
python interpreter may refuse to exit because this thread will still
|
this thread will still be running.
|
||||||
be running.
|
|
||||||
|
|
||||||
@param name: name of the requested subsystem.
|
@param name: name of the requested subsystem.
|
||||||
@type name: str
|
@type name: str
|
||||||
|
|
|
@ -37,37 +37,35 @@ class SFTPServer (BaseSFTP, SubsystemHandler):
|
||||||
Use L{Transport.set_subsystem_handler} to activate this class.
|
Use L{Transport.set_subsystem_handler} to activate this class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, channel, name, server=SFTPServerInterface, server_args=None):
|
def __init__(self, channel, name, server, sftp_si=SFTPServerInterface, *largs, **kwargs):
|
||||||
"""
|
"""
|
||||||
The constructor for SFTPServer is meant to be called from within the
|
The constructor for SFTPServer is meant to be called from within the
|
||||||
L{Transport} as a subsystem handler. The C{server} and C{server_args}
|
L{Transport} as a subsystem handler. C{server} and any additional
|
||||||
parameters are passed from the original call to
|
parameters or keyword parameters are passed from the original call to
|
||||||
L{Transport.set_subsystem_handler}.
|
L{Transport.set_subsystem_handler}.
|
||||||
|
|
||||||
@param channel: channel passed from the L{Transport}.
|
@param channel: channel passed from the L{Transport}.
|
||||||
@type channel: L{Channel}
|
@type channel: L{Channel}
|
||||||
@param name: name of the requested subsystem.
|
@param name: name of the requested subsystem.
|
||||||
@type name: str
|
@type name: str
|
||||||
@param server: a subclass of L{SFTPServerInterface} to use for handling
|
@param server: the server object associated with this channel and
|
||||||
individual requests.
|
subsystem
|
||||||
@type server: class
|
@type server: L{ServerInterface}
|
||||||
@param server_args: keyword parameters to pass to C{server} when it's
|
@param sftp_si: a subclass of L{SFTPServerInterface} to use for handling
|
||||||
constructed.
|
individual requests.
|
||||||
@type server_args: dict
|
@type sftp_si: class
|
||||||
"""
|
"""
|
||||||
BaseSFTP.__init__(self)
|
BaseSFTP.__init__(self)
|
||||||
SubsystemHandler.__init__(self, channel, name)
|
SubsystemHandler.__init__(self, channel, name, server)
|
||||||
transport = channel.get_transport()
|
transport = channel.get_transport()
|
||||||
self.logger = util.get_logger(transport.get_log_channel() + '.' +
|
self.logger = util.get_logger(transport.get_log_channel() + '.' +
|
||||||
channel.get_name() + '.sftp')
|
channel.get_name() + '.sftp')
|
||||||
self.ultra_debug = transport.ultra_debug
|
self.ultra_debug = transport.ultra_debug
|
||||||
self.next_handle = 1
|
self.next_handle = 1
|
||||||
# map of handle-string to SFTPHandle for files & folders:
|
# map of handle-string to SFTPHandle for files & folders:
|
||||||
self.file_table = { }
|
self.file_table = { }
|
||||||
self.folder_table = { }
|
self.folder_table = { }
|
||||||
if server_args is None:
|
self.server = sftp_si(server, *largs, **kwargs)
|
||||||
server_args = {}
|
|
||||||
self.server = server(**server_args)
|
|
||||||
|
|
||||||
def start_subsystem(self, name, transport, channel):
|
def start_subsystem(self, name, transport, channel):
|
||||||
self.sock = channel
|
self.sock = channel
|
||||||
|
|
|
@ -37,6 +37,17 @@ class SFTPServerInterface (object):
|
||||||
session to abruptly end, so you will usually want to catch exceptions and
|
session to abruptly end, so you will usually want to catch exceptions and
|
||||||
return an appropriate error code.
|
return an appropriate error code.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def __init__ (self, server, *largs, **kwargs):
|
||||||
|
"""
|
||||||
|
Create a new SFTPServerInterface object. This method does nothing by
|
||||||
|
default and is meant to be overridden by subclasses.
|
||||||
|
|
||||||
|
@param server: the server object associated with this channel and
|
||||||
|
SFTP subsystem
|
||||||
|
@type server: L{ServerInterface}
|
||||||
|
"""
|
||||||
|
super(SFTPServerInterface, self).__init__(*largs, **kwargs)
|
||||||
|
|
||||||
def session_started(self):
|
def session_started(self):
|
||||||
"""
|
"""
|
||||||
|
@ -80,13 +91,13 @@ class SFTPServerInterface (object):
|
||||||
the client didn't specify them.
|
the client didn't specify them.
|
||||||
|
|
||||||
@note: The SFTP protocol defines all files to be in "binary" mode.
|
@note: The SFTP protocol defines all files to be in "binary" mode.
|
||||||
There is no equivalent to python's "text" mode.
|
There is no equivalent to python's "text" mode.
|
||||||
|
|
||||||
@param path: the requested path (relative or absolute) of the file
|
@param path: the requested path (relative or absolute) of the file
|
||||||
to be opened.
|
to be opened.
|
||||||
@type path: str
|
@type path: str
|
||||||
@param flags: flags or'd together from the C{os} module indicating the
|
@param flags: flags or'd together from the C{os} module indicating the
|
||||||
requested mode for opening the file.
|
requested mode for opening the file.
|
||||||
@type flags: int
|
@type flags: int
|
||||||
@param attr: requested attributes of the file if it is newly created.
|
@param attr: requested attributes of the file if it is newly created.
|
||||||
@type attr: L{SFTPAttributes}
|
@type attr: L{SFTPAttributes}
|
||||||
|
@ -114,7 +125,7 @@ class SFTPServerInterface (object):
|
||||||
@param path: the requested path (relative or absolute) to be listed.
|
@param path: the requested path (relative or absolute) to be listed.
|
||||||
@type path: str
|
@type path: str
|
||||||
@return: a list of the files in the given folder, using
|
@return: a list of the files in the given folder, using
|
||||||
L{SFTPAttributes} objects.
|
L{SFTPAttributes} objects.
|
||||||
@rtype: list of L{SFTPAttributes} I{or error code}
|
@rtype: list of L{SFTPAttributes} I{or error code}
|
||||||
|
|
||||||
@note: You should normalize the given C{path} first (see the
|
@note: You should normalize the given C{path} first (see the
|
||||||
|
@ -133,10 +144,10 @@ class SFTPServerInterface (object):
|
||||||
call that doesn't follow symlinks/aliases.)
|
call that doesn't follow symlinks/aliases.)
|
||||||
|
|
||||||
@param path: the requested path (relative or absolute) to fetch
|
@param path: the requested path (relative or absolute) to fetch
|
||||||
file statistics for.
|
file statistics for.
|
||||||
@type path: str
|
@type path: str
|
||||||
@return: an attributes object for the given file, or an SFTP error
|
@return: an attributes object for the given file, or an SFTP error
|
||||||
code (like L{SFTP_PERMISSION_DENIED}).
|
code (like L{SFTP_PERMISSION_DENIED}).
|
||||||
@rtype: L{SFTPAttributes} I{or error code}
|
@rtype: L{SFTPAttributes} I{or error code}
|
||||||
"""
|
"""
|
||||||
return SFTP_OP_UNSUPPORTED
|
return SFTP_OP_UNSUPPORTED
|
||||||
|
@ -150,10 +161,10 @@ class SFTPServerInterface (object):
|
||||||
corresponding call that follows symlinks/aliases.)
|
corresponding call that follows symlinks/aliases.)
|
||||||
|
|
||||||
@param path: the requested path (relative or absolute) to fetch
|
@param path: the requested path (relative or absolute) to fetch
|
||||||
file statistics for.
|
file statistics for.
|
||||||
@type path: str
|
@type path: str
|
||||||
@return: an attributes object for the given file, or an SFTP error
|
@return: an attributes object for the given file, or an SFTP error
|
||||||
code (like L{SFTP_PERMISSION_DENIED}).
|
code (like L{SFTP_PERMISSION_DENIED}).
|
||||||
@rtype: L{SFTPAttributes} I{or error code}
|
@rtype: L{SFTPAttributes} I{or error code}
|
||||||
"""
|
"""
|
||||||
return SFTP_OP_UNSUPPORTED
|
return SFTP_OP_UNSUPPORTED
|
||||||
|
@ -163,7 +174,7 @@ class SFTPServerInterface (object):
|
||||||
Delete a file, if possible.
|
Delete a file, if possible.
|
||||||
|
|
||||||
@param path: the requested path (relative or absolute) of the file
|
@param path: the requested path (relative or absolute) of the file
|
||||||
to delete.
|
to delete.
|
||||||
@type path: str
|
@type path: str
|
||||||
@return: an SFTP error code like L{SFTP_OK}.
|
@return: an SFTP error code like L{SFTP_OK}.
|
||||||
@rtype: int
|
@rtype: int
|
||||||
|
@ -179,11 +190,11 @@ class SFTPServerInterface (object):
|
||||||
files that cross disk partition boundaries, if at all possible.
|
files that cross disk partition boundaries, if at all possible.
|
||||||
|
|
||||||
@note: You should return an error if a file with the same name as
|
@note: You should return an error if a file with the same name as
|
||||||
C{newpath} already exists. (The rename operation should be
|
C{newpath} already exists. (The rename operation should be
|
||||||
non-desctructive.)
|
non-desctructive.)
|
||||||
|
|
||||||
@param oldpath: the requested path (relative or absolute) of the
|
@param oldpath: the requested path (relative or absolute) of the
|
||||||
existing file.
|
existing file.
|
||||||
@type oldpath: str
|
@type oldpath: str
|
||||||
@param newpath: the requested new path of the file.
|
@param newpath: the requested new path of the file.
|
||||||
@type newpath: str
|
@type newpath: str
|
||||||
|
@ -203,7 +214,7 @@ class SFTPServerInterface (object):
|
||||||
object may be completely empty.
|
object may be completely empty.
|
||||||
|
|
||||||
@param path: requested path (relative or absolute) of the new
|
@param path: requested path (relative or absolute) of the new
|
||||||
folder.
|
folder.
|
||||||
@type path: str
|
@type path: str
|
||||||
@param attr: requested attributes of the new folder.
|
@param attr: requested attributes of the new folder.
|
||||||
@type attr: L{SFTPAttributes}
|
@type attr: L{SFTPAttributes}
|
||||||
|
@ -219,7 +230,7 @@ class SFTPServerInterface (object):
|
||||||
error.
|
error.
|
||||||
|
|
||||||
@param path: requested path (relative or absolute) of the folder
|
@param path: requested path (relative or absolute) of the folder
|
||||||
to remove.
|
to remove.
|
||||||
@type path: str
|
@type path: str
|
||||||
@return: an SFTP error code like L{SFTP_OK}.
|
@return: an SFTP error code like L{SFTP_OK}.
|
||||||
@rtype: int
|
@rtype: int
|
||||||
|
@ -233,7 +244,7 @@ class SFTPServerInterface (object):
|
||||||
should check for the presence of fields before using them.
|
should check for the presence of fields before using them.
|
||||||
|
|
||||||
@param path: requested path (relative or absolute) of the file to
|
@param path: requested path (relative or absolute) of the file to
|
||||||
change.
|
change.
|
||||||
@type path: str
|
@type path: str
|
||||||
@param attr: requested attributes to change on the file.
|
@param attr: requested attributes to change on the file.
|
||||||
@type attr: L{SFTPAttributes}
|
@type attr: L{SFTPAttributes}
|
||||||
|
|
|
@ -762,7 +762,7 @@ class BaseTransport (threading.Thread):
|
||||||
|
|
||||||
def set_subsystem_handler(self, name, handler, *larg, **kwarg):
|
def set_subsystem_handler(self, name, handler, *larg, **kwarg):
|
||||||
"""
|
"""
|
||||||
Set the handler class for a subsystem in server mode. If a reqeuest
|
Set the handler class for a subsystem in server mode. If a request
|
||||||
for this subsystem is made on an open ssh channel later, this handler
|
for this subsystem is made on an open ssh channel later, this handler
|
||||||
will be constructed and called -- see L{SubsystemHandler} for more
|
will be constructed and called -- see L{SubsystemHandler} for more
|
||||||
detailed documentation.
|
detailed documentation.
|
||||||
|
@ -773,7 +773,7 @@ class BaseTransport (threading.Thread):
|
||||||
@param name: name of the subsystem.
|
@param name: name of the subsystem.
|
||||||
@type name: str
|
@type name: str
|
||||||
@param handler: subclass of L{SubsystemHandler} that handles this
|
@param handler: subclass of L{SubsystemHandler} that handles this
|
||||||
subsystem.
|
subsystem.
|
||||||
@type handler: class
|
@type handler: class
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -56,7 +56,7 @@ class StubSFTPServer (SFTPServerInterface):
|
||||||
# assume current folder is a fine root
|
# assume current folder is a fine root
|
||||||
# (the tests always create and eventualy delete a subfolder, so there shouldn't be any mess)
|
# (the tests always create and eventualy delete a subfolder, so there shouldn't be any mess)
|
||||||
ROOT = os.getcwd()
|
ROOT = os.getcwd()
|
||||||
|
|
||||||
def _realpath(self, path):
|
def _realpath(self, path):
|
||||||
return self.ROOT + self.canonicalize(path)
|
return self.ROOT + self.canonicalize(path)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue