aboutsummaryrefslogtreecommitdiff
path: root/paramiko/server.py
diff options
context:
space:
mode:
Diffstat (limited to 'paramiko/server.py')
-rw-r--r--paramiko/server.py584
1 files changed, 267 insertions, 317 deletions
diff --git a/paramiko/server.py b/paramiko/server.py
index fdb4094..496cd60 100644
--- a/paramiko/server.py
+++ b/paramiko/server.py
@@ -17,62 +17,21 @@
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
"""
-L{ServerInterface} is an interface to override for server support.
+`.ServerInterface` is an interface to override for server support.
"""
import threading
-from paramiko.common import *
from paramiko import util
-
-
-class InteractiveQuery (object):
- """
- A query (set of prompts) for a user during interactive authentication.
- """
-
- def __init__(self, name='', instructions='', *prompts):
- """
- Create a new interactive query to send to the client. The name and
- instructions are optional, but are generally displayed to the end
- user. A list of prompts may be included, or they may be added via
- the L{add_prompt} method.
-
- @param name: name of this query
- @type name: str
- @param instructions: user instructions (usually short) about this query
- @type instructions: str
- @param prompts: one or more authentication prompts
- @type prompts: str
- """
- self.name = name
- self.instructions = instructions
- self.prompts = []
- for x in prompts:
- if (type(x) is str) or (type(x) is unicode):
- self.add_prompt(x)
- else:
- self.add_prompt(x[0], x[1])
-
- def add_prompt(self, prompt, echo=True):
- """
- Add a prompt to this query. The prompt should be a (reasonably short)
- string. Multiple prompts can be added to the same query.
-
- @param prompt: the user prompt
- @type prompt: str
- @param echo: C{True} (default) if the user's response should be echoed;
- C{False} if not (for a password or similar)
- @type echo: bool
- """
- self.prompts.append((prompt, echo))
+from paramiko.common import DEBUG, ERROR, OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED, AUTH_FAILED
+from paramiko.py3compat import string_types
class ServerInterface (object):
"""
- This class defines an interface for controlling the behavior of paramiko
+ This class defines an interface for controlling the behavior of Paramiko
in server mode.
- Methods on this class are called from paramiko's primary thread, so you
+ Methods on this class are called from Paramiko's primary thread, so you
shouldn't do too much work in them. (Certainly nothing that blocks or
sleeps.)
"""
@@ -80,7 +39,7 @@ class ServerInterface (object):
def check_channel_request(self, kind, chanid):
"""
Determine if a channel request of a given type will be granted, and
- return C{OPEN_SUCCEEDED} or an error code. This method is
+ return ``OPEN_SUCCEEDED`` or an error code. This method is
called in server mode when the client requests a channel, after
authentication is complete.
@@ -88,37 +47,37 @@ class ServerInterface (object):
useless), you should also override some of the channel request methods
below, which are used to determine which services will be allowed on
a given channel:
- - L{check_channel_pty_request}
- - L{check_channel_shell_request}
- - L{check_channel_subsystem_request}
- - L{check_channel_window_change_request}
- - L{check_channel_x11_request}
- - L{check_channel_forward_agent_request}
-
- The C{chanid} parameter is a small number that uniquely identifies the
- channel within a L{Transport}. A L{Channel} object is not created
- unless this method returns C{OPEN_SUCCEEDED} -- once a
- L{Channel} object is created, you can call L{Channel.get_id} to
+
+ - `check_channel_pty_request`
+ - `check_channel_shell_request`
+ - `check_channel_subsystem_request`
+ - `check_channel_window_change_request`
+ - `check_channel_x11_request`
+ - `check_channel_forward_agent_request`
+
+ The ``chanid`` parameter is a small number that uniquely identifies the
+ channel within a `.Transport`. A `.Channel` object is not created
+ unless this method returns ``OPEN_SUCCEEDED`` -- once a
+ `.Channel` object is created, you can call `.Channel.get_id` to
retrieve the channel ID.
- The return value should either be C{OPEN_SUCCEEDED} (or
- C{0}) to allow the channel request, or one of the following error
+ The return value should either be ``OPEN_SUCCEEDED`` (or
+ ``0``) to allow the channel request, or one of the following error
codes to reject it:
- - C{OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED}
- - C{OPEN_FAILED_CONNECT_FAILED}
- - C{OPEN_FAILED_UNKNOWN_CHANNEL_TYPE}
- - C{OPEN_FAILED_RESOURCE_SHORTAGE}
+
+ - ``OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED``
+ - ``OPEN_FAILED_CONNECT_FAILED``
+ - ``OPEN_FAILED_UNKNOWN_CHANNEL_TYPE``
+ - ``OPEN_FAILED_RESOURCE_SHORTAGE``
The default implementation always returns
- C{OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED}.
+ ``OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED``.
- @param kind: the kind of channel the client would like to open
- (usually C{"session"}).
- @type kind: str
- @param chanid: ID of the channel
- @type chanid: int
- @return: a success or failure code (listed above)
- @rtype: int
+ :param str kind:
+ the kind of channel the client would like to open (usually
+ ``"session"``).
+ :param int chanid: ID of the channel
+ :return: an `int` success or failure code (listed above)
"""
return OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
@@ -129,15 +88,13 @@ class ServerInterface (object):
of authentication methods that might be successful.
The "list" is actually a string of comma-separated names of types of
- authentication. Possible values are C{"password"}, C{"publickey"},
- and C{"none"}.
+ authentication. Possible values are ``"password"``, ``"publickey"``,
+ and ``"none"``.
- The default implementation always returns C{"password"}.
+ The default implementation always returns ``"password"``.
- @param username: the username requesting authentication.
- @type username: str
- @return: a comma-separated list of authentication types
- @rtype: str
+ :param str username: the username requesting authentication.
+ :return: a comma-separated `str` of authentication types
"""
return 'password'
@@ -146,17 +103,17 @@ class ServerInterface (object):
Determine if a client may open channels with no (further)
authentication.
- Return L{AUTH_FAILED} if the client must authenticate, or
- L{AUTH_SUCCESSFUL} if it's okay for the client to not
+ Return `.AUTH_FAILED` if the client must authenticate, or
+ `.AUTH_SUCCESSFUL` if it's okay for the client to not
authenticate.
- The default implementation always returns L{AUTH_FAILED}.
+ The default implementation always returns `.AUTH_FAILED`.
- @param username: the username of the client.
- @type username: str
- @return: L{AUTH_FAILED} if the authentication fails;
- L{AUTH_SUCCESSFUL} if it succeeds.
- @rtype: int
+ :param str username: the username of the client.
+ :return:
+ `.AUTH_FAILED` if the authentication fails; `.AUTH_SUCCESSFUL` if
+ it succeeds.
+ :rtype: int
"""
return AUTH_FAILED
@@ -165,25 +122,23 @@ class ServerInterface (object):
Determine if a given username and password supplied by the client is
acceptable for use in authentication.
- Return L{AUTH_FAILED} if the password is not accepted,
- L{AUTH_SUCCESSFUL} if the password is accepted and completes
- the authentication, or L{AUTH_PARTIALLY_SUCCESSFUL} if your
+ Return `.AUTH_FAILED` if the password is not accepted,
+ `.AUTH_SUCCESSFUL` if the password is accepted and completes
+ the authentication, or `.AUTH_PARTIALLY_SUCCESSFUL` if your
authentication is stateful, and this key is accepted for
authentication, but more authentication is required. (In this latter
- case, L{get_allowed_auths} will be called to report to the client what
+ case, `get_allowed_auths` will be called to report to the client what
options it has for continuing the authentication.)
- The default implementation always returns L{AUTH_FAILED}.
+ The default implementation always returns `.AUTH_FAILED`.
- @param username: the username of the authenticating client.
- @type username: str
- @param password: the password given by the client.
- @type password: str
- @return: L{AUTH_FAILED} if the authentication fails;
- L{AUTH_SUCCESSFUL} if it succeeds;
- L{AUTH_PARTIALLY_SUCCESSFUL} if the password auth is
+ :param str username: the username of the authenticating client.
+ :param str password: the password given by the client.
+ :return:
+ `.AUTH_FAILED` if the authentication fails; `.AUTH_SUCCESSFUL` if
+ it succeeds; `.AUTH_PARTIALLY_SUCCESSFUL` if the password auth is
successful, but authentication must continue.
- @rtype: int
+ :rtype: int
"""
return AUTH_FAILED
@@ -194,29 +149,28 @@ class ServerInterface (object):
check the username and key and decide if you would accept a signature
made using this key.
- Return L{AUTH_FAILED} if the key is not accepted,
- L{AUTH_SUCCESSFUL} if the key is accepted and completes the
- authentication, or L{AUTH_PARTIALLY_SUCCESSFUL} if your
+ Return `.AUTH_FAILED` if the key is not accepted,
+ `.AUTH_SUCCESSFUL` if the key is accepted and completes the
+ authentication, or `.AUTH_PARTIALLY_SUCCESSFUL` if your
authentication is stateful, and this password is accepted for
authentication, but more authentication is required. (In this latter
- case, L{get_allowed_auths} will be called to report to the client what
+ case, `get_allowed_auths` will be called to report to the client what
options it has for continuing the authentication.)
Note that you don't have to actually verify any key signtature here.
- If you're willing to accept the key, paramiko will do the work of
+ If you're willing to accept the key, Paramiko will do the work of
verifying the client's signature.
- The default implementation always returns L{AUTH_FAILED}.
-
- @param username: the username of the authenticating client
- @type username: str
- @param key: the key object provided by the client
- @type key: L{PKey <pkey.PKey>}
- @return: L{AUTH_FAILED} if the client can't authenticate
- with this key; L{AUTH_SUCCESSFUL} if it can;
- L{AUTH_PARTIALLY_SUCCESSFUL} if it can authenticate with
- this key but must continue with authentication
- @rtype: int
+ The default implementation always returns `.AUTH_FAILED`.
+
+ :param str username: the username of the authenticating client
+ :param .PKey key: the key object provided by the client
+ :return:
+ `.AUTH_FAILED` if the client can't authenticate with this key;
+ `.AUTH_SUCCESSFUL` if it can; `.AUTH_PARTIALLY_SUCCESSFUL` if it
+ can authenticate with this key but must continue with
+ authentication
+ :rtype: int
"""
return AUTH_FAILED
@@ -224,24 +178,24 @@ class ServerInterface (object):
"""
Begin an interactive authentication challenge, if supported. You
should override this method in server mode if you want to support the
- C{"keyboard-interactive"} auth type, which requires you to send a
+ ``"keyboard-interactive"`` auth type, which requires you to send a
series of questions for the client to answer.
- Return L{AUTH_FAILED} if this auth method isn't supported. Otherwise,
- you should return an L{InteractiveQuery} object containing the prompts
+ Return `.AUTH_FAILED` if this auth method isn't supported. Otherwise,
+ you should return an `.InteractiveQuery` object containing the prompts
and instructions for the user. The response will be sent via a call
- to L{check_auth_interactive_response}.
+ to `check_auth_interactive_response`.
- The default implementation always returns L{AUTH_FAILED}.
+ The default implementation always returns `.AUTH_FAILED`.
- @param username: the username of the authenticating client
- @type username: str
- @param submethods: a comma-separated list of methods preferred by the
- client (usually empty)
- @type submethods: str
- @return: L{AUTH_FAILED} if this auth method isn't supported; otherwise
- an object containing queries for the user
- @rtype: int or L{InteractiveQuery}
+ :param str username: the username of the authenticating client
+ :param str submethods:
+ a comma-separated list of methods preferred by the client (usually
+ empty)
+ :return:
+ `.AUTH_FAILED` if this auth method isn't supported; otherwise an
+ object containing queries for the user
+ :rtype: int or `.InteractiveQuery`
"""
return AUTH_FAILED
@@ -249,31 +203,30 @@ class ServerInterface (object):
"""
Continue or finish an interactive authentication challenge, if
supported. You should override this method in server mode if you want
- to support the C{"keyboard-interactive"} auth type.
+ to support the ``"keyboard-interactive"`` auth type.
- Return L{AUTH_FAILED} if the responses are not accepted,
- L{AUTH_SUCCESSFUL} if the responses are accepted and complete
- the authentication, or L{AUTH_PARTIALLY_SUCCESSFUL} if your
+ Return `.AUTH_FAILED` if the responses are not accepted,
+ `.AUTH_SUCCESSFUL` if the responses are accepted and complete
+ the authentication, or `.AUTH_PARTIALLY_SUCCESSFUL` if your
authentication is stateful, and this set of responses is accepted for
authentication, but more authentication is required. (In this latter
- case, L{get_allowed_auths} will be called to report to the client what
+ case, `get_allowed_auths` will be called to report to the client what
options it has for continuing the authentication.)
If you wish to continue interactive authentication with more questions,
- you may return an L{InteractiveQuery} object, which should cause the
+ you may return an `.InteractiveQuery` object, which should cause the
client to respond with more answers, calling this method again. This
cycle can continue indefinitely.
- The default implementation always returns L{AUTH_FAILED}.
+ The default implementation always returns `.AUTH_FAILED`.
- @param responses: list of responses from the client
- @type responses: list(str)
- @return: L{AUTH_FAILED} if the authentication fails;
- L{AUTH_SUCCESSFUL} if it succeeds;
- L{AUTH_PARTIALLY_SUCCESSFUL} if the interactive auth is
- successful, but authentication must continue; otherwise an object
- containing queries for the user
- @rtype: int or L{InteractiveQuery}
+ :param list responses: list of `str` responses from the client
+ :return:
+ `.AUTH_FAILED` if the authentication fails; `.AUTH_SUCCESSFUL` if
+ it succeeds; `.AUTH_PARTIALLY_SUCCESSFUL` if the interactive auth
+ is successful, but authentication must continue; otherwise an
+ object containing queries for the user
+ :rtype: int or `.InteractiveQuery`
"""
return AUTH_FAILED
@@ -281,22 +234,20 @@ class ServerInterface (object):
"""
Handle a request for port forwarding. The client is asking that
connections to the given address and port be forwarded back across
- this ssh connection. An address of C{"0.0.0.0"} indicates a global
- address (any address associated with this server) and a port of C{0}
+ this ssh connection. An address of ``"0.0.0.0"`` indicates a global
+ address (any address associated with this server) and a port of ``0``
indicates that no specific port is requested (usually the OS will pick
a port).
- The default implementation always returns C{False}, rejecting the
+ The default implementation always returns ``False``, rejecting the
port forwarding request. If the request is accepted, you should return
the port opened for listening.
- @param address: the requested address
- @type address: str
- @param port: the requested port
- @type port: int
- @return: the port number that was opened for listening, or C{False} to
- reject
- @rtype: int
+ :param str address: the requested address
+ :param int port: the requested port
+ :return:
+ the port number (`int`) that was opened for listening, or ``False``
+ to reject
"""
return False
@@ -306,19 +257,17 @@ class ServerInterface (object):
If the given address and port is being forwarded across this ssh
connection, the port should be closed.
- @param address: the forwarded address
- @type address: str
- @param port: the forwarded port
- @type port: int
+ :param str address: the forwarded address
+ :param int port: the forwarded port
"""
pass
def check_global_request(self, kind, msg):
"""
- Handle a global request of the given C{kind}. This method is called
+ Handle a global request of the given ``kind``. This method is called
in server mode and client mode, whenever the remote host makes a global
request. If there are any arguments to the request, they will be in
- C{msg}.
+ ``msg``.
There aren't any useful global requests defined, aside from port
forwarding, so usually this type of request is an extension to the
@@ -329,115 +278,100 @@ class ServerInterface (object):
sent back with the successful result. (Note that the items in the
tuple can only be strings, ints, longs, or bools.)
- The default implementation always returns C{False}, indicating that it
+ The default implementation always returns ``False``, indicating that it
does not support any global requests.
- @note: Port forwarding requests are handled separately, in
- L{check_port_forward_request}.
-
- @param kind: the kind of global request being made.
- @type kind: str
- @param msg: any extra arguments to the request.
- @type msg: L{Message}
- @return: C{True} or a tuple of data if the request was granted;
- C{False} otherwise.
- @rtype: bool
+ .. note:: Port forwarding requests are handled separately, in
+ `check_port_forward_request`.
+
+ :param str kind: the kind of global request being made.
+ :param .Message msg: any extra arguments to the request.
+ :return:
+ ``True`` or a `tuple` of data if the request was granted; ``False``
+ otherwise.
"""
return False
-
### Channel requests
-
def check_channel_pty_request(self, channel, term, width, height, pixelwidth, pixelheight,
modes):
"""
Determine if a pseudo-terminal of the given dimensions (usually
requested for shell access) can be provided on the given channel.
- The default implementation always returns C{False}.
-
- @param channel: the L{Channel} the pty request arrived on.
- @type channel: L{Channel}
- @param term: type of terminal requested (for example, C{"vt100"}).
- @type term: str
- @param width: width of screen in characters.
- @type width: int
- @param height: height of screen in characters.
- @type height: int
- @param pixelwidth: width of screen in pixels, if known (may be C{0} if
- unknown).
- @type pixelwidth: int
- @param pixelheight: height of screen in pixels, if known (may be C{0}
- if unknown).
- @type pixelheight: int
- @return: C{True} if the psuedo-terminal has been allocated; C{False}
+ The default implementation always returns ``False``.
+
+ :param .Channel channel: the `.Channel` the pty request arrived on.
+ :param str term: type of terminal requested (for example, ``"vt100"``).
+ :param int width: width of screen in characters.
+ :param int height: height of screen in characters.
+ :param int pixelwidth:
+ width of screen in pixels, if known (may be ``0`` if unknown).
+ :param int pixelheight:
+ height of screen in pixels, if known (may be ``0`` if unknown).
+ :return:
+ ``True`` if the psuedo-terminal has been allocated; ``False``
otherwise.
- @rtype: bool
"""
return False
def check_channel_shell_request(self, channel):
"""
Determine if a shell will be provided to the client on the given
- channel. If this method returns C{True}, the channel should be
+ channel. If this method returns ``True``, the channel should be
connected to the stdin/stdout of a shell (or something that acts like
a shell).
- The default implementation always returns C{False}.
+ The default implementation always returns ``False``.
- @param channel: the L{Channel} the request arrived on.
- @type channel: L{Channel}
- @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.
- @rtype: bool
+ :param .Channel channel: the `.Channel` the request arrived on.
+ :return:
+ ``True`` if this channel is now hooked up to a shell; ``False`` if
+ a shell can't or won't be provided.
"""
return False
def check_channel_exec_request(self, channel, command):
"""
Determine if a shell command will be executed for the client. If this
- method returns C{True}, the channel should be connected to the stdin,
+ method returns ``True``, the channel should be connected to the stdin,
stdout, and stderr of the shell command.
- The default implementation always returns C{False}.
+ The default implementation always returns ``False``.
- @param channel: the L{Channel} the request arrived on.
- @type channel: L{Channel}
- @param command: the command to execute.
- @type command: str
- @return: C{True} if this channel is now hooked up to the stdin,
- stdout, and stderr of the executing command; C{False} if the
- command will not be executed.
- @rtype: bool
+ :param .Channel channel: the `.Channel` the request arrived on.
+ :param str command: the command to execute.
+ :return:
+ ``True`` if this channel is now hooked up to the stdin, stdout, and
+ stderr of the executing command; ``False`` if the command will not
+ be executed.
- @since: 1.1
+ .. versionadded:: 1.1
"""
return False
def check_channel_subsystem_request(self, channel, name):
"""
Determine if a requested subsystem will be provided to the client on
- the given channel. If this method returns C{True}, all future I/O
+ the given channel. If this method returns ``True``, all future I/O
through this channel will be assumed to be connected to the requested
- subsystem. An example of a subsystem is C{sftp}.
+ subsystem. An example of a subsystem is ``sftp``.
The default implementation checks for a subsystem handler assigned via
- L{Transport.set_subsystem_handler}.
+ `.Transport.set_subsystem_handler`.
If one has been set, the handler is invoked and this method returns
- C{True}. Otherwise it returns C{False}.
+ ``True``. Otherwise it returns ``False``.
- @note: Because the default implementation uses the L{Transport} to
+ .. note:: Because the default implementation uses the `.Transport` to
identify valid subsystems, you probably won't need to override this
method.
- @param channel: the L{Channel} the pty request arrived on.
- @type channel: L{Channel}
- @param name: name of the requested subsystem.
- @type name: str
- @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.
- @rtype: bool
+ :param .Channel channel: the `.Channel` the pty request arrived on.
+ :param str name: name of the requested subsystem.
+ :return:
+ ``True`` if this channel is now hooked up to the requested
+ subsystem; ``False`` if that subsystem can't or won't be provided.
"""
handler_class, larg, kwarg = channel.get_transport()._get_subsystem_handler(name)
if handler_class is None:
@@ -451,102 +385,88 @@ class ServerInterface (object):
Determine if the pseudo-terminal on the given channel can be resized.
This only makes sense if a pty was previously allocated on it.
- The default implementation always returns C{False}.
+ The default implementation always returns ``False``.
- @param channel: the L{Channel} the pty request arrived on.
- @type channel: L{Channel}
- @param width: width of screen in characters.
- @type width: int
- @param height: height of screen in characters.
- @type height: int
- @param pixelwidth: width of screen in pixels, if known (may be C{0} if
- unknown).
- @type pixelwidth: int
- @param pixelheight: height of screen in pixels, if known (may be C{0}
- if unknown).
- @type pixelheight: int
- @return: C{True} if the terminal was resized; C{False} if not.
- @rtype: bool
+ :param .Channel channel: the `.Channel` the pty request arrived on.
+ :param int width: width of screen in characters.
+ :param int height: height of screen in characters.
+ :param int pixelwidth:
+ width of screen in pixels, if known (may be ``0`` if unknown).
+ :param int pixelheight:
+ height of screen in pixels, if known (may be ``0`` if unknown).
+ :return: ``True`` if the terminal was resized; ``False`` if not.
"""
return False
def check_channel_x11_request(self, channel, single_connection, auth_protocol, auth_cookie, screen_number):
"""
Determine if the client will be provided with an X11 session. If this
- method returns C{True}, X11 applications should be routed through new
- SSH channels, using L{Transport.open_x11_channel}.
+ method returns ``True``, X11 applications should be routed through new
+ SSH channels, using `.Transport.open_x11_channel`.
- The default implementation always returns C{False}.
+ The default implementation always returns ``False``.
- @param channel: the L{Channel} the X11 request arrived on
- @type channel: L{Channel}
- @param single_connection: C{True} if only a single X11 channel should
- be opened
- @type single_connection: bool
- @param auth_protocol: the protocol used for X11 authentication
- @type auth_protocol: str
- @param auth_cookie: the cookie used to authenticate to X11
- @type auth_cookie: str
- @param screen_number: the number of the X11 screen to connect to
- @type screen_number: int
- @return: C{True} if the X11 session was opened; C{False} if not
- @rtype: bool
+ :param .Channel channel: the `.Channel` the X11 request arrived on
+ :param bool single_connection:
+ ``True`` if only a single X11 channel should be opened, else
+ ``False``.
+ :param str auth_protocol: the protocol used for X11 authentication
+ :param str auth_cookie: the cookie used to authenticate to X11
+ :param int screen_number: the number of the X11 screen to connect to
+ :return: ``True`` if the X11 session was opened; ``False`` if not
"""
return False
def check_channel_forward_agent_request(self, channel):
"""
Determine if the client will be provided with an forward agent session.
- If this method returns C{True}, the server will allow SSH Agent
+ If this method returns ``True``, the server will allow SSH Agent
forwarding.
- The default implementation always returns C{False}.
+ The default implementation always returns ``False``.
- @param channel: the L{Channel} the request arrived on
- @type channel: L{Channel}
- @return: C{True} if the AgentForward was loaded; C{False} if not
- @rtype: bool
+ :param .Channel channel: the `.Channel` the request arrived on
+ :return: ``True`` if the AgentForward was loaded; ``False`` if not
"""
return False
def check_channel_direct_tcpip_request(self, chanid, origin, destination):
"""
Determine if a local port forwarding channel will be granted, and
- return C{OPEN_SUCCEEDED} or an error code. This method is
+ return ``OPEN_SUCCEEDED`` or an error code. This method is
called in server mode when the client requests a channel, after
authentication is complete.
- The C{chanid} parameter is a small number that uniquely identifies the
- channel within a L{Transport}. A L{Channel} object is not created
- unless this method returns C{OPEN_SUCCEEDED} -- once a
- L{Channel} object is created, you can call L{Channel.get_id} to
+ The ``chanid`` parameter is a small number that uniquely identifies the
+ channel within a `.Transport`. A `.Channel` object is not created
+ unless this method returns ``OPEN_SUCCEEDED`` -- once a
+ `.Channel` object is created, you can call `.Channel.get_id` to
retrieve the channel ID.
The origin and destination parameters are (ip_address, port) tuples
that correspond to both ends of the TCP connection in the forwarding
tunnel.
- The return value should either be C{OPEN_SUCCEEDED} (or
- C{0}) to allow the channel request, or one of the following error
+ The return value should either be ``OPEN_SUCCEEDED`` (or
+ ``0``) to allow the channel request, or one of the following error
codes to reject it:
- - C{OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED}
- - C{OPEN_FAILED_CONNECT_FAILED}
- - C{OPEN_FAILED_UNKNOWN_CHANNEL_TYPE}
- - C{OPEN_FAILED_RESOURCE_SHORTAGE}
+
+ - ``OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED``
+ - ``OPEN_FAILED_CONNECT_FAILED``
+ - ``OPEN_FAILED_UNKNOWN_CHANNEL_TYPE``
+ - ``OPEN_FAILED_RESOURCE_SHORTAGE``
The default implementation always returns
- C{OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED}.
-
- @param chanid: ID of the channel
- @type chanid: int
- @param origin: 2-tuple containing the IP address and port of the
- originator (client side)
- @type origin: tuple
- @param destination: 2-tuple containing the IP address and port of the
- destination (server side)
- @type destination: tuple
- @return: a success or failure code (listed above)
- @rtype: int
+ ``OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED``.
+
+ :param int chanid: ID of the channel
+ :param tuple origin:
+ 2-tuple containing the IP address and port of the originator
+ (client side)
+ :param tuple destination:
+ 2-tuple containing the IP address and port of the destination
+ (server side)
+ :return: an `int` success or failure code (listed above)
"""
return OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
@@ -572,37 +492,71 @@ class ServerInterface (object):
return False
+class InteractiveQuery (object):
+ """
+ A query (set of prompts) for a user during interactive authentication.
+ """
+
+ def __init__(self, name='', instructions='', *prompts):
+ """
+ Create a new interactive query to send to the client. The name and
+ instructions are optional, but are generally displayed to the end
+ user. A list of prompts may be included, or they may be added via
+ the `add_prompt` method.
+
+ :param str name: name of this query
+ :param str instructions:
+ user instructions (usually short) about this query
+ :param str prompts: one or more authentication prompts
+ """
+ self.name = name
+ self.instructions = instructions
+ self.prompts = []
+ for x in prompts:
+ if isinstance(x, string_types):
+ self.add_prompt(x)
+ else:
+ self.add_prompt(x[0], x[1])
+
+ def add_prompt(self, prompt, echo=True):
+ """
+ Add a prompt to this query. The prompt should be a (reasonably short)
+ string. Multiple prompts can be added to the same query.
+
+ :param str prompt: the user prompt
+ :param bool echo:
+ ``True`` (default) if the user's response should be echoed;
+ ``False`` if not (for a password or similar)
+ """
+ self.prompts.append((prompt, echo))
+
+
class SubsystemHandler (threading.Thread):
"""
Handler for a subsytem in server mode. If you create a subclass of this
- class and pass it to
- L{Transport.set_subsystem_handler},
- an object of this
+ class and pass it to `.Transport.set_subsystem_handler`, an object of this
class will be created for each request for this subsystem. Each new object
- will be executed within its own new thread by calling L{start_subsystem}.
+ will be executed within its own new thread by calling `start_subsystem`.
When that method completes, the channel is closed.
- For example, if you made a subclass C{MP3Handler} and registered it as the
- handler for subsystem C{"mp3"}, then whenever a client has successfully
- authenticated and requests subsytem C{"mp3"}, an object of class
- C{MP3Handler} will be created, and L{start_subsystem} will be called on
+ For example, if you made a subclass ``MP3Handler`` and registered it as the
+ handler for subsystem ``"mp3"``, then whenever a client has successfully
+ authenticated and requests subsytem ``"mp3"``, an object of class
+ ``MP3Handler`` will be created, and `start_subsystem` will be called on
it from a new thread.
"""
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 `.ServerInterface`
to start up a new handler when a channel requests this subsystem. You
don't need to override this method, but if you do, be sure to pass the
- C{channel} and C{name} parameters through to the original C{__init__}
+ ``channel`` and ``name`` parameters through to the original ``__init__``
method here.
- @param channel: the channel associated with this subsystem request.
- @type channel: L{Channel}
- @param name: name of the requested subsystem.
- @type name: str
- @param server: the server object for the session that started this
- subsystem
- @type server: L{ServerInterface}
+ :param .Channel channel: the channel associated with this subsystem request.
+ :param str name: name of the requested subsystem.
+ :param .ServerInterface server:
+ the server object for the session that started this subsystem
"""
threading.Thread.__init__(self, target=self._run)
self.__channel = channel
@@ -612,10 +566,8 @@ class SubsystemHandler (threading.Thread):
def get_server(self):
"""
- Return the L{ServerInterface} object associated with this channel and
+ Return the `.ServerInterface` object associated with this channel and
subsystem.
-
- @rtype: L{ServerInterface}
"""
return self.__server
@@ -623,7 +575,7 @@ class SubsystemHandler (threading.Thread):
try:
self.__transport._log(DEBUG, 'Starting handler for subsystem %s' % self.__name)
self.start_subsystem(self.__name, self.__transport, self.__channel)
- except Exception, e:
+ except Exception as e:
self.__transport._log(ERROR, 'Exception in subsystem handler for "%s": %s' %
(self.__name, str(e)))
self.__transport._log(ERROR, util.tb_strings())
@@ -640,22 +592,20 @@ class SubsystemHandler (threading.Thread):
subsystem is finished, this method will return. After this method
returns, the channel is closed.
- The combination of C{transport} and C{channel} are unique; this handler
- corresponds to exactly one L{Channel} on one L{Transport}.
+ The combination of ``transport`` and ``channel`` are unique; this handler
+ corresponds to exactly one `.Channel` on one `.Transport`.
- @note: It is the responsibility of this method to exit if the
- underlying L{Transport} is closed. This can be done by checking
- L{Transport.is_active} or noticing an EOF
- on the L{Channel}. If this method loops forever without checking
- for this case, your python interpreter may refuse to exit because
- this thread will still be running.
+ .. note::
+ It is the responsibility of this method to exit if the underlying
+ `.Transport` is closed. This can be done by checking
+ `.Transport.is_active` or noticing an EOF on the `.Channel`. If
+ this method loops forever without checking for this case, your
+ Python interpreter may refuse to exit because this thread will
+ still be running.
- @param name: name of the requested subsystem.
- @type name: str
- @param transport: the server-mode L{Transport}.
- @type transport: L{Transport}
- @param channel: the channel associated with this subsystem request.
- @type channel: L{Channel}
+ :param str name: name of the requested subsystem.
+ :param .Transport transport: the server-mode `.Transport`.
+ :param .Channel channel: the channel associated with this subsystem request.
"""
pass
@@ -664,6 +614,6 @@ class SubsystemHandler (threading.Thread):
Perform any cleanup at the end of a subsystem. The default
implementation just closes the channel.
- @since: 1.1
+ .. versionadded:: 1.1
"""
self.__channel.close()