1# Copyright (c) 2013-2020 by Ron Frederick <ronf@timeheart.net> and others.
2#
3# This program and the accompanying materials are made available under
4# the terms of the Eclipse Public License v2.0 which accompanies this
5# distribution and is available at:
6#
7#     http://www.eclipse.org/legal/epl-2.0/
8#
9# This program may also be made available under the following secondary
10# licenses when the conditions for such availability set forth in the
11# Eclipse Public License v2.0 are satisfied:
12#
13#    GNU General Public License, Version 2.0, or any later versions of
14#    that license
15#
16# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
17#
18# Contributors:
19#     Ron Frederick - initial implementation, API, and documentation
20
21"""SSH server protocol handler"""
22
23
24class SSHServer:
25    """SSH server protocol handler
26
27       Applications may subclass this when implementing an SSH server to
28       provide custom authentication and request handlers.
29
30       The method :meth:`begin_auth` can be overridden decide whether
31       or not authentication is required, and additional callbacks are
32       provided for each form of authentication in cases where authentication
33       information is not provided in the call to :func:`create_server`.
34
35       In addition, the methods :meth:`session_requested`,
36       :meth:`connection_requested`, :meth:`server_requested`,
37       :meth:`unix_connection_requested`, or :meth:`unix_server_requested`
38       can be overridden to handle requests to open sessions or direct
39       connections or set up listeners for forwarded connections.
40
41       .. note:: The authentication callbacks described here can be
42                 defined as coroutines. However, they may be cancelled if
43                 they are running when the SSH connection is closed by
44                 the client. If they attempt to catch the CancelledError
45                 exception to perform cleanup, they should make sure to
46                 re-raise it to allow AsyncSSH to finish its own cleanup.
47
48    """
49
50    # pylint: disable=no-self-use,unused-argument
51
52    def connection_made(self, conn):
53        """Called when a connection is made
54
55           This method is called when a new TCP connection is accepted. The
56           `conn` parameter should be stored if needed for later use.
57
58           :param conn:
59               The connection which was successfully opened
60           :type conn: :class:`SSHServerConnection`
61
62        """
63
64    def connection_lost(self, exc):
65        """Called when a connection is lost or closed
66
67           This method is called when a connection is closed. If the
68           connection is shut down cleanly, *exc* will be `None`.
69           Otherwise, it will be an exception explaining the reason for
70           the disconnect.
71
72        """
73
74    def debug_msg_received(self, msg, lang, always_display):
75        """A debug message was received on this connection
76
77           This method is called when the other end of the connection sends
78           a debug message. Applications should implement this method if
79           they wish to process these debug messages.
80
81           :param msg:
82               The debug message sent
83           :param lang:
84               The language the message is in
85           :param always_display:
86               Whether or not to display the message
87           :type msg: `str`
88           :type lang: `str`
89           :type always_display: `bool`
90
91        """
92
93    def begin_auth(self, username):
94        """Authentication has been requested by the client
95
96           This method will be called when authentication is attempted for
97           the specified user. Applications should use this method to
98           prepare whatever state they need to complete the authentication,
99           such as loading in the set of authorized keys for that user. If
100           no authentication is required for this user, this method should
101           return `False` to cause the authentication to immediately
102           succeed. Otherwise, it should return `True` to indicate that
103           authentication should proceed.
104
105           If blocking operations need to be performed to prepare the
106           state needed to complete the authentication, this method may
107           be defined as a coroutine.
108
109           :param username:
110               The name of the user being authenticated
111           :type username: `str`
112
113           :returns: A `bool` indicating whether authentication is required
114
115        """
116
117        return True # pragma: no cover
118
119    def auth_completed(self):
120        """Authentication was completed successfully
121
122           This method is called when authentication has completed
123           succesfully. Applications may use this method to perform
124           processing based on the authenticated username or options in
125           the authorized keys list or certificate associated with the
126           user before any sessions are opened or forwarding requests
127           are handled.
128
129        """
130
131    def validate_gss_principal(self, username, user_principal,
132                               host_principal):
133        """Return whether a GSS principal is valid for this user
134
135           This method should return `True` if the specified user
136           principal is valid for the user being authenticated. It can
137           be overridden by applications wishing to perform their own
138           authentication.
139
140           If blocking operations need to be performed to determine the
141           validity of the principal, this method may be defined as a
142           coroutine.
143
144           By default, this method will return `True` only when the
145           name in the user principal exactly matches the username and
146           the domain of the user principal matches the domain of the
147           host principal.
148
149           :param username:
150               The user being authenticated
151           :param user_principal:
152               The user principal sent by the client
153           :param host_principal:
154               The host principal sent by the server
155           :type username: `str`
156           :type user_principal: `str`
157           :type host_principal: `str`
158
159           :returns: A `bool` indicating if the specified user principal
160                     is valid for the user being authenticated
161
162        """
163
164        host_domain = host_principal.rsplit('@')[-1]
165        return user_principal == username + '@' + host_domain
166
167    def host_based_auth_supported(self):
168        """Return whether or not host-based authentication is supported
169
170           This method should return `True` if client host-based
171           authentication is supported. Applications wishing to support
172           it must have this method return `True` and implement
173           :meth:`validate_host_public_key` and/or :meth:`validate_host_ca_key`
174           to return whether or not the key provided by the client is valid
175           for the client host being authenticated.
176
177           By default, it returns `False` indicating the client host
178           based authentication is not supported.
179
180           :returns: A `bool` indicating if host-based authentication is
181                     supported or not
182
183        """
184
185        return False # pragma: no cover
186
187    def validate_host_public_key(self, client_host, client_addr,
188                                 client_port, key):
189        """Return whether key is an authorized host key for this client host
190
191           Host key based client authentication can be supported by
192           passing authorized host keys in the `known_client_hosts`
193           argument of :func:`create_server`. However, for more flexibility
194           in matching on the allowed set of keys, this method can be
195           implemented by the application to do the matching itself. It
196           should return `True` if the specified key is a valid host key
197           for the client host being authenticated.
198
199           This method may be called multiple times with different keys
200           provided by the client. Applications should precompute as
201           much as possible in the :meth:`begin_auth` method so that
202           this function can quickly return whether the key provided is
203           in the list.
204
205           By default, this method returns `False` for all client host keys.
206
207               .. note:: This function only needs to report whether the
208                         public key provided is a valid key for this client
209                         host. If it is, AsyncSSH will verify that the
210                         client possesses the corresponding private key
211                         before allowing the authentication to succeed.
212
213           :param client_host:
214               The hostname of the client host
215           :param client_addr:
216               The IP address of the client host
217           :param client_port:
218               The port number on the client host
219           :param key:
220               The host public key sent by the client
221           :type client_host: `str`
222           :type client_addr: `str`
223           :type client_port: `int`
224           :type key: :class:`SSHKey` *public key*
225
226           :returns: A `bool` indicating if the specified key is a valid
227                     key for the client host being authenticated
228
229        """
230
231        return False # pragma: no cover
232
233    def validate_host_ca_key(self, client_host, client_addr,
234                             client_port, key):
235        """Return whether key is an authorized CA key for this client host
236
237           Certificate based client host authentication can be
238           supported by passing authorized host CA keys in the
239           `known_client_hosts` argument of :func:`create_server`.
240           However, for more flexibility in matching on the allowed
241           set of keys, this method can be implemented by the application
242           to do the matching itself. It should return `True` if the
243           specified key is a valid certificate authority key for the
244           client host being authenticated.
245
246           This method may be called multiple times with different keys
247           provided by the client. Applications should precompute as
248           much as possible in the :meth:`begin_auth` method so that
249           this function can quickly return whether the key provided is
250           in the list.
251
252           By default, this method returns `False` for all CA keys.
253
254               .. note:: This function only needs to report whether the
255                         public key provided is a valid CA key for this
256                         client host. If it is, AsyncSSH will verify that
257                         the certificate is valid, that the client host is
258                         one of the valid principals for the certificate,
259                         and that the client possesses the private key
260                         corresponding to the public key in the certificate
261                         before allowing the authentication to succeed.
262
263           :param client_host:
264               The hostname of the client host
265           :param client_addr:
266               The IP address of the client host
267           :param client_port:
268               The port number on the client host
269           :param key:
270               The public key which signed the certificate sent by the client
271           :type client_host: `str`
272           :type client_addr: `str`
273           :type client_port: `int`
274           :type key: :class:`SSHKey` *public key*
275
276           :returns: A `bool` indicating if the specified key is a valid
277                     CA key for the client host being authenticated
278
279        """
280
281        return False # pragma: no cover
282
283    def validate_host_based_user(self, username, client_host, client_username):
284        """Return whether remote host and user is authorized for this user
285
286           This method should return `True` if the specified client host
287           and user is valid for the user being authenticated. It can be
288           overridden by applications wishing to enforce restrictions on
289           which remote users are allowed to authenticate as particular
290           local users.
291
292           If blocking operations need to be performed to determine the
293           validity of the client host and user, this method may be defined
294           as a coroutine.
295
296           By default, this method will return `True` when the client
297           username matches the name of the user being authenticated.
298
299           :param username:
300               The user being authenticated
301           :param client_host:
302               The hostname of the client host making the request
303           :param client_username:
304               The username of the user on the client host
305           :type username: `str`
306           :type client_host: `str`
307           :type client_username: `str`
308
309           :returns: A `bool` indicating if the specified client host
310                     and user is valid for the user being authenticated
311
312        """
313
314        return username == client_username
315
316    def public_key_auth_supported(self):
317        """Return whether or not public key authentication is supported
318
319           This method should return `True` if client public key
320           authentication is supported. Applications wishing to support
321           it must have this method return `True` and implement
322           :meth:`validate_public_key` and/or :meth:`validate_ca_key`
323           to return whether or not the key provided by the client is
324           valid for the user being authenticated.
325
326           By default, it returns `False` indicating the client public
327           key authentication is not supported.
328
329           :returns: A `bool` indicating if public key authentication is
330                     supported or not
331
332        """
333
334        return False # pragma: no cover
335
336    def validate_public_key(self, username, key):
337        """Return whether key is an authorized client key for this user
338
339           Key based client authentication can be supported by
340           passing authorized keys in the `authorized_client_keys`
341           argument of :func:`create_server`, or by calling
342           :meth:`set_authorized_keys
343           <SSHServerConnection.set_authorized_keys>` on the server
344           connection from the :meth:`begin_auth` method. However, for
345           more flexibility in matching on the allowed set of keys, this
346           method can be implemented by the application to do the
347           matching itself. It should return `True` if the specified
348           key is a valid client key for the user being authenticated.
349
350           This method may be called multiple times with different keys
351           provided by the client. Applications should precompute as
352           much as possible in the :meth:`begin_auth` method so that
353           this function can quickly return whether the key provided is
354           in the list.
355
356           If blocking operations need to be performed to determine the
357           validity of the key, this method may be defined as a coroutine.
358
359           By default, this method returns `False` for all client keys.
360
361               .. note:: This function only needs to report whether the
362                         public key provided is a valid client key for this
363                         user. If it is, AsyncSSH will verify that the
364                         client possesses the corresponding private key
365                         before allowing the authentication to succeed.
366
367           :param username:
368               The user being authenticated
369           :param key:
370               The public key sent by the client
371           :type username: `str`
372           :type key: :class:`SSHKey` *public key*
373
374           :returns: A `bool` indicating if the specified key is a valid
375                     client key for the user being authenticated
376
377        """
378
379        return False # pragma: no cover
380
381    def validate_ca_key(self, username, key):
382        """Return whether key is an authorized CA key for this user
383
384           Certificate based client authentication can be supported by
385           passing authorized CA keys in the `authorized_client_keys`
386           argument of :func:`create_server`, or by calling
387           :meth:`set_authorized_keys
388           <SSHServerConnection.set_authorized_keys>` on the server
389           connection from the :meth:`begin_auth` method. However, for
390           more flexibility in matching on the allowed set of keys, this
391           method can be implemented by the application to do the
392           matching itself. It should return `True` if the specified
393           key is a valid certificate authority key for the user being
394           authenticated.
395
396           This method may be called multiple times with different keys
397           provided by the client. Applications should precompute as
398           much as possible in the :meth:`begin_auth` method so that
399           this function can quickly return whether the key provided is
400           in the list.
401
402           If blocking operations need to be performed to determine the
403           validity of the key, this method may be defined as a coroutine.
404
405           By default, this method returns `False` for all CA keys.
406
407               .. note:: This function only needs to report whether the
408                         public key provided is a valid CA key for this
409                         user. If it is, AsyncSSH will verify that the
410                         certificate is valid, that the user is one of
411                         the valid principals for the certificate, and
412                         that the client possesses the private key
413                         corresponding to the public key in the certificate
414                         before allowing the authentication to succeed.
415
416           :param username:
417               The user being authenticated
418           :param key:
419               The public key which signed the certificate sent by the client
420           :type username: `str`
421           :type key: :class:`SSHKey` *public key*
422
423           :returns: A `bool` indicating if the specified key is a valid
424                     CA key for the user being authenticated
425
426        """
427
428        return False # pragma: no cover
429
430    def password_auth_supported(self):
431        """Return whether or not password authentication is supported
432
433           This method should return `True` if password authentication
434           is supported. Applications wishing to support it must have
435           this method return `True` and implement :meth:`validate_password`
436           to return whether or not the password provided by the client
437           is valid for the user being authenticated.
438
439           By default, this method returns `False` indicating that
440           password authentication is not supported.
441
442           :returns: A `bool` indicating if password authentication is
443                     supported or not
444
445        """
446
447        return False # pragma: no cover
448
449    def validate_password(self, username, password):
450        """Return whether password is valid for this user
451
452           This method should return `True` if the specified password
453           is a valid password for the user being authenticated. It must
454           be overridden by applications wishing to support password
455           authentication.
456
457           If the password provided is valid but expired, this method
458           may raise :exc:`PasswordChangeRequired` to request that the
459           client provide a new password before authentication is
460           allowed to complete. In this case, the application must
461           override :meth:`change_password` to handle the password
462           change request.
463
464           This method may be called multiple times with different
465           passwords provided by the client. Applications may wish
466           to limit the number of attempts which are allowed. This
467           can be done by having :meth:`password_auth_supported` begin
468           returning `False` after the maximum number of attempts is
469           exceeded.
470
471           If blocking operations need to be performed to determine the
472           validity of the password, this method may be defined as a
473           coroutine.
474
475           By default, this method returns `False` for all passwords.
476
477           :param username:
478               The user being authenticated
479           :param password:
480               The password sent by the client
481           :type username: `str`
482           :type password: `str`
483
484           :returns: A `bool` indicating if the specified password is
485                     valid for the user being authenticated
486
487           :raises: :exc:`PasswordChangeRequired` if the password
488                    provided is expired and needs to be changed
489
490        """
491
492        return False # pragma: no cover
493
494    def change_password(self, username, old_password, new_password):
495        """Handle a request to change a user's password
496
497           This method is called when a user makes a request to
498           change their password. It should first validate that
499           the old password provided is correct and then attempt
500           to change the user's password to the new value.
501
502           If the old password provided is valid and the change to
503           the new password is successful, this method should
504           return `True`. If the old password is not valid or
505           password changes are not supported, it should return
506           `False`. It may also raise :exc:`PasswordChangeRequired`
507           to request that the client try again if the new password
508           is not acceptable for some reason.
509
510           If blocking operations need to be performed to determine the
511           validity of the old password or to change to the new password,
512           this method may be defined as a coroutine.
513
514           By default, this method returns `False`, rejecting all
515           password changes.
516
517           :param username:
518               The user whose password should be changed
519           :param old_password:
520               The user's current password
521           :param new_password:
522               The new password being requested
523           :type username: `str`
524           :type old_password: `str`
525           :type new_password: `str`
526
527           :returns: A `bool` indicating if the password change
528                     is successful or not
529
530           :raises: :exc:`PasswordChangeRequired` if the new password
531                    is not acceptable and the client should be asked
532                    to provide another
533
534        """
535
536        return False # pragma: no cover
537
538    def kbdint_auth_supported(self):
539        """Return whether or not keyboard-interactive authentication
540           is supported
541
542           This method should return `True` if keyboard-interactive
543           authentication is supported. Applications wishing to support
544           it must have this method return `True` and implement
545           :meth:`get_kbdint_challenge` and :meth:`validate_kbdint_response`
546           to generate the apporiate challenges and validate the responses
547           for the user being authenticated.
548
549           By default, this method returns `NotImplemented` tying
550           this authentication to password authentication. If the
551           application implements password authentication and this
552           method is not overridden, keyboard-interactive authentication
553           will be supported by prompting for a password and passing
554           that to the password authentication callbacks.
555
556           :returns: A `bool` indicating if keyboard-interactive
557                     authentication is supported or not
558
559        """
560
561        return NotImplemented # pragma: no cover
562
563    def get_kbdint_challenge(self, username, lang, submethods):
564        """Return a keyboard-interactive auth challenge
565
566           This method should return `True` if authentication should
567           succeed without any challenge, `False` if authentication
568           should fail without any challenge, or an auth challenge
569           consisting of a challenge name, instructions, a language tag,
570           and a list of tuples containing prompt strings and booleans
571           indicating whether input should be echoed when a value is
572           entered for that prompt.
573
574           If blocking operations need to be performed to determine the
575           challenge to issue, this method may be defined as a coroutine.
576
577           :param username:
578               The user being authenticated
579           :param lang:
580               The language requested by the client for the challenge
581           :param submethods:
582               A comma-separated list of the types of challenges the client
583               can support, or the empty string if the server should choose
584           :type username: `str`
585           :type lang: `str`
586           :type submethods: `str`
587
588           :returns: An authentication challenge as described above
589
590        """
591
592        return False # pragma: no cover
593
594    def validate_kbdint_response(self, username, responses):
595        """Return whether the keyboard-interactive response is valid
596           for this user
597
598           This method should validate the keyboard-interactive responses
599           provided and return `True` if authentication should succeed
600           with no further challenge, `False` if authentication should
601           fail, or an additional auth challenge in the same format returned
602           by :meth:`get_kbdint_challenge`. Any series of challenges can be
603           returned this way. To print a message in the middle of a sequence
604           of challenges without prompting for additional data, a challenge
605           can be returned with an empty list of prompts. After the client
606           acknowledges this message, this function will be called again
607           with an empty list of responses to continue the authentication.
608
609           If blocking operations need to be performed to determine the
610           validity of the response or the next challenge to issue, this
611           method may be defined as a coroutine.
612
613           :param username:
614               The user being authenticated
615           :param responses:
616               A list of responses to the last challenge
617           :type username: `str`
618           :type responses: `list` of `str`
619
620           :returns: `True`, `False`, or the next challenge
621
622        """
623
624        return False # pragma: no cover
625
626    def session_requested(self):
627        """Handle an incoming session request
628
629           This method is called when a session open request is received
630           from the client, indicating it wishes to open a channel to be
631           used for running a shell, executing a command, or connecting
632           to a subsystem. If the application wishes to accept the session,
633           it must override this method to return either an
634           :class:`SSHServerSession` object to use to process
635           the data received on the channel or a tuple consisting of an
636           :class:`SSHServerChannel` object created with
637           :meth:`create_server_channel
638           <SSHServerConnection.create_server_channel>` and an
639           :class:`SSHServerSession`, if the application
640           wishes to pass non-default arguments when creating the channel.
641
642           If blocking operations need to be performed before the session
643           can be created, a coroutine which returns an
644           :class:`SSHServerSession` object can be returned instead of
645           the session iself. This can be either returned directly or as
646           a part of a tuple with an :class:`SSHServerChannel` object.
647
648           To reject this request, this method should return `False`
649           to send back a "Session refused" response or raise a
650           :exc:`ChannelOpenError` exception with the reason for
651           the failure.
652
653           The details of what type of session the client wants to start
654           will be delivered to methods on the :class:`SSHServerSession`
655           object which is returned, along with other information such
656           as environment variables, terminal type, size, and modes.
657
658           By default, all session requests are rejected.
659
660           :returns: One of the following:
661
662                       * An :class:`SSHServerSession` object or a coroutine
663                         which returns an :class:`SSHServerSession`
664                       * A tuple consisting of an :class:`SSHServerChannel`
665                         and the above
666                       * A `callable` or coroutine handler function which
667                         takes AsyncSSH stream objects for stdin, stdout,
668                         and stderr as arguments
669                       * A tuple consisting of an :class:`SSHServerChannel`
670                         and the above
671                       * `False` to refuse the request
672
673           :raises: :exc:`ChannelOpenError` if the session shouldn't
674                    be accepted
675
676        """
677
678        return False # pragma: no cover
679
680    def connection_requested(self, dest_host, dest_port, orig_host, orig_port):
681        """Handle a direct TCP/IP connection request
682
683           This method is called when a direct TCP/IP connection
684           request is received by the server. Applications wishing
685           to accept such connections must override this method.
686
687           To allow standard port forwarding of data on the connection
688           to the requested destination host and port, this method
689           should return `True`.
690
691           To reject this request, this method should return `False`
692           to send back a "Connection refused" response or raise an
693           :exc:`ChannelOpenError` exception with the reason for
694           the failure.
695
696           If the application wishes to process the data on the
697           connection itself, this method should return either an
698           :class:`SSHTCPSession` object which can be used to process the
699           data received on the channel or a tuple consisting of of an
700           :class:`SSHTCPChannel` object created with
701           :meth:`create_tcp_channel()
702           <SSHServerConnection.create_tcp_channel>` and an
703           :class:`SSHTCPSession`, if the application wishes
704           to pass non-default arguments when creating the channel.
705
706           If blocking operations need to be performed before the session
707           can be created, a coroutine which returns an
708           :class:`SSHTCPSession` object can be returned instead of
709           the session iself. This can be either returned directly or as
710           a part of a tuple with an :class:`SSHTCPChannel` object.
711
712           By default, all connection requests are rejected.
713
714           :param dest_host:
715               The address the client wishes to connect to
716           :param dest_port:
717               The port the client wishes to connect to
718           :param orig_host:
719               The address the connection was originated from
720           :param orig_port:
721               The port the connection was originated from
722           :type dest_host: `str`
723           :type dest_port: `int`
724           :type orig_host: `str`
725           :type orig_port: `int`
726
727           :returns: One of the following:
728
729                     * An :class:`SSHTCPSession` object or a coroutine
730                       which returns an :class:`SSHTCPSession`
731                     * A tuple consisting of an :class:`SSHTCPChannel`
732                       and the above
733                     * A `callable` or coroutine handler function which
734                       takes AsyncSSH stream objects for reading from
735                       and writing to the connection
736                     * A tuple consisting of an :class:`SSHTCPChannel`
737                       and the above
738                     * `True` to request standard port forwarding
739                     * `False` to refuse the connection
740
741           :raises: :exc:`ChannelOpenError` if the connection shouldn't
742                    be accepted
743
744        """
745
746        return False # pragma: no cover
747
748    def server_requested(self, listen_host, listen_port):
749        """Handle a request to listen on a TCP/IP address and port
750
751           This method is called when a client makes a request to
752           listen on an address and port for incoming TCP connections.
753           The port to listen on may be `0` to request a dynamically
754           allocated port. Applications wishing to allow TCP/IP connection
755           forwarding must override this method.
756
757           To set up standard port forwarding of connections received
758           on this address and port, this method should return `True`.
759
760           If the application wishes to manage listening for incoming
761           connections itself, this method should return an
762           :class:`SSHListener` object that listens for new connections
763           and calls :meth:`create_connection
764           <SSHServerConnection.create_connection>` on each of them to
765           forward them back to the client or return `None` if the
766           listener can't be set up.
767
768           If blocking operations need to be performed to set up the
769           listener, a coroutine which returns an :class:`SSHListener`
770           can be returned instead of the listener itself.
771
772           To reject this request, this method should return `False`.
773
774           By default, this method rejects all server requests.
775
776           :param listen_host:
777               The address the server should listen on
778           :param listen_port:
779               The port the server should listen on, or the value `0`
780               to request that the server dynamically allocate a port
781           :type listen_host: `str`
782           :type listen_port: `int`
783
784           :returns: One of the following:
785
786                     * An :class:`SSHListener` object
787                     * `True` to set up standard port forwarding
788                     * `False` to reject the request
789                     * A coroutine object which returns one of the above
790
791        """
792
793        return False # pragma: no cover
794
795    def unix_connection_requested(self, dest_path):
796        """Handle a direct UNIX domain socket connection request
797
798           This method is called when a direct UNIX domain socket connection
799           request is received by the server. Applications wishing to accept
800           such connections must override this method.
801
802           To allow standard path forwarding of data on the connection to the
803           requested destination path, this method should return `True`.
804
805           To reject this request, this method should return `False`
806           to send back a "Connection refused" response or raise an
807           :exc:`ChannelOpenError` exception with the reason for
808           the failure.
809
810           If the application wishes to process the data on the
811           connection itself, this method should return either an
812           :class:`SSHUNIXSession` object which can be used to process the
813           data received on the channel or a tuple consisting of of an
814           :class:`SSHUNIXChannel` object created with
815           :meth:`create_unix_channel()
816           <SSHServerConnection.create_unix_channel>` and an
817           :class:`SSHUNIXSession`, if the application wishes
818           to pass non-default arguments when creating the channel.
819
820           If blocking operations need to be performed before the session
821           can be created, a coroutine which returns an
822           :class:`SSHUNIXSession` object can be returned instead of
823           the session iself. This can be either returned directly or as
824           a part of a tuple with an :class:`SSHUNIXChannel` object.
825
826           By default, all connection requests are rejected.
827
828           :param dest_path:
829               The path the client wishes to connect to
830           :type dest_path: `str`
831
832           :returns: One of the following:
833
834                     * An :class:`SSHUNIXSession` object or a coroutine
835                       which returns an :class:`SSHUNIXSession`
836                     * A tuple consisting of an :class:`SSHUNIXChannel`
837                       and the above
838                     * A `callable` or coroutine handler function which
839                       takes AsyncSSH stream objects for reading from
840                       and writing to the connection
841                     * A tuple consisting of an :class:`SSHUNIXChannel`
842                       and the above
843                     * `True` to request standard path forwarding
844                     * `False` to refuse the connection
845
846           :raises: :exc:`ChannelOpenError` if the connection shouldn't
847                    be accepted
848
849        """
850
851        return False # pragma: no cover
852
853    def unix_server_requested(self, listen_path):
854        """Handle a request to listen on a UNIX domain socket
855
856           This method is called when a client makes a request to
857           listen on a path for incoming UNIX domain socket connections.
858           Applications wishing to allow UNIX domain socket forwarding
859           must override this method.
860
861           To set up standard path forwarding of connections received
862           on this path, this method should return `True`.
863
864           If the application wishes to manage listening for incoming
865           connections itself, this method should return an
866           :class:`SSHListener` object that listens for new connections
867           and calls :meth:`create_unix_connection
868           <SSHServerConnection.create_unix_connection>` on each of them to
869           forward them back to the client or return `None` if the
870           listener can't be set up.
871
872           If blocking operations need to be performed to set up the
873           listener, a coroutine which returns an :class:`SSHListener`
874           can be returned instead of the listener itself.
875
876           To reject this request, this method should return `False`.
877
878           By default, this method rejects all server requests.
879
880           :param listen_path:
881               The path the server should listen on
882           :type listen_path: `str`
883
884           :returns: One of the following:
885
886                     * An :class:`SSHListener` object or a coroutine
887                       which returns an :class:`SSHListener` or `False`
888                       if the listener can't be opened
889                     * `True` to set up standard path forwarding
890                     * `False` to reject the request
891
892        """
893
894        return False # pragma: no cover
895