LEFT | RIGHT |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package ssh | 5 package ssh |
6 | 6 |
7 import ( | 7 import ( |
8 "errors" | 8 "errors" |
9 "fmt" | 9 "fmt" |
10 "io" | 10 "io" |
11 "log" | |
12 "math/rand" | 11 "math/rand" |
13 "net" | 12 "net" |
14 "strconv" | 13 "strconv" |
15 "strings" | 14 "strings" |
16 "sync" | 15 "sync" |
17 "time" | 16 "time" |
18 ) | 17 ) |
19 | 18 |
20 // Listen requests the remote peer open a listening socket | 19 // Listen requests the remote peer open a listening socket |
21 // on addr. Incoming connections will be available by calling | 20 // on addr. Incoming connections will be available by calling |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 func (c *ClientConn) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { | 87 func (c *ClientConn) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { |
89 if laddr.Port == 0 && isBrokenOpenSSHVersion(c.serverVersion) { | 88 if laddr.Port == 0 && isBrokenOpenSSHVersion(c.serverVersion) { |
90 return c.autoPortListenWorkaround(laddr) | 89 return c.autoPortListenWorkaround(laddr) |
91 } | 90 } |
92 | 91 |
93 m := channelForwardMsg{ | 92 m := channelForwardMsg{ |
94 laddr.IP.String(), | 93 laddr.IP.String(), |
95 uint32(laddr.Port), | 94 uint32(laddr.Port), |
96 } | 95 } |
97 // send message | 96 // send message |
98 » ok, resp, err := c.mux.SendRequest("tcpip-forward", true, marshal(0, m)[
1:]) | 97 » ok, resp, err := c.mux.SendRequest("tcpip-forward", true, marshal(0, m)) |
99 if err != nil { | 98 if err != nil { |
100 return nil, err | 99 return nil, err |
101 } | 100 } |
102 if !ok { | 101 if !ok { |
103 return nil, errors.New("tcpip-forward denied") | 102 return nil, errors.New("tcpip-forward denied") |
104 } | 103 } |
105 | 104 |
106 // If the original port was 0, then the remote side will | 105 // If the original port was 0, then the remote side will |
107 // supply a real port number in the response. | 106 // supply a real port number in the response. |
108 if laddr.Port == 0 { | 107 if laddr.Port == 0 { |
(...skipping 21 matching lines...) Expand all Loading... |
130 // remote ssh server to a channel connected to a tcpListener. | 129 // remote ssh server to a channel connected to a tcpListener. |
131 type forwardEntry struct { | 130 type forwardEntry struct { |
132 laddr net.TCPAddr | 131 laddr net.TCPAddr |
133 c chan forward | 132 c chan forward |
134 } | 133 } |
135 | 134 |
136 // forward represents an incoming forwarded tcpip connection. The | 135 // forward represents an incoming forwarded tcpip connection. The |
137 // arguments to add/remove/lookup should be address as specified in | 136 // arguments to add/remove/lookup should be address as specified in |
138 // the original forward-request. | 137 // the original forward-request. |
139 type forward struct { | 138 type forward struct { |
140 » c Channel // the ssh client channel underlying this forward | 139 » c *channel // the ssh client channel underlying this forward |
141 raddr *net.TCPAddr // the raddr of the incoming connection | 140 raddr *net.TCPAddr // the raddr of the incoming connection |
142 } | 141 } |
143 | 142 |
144 func (l *forwardList) add(addr net.TCPAddr) chan forward { | 143 func (l *forwardList) add(addr net.TCPAddr) chan forward { |
145 l.Lock() | 144 l.Lock() |
146 defer l.Unlock() | 145 defer l.Unlock() |
147 f := forwardEntry{ | 146 f := forwardEntry{ |
148 addr, | 147 addr, |
149 make(chan forward, 1), | 148 make(chan forward, 1), |
150 } | 149 } |
151 l.entries = append(l.entries, f) | 150 l.entries = append(l.entries, f) |
152 return f.c | 151 return f.c |
153 } | 152 } |
154 | 153 |
155 // remove removes the forward entry, and the channel feeding its | 154 // remove removes the forward entry, and the channel feeding its |
156 // listener. | 155 // listener. |
157 func (l *forwardList) remove(addr net.TCPAddr) { | 156 func (l *forwardList) remove(addr net.TCPAddr) { |
158 l.Lock() | 157 l.Lock() |
159 defer l.Unlock() | 158 defer l.Unlock() |
160 for i, f := range l.entries { | 159 for i, f := range l.entries { |
161 if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port { | 160 if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port { |
162 l.entries = append(l.entries[:i], l.entries[i+1:]...) | 161 l.entries = append(l.entries[:i], l.entries[i+1:]...) |
163 log.Println("REMOVE") | |
164 close(f.c) | 162 close(f.c) |
165 return | 163 return |
166 } | 164 } |
167 } | 165 } |
168 } | 166 } |
169 | 167 |
170 // closeAll closes and clears all forwards. | 168 // closeAll closes and clears all forwards. |
171 func (l *forwardList) closeAll() { | 169 func (l *forwardList) closeAll() { |
172 l.Lock() | 170 l.Lock() |
173 defer l.Unlock() | 171 defer l.Unlock() |
(...skipping 21 matching lines...) Expand all Loading... |
195 in <-chan forward | 193 in <-chan forward |
196 } | 194 } |
197 | 195 |
198 // Accept waits for and returns the next connection to the listener. | 196 // Accept waits for and returns the next connection to the listener. |
199 func (l *tcpListener) Accept() (net.Conn, error) { | 197 func (l *tcpListener) Accept() (net.Conn, error) { |
200 s, ok := <-l.in | 198 s, ok := <-l.in |
201 if !ok { | 199 if !ok { |
202 return nil, io.EOF | 200 return nil, io.EOF |
203 } | 201 } |
204 return &tcpChanConn{ | 202 return &tcpChanConn{ |
205 » » Channel: s.c, | 203 » » channel: s.c, |
206 laddr: l.laddr, | 204 laddr: l.laddr, |
207 raddr: s.raddr, | 205 raddr: s.raddr, |
208 }, nil | 206 }, nil |
209 } | 207 } |
210 | 208 |
211 // Close closes the listener. | 209 // Close closes the listener. |
212 func (l *tcpListener) Close() error { | 210 func (l *tcpListener) Close() error { |
213 m := channelForwardMsg{ | 211 m := channelForwardMsg{ |
214 l.laddr.IP.String(), | 212 l.laddr.IP.String(), |
215 uint32(l.laddr.Port), | 213 uint32(l.laddr.Port), |
216 } | 214 } |
217 | 215 |
218 // this also closes the listener. | 216 // this also closes the listener. |
219 l.conn.forwardList.remove(*l.laddr) | 217 l.conn.forwardList.remove(*l.laddr) |
220 » ok, _, err := l.conn.mux.SendRequest("cancel-tcpip-forward", true, marsh
al(0, m)[1:]) | 218 » ok, _, err := l.conn.mux.SendRequest("cancel-tcpip-forward", true, marsh
al(0, m)) |
221 if err == nil && !ok { | 219 if err == nil && !ok { |
222 err = errors.New("ssh: cancel-tcpip-forward failed") | 220 err = errors.New("ssh: cancel-tcpip-forward failed") |
223 } | 221 } |
224 return err | 222 return err |
225 } | 223 } |
226 | 224 |
227 // Addr returns the listener's network address. | 225 // Addr returns the listener's network address. |
228 func (l *tcpListener) Addr() net.Addr { | 226 func (l *tcpListener) Addr() net.Addr { |
229 return l.laddr | 227 return l.laddr |
230 } | 228 } |
(...skipping 13 matching lines...) Expand all Loading... |
244 // Use a zero address for local and remote address. | 242 // Use a zero address for local and remote address. |
245 zeroAddr := &net.TCPAddr{ | 243 zeroAddr := &net.TCPAddr{ |
246 IP: net.IPv4zero, | 244 IP: net.IPv4zero, |
247 Port: 0, | 245 Port: 0, |
248 } | 246 } |
249 ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port)) | 247 ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port)) |
250 if err != nil { | 248 if err != nil { |
251 return nil, err | 249 return nil, err |
252 } | 250 } |
253 return &tcpChanConn{ | 251 return &tcpChanConn{ |
254 » » Channel: ch, | 252 » » channel: ch, |
255 laddr: zeroAddr, | 253 laddr: zeroAddr, |
256 raddr: zeroAddr, | 254 raddr: zeroAddr, |
257 }, nil | 255 }, nil |
258 } | 256 } |
259 | 257 |
260 // DialTCP connects to the remote address raddr on the network net, | 258 // DialTCP connects to the remote address raddr on the network net, |
261 // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used | 259 // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used |
262 // as the local address for the connection. | 260 // as the local address for the connection. |
263 func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, err
or) { | 261 func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, err
or) { |
264 if laddr == nil { | 262 if laddr == nil { |
265 laddr = &net.TCPAddr{ | 263 laddr = &net.TCPAddr{ |
266 IP: net.IPv4zero, | 264 IP: net.IPv4zero, |
267 Port: 0, | 265 Port: 0, |
268 } | 266 } |
269 } | 267 } |
270 ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), radd
r.Port) | 268 ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), radd
r.Port) |
271 if err != nil { | 269 if err != nil { |
272 return nil, err | 270 return nil, err |
273 } | 271 } |
274 return &tcpChanConn{ | 272 return &tcpChanConn{ |
275 » » Channel: ch, | 273 » » channel: ch, |
276 laddr: laddr, | 274 laddr: laddr, |
277 raddr: raddr, | 275 raddr: raddr, |
278 }, nil | 276 }, nil |
279 } | 277 } |
280 | 278 |
281 // RFC 4254 7.2 | 279 // RFC 4254 7.2 |
282 type channelOpenDirectMsg struct { | 280 type channelOpenDirectMsg struct { |
283 raddr string | 281 raddr string |
284 rport uint32 | 282 rport uint32 |
285 laddr string | 283 laddr string |
286 lport uint32 | 284 lport uint32 |
287 } | 285 } |
288 | 286 |
289 // dial opens a direct-tcpip connection to the remote server. laddr and raddr ar
e passed as | 287 // dial opens a direct-tcpip connection to the remote server. laddr and raddr ar
e passed as |
290 // strings and are expected to be resolveable at the remote end. | 288 // strings and are expected to be resolvable at the remote end. |
291 func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (Cha
nnel, error) { | 289 func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*ch
annel, error) { |
292 msg := channelOpenDirectMsg{ | 290 msg := channelOpenDirectMsg{ |
293 raddr: raddr, | 291 raddr: raddr, |
294 rport: uint32(rport), | 292 rport: uint32(rport), |
295 laddr: laddr, | 293 laddr: laddr, |
296 lport: uint32(lport), | 294 lport: uint32(lport), |
297 } | 295 } |
298 | 296 |
299 » return c.mux.OpenChannel("direct-tcpip", marshal(0, msg)[1:]) | 297 » return c.mux.OpenChannel("direct-tcpip", marshal(0, msg)) |
300 } | 298 } |
301 | 299 |
302 // tcpChanConn fulfills the net.Conn interface without | 300 // tcpChanConn fulfills the net.Conn interface without |
303 // the tcpChan having to hold laddr or raddr directly. | 301 // the tcpChan having to hold laddr or raddr directly. |
304 type tcpChanConn struct { | 302 type tcpChanConn struct { |
305 » Channel | 303 » *channel |
306 laddr, raddr net.Addr | 304 laddr, raddr net.Addr |
307 } | 305 } |
308 | 306 |
309 // LocalAddr returns the local network address. | 307 // LocalAddr returns the local network address. |
310 func (t *tcpChanConn) LocalAddr() net.Addr { | 308 func (t *tcpChanConn) LocalAddr() net.Addr { |
311 return t.laddr | 309 return t.laddr |
312 } | 310 } |
313 | 311 |
314 // RemoteAddr returns the remote network address. | 312 // RemoteAddr returns the remote network address. |
315 func (t *tcpChanConn) RemoteAddr() net.Addr { | 313 func (t *tcpChanConn) RemoteAddr() net.Addr { |
(...skipping 15 matching lines...) Expand all Loading... |
331 // with Timeout() == true. | 329 // with Timeout() == true. |
332 func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error { | 330 func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error { |
333 return errors.New("ssh: tcpChan: deadline not supported") | 331 return errors.New("ssh: tcpChan: deadline not supported") |
334 } | 332 } |
335 | 333 |
336 // SetWriteDeadline exists to satisfy the net.Conn interface | 334 // SetWriteDeadline exists to satisfy the net.Conn interface |
337 // but is not implemented by this type. It always returns an error. | 335 // but is not implemented by this type. It always returns an error. |
338 func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error { | 336 func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error { |
339 return errors.New("ssh: tcpChan: deadline not supported") | 337 return errors.New("ssh: tcpChan: deadline not supported") |
340 } | 338 } |
LEFT | RIGHT |