Skip to content

Commit

Permalink
Network: validate hostname according to RFC 6125 (#1139)
Browse files Browse the repository at this point in the history
Co-authored-by: Rein Krul <[email protected]>
  • Loading branch information
reinkrul and reinkrul authored May 23, 2022
1 parent 02f6c4a commit 9a60334
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 19 deletions.
15 changes: 6 additions & 9 deletions network/transport/grpc/authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"google.golang.org/grpc/credentials"
grpcPeer "google.golang.org/grpc/peer"
"net/url"
"strings"
)

// Authenticator verifies node identities.
Expand Down Expand Up @@ -61,7 +60,7 @@ func (t tlsAuthenticator) Authenticate(nodeDID did.DID, grpcPeer grpcPeer.Peer,
if !isTLS || len(tlsInfo.State.PeerCertificates) == 0 {
return withOverride(peer, fmt.Errorf("missing TLS info (nodeDID=%s)", nodeDID))
}
dnsNames := tlsInfo.State.PeerCertificates[0].DNSNames
peerCertificate := tlsInfo.State.PeerCertificates[0]

// Resolve NutsComm endpoint of contained in DID document associated with node DID
nutsCommService, err := t.serviceResolver.Resolve(doc.MakeServiceReference(nodeDID, transport.NutsCommServiceType), doc.DefaultMaxServiceReferenceDepth)
Expand All @@ -76,13 +75,11 @@ func (t tlsAuthenticator) Authenticate(nodeDID did.DID, grpcPeer grpcPeer.Peer,
}

// Check whether one of the DNS names matches one of the NutsComm endpoints
hostname := nutsCommURL.Hostname()
for _, dnsName := range dnsNames {
if strings.EqualFold(dnsName, hostname) {
log.Logger().Debugf("Connection successfully authenticated (nodeDID=%s)", nodeDID)
peer.NodeDID = nodeDID
return peer, nil
}
err = peerCertificate.VerifyHostname(nutsCommURL.Hostname())
if err == nil {
log.Logger().Debugf("Connection successfully authenticated (nodeDID=%s)", nodeDID)
peer.NodeDID = nodeDID
return peer, nil
}
return withOverride(peer, fmt.Errorf("none of the DNS names in the peer's TLS certificate match the NutsComm endpoint (nodeDID=%s)", nodeDID))
}
Expand Down
28 changes: 18 additions & 10 deletions network/transport/grpc/authenticator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ import (
)

func Test_tlsAuthenticator_Authenticate(t *testing.T) {
data, _ := os.ReadFile("test/nuts.nl.cer")
cert, _ := x509.ParseCertificate(data)
certData, _ := os.ReadFile("test/nuts.nl.cer")
cert, _ := x509.ParseCertificate(certData)
wildcardCertData, _ := os.ReadFile("test/wildcard.nuts.nl.cer")
wildcardCert, _ := x509.ParseCertificate(wildcardCertData)
grpcPeer := peer.Peer{
AuthInfo: credentials.TLSInfo{
State: tls.ConnectionState{
Expand All @@ -54,13 +56,6 @@ func Test_tlsAuthenticator_Authenticate(t *testing.T) {
serviceResolver := doc.NewMockServiceResolver(ctrl)
serviceResolver.EXPECT().Resolve(query, gomock.Any()).Return(did.Service{ServiceEndpoint: "grpc://nuts.nl:5555"}, nil)
authenticator := NewTLSAuthenticator(serviceResolver)
grpcPeer := peer.Peer{
AuthInfo: credentials.TLSInfo{
State: tls.ConnectionState{
PeerCertificates: []*x509.Certificate{cert},
},
},
}

authenticatedPeer, err := authenticator.Authenticate(nodeDID, grpcPeer, transport.Peer{})

Expand All @@ -74,10 +69,23 @@ func Test_tlsAuthenticator_Authenticate(t *testing.T) {
serviceResolver := doc.NewMockServiceResolver(ctrl)
serviceResolver.EXPECT().Resolve(query, gomock.Any()).Return(did.Service{ServiceEndpoint: "grpc://Nuts.nl:5555"}, nil)
authenticator := NewTLSAuthenticator(serviceResolver)

authenticatedPeer, err := authenticator.Authenticate(nodeDID, grpcPeer, transport.Peer{})

if !assert.NoError(t, err) {
return
}
assert.Equal(t, authenticatedPeer.NodeDID, nodeDID)
})
t.Run("ok - wildcard comparison", func(t *testing.T) {
ctrl := gomock.NewController(t)
serviceResolver := doc.NewMockServiceResolver(ctrl)
serviceResolver.EXPECT().Resolve(query, gomock.Any()).Return(did.Service{ServiceEndpoint: "grpc://node.nuts.nl:5555"}, nil)
authenticator := NewTLSAuthenticator(serviceResolver)
grpcPeer := peer.Peer{
AuthInfo: credentials.TLSInfo{
State: tls.ConnectionState{
PeerCertificates: []*x509.Certificate{cert},
PeerCertificates: []*x509.Certificate{wildcardCert},
},
},
}
Expand Down
Binary file added network/transport/grpc/test/wildcard.nuts.nl.cer
Binary file not shown.

0 comments on commit 9a60334

Please sign in to comment.