OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / crypto / ssh / streamlocal.go
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 }