forked from TrueCloudLab/frostfs-node
[#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>support/v0.27
parent
16e9e726ff
commit
ea5c74e761
|
@ -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
|
||||
}
|
|
@ -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 New Issue