You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
3.3 KiB

  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package ssh
  5. import (
  6. "fmt"
  7. "net"
  8. )
  9. // OpenChannelError is returned if the other side rejects an
  10. // OpenChannel request.
  11. type OpenChannelError struct {
  12. Reason RejectionReason
  13. Message string
  14. }
  15. func (e *OpenChannelError) Error() string {
  16. return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message)
  17. }
  18. // ConnMetadata holds metadata for the connection.
  19. type ConnMetadata interface {
  20. // User returns the user ID for this connection.
  21. User() string
  22. // SessionID returns the session hash, also denoted by H.
  23. SessionID() []byte
  24. // ClientVersion returns the client's version string as hashed
  25. // into the session ID.
  26. ClientVersion() []byte
  27. // ServerVersion returns the server's version string as hashed
  28. // into the session ID.
  29. ServerVersion() []byte
  30. // RemoteAddr returns the remote address for this connection.
  31. RemoteAddr() net.Addr
  32. // LocalAddr returns the local address for this connection.
  33. LocalAddr() net.Addr
  34. }
  35. // Conn represents an SSH connection for both server and client roles.
  36. // Conn is the basis for implementing an application layer, such
  37. // as ClientConn, which implements the traditional shell access for
  38. // clients.
  39. type Conn interface {
  40. ConnMetadata
  41. // SendRequest sends a global request, and returns the
  42. // reply. If wantReply is true, it returns the response status
  43. // and payload. See also RFC4254, section 4.
  44. SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error)
  45. // OpenChannel tries to open an channel. If the request is
  46. // rejected, it returns *OpenChannelError. On success it returns
  47. // the SSH Channel and a Go channel for incoming, out-of-band
  48. // requests. The Go channel must be serviced, or the
  49. // connection will hang.
  50. OpenChannel(name string, data []byte) (Channel, <-chan *Request, error)
  51. // Close closes the underlying network connection
  52. Close() error
  53. // Wait blocks until the connection has shut down, and returns the
  54. // error causing the shutdown.
  55. Wait() error
  56. // TODO(hanwen): consider exposing:
  57. // RequestKeyChange
  58. // Disconnect
  59. }
  60. // DiscardRequests consumes and rejects all requests from the
  61. // passed-in channel.
  62. func DiscardRequests(in <-chan *Request) {
  63. for req := range in {
  64. if req.WantReply {
  65. req.Reply(false, nil)
  66. }
  67. }
  68. }
  69. // A connection represents an incoming connection.
  70. type connection struct {
  71. transport *handshakeTransport
  72. sshConn
  73. // The connection protocol.
  74. *mux
  75. }
  76. func (c *connection) Close() error {
  77. return c.sshConn.conn.Close()
  78. }
  79. // sshconn provides net.Conn metadata, but disallows direct reads and
  80. // writes.
  81. type sshConn struct {
  82. conn net.Conn
  83. user string
  84. sessionID []byte
  85. clientVersion []byte
  86. serverVersion []byte
  87. }
  88. func dup(src []byte) []byte {
  89. dst := make([]byte, len(src))
  90. copy(dst, src)
  91. return dst
  92. }
  93. func (c *sshConn) User() string {
  94. return c.user
  95. }
  96. func (c *sshConn) RemoteAddr() net.Addr {
  97. return c.conn.RemoteAddr()
  98. }
  99. func (c *sshConn) Close() error {
  100. return c.conn.Close()
  101. }
  102. func (c *sshConn) LocalAddr() net.Addr {
  103. return c.conn.LocalAddr()
  104. }
  105. func (c *sshConn) SessionID() []byte {
  106. return dup(c.sessionID)
  107. }
  108. func (c *sshConn) ClientVersion() []byte {
  109. return dup(c.clientVersion)
  110. }
  111. func (c *sshConn) ServerVersion() []byte {
  112. return dup(c.serverVersion)
  113. }