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