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

Delta Between Two Patch Sets: ssh/tcpip.go

Issue 11921043: code review 11921043: go.crypto/ssh: add workaround for broken port forwarding in (Closed)
Left Patch Set: diff -r c0932d3462e8 https://code.google.com/p/go.crypto Created 11 years, 8 months ago
Right Patch Set: diff -r c0932d3462e8 https://code.google.com/p/go.crypto Created 11 years, 8 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:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « ssh/client.go ('k') | ssh/tcpip_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 26 matching lines...) Expand all
37 37
38 // Automatic port allocation is broken with OpenSSH before 6.0. See 38 // Automatic port allocation is broken with OpenSSH before 6.0. See
39 // also https://bugzilla.mindrot.org/show_bug.cgi?id=2017. In 39 // also https://bugzilla.mindrot.org/show_bug.cgi?id=2017. In
40 // particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0, 40 // particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0,
41 // rather than the actual port number. This means you can never open 41 // rather than the actual port number. This means you can never open
42 // two different listeners with auto allocated ports. We work around 42 // two different listeners with auto allocated ports. We work around
43 // this by trying explicit ports until we succeed. 43 // this by trying explicit ports until we succeed.
44 44
45 const openSSHPrefix = "OpenSSH_" 45 const openSSHPrefix = "OpenSSH_"
46 46
47 func autoPortListenBroken(versionStr string) bool { 47 // isBrokenOpenSSHVersion returns true if the given version string
48 // specifies a version of OpenSSH that is known to have a bug in port
49 // forwarding.
50 func isBrokenOpenSSHVersion(versionStr string) bool {
48 i := strings.Index(versionStr, openSSHPrefix) 51 i := strings.Index(versionStr, openSSHPrefix)
49 if i < 0 { 52 if i < 0 {
50 return false 53 return false
51 } 54 }
52 i += len(openSSHPrefix) 55 i += len(openSSHPrefix)
53 j := i 56 j := i
54 for ; j < len(versionStr); j++ { 57 for ; j < len(versionStr); j++ {
55 » » if versionStr[j] < '0' && versionStr[j] > '9' { 58 » » if versionStr[j] < '0' || versionStr[j] > '9' {
56 break 59 break
57 } 60 }
58 } 61 }
62 fmt.Printf("V %q", versionStr[i:j])
agl1 2013/07/26 18:38:06 Looks like debugging - will remove before landing.
59 version, _ := strconv.Atoi(versionStr[i:j]) 63 version, _ := strconv.Atoi(versionStr[i:j])
60 return version < 6 64 return version < 6
61 } 65 }
62 66
67 // autoPortListenWorkaround simulates automatic port allocation by
68 // trying random ports repeatedly.
63 func (c *ClientConn) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) { 69 func (c *ClientConn) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) {
64 var sshListener net.Listener 70 var sshListener net.Listener
65 var err error 71 var err error
66 const tries = 10 72 const tries = 10
67 for i := 0; i < tries; i++ { 73 for i := 0; i < tries; i++ {
68 addr := *laddr 74 addr := *laddr
69 addr.Port = 1024 + rand.Intn(60000) 75 addr.Port = 1024 + rand.Intn(60000)
70 sshListener, err = c.ListenTCP(&addr) 76 sshListener, err = c.ListenTCP(&addr)
71 if err == nil { 77 if err == nil {
72 laddr.Port = addr.Port 78 laddr.Port = addr.Port
73 return sshListener, err 79 return sshListener, err
74 } 80 }
75 } 81 }
76 return nil, fmt.Errorf("ssh: listen on random port failed after %d tries : %v", tries, err) 82 return nil, fmt.Errorf("ssh: listen on random port failed after %d tries : %v", tries, err)
77 } 83 }
78 84
79 // ListenTCP requests the remote peer open a listening socket 85 // ListenTCP requests the remote peer open a listening socket
80 // on laddr. Incoming connections will be available by calling 86 // on laddr. Incoming connections will be available by calling
81 // Accept on the returned net.Listener. 87 // Accept on the returned net.Listener.
82 func (c *ClientConn) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { 88 func (c *ClientConn) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
83 » if laddr.Port == 0 && autoPortListenBroken(c.serverVersion) { 89 » if laddr.Port == 0 && isBrokenOpenSSHVersion(c.serverVersion) {
84 return c.autoPortListenWorkaround(laddr) 90 return c.autoPortListenWorkaround(laddr)
85 } 91 }
86 92
87 m := channelForwardMsg{ 93 m := channelForwardMsg{
88 "tcpip-forward", 94 "tcpip-forward",
89 true, // sendGlobalRequest waits for a reply 95 true, // sendGlobalRequest waits for a reply
90 laddr.IP.String(), 96 laddr.IP.String(),
91 uint32(laddr.Port), 97 uint32(laddr.Port),
92 } 98 }
93 // send message 99 // send message
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 // with Timeout() == true. 341 // with Timeout() == true.
336 func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error { 342 func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error {
337 return errors.New("ssh: tcpChan: deadline not supported") 343 return errors.New("ssh: tcpChan: deadline not supported")
338 } 344 }
339 345
340 // SetWriteDeadline exists to satisfy the net.Conn interface 346 // SetWriteDeadline exists to satisfy the net.Conn interface
341 // but is not implemented by this type. It always returns an error. 347 // but is not implemented by this type. It always returns an error.
342 func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error { 348 func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error {
343 return errors.New("ssh: tcpChan: deadline not supported") 349 return errors.New("ssh: tcpChan: deadline not supported")
344 } 350 }
LEFTRIGHT

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