Skip to content

Commit 72116d5

Browse files
hanwenagl
authored andcommitted
go.crypto/ssh: clean up address parsing in forward code.
LGTM=agl R=agl, dave, jpsugar CC=golang-codereviews https://golang.org/cl/134700043
1 parent fc84ae5 commit 72116d5

File tree

2 files changed

+36
-27
lines changed

2 files changed

+36
-27
lines changed

ssh/client.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -159,25 +159,6 @@ func (c *Client) handleChannelOpens(in <-chan NewChannel) {
159159
c.mu.Unlock()
160160
}
161161

162-
// parseTCPAddr parses the originating address from the remote into a *net.TCPAddr.
163-
// RFC 4254 section 7.2 is mute on what to do if parsing fails but the forwardlist
164-
// requires a valid *net.TCPAddr to operate, so we enforce that restriction here.
165-
func parseTCPAddr(b []byte) (*net.TCPAddr, []byte, bool) {
166-
addr, b, ok := parseString(b)
167-
if !ok {
168-
return nil, b, false
169-
}
170-
port, b, ok := parseUint32(b)
171-
if !ok || port == 0 || port > 65535 {
172-
return nil, b, false
173-
}
174-
ip := net.ParseIP(string(addr))
175-
if ip == nil {
176-
return nil, b, false
177-
}
178-
return &net.TCPAddr{IP: ip, Port: int(port)}, b, true
179-
}
180-
181162
// Dial starts a client connection to the given SSH server. It is a
182163
// convenience function that connects to the given network address,
183164
// initiates the SSH handshake, and then sets up a Client. For access

ssh/tcpip.go

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,47 @@ func (l *forwardList) add(addr net.TCPAddr) chan forward {
154154
return f.c
155155
}
156156

157+
// See RFC 4254, section 7.2
158+
type forwardedTCPPayload struct {
159+
Addr string
160+
Port uint32
161+
OriginAddr string
162+
OriginPort uint32
163+
}
164+
165+
// parseTCPAddr parses the originating address from the remote into a *net.TCPAddr.
166+
func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) {
167+
if port == 0 || port > 65535 {
168+
return nil, fmt.Errorf("ssh: port number out of range: %d", port)
169+
}
170+
ip := net.ParseIP(string(addr))
171+
if ip == nil {
172+
return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr)
173+
}
174+
return &net.TCPAddr{IP: ip, Port: int(port)}, nil
175+
}
176+
157177
func (l *forwardList) handleChannels(in <-chan NewChannel) {
158178
for ch := range in {
159-
laddr, rest, ok := parseTCPAddr(ch.ExtraData())
160-
if !ok {
161-
// invalid request
162-
ch.Reject(ConnectionFailed, "could not parse TCP address")
179+
var payload forwardedTCPPayload
180+
if err := Unmarshal(ch.ExtraData(), &payload); err != nil {
181+
ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
163182
continue
164183
}
165184

166-
raddr, rest, ok := parseTCPAddr(rest)
167-
if !ok {
168-
// invalid request
169-
ch.Reject(ConnectionFailed, "could not parse TCP address")
185+
// RFC 4254 section 7.2 specifies that incoming
186+
// addresses should list the address, in string
187+
// format. It is implied that this should be an IP
188+
// address, as it would be impossible to connect to it
189+
// otherwise.
190+
laddr, err := parseTCPAddr(payload.Addr, payload.Port)
191+
if err != nil {
192+
ch.Reject(ConnectionFailed, err.Error())
193+
continue
194+
}
195+
raddr, err := parseTCPAddr(payload.OriginAddr, payload.OriginPort)
196+
if err != nil {
197+
ch.Reject(ConnectionFailed, err.Error())
170198
continue
171199
}
172200

0 commit comments

Comments
 (0)