Coverage for /pythoncovmergedfiles/medio/medio/src/paramiko/paramiko/server.py: 39%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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.
19"""
20`.ServerInterface` is an interface to override for server support.
21"""
23import threading
25from paramiko import util
26from paramiko.common import (
27 AUTH_FAILED,
28 DEBUG,
29 ERROR,
30 OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED,
31)
34class ServerInterface:
35 """
36 This class defines an interface for controlling the behavior of Paramiko
37 in server mode.
39 Methods on this class are called from Paramiko's primary thread, so you
40 shouldn't do too much work in them. (Certainly nothing that blocks or
41 sleeps.)
42 """
44 def check_channel_request(self, kind, chanid):
45 """
46 Determine if a channel request of a given type will be granted, and
47 return ``OPEN_SUCCEEDED`` or an error code. This method is
48 called in server mode when the client requests a channel, after
49 authentication is complete.
51 If you allow channel requests (and an ssh server that didn't would be
52 useless), you should also override some of the channel request methods
53 below, which are used to determine which services will be allowed on
54 a given channel:
56 - `check_channel_pty_request`
57 - `check_channel_shell_request`
58 - `check_channel_subsystem_request`
59 - `check_channel_window_change_request`
60 - `check_channel_x11_request`
61 - `check_channel_forward_agent_request`
63 The ``chanid`` parameter is a small number that uniquely identifies the
64 channel within a `.Transport`. A `.Channel` object is not created
65 unless this method returns ``OPEN_SUCCEEDED`` -- once a
66 `.Channel` object is created, you can call `.Channel.get_id` to
67 retrieve the channel ID.
69 The return value should either be ``OPEN_SUCCEEDED`` (or
70 ``0``) to allow the channel request, or one of the following error
71 codes to reject it:
73 - ``OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED``
74 - ``OPEN_FAILED_CONNECT_FAILED``
75 - ``OPEN_FAILED_UNKNOWN_CHANNEL_TYPE``
76 - ``OPEN_FAILED_RESOURCE_SHORTAGE``
78 The default implementation always returns
79 ``OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED``.
81 :param str kind:
82 the kind of channel the client would like to open (usually
83 ``"session"``).
84 :param int chanid: ID of the channel
85 :return: an `int` success or failure code (listed above)
86 """
87 return OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
89 def get_allowed_auths(self, username):
90 """
91 Return a list of authentication methods supported by the server.
92 This list is sent to clients attempting to authenticate, to inform them
93 of authentication methods that might be successful.
95 The "list" is actually a string of comma-separated names of types of
96 authentication. Possible values are ``"password"``, ``"publickey"``,
97 and ``"none"``.
99 The default implementation always returns ``"password"``.
101 :param str username: the username requesting authentication.
102 :return: a comma-separated `str` of authentication types
103 """
104 return "password"
106 def check_auth_none(self, username):
107 """
108 Determine if a client may open channels with no (further)
109 authentication.
111 Return ``AUTH_FAILED`` if the client must authenticate, or
112 ``AUTH_SUCCESSFUL`` if it's okay for the client to not
113 authenticate.
115 The default implementation always returns ``AUTH_FAILED``.
117 :param str username: the username of the client.
118 :return:
119 ``AUTH_FAILED`` if the authentication fails; ``AUTH_SUCCESSFUL`` if
120 it succeeds.
121 :rtype: int
122 """
123 return AUTH_FAILED
125 def check_auth_password(self, username, password):
126 """
127 Determine if a given username and password supplied by the client is
128 acceptable for use in authentication.
130 Return ``AUTH_FAILED`` if the password is not accepted,
131 ``AUTH_SUCCESSFUL`` if the password is accepted and completes
132 the authentication, or ``AUTH_PARTIALLY_SUCCESSFUL`` if your
133 authentication is stateful, and this key is accepted for
134 authentication, but more authentication is required. (In this latter
135 case, `get_allowed_auths` will be called to report to the client what
136 options it has for continuing the authentication.)
138 The default implementation always returns ``AUTH_FAILED``.
140 :param str username: the username of the authenticating client.
141 :param str password: the password given by the client.
142 :return:
143 ``AUTH_FAILED`` if the authentication fails; ``AUTH_SUCCESSFUL`` if
144 it succeeds; ``AUTH_PARTIALLY_SUCCESSFUL`` if the password auth is
145 successful, but authentication must continue.
146 :rtype: int
147 """
148 return AUTH_FAILED
150 def check_auth_publickey(self, username, key):
151 """
152 Determine if a given key supplied by the client is acceptable for use
153 in authentication. You should override this method in server mode to
154 check the username and key and decide if you would accept a signature
155 made using this key.
157 Return ``AUTH_FAILED`` if the key is not accepted,
158 ``AUTH_SUCCESSFUL`` if the key is accepted and completes the
159 authentication, or ``AUTH_PARTIALLY_SUCCESSFUL`` if your
160 authentication is stateful, and this password is accepted for
161 authentication, but more authentication is required. (In this latter
162 case, `get_allowed_auths` will be called to report to the client what
163 options it has for continuing the authentication.)
165 Note that you don't have to actually verify any key signtature here.
166 If you're willing to accept the key, Paramiko will do the work of
167 verifying the client's signature.
169 The default implementation always returns ``AUTH_FAILED``.
171 :param str username: the username of the authenticating client
172 :param .PKey key: the key object provided by the client
173 :return:
174 ``AUTH_FAILED`` if the client can't authenticate with this key;
175 ``AUTH_SUCCESSFUL`` if it can; ``AUTH_PARTIALLY_SUCCESSFUL`` if it
176 can authenticate with this key but must continue with
177 authentication
178 :rtype: int
179 """
180 return AUTH_FAILED
182 def check_auth_interactive(self, username, submethods):
183 """
184 Begin an interactive authentication challenge, if supported. You
185 should override this method in server mode if you want to support the
186 ``"keyboard-interactive"`` auth type, which requires you to send a
187 series of questions for the client to answer.
189 Return ``AUTH_FAILED`` if this auth method isn't supported. Otherwise,
190 you should return an `.InteractiveQuery` object containing the prompts
191 and instructions for the user. The response will be sent via a call
192 to `check_auth_interactive_response`.
194 The default implementation always returns ``AUTH_FAILED``.
196 :param str username: the username of the authenticating client
197 :param str submethods:
198 a comma-separated list of methods preferred by the client (usually
199 empty)
200 :return:
201 ``AUTH_FAILED`` if this auth method isn't supported; otherwise an
202 object containing queries for the user
203 :rtype: int or `.InteractiveQuery`
204 """
205 return AUTH_FAILED
207 def check_auth_interactive_response(self, responses):
208 """
209 Continue or finish an interactive authentication challenge, if
210 supported. You should override this method in server mode if you want
211 to support the ``"keyboard-interactive"`` auth type.
213 Return ``AUTH_FAILED`` if the responses are not accepted,
214 ``AUTH_SUCCESSFUL`` if the responses are accepted and complete
215 the authentication, or ``AUTH_PARTIALLY_SUCCESSFUL`` if your
216 authentication is stateful, and this set of responses is accepted for
217 authentication, but more authentication is required. (In this latter
218 case, `get_allowed_auths` will be called to report to the client what
219 options it has for continuing the authentication.)
221 If you wish to continue interactive authentication with more questions,
222 you may return an `.InteractiveQuery` object, which should cause the
223 client to respond with more answers, calling this method again. This
224 cycle can continue indefinitely.
226 The default implementation always returns ``AUTH_FAILED``.
228 :param responses: list of `str` responses from the client
229 :return:
230 ``AUTH_FAILED`` if the authentication fails; ``AUTH_SUCCESSFUL`` if
231 it succeeds; ``AUTH_PARTIALLY_SUCCESSFUL`` if the interactive auth
232 is successful, but authentication must continue; otherwise an
233 object containing queries for the user
234 :rtype: int or `.InteractiveQuery`
235 """
236 return AUTH_FAILED
238 def check_port_forward_request(self, address, port):
239 """
240 Handle a request for port forwarding. The client is asking that
241 connections to the given address and port be forwarded back across
242 this ssh connection. An address of ``"0.0.0.0"`` indicates a global
243 address (any address associated with this server) and a port of ``0``
244 indicates that no specific port is requested (usually the OS will pick
245 a port).
247 The default implementation always returns ``False``, rejecting the
248 port forwarding request. If the request is accepted, you should return
249 the port opened for listening.
251 :param str address: the requested address
252 :param int port: the requested port
253 :return:
254 the port number (`int`) that was opened for listening, or ``False``
255 to reject
256 """
257 return False
259 def cancel_port_forward_request(self, address, port):
260 """
261 The client would like to cancel a previous port-forwarding request.
262 If the given address and port is being forwarded across this ssh
263 connection, the port should be closed.
265 :param str address: the forwarded address
266 :param int port: the forwarded port
267 """
268 pass
270 def check_global_request(self, kind, msg):
271 """
272 Handle a global request of the given ``kind``. This method is called
273 in server mode and client mode, whenever the remote host makes a global
274 request. If there are any arguments to the request, they will be in
275 ``msg``.
277 There aren't any useful global requests defined, aside from port
278 forwarding, so usually this type of request is an extension to the
279 protocol.
281 If the request was successful and you would like to return contextual
282 data to the remote host, return a tuple. Items in the tuple will be
283 sent back with the successful result. (Note that the items in the
284 tuple can only be strings, ints, or bools.)
286 The default implementation always returns ``False``, indicating that it
287 does not support any global requests.
289 .. note:: Port forwarding requests are handled separately, in
290 `check_port_forward_request`.
292 :param str kind: the kind of global request being made.
293 :param .Message msg: any extra arguments to the request.
294 :return:
295 ``True`` or a `tuple` of data if the request was granted; ``False``
296 otherwise.
297 """
298 return False
300 # ...Channel requests...
302 def check_channel_pty_request(
303 self, channel, term, width, height, pixelwidth, pixelheight, modes
304 ):
305 """
306 Determine if a pseudo-terminal of the given dimensions (usually
307 requested for shell access) can be provided on the given channel.
309 The default implementation always returns ``False``.
311 :param .Channel channel: the `.Channel` the pty request arrived on.
312 :param str term: type of terminal requested (for example, ``"vt100"``).
313 :param int width: width of screen in characters.
314 :param int height: height of screen in characters.
315 :param int pixelwidth:
316 width of screen in pixels, if known (may be ``0`` if unknown).
317 :param int pixelheight:
318 height of screen in pixels, if known (may be ``0`` if unknown).
319 :return:
320 ``True`` if the pseudo-terminal has been allocated; ``False``
321 otherwise.
322 """
323 return False
325 def check_channel_shell_request(self, channel):
326 """
327 Determine if a shell will be provided to the client on the given
328 channel. If this method returns ``True``, the channel should be
329 connected to the stdin/stdout of a shell (or something that acts like
330 a shell).
332 The default implementation always returns ``False``.
334 :param .Channel channel: the `.Channel` the request arrived on.
335 :return:
336 ``True`` if this channel is now hooked up to a shell; ``False`` if
337 a shell can't or won't be provided.
338 """
339 return False
341 def check_channel_exec_request(self, channel, command):
342 """
343 Determine if a shell command will be executed for the client. If this
344 method returns ``True``, the channel should be connected to the stdin,
345 stdout, and stderr of the shell command.
347 The default implementation always returns ``False``.
349 :param .Channel channel: the `.Channel` the request arrived on.
350 :param str command: the command to execute.
351 :return:
352 ``True`` if this channel is now hooked up to the stdin, stdout, and
353 stderr of the executing command; ``False`` if the command will not
354 be executed.
356 .. versionadded:: 1.1
357 """
358 return False
360 def check_channel_subsystem_request(self, channel, name):
361 """
362 Determine if a requested subsystem will be provided to the client on
363 the given channel. If this method returns ``True``, all future I/O
364 through this channel will be assumed to be connected to the requested
365 subsystem. An example of a subsystem is ``sftp``.
367 The default implementation checks for a subsystem handler assigned via
368 `.Transport.set_subsystem_handler`.
369 If one has been set, the handler is invoked and this method returns
370 ``True``. Otherwise it returns ``False``.
372 .. note:: Because the default implementation uses the `.Transport` to
373 identify valid subsystems, you probably won't need to override this
374 method.
376 :param .Channel channel: the `.Channel` the pty request arrived on.
377 :param str name: name of the requested subsystem.
378 :return:
379 ``True`` if this channel is now hooked up to the requested
380 subsystem; ``False`` if that subsystem can't or won't be provided.
381 """
382 transport = channel.get_transport()
383 handler_class, args, kwargs = transport._get_subsystem_handler(name)
384 if handler_class is None:
385 return False
386 handler = handler_class(channel, name, self, *args, **kwargs)
387 handler.start()
388 return True
390 def check_channel_window_change_request(
391 self, channel, width, height, pixelwidth, pixelheight
392 ):
393 """
394 Determine if the pseudo-terminal on the given channel can be resized.
395 This only makes sense if a pty was previously allocated on it.
397 The default implementation always returns ``False``.
399 :param .Channel channel: the `.Channel` the pty request arrived on.
400 :param int width: width of screen in characters.
401 :param int height: height of screen in characters.
402 :param int pixelwidth:
403 width of screen in pixels, if known (may be ``0`` if unknown).
404 :param int pixelheight:
405 height of screen in pixels, if known (may be ``0`` if unknown).
406 :return: ``True`` if the terminal was resized; ``False`` if not.
407 """
408 return False
410 def check_channel_x11_request(
411 self,
412 channel,
413 single_connection,
414 auth_protocol,
415 auth_cookie,
416 screen_number,
417 ):
418 """
419 Determine if the client will be provided with an X11 session. If this
420 method returns ``True``, X11 applications should be routed through new
421 SSH channels, using `.Transport.open_x11_channel`.
423 The default implementation always returns ``False``.
425 :param .Channel channel: the `.Channel` the X11 request arrived on
426 :param bool single_connection:
427 ``True`` if only a single X11 channel should be opened, else
428 ``False``.
429 :param str auth_protocol: the protocol used for X11 authentication
430 :param str auth_cookie: the cookie used to authenticate to X11
431 :param int screen_number: the number of the X11 screen to connect to
432 :return: ``True`` if the X11 session was opened; ``False`` if not
433 """
434 return False
436 def check_channel_forward_agent_request(self, channel):
437 """
438 Determine if the client will be provided with an forward agent session.
439 If this method returns ``True``, the server will allow SSH Agent
440 forwarding.
442 The default implementation always returns ``False``.
444 :param .Channel channel: the `.Channel` the request arrived on
445 :return: ``True`` if the AgentForward was loaded; ``False`` if not
447 If ``True`` is returned, the server should create an
448 :class:`AgentServerProxy` to access the agent.
449 """
450 return False
452 def check_channel_direct_tcpip_request(self, chanid, origin, destination):
453 """
454 Determine if a local port forwarding channel will be granted, and
455 return ``OPEN_SUCCEEDED`` or an error code. This method is
456 called in server mode when the client requests a channel, after
457 authentication is complete.
459 The ``chanid`` parameter is a small number that uniquely identifies the
460 channel within a `.Transport`. A `.Channel` object is not created
461 unless this method returns ``OPEN_SUCCEEDED`` -- once a
462 `.Channel` object is created, you can call `.Channel.get_id` to
463 retrieve the channel ID.
465 The origin and destination parameters are (ip_address, port) tuples
466 that correspond to both ends of the TCP connection in the forwarding
467 tunnel.
469 The return value should either be ``OPEN_SUCCEEDED`` (or
470 ``0``) to allow the channel request, or one of the following error
471 codes to reject it:
473 - ``OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED``
474 - ``OPEN_FAILED_CONNECT_FAILED``
475 - ``OPEN_FAILED_UNKNOWN_CHANNEL_TYPE``
476 - ``OPEN_FAILED_RESOURCE_SHORTAGE``
478 The default implementation always returns
479 ``OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED``.
481 :param int chanid: ID of the channel
482 :param tuple origin:
483 2-tuple containing the IP address and port of the originator
484 (client side)
485 :param tuple destination:
486 2-tuple containing the IP address and port of the destination
487 (server side)
488 :return: an `int` success or failure code (listed above)
489 """
490 return OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
492 def check_channel_env_request(self, channel, name, value):
493 """
494 Check whether a given environment variable can be specified for the
495 given channel. This method should return ``True`` if the server
496 is willing to set the specified environment variable. Note that
497 some environment variables (e.g., PATH) can be exceedingly
498 dangerous, so blindly allowing the client to set the environment
499 is almost certainly not a good idea.
501 The default implementation always returns ``False``.
503 :param channel: the `.Channel` the env request arrived on
504 :param str name: name
505 :param str value: Channel value
506 :returns: A boolean
507 """
508 return False
510 def get_banner(self):
511 """
512 A pre-login banner to display to the user. The message may span
513 multiple lines separated by crlf pairs. The language should be in
514 rfc3066 style, for example: en-US
516 The default implementation always returns ``(None, None)``.
518 :returns: A tuple containing the banner and language code.
520 .. versionadded:: 2.3
521 """
522 return (None, None)
525class InteractiveQuery:
526 """
527 A query (set of prompts) for a user during interactive authentication.
528 """
530 def __init__(self, name="", instructions="", *prompts):
531 """
532 Create a new interactive query to send to the client. The name and
533 instructions are optional, but are generally displayed to the end
534 user. A list of prompts may be included, or they may be added via
535 the `add_prompt` method.
537 :param str name: name of this query
538 :param str instructions:
539 user instructions (usually short) about this query
540 :param str prompts: one or more authentication prompts
541 """
542 self.name = name
543 self.instructions = instructions
544 self.prompts = []
545 for x in prompts:
546 if isinstance(x, str):
547 self.add_prompt(x)
548 else:
549 self.add_prompt(x[0], x[1])
551 def add_prompt(self, prompt, echo=True):
552 """
553 Add a prompt to this query. The prompt should be a (reasonably short)
554 string. Multiple prompts can be added to the same query.
556 :param str prompt: the user prompt
557 :param bool echo:
558 ``True`` (default) if the user's response should be echoed;
559 ``False`` if not (for a password or similar)
560 """
561 self.prompts.append((prompt, echo))
564class SubsystemHandler(threading.Thread):
565 """
566 Handler for a subsystem in server mode. If you create a subclass of this
567 class and pass it to `.Transport.set_subsystem_handler`, an object of this
568 class will be created for each request for this subsystem. Each new object
569 will be executed within its own new thread by calling `start_subsystem`.
570 When that method completes, the channel is closed.
572 For example, if you made a subclass ``MP3Handler`` and registered it as the
573 handler for subsystem ``"mp3"``, then whenever a client has successfully
574 authenticated and requests subsystem ``"mp3"``, an object of class
575 ``MP3Handler`` will be created, and `start_subsystem` will be called on
576 it from a new thread.
577 """
579 def __init__(self, channel, name, server):
580 """
581 Create a new handler for a channel. This is used by `.ServerInterface`
582 to start up a new handler when a channel requests this subsystem. You
583 don't need to override this method, but if you do, be sure to pass the
584 ``channel`` and ``name`` parameters through to the original
585 ``__init__`` method here.
587 :param .Channel channel: the channel associated with this
588 subsystem request.
589 :param str name: name of the requested subsystem.
590 :param .ServerInterface server:
591 the server object for the session that started this subsystem
592 """
593 threading.Thread.__init__(self, target=self._run)
594 self.__channel = channel
595 self.__transport = channel.get_transport()
596 self.__name = name
597 self.__server = server
599 def get_server(self):
600 """
601 Return the `.ServerInterface` object associated with this channel and
602 subsystem.
603 """
604 return self.__server
606 def _run(self):
607 try:
608 self.__transport._log(
609 DEBUG, "Starting handler for subsystem {}".format(self.__name)
610 )
611 self.start_subsystem(self.__name, self.__transport, self.__channel)
612 except Exception as e:
613 self.__transport._log(
614 ERROR,
615 'Exception in subsystem handler for "{}": {}'.format(
616 self.__name, e
617 ),
618 )
619 self.__transport._log(ERROR, util.tb_strings())
620 try:
621 self.finish_subsystem()
622 except:
623 pass
625 def start_subsystem(self, name, transport, channel):
626 """
627 Process an ssh subsystem in server mode. This method is called on a
628 new object (and in a new thread) for each subsystem request. It is
629 assumed that all subsystem logic will take place here, and when the
630 subsystem is finished, this method will return. After this method
631 returns, the channel is closed.
633 The combination of ``transport`` and ``channel`` are unique; this
634 handler corresponds to exactly one `.Channel` on one `.Transport`.
636 .. note::
637 It is the responsibility of this method to exit if the underlying
638 `.Transport` is closed. This can be done by checking
639 `.Transport.is_active` or noticing an EOF on the `.Channel`. If
640 this method loops forever without checking for this case, your
641 Python interpreter may refuse to exit because this thread will
642 still be running.
644 :param str name: name of the requested subsystem.
645 :param .Transport transport: the server-mode `.Transport`.
646 :param .Channel channel: the channel associated with this subsystem
647 request.
648 """
649 pass
651 def finish_subsystem(self):
652 """
653 Perform any cleanup at the end of a subsystem. The default
654 implementation just closes the channel.
656 .. versionadded:: 1.1
657 """
658 self.__channel.close()