Merge pull request #2493 from halseth/tor-addr-sanity-check

Validate addresses before writing them to DB
This commit is contained in:
Olaoluwa Osuntokun
2019-01-31 17:15:22 -08:00
committed by GitHub
2 changed files with 105 additions and 9 deletions

View File

@@ -3,6 +3,7 @@ package channeldb
import ( import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt"
"io" "io"
"net" "net"
@@ -43,6 +44,10 @@ func encodeTCPAddr(w io.Writer, addr *net.TCPAddr) error {
ip = addr.IP.To16() ip = addr.IP.To16()
} }
if ip == nil {
return fmt.Errorf("unable to encode IP %v", addr.IP)
}
if _, err := w.Write([]byte{addrType}); err != nil { if _, err := w.Write([]byte{addrType}); err != nil {
return err return err
} }
@@ -64,7 +69,8 @@ func encodeTCPAddr(w io.Writer, addr *net.TCPAddr) error {
// representation. // representation.
func encodeOnionAddr(w io.Writer, addr *tor.OnionAddr) error { func encodeOnionAddr(w io.Writer, addr *tor.OnionAddr) error {
var suffixIndex int var suffixIndex int
switch len(addr.OnionService) { hostLen := len(addr.OnionService)
switch hostLen {
case tor.V2Len: case tor.V2Len:
if _, err := w.Write([]byte{byte(v2OnionAddr)}); err != nil { if _, err := w.Write([]byte{byte(v2OnionAddr)}); err != nil {
return err return err
@@ -79,12 +85,29 @@ func encodeOnionAddr(w io.Writer, addr *tor.OnionAddr) error {
return errors.New("unknown onion service length") return errors.New("unknown onion service length")
} }
suffix := addr.OnionService[suffixIndex:]
if suffix != tor.OnionSuffix {
return fmt.Errorf("invalid suffix \"%v\"", suffix)
}
host, err := tor.Base32Encoding.DecodeString( host, err := tor.Base32Encoding.DecodeString(
addr.OnionService[:suffixIndex], addr.OnionService[:suffixIndex],
) )
if err != nil { if err != nil {
return err return err
} }
// Sanity check the decoded length.
switch {
case hostLen == tor.V2Len && len(host) != tor.V2DecodedLen:
return fmt.Errorf("onion service %v decoded to invalid host %x",
addr.OnionService, host)
case hostLen == tor.V3Len && len(host) != tor.V3DecodedLen:
return fmt.Errorf("onion service %v decoded to invalid host %x",
addr.OnionService, host)
}
if _, err := w.Write(host); err != nil { if _, err := w.Write(host); err != nil {
return err return err
} }

View File

@@ -3,6 +3,7 @@ package channeldb
import ( import (
"bytes" "bytes"
"net" "net"
"strings"
"testing" "testing"
"github.com/lightningnetwork/lnd/tor" "github.com/lightningnetwork/lnd/tor"
@@ -13,19 +14,23 @@ type unknownAddrType struct{}
func (t unknownAddrType) Network() string { return "unknown" } func (t unknownAddrType) Network() string { return "unknown" }
func (t unknownAddrType) String() string { return "unknown" } func (t unknownAddrType) String() string { return "unknown" }
var testIP4 = net.ParseIP("192.168.1.1")
var testIP6 = net.ParseIP("2001:0db8:0000:0000:0000:ff00:0042:8329")
var addrTests = []struct { var addrTests = []struct {
expAddr net.Addr expAddr net.Addr
serErr error serErr string
}{ }{
// Valid addresses.
{ {
expAddr: &net.TCPAddr{ expAddr: &net.TCPAddr{
IP: net.ParseIP("192.168.1.1"), IP: testIP4,
Port: 12345, Port: 12345,
}, },
}, },
{ {
expAddr: &net.TCPAddr{ expAddr: &net.TCPAddr{
IP: net.ParseIP("2001:0db8:0000:0000:0000:ff00:0042:8329"), IP: testIP6,
Port: 65535, Port: 65535,
}, },
}, },
@@ -41,9 +46,67 @@ var addrTests = []struct {
Port: 80, Port: 80,
}, },
}, },
// Invalid addresses.
{ {
expAddr: unknownAddrType{}, expAddr: unknownAddrType{},
serErr: ErrUnknownAddressType, serErr: ErrUnknownAddressType.Error(),
},
{
expAddr: &net.TCPAddr{
// Remove last byte of IPv4 address.
IP: testIP4[:len(testIP4)-1],
Port: 12345,
},
serErr: "unable to encode",
},
{
expAddr: &net.TCPAddr{
// Add an extra byte of IPv4 address.
IP: append(testIP4, 0xff),
Port: 12345,
},
serErr: "unable to encode",
},
{
expAddr: &net.TCPAddr{
// Remove last byte of IPv6 address.
IP: testIP6[:len(testIP6)-1],
Port: 65535,
},
serErr: "unable to encode",
},
{
expAddr: &net.TCPAddr{
// Add an extra byte to the IPv6 address.
IP: append(testIP6, 0xff),
Port: 65535,
},
serErr: "unable to encode",
},
{
expAddr: &tor.OnionAddr{
// Invalid suffix.
OnionService: "vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd.inion",
Port: 80,
},
serErr: "invalid suffix",
},
{
expAddr: &tor.OnionAddr{
// Invalid length.
OnionService: "vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyy.onion",
Port: 80,
},
serErr: "unknown onion service length",
},
{
expAddr: &tor.OnionAddr{
// Invalid encoding.
OnionService: "vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyA.onion",
Port: 80,
},
serErr: "illegal base32",
}, },
} }
@@ -55,11 +118,21 @@ func TestAddrSerialization(t *testing.T) {
var b bytes.Buffer var b bytes.Buffer
for _, test := range addrTests { for _, test := range addrTests {
err := serializeAddr(&b, test.expAddr) err := serializeAddr(&b, test.expAddr)
if err != test.serErr { switch {
case err == nil && test.serErr != "":
t.Fatalf("expected serialization err for addr %v",
test.expAddr)
case err != nil && test.serErr == "":
t.Fatalf("unexpected serialization err for addr %v: %v",
test.expAddr, err)
case err != nil && !strings.Contains(err.Error(), test.serErr):
t.Fatalf("unexpected serialization err for addr %v, "+ t.Fatalf("unexpected serialization err for addr %v, "+
"want: %v, got %v", "want: %v, got %v", test.expAddr, test.serErr,
test.expAddr, test.serErr, err) err)
} else if test.serErr != nil {
case err != nil:
continue continue
} }