connection.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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 RFC 4254, 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. // [Psiphon]
  78. // Ensure handshakeTransport.interrupt is invoked.
  79. // handshakeTransport.Close also closes the underlying network
  80. // connection, so c.sshConn.conn.Close in not necessary in this case.
  81. if c.transport != nil {
  82. return c.transport.Close()
  83. }
  84. return c.sshConn.conn.Close()
  85. }
  86. // sshConn provides net.Conn metadata, but disallows direct reads and
  87. // writes.
  88. type sshConn struct {
  89. conn net.Conn
  90. user string
  91. sessionID []byte
  92. clientVersion []byte
  93. serverVersion []byte
  94. }
  95. func dup(src []byte) []byte {
  96. dst := make([]byte, len(src))
  97. copy(dst, src)
  98. return dst
  99. }
  100. func (c *sshConn) User() string {
  101. return c.user
  102. }
  103. func (c *sshConn) RemoteAddr() net.Addr {
  104. return c.conn.RemoteAddr()
  105. }
  106. func (c *sshConn) Close() error {
  107. return c.conn.Close()
  108. }
  109. func (c *sshConn) LocalAddr() net.Addr {
  110. return c.conn.LocalAddr()
  111. }
  112. func (c *sshConn) SessionID() []byte {
  113. return dup(c.sessionID)
  114. }
  115. func (c *sshConn) ClientVersion() []byte {
  116. return dup(c.clientVersion)
  117. }
  118. func (c *sshConn) ServerVersion() []byte {
  119. return dup(c.serverVersion)
  120. }