Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(2452)

Delta Between Two Patch Sets: ssh/tcpip.go

Issue 14225043: code review 14225043: go.crypto/ssh: reimplement SSH connection protocol modu... (Closed)
Left Patch Set: diff -r 2cd6b3b93cdb https://code.google.com/p/go.crypto Created 10 years, 6 months ago
Right Patch Set: diff -r cd1eea1eb828 https://code.google.com/p/go.crypto Created 10 years, 5 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « ssh/session_test.go ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
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"
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 if err == nil { 70 if err == nil {
71 laddr.Port = addr.Port 71 laddr.Port = addr.Port
72 return sshListener, err 72 return sshListener, err
73 } 73 }
74 } 74 }
75 return nil, fmt.Errorf("ssh: listen on random port failed after %d tries : %v", tries, err) 75 return nil, fmt.Errorf("ssh: listen on random port failed after %d tries : %v", tries, err)
76 } 76 }
77 77
78 // RFC 4254 7.1 78 // RFC 4254 7.1
79 type channelForwardMsg struct { 79 type channelForwardMsg struct {
80 » Message string 80 » addr string
81 » WantReply bool 81 » rport uint32
82 » raddr string
83 » rport uint32
84 } 82 }
85 83
86 // ListenTCP requests the remote peer open a listening socket 84 // ListenTCP requests the remote peer open a listening socket
87 // on laddr. Incoming connections will be available by calling 85 // on laddr. Incoming connections will be available by calling
88 // Accept on the returned net.Listener. 86 // Accept on the returned net.Listener.
89 func (c *ClientConn) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { 87 func (c *ClientConn) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
90 if laddr.Port == 0 && isBrokenOpenSSHVersion(c.serverVersion) { 88 if laddr.Port == 0 && isBrokenOpenSSHVersion(c.serverVersion) {
91 return c.autoPortListenWorkaround(laddr) 89 return c.autoPortListenWorkaround(laddr)
92 } 90 }
93 91
94 m := channelForwardMsg{ 92 m := channelForwardMsg{
95 "tcpip-forward",
96 true, // sendGlobalRequest waits for a reply
97 laddr.IP.String(), 93 laddr.IP.String(),
98 uint32(laddr.Port), 94 uint32(laddr.Port),
99 } 95 }
100 // send message 96 // send message
101 » resp, err := c.sendGlobalRequest(m) 97 » ok, resp, err := c.mux.SendRequest("tcpip-forward", true, marshal(0, m))
102 » if err != nil { 98 » if err != nil {
103 » » return nil, err 99 » » return nil, err
100 » }
101 » if !ok {
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 {
109 » » port, _, ok := parseUint32(resp.Data) 108 » » port, _, ok := parseUint32(resp)
110 if !ok { 109 if !ok {
111 return nil, errors.New("unable to parse response") 110 return nil, errors.New("unable to parse response")
112 } 111 }
113 laddr.Port = int(port) 112 laddr.Port = int(port)
114 } 113 }
115 114
116 // Register this forward, using the port number we obtained. 115 // Register this forward, using the port number we obtained.
117 ch := c.forwardList.add(*laddr) 116 ch := c.forwardList.add(*laddr)
118 117
119 return &tcpListener{laddr, c, ch}, nil 118 return &tcpListener{laddr, c, ch}, nil
(...skipping 10 matching lines...) Expand all
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 *clientChan // 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 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 in <-chan forward 193 in <-chan forward
195 } 194 }
196 195
197 // Accept waits for and returns the next connection to the listener. 196 // Accept waits for and returns the next connection to the listener.
198 func (l *tcpListener) Accept() (net.Conn, error) { 197 func (l *tcpListener) Accept() (net.Conn, error) {
199 s, ok := <-l.in 198 s, ok := <-l.in
200 if !ok { 199 if !ok {
201 return nil, io.EOF 200 return nil, io.EOF
202 } 201 }
203 return &tcpChanConn{ 202 return &tcpChanConn{
204 » » tcpChan: &tcpChan{ 203 » » channel: s.c,
205 » » » clientChan: s.c, 204 » » laddr: l.laddr,
206 » » » Reader: s.c.stdout, 205 » » raddr: s.raddr,
207 » » » Writer: s.c.stdin,
208 » » },
209 » » laddr: l.laddr,
210 » » raddr: s.raddr,
211 }, nil 206 }, nil
212 } 207 }
213 208
214 // Close closes the listener. 209 // Close closes the listener.
215 func (l *tcpListener) Close() error { 210 func (l *tcpListener) Close() error {
216 m := channelForwardMsg{ 211 m := channelForwardMsg{
217 "cancel-tcpip-forward",
218 true,
219 l.laddr.IP.String(), 212 l.laddr.IP.String(),
220 uint32(l.laddr.Port), 213 uint32(l.laddr.Port),
221 } 214 }
215
216 // this also closes the listener.
222 l.conn.forwardList.remove(*l.laddr) 217 l.conn.forwardList.remove(*l.laddr)
223 » if _, err := l.conn.sendGlobalRequest(m); err != nil { 218 » ok, _, err := l.conn.mux.SendRequest("cancel-tcpip-forward", true, marsh al(0, m))
224 » » return err 219 » if err == nil && !ok {
225 » } 220 » » err = errors.New("ssh: cancel-tcpip-forward failed")
226 » return nil 221 » }
222 » return err
227 } 223 }
228 224
229 // Addr returns the listener's network address. 225 // Addr returns the listener's network address.
230 func (l *tcpListener) Addr() net.Addr { 226 func (l *tcpListener) Addr() net.Addr {
231 return l.laddr 227 return l.laddr
232 } 228 }
233 229
234 // Dial initiates a connection to the addr from the remote host. 230 // Dial initiates a connection to the addr from the remote host.
235 // The resulting connection has a zero LocalAddr() and RemoteAddr(). 231 // The resulting connection has a zero LocalAddr() and RemoteAddr().
236 func (c *ClientConn) Dial(n, addr string) (net.Conn, error) { 232 func (c *ClientConn) Dial(n, addr string) (net.Conn, error) {
237 // Parse the address into host and numeric port. 233 // Parse the address into host and numeric port.
238 host, portString, err := net.SplitHostPort(addr) 234 host, portString, err := net.SplitHostPort(addr)
239 if err != nil { 235 if err != nil {
240 return nil, err 236 return nil, err
241 } 237 }
242 port, err := strconv.ParseUint(portString, 10, 16) 238 port, err := strconv.ParseUint(portString, 10, 16)
243 if err != nil { 239 if err != nil {
244 return nil, err 240 return nil, err
245 } 241 }
246 // Use a zero address for local and remote address. 242 // Use a zero address for local and remote address.
247 zeroAddr := &net.TCPAddr{ 243 zeroAddr := &net.TCPAddr{
248 IP: net.IPv4zero, 244 IP: net.IPv4zero,
249 Port: 0, 245 Port: 0,
250 } 246 }
251 ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port)) 247 ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port))
252 if err != nil { 248 if err != nil {
253 return nil, err 249 return nil, err
254 } 250 }
255 return &tcpChanConn{ 251 return &tcpChanConn{
256 » » tcpChan: ch, 252 » » channel: ch,
257 laddr: zeroAddr, 253 laddr: zeroAddr,
258 raddr: zeroAddr, 254 raddr: zeroAddr,
259 }, nil 255 }, nil
260 } 256 }
261 257
262 // DialTCP connects to the remote address raddr on the network net, 258 // DialTCP connects to the remote address raddr on the network net,
263 // 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
264 // as the local address for the connection. 260 // as the local address for the connection.
265 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) {
266 if laddr == nil { 262 if laddr == nil {
267 laddr = &net.TCPAddr{ 263 laddr = &net.TCPAddr{
268 IP: net.IPv4zero, 264 IP: net.IPv4zero,
269 Port: 0, 265 Port: 0,
270 } 266 }
271 } 267 }
272 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)
273 if err != nil { 269 if err != nil {
274 return nil, err 270 return nil, err
275 } 271 }
276 return &tcpChanConn{ 272 return &tcpChanConn{
277 » » tcpChan: ch, 273 » » channel: ch,
278 laddr: laddr, 274 laddr: laddr,
279 raddr: raddr, 275 raddr: raddr,
280 }, nil 276 }, nil
281 } 277 }
282 278
283 // RFC 4254 7.2 279 // RFC 4254 7.2
284 type channelOpenDirectMsg struct { 280 type channelOpenDirectMsg struct {
285 » ChanType string 281 » raddr string
286 » PeersId uint32 282 » rport uint32
287 » PeersWindow uint32 283 » laddr string
288 » MaxPacketSize uint32 284 » lport uint32
289 » raddr string
290 » rport uint32
291 » laddr string
292 » lport uint32
293 } 285 }
294 286
295 // 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
296 // strings and are expected to be resolvable at the remote end. 288 // strings and are expected to be resolvable at the remote end.
297 func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tc pChan, error) { 289 func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*ch annel, error) {
298 » ch := c.newChan(c.transport) 290 » msg := channelOpenDirectMsg{
299 » if err := c.transport.writePacket(marshal(msgChannelOpen, channelOpenDir ectMsg{ 291 » » raddr: raddr,
300 » » ChanType: "direct-tcpip", 292 » » rport: uint32(rport),
301 » » PeersId: ch.localId, 293 » » laddr: laddr,
302 » » PeersWindow: 1 << 14, 294 » » lport: uint32(lport),
303 » » MaxPacketSize: 1 << 15, // RFC 4253 6.1 295 » }
304 » » raddr: raddr, 296
305 » » rport: uint32(rport), 297 » return c.mux.OpenChannel("direct-tcpip", marshal(0, msg))
306 » » laddr: laddr,
307 » » lport: uint32(lport),
308 » })); err != nil {
309 » » c.chanList.remove(ch.localId)
310 » » return nil, err
311 » }
312 » if err := ch.waitForChannelOpenResponse(); err != nil {
313 » » c.chanList.remove(ch.localId)
314 » » return nil, fmt.Errorf("ssh: unable to open direct tcpip connect ion: %v", err)
315 » }
316 » return &tcpChan{
317 » » clientChan: ch,
318 » » Reader: ch.stdout,
319 » » Writer: ch.stdin,
320 » }, nil
321 }
322
323 type tcpChan struct {
324 » *clientChan // the backing channel
325 » io.Reader
326 » io.Writer
327 } 298 }
328 299
329 // tcpChanConn fulfills the net.Conn interface without 300 // tcpChanConn fulfills the net.Conn interface without
330 // the tcpChan having to hold laddr or raddr directly. 301 // the tcpChan having to hold laddr or raddr directly.
331 type tcpChanConn struct { 302 type tcpChanConn struct {
332 » *tcpChan 303 » *channel
333 laddr, raddr net.Addr 304 laddr, raddr net.Addr
334 } 305 }
335 306
336 // LocalAddr returns the local network address. 307 // LocalAddr returns the local network address.
337 func (t *tcpChanConn) LocalAddr() net.Addr { 308 func (t *tcpChanConn) LocalAddr() net.Addr {
338 return t.laddr 309 return t.laddr
339 } 310 }
340 311
341 // RemoteAddr returns the remote network address. 312 // RemoteAddr returns the remote network address.
342 func (t *tcpChanConn) RemoteAddr() net.Addr { 313 func (t *tcpChanConn) RemoteAddr() net.Addr {
(...skipping 15 matching lines...) Expand all
358 // with Timeout() == true. 329 // with Timeout() == true.
359 func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error { 330 func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error {
360 return errors.New("ssh: tcpChan: deadline not supported") 331 return errors.New("ssh: tcpChan: deadline not supported")
361 } 332 }
362 333
363 // SetWriteDeadline exists to satisfy the net.Conn interface 334 // SetWriteDeadline exists to satisfy the net.Conn interface
364 // 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.
365 func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error { 336 func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error {
366 return errors.New("ssh: tcpChan: deadline not supported") 337 return errors.New("ssh: tcpChan: deadline not supported")
367 } 338 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b