github.com/devops-filetransfer/sshego@v7.0.4+incompatible/_vendor/golang.org/x/crypto/ssh/streamlocal.go (about) 1 package ssh 2 3 import ( 4 "errors" 5 "io" 6 "net" 7 ) 8 9 // streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message 10 // with "direct-streamlocal@openssh.com" string. 11 // 12 // See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding 13 // https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235 14 type streamLocalChannelOpenDirectMsg struct { 15 socketPath string 16 reserved0 string 17 reserved1 uint32 18 } 19 20 // forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message 21 // with "forwarded-streamlocal@openssh.com" string. 22 type forwardedStreamLocalPayload struct { 23 SocketPath string 24 Reserved0 string 25 } 26 27 // streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message 28 // with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string. 29 type streamLocalChannelForwardMsg struct { 30 socketPath string 31 } 32 33 // ListenUnix is similar to ListenTCP but uses a Unix domain socket. 34 func (c *Client) ListenUnix(socketPath string) (net.Listener, error) { 35 m := streamLocalChannelForwardMsg{ 36 socketPath, 37 } 38 // send message 39 ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m)) 40 if err != nil { 41 return nil, err 42 } 43 if !ok { 44 return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer") 45 } 46 ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"}) 47 48 return &unixListener{socketPath, c, ch}, nil 49 } 50 51 func (c *Client) dialStreamLocal(socketPath string) (Channel, error) { 52 msg := streamLocalChannelOpenDirectMsg{ 53 socketPath: socketPath, 54 } 55 ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg)) 56 if err != nil { 57 return nil, err 58 } 59 go DiscardRequests(in) 60 return ch, err 61 } 62 63 type unixListener struct { 64 socketPath string 65 66 conn *Client 67 in <-chan forward 68 } 69 70 // Accept waits for and returns the next connection to the listener. 71 func (l *unixListener) Accept() (net.Conn, error) { 72 s, ok := <-l.in 73 if !ok { 74 return nil, io.EOF 75 } 76 ch, incoming, err := s.newCh.Accept() 77 if err != nil { 78 return nil, err 79 } 80 go DiscardRequests(incoming) 81 82 return &chanConn{ 83 Channel: ch, 84 laddr: &net.UnixAddr{ 85 Name: l.socketPath, 86 Net: "unix", 87 }, 88 raddr: &net.UnixAddr{ 89 Name: "@", 90 Net: "unix", 91 }, 92 }, nil 93 } 94 95 // Close closes the listener. 96 func (l *unixListener) Close() error { 97 // this also closes the listener. 98 l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"}) 99 m := streamLocalChannelForwardMsg{ 100 l.socketPath, 101 } 102 ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m)) 103 if err == nil && !ok { 104 err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed") 105 } 106 return err 107 } 108 109 // Addr returns the listener's network address. 110 func (l *unixListener) Addr() net.Addr { 111 return &net.UnixAddr{ 112 Name: l.socketPath, 113 Net: "unix", 114 } 115 }