[#622] pkg/network: Add multiaddress validation

Validation checks:
1. if address can be parsed by network package;
2. if address contains correct amount of protocols;
3. if address's protocols are in correct order.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
Pavel Karpy 2021-06-18 13:11:57 +03:00 committed by Pavel Karpy
parent 16e9e726ff
commit ea5c74e761
2 changed files with 151 additions and 0 deletions

87
pkg/network/validation.go Normal file
View file

@ -0,0 +1,87 @@
package network
import (
"errors"
"fmt"
"github.com/nspcc-dev/neofs-api-go/pkg/netmap"
)
const (
// maxProtocolsAmount is maximal amount of protocols
// in multiaddress after parsing with network.AddressFromString
maxProtocolsAmount = 3
// minProtocolsAmount is minimal amount of protocols
// in multiaddress after parsing with network.AddressFromString:
// host(ip) and port.
minProtocolsAmount = 2
// network protocols
dns, ip4, ip6 = "dns4", "ip4", "ip6"
// transport protocols
tcp = "tcp"
)
var (
errIncorrectProtocolAmount = errors.New("numbers of protocols in multiaddress incorrect")
errUnsupportedNetworkProtocol = errors.New("unsupported network protocol in multiaddress")
errUnsupportedTransportProtocol = errors.New("unsupported transport protocol in multiaddress")
errUnsupportedPresentationProtocol = errors.New("unsupported presentation protocol in multiaddress")
)
// VerifyMultiAddress validates multiaddress of n.
//
// If n's address contains more than 3 protocols
// or less than 2 protocols an error returns.
//
// If n's address's protocol order is incorrect
// an error returns.
//
// Correct composition(and order from low to high level)
// of protocols:
//
// 1. dns4/ip4/ip6
// 2. tcp
// 3. tls(optional, may be absent)
//
func VerifyMultiAddress(ni *netmap.NodeInfo) error {
// check if it can be parsed to network.Address
var netAddr Address
err := netAddr.FromString(ni.Address())
if err != nil {
return fmt.Errorf("could not parse multiaddr from NodeInfo: %w", err)
}
// check amount of protocols and its order
return checkProtocols(netAddr)
}
func checkProtocols(a Address) error {
pp := a.ma.Protocols()
parsedProtocolsAmount := len(pp)
if parsedProtocolsAmount > maxProtocolsAmount || parsedProtocolsAmount < minProtocolsAmount {
return errIncorrectProtocolAmount
}
switch pp[0].Name {
case dns, ip4, ip6:
default:
return errUnsupportedNetworkProtocol
}
if pp[1].Name != tcp {
return errUnsupportedTransportProtocol
}
if parsedProtocolsAmount != minProtocolsAmount {
if pp[2].Name != tlsProtocolName {
return errUnsupportedPresentationProtocol
}
}
return nil
}

View file

@ -0,0 +1,64 @@
package network
import (
"testing"
"github.com/nspcc-dev/neofs-api-go/pkg/netmap"
"github.com/stretchr/testify/require"
)
type testCase struct {
input string
err error
}
func TestVerifyMultiAddress_Order(t *testing.T) {
testCases := []testCase{
{
input: "/ip4/1.2.3.4/tcp/80",
err: nil,
},
{
input: "/ip6/1.2.3.4/tcp/80",
err: nil,
},
{
input: "/dns4/1.2.3.4/tcp/80",
err: nil,
},
{
input: "/dns4/1.2.3.4/tcp/80/tls",
err: nil,
},
{
input: "/tls/dns4/1.2.3.4/tcp/80",
err: errUnsupportedNetworkProtocol,
},
{
input: "/dns4/1.2.3.4/tls/tcp/80",
err: errUnsupportedTransportProtocol,
},
{
input: "/dns4/1.2.3.4/tcp/80/wss",
err: errUnsupportedPresentationProtocol,
},
}
for _, test := range testCases {
ni := constructNodeInfo(test.input)
if test.err != nil {
require.EqualError(t, test.err, VerifyMultiAddress(ni).Error())
} else {
require.NoError(t, VerifyMultiAddress(ni))
}
}
}
func constructNodeInfo(address string) *netmap.NodeInfo {
ni := new(netmap.NodeInfo)
ni.SetAddress(address)
return ni
}