| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | // Copyright 2013 The Go Authors. All rights reserved. | 
					
						
							|  |  |  | // Use of this source code is governed by a BSD-style | 
					
						
							|  |  |  | // license that can be found in the LICENSE file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package ssh | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"net" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // OpenChannelError is returned if the other side rejects an | 
					
						
							|  |  |  | // OpenChannel request. | 
					
						
							|  |  |  | type OpenChannelError struct { | 
					
						
							|  |  |  | 	Reason  RejectionReason | 
					
						
							|  |  |  | 	Message string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *OpenChannelError) Error() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ConnMetadata holds metadata for the connection. | 
					
						
							|  |  |  | type ConnMetadata interface { | 
					
						
							|  |  |  | 	// User returns the user ID for this connection. | 
					
						
							|  |  |  | 	User() string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// SessionID returns the session hash, also denoted by H. | 
					
						
							|  |  |  | 	SessionID() []byte | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// ClientVersion returns the client's version string as hashed | 
					
						
							|  |  |  | 	// into the session ID. | 
					
						
							|  |  |  | 	ClientVersion() []byte | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// ServerVersion returns the server's version string as hashed | 
					
						
							|  |  |  | 	// into the session ID. | 
					
						
							|  |  |  | 	ServerVersion() []byte | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// RemoteAddr returns the remote address for this connection. | 
					
						
							|  |  |  | 	RemoteAddr() net.Addr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// LocalAddr returns the local address for this connection. | 
					
						
							|  |  |  | 	LocalAddr() net.Addr | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Conn represents an SSH connection for both server and client roles. | 
					
						
							|  |  |  | // Conn is the basis for implementing an application layer, such | 
					
						
							|  |  |  | // as ClientConn, which implements the traditional shell access for | 
					
						
							|  |  |  | // clients. | 
					
						
							|  |  |  | type Conn interface { | 
					
						
							|  |  |  | 	ConnMetadata | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// SendRequest sends a global request, and returns the | 
					
						
							|  |  |  | 	// reply. If wantReply is true, it returns the response status | 
					
						
							| 
									
										
										
										
											2023-01-30 10:45:34 +01:00
										 |  |  | 	// and payload. See also RFC 4254, section 4. | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// OpenChannel tries to open an channel. If the request is | 
					
						
							|  |  |  | 	// rejected, it returns *OpenChannelError. On success it returns | 
					
						
							|  |  |  | 	// the SSH Channel and a Go channel for incoming, out-of-band | 
					
						
							|  |  |  | 	// requests. The Go channel must be serviced, or the | 
					
						
							|  |  |  | 	// connection will hang. | 
					
						
							|  |  |  | 	OpenChannel(name string, data []byte) (Channel, <-chan *Request, error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Close closes the underlying network connection | 
					
						
							|  |  |  | 	Close() error | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Wait blocks until the connection has shut down, and returns the | 
					
						
							|  |  |  | 	// error causing the shutdown. | 
					
						
							|  |  |  | 	Wait() error | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// TODO(hanwen): consider exposing: | 
					
						
							|  |  |  | 	//   RequestKeyChange | 
					
						
							|  |  |  | 	//   Disconnect | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-10 01:08:57 +02:00
										 |  |  | // AlgorithmsConnMetadata is a ConnMetadata that can return the algorithms | 
					
						
							|  |  |  | // negotiated between client and server. | 
					
						
							|  |  |  | type AlgorithmsConnMetadata interface { | 
					
						
							|  |  |  | 	ConnMetadata | 
					
						
							|  |  |  | 	Algorithms() NegotiatedAlgorithms | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | // DiscardRequests consumes and rejects all requests from the | 
					
						
							|  |  |  | // passed-in channel. | 
					
						
							|  |  |  | func DiscardRequests(in <-chan *Request) { | 
					
						
							|  |  |  | 	for req := range in { | 
					
						
							|  |  |  | 		if req.WantReply { | 
					
						
							|  |  |  | 			req.Reply(false, nil) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A connection represents an incoming connection. | 
					
						
							|  |  |  | type connection struct { | 
					
						
							|  |  |  | 	transport *handshakeTransport | 
					
						
							|  |  |  | 	sshConn | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// The connection protocol. | 
					
						
							|  |  |  | 	*mux | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *connection) Close() error { | 
					
						
							|  |  |  | 	return c.sshConn.conn.Close() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 12:35:05 +02:00
										 |  |  | // sshConn provides net.Conn metadata, but disallows direct reads and | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | // writes. | 
					
						
							|  |  |  | type sshConn struct { | 
					
						
							|  |  |  | 	conn net.Conn | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	user          string | 
					
						
							|  |  |  | 	sessionID     []byte | 
					
						
							|  |  |  | 	clientVersion []byte | 
					
						
							|  |  |  | 	serverVersion []byte | 
					
						
							| 
									
										
										
										
											2025-06-10 01:08:57 +02:00
										 |  |  | 	algorithms    NegotiatedAlgorithms | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func dup(src []byte) []byte { | 
					
						
							|  |  |  | 	dst := make([]byte, len(src)) | 
					
						
							|  |  |  | 	copy(dst, src) | 
					
						
							|  |  |  | 	return dst | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *sshConn) User() string { | 
					
						
							|  |  |  | 	return c.user | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *sshConn) RemoteAddr() net.Addr { | 
					
						
							|  |  |  | 	return c.conn.RemoteAddr() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *sshConn) Close() error { | 
					
						
							|  |  |  | 	return c.conn.Close() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *sshConn) LocalAddr() net.Addr { | 
					
						
							|  |  |  | 	return c.conn.LocalAddr() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *sshConn) SessionID() []byte { | 
					
						
							|  |  |  | 	return dup(c.sessionID) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *sshConn) ClientVersion() []byte { | 
					
						
							|  |  |  | 	return dup(c.clientVersion) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *sshConn) ServerVersion() []byte { | 
					
						
							|  |  |  | 	return dup(c.serverVersion) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-06-10 01:08:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (c *sshConn) Algorithms() NegotiatedAlgorithms { | 
					
						
							|  |  |  | 	return c.algorithms | 
					
						
							|  |  |  | } |