[#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:
parent
16e9e726ff
commit
ea5c74e761
2 changed files with 151 additions and 0 deletions
87
pkg/network/validation.go
Normal file
87
pkg/network/validation.go
Normal 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
|
||||||
|
}
|
64
pkg/network/validation_test.go
Normal file
64
pkg/network/validation_test.go
Normal 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
|
||||||
|
}
|
Loading…
Reference in a new issue