fix: validate signed envelopes

This commit is contained in:
Richard Ramos 2021-10-04 21:36:46 -04:00
parent b0065d5318
commit b53661c585
No known key found for this signature in database
GPG Key ID: 80D4B01265FDFE8F
2 changed files with 47 additions and 9 deletions

View File

@ -14,6 +14,7 @@ import (
"github.com/libp2p/go-libp2p-core/host"
inet "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/peerstore"
)
var (
@ -187,10 +188,10 @@ func (rp *rendezvousPoint) Discover(ctx context.Context, ns string, limit int) (
r := ggio.NewDelimitedReader(s, inet.MessageSizeMax)
w := ggio.NewDelimitedWriter(s)
return discoverQuery(ns, limit, r, w)
return rp.discoverQuery(ns, limit, r, w)
}
func discoverQuery(ns string, limit int, r ggio.Reader, w ggio.Writer) ([]Registration, error) {
func (rp *rendezvousPoint) discoverQuery(ns string, limit int, r ggio.Reader, w ggio.Writer) ([]Registration, error) {
req := newDiscoverMessage(ns, limit)
err := w.WriteMsg(req)
if err != nil {
@ -215,12 +216,32 @@ func discoverQuery(ns string, limit int, r ggio.Reader, w ggio.Writer) ([]Regist
regs := res.GetDiscoverResponse().GetRegistrations()
result := make([]Registration, 0, len(regs))
for _, reg := range regs {
pi, err := pbToPeerRecord(reg.GetPeer())
envelope, err := pbToEnvelope(reg.GetPeer())
if err != nil {
log.Errorf("Invalid peer info: %s", err.Error())
continue
}
result = append(result, Registration{Peer: pi, Ns: reg.GetNs(), Ttl: int(reg.GetTtl())})
cab, ok := peerstore.GetCertifiedAddrBook(rp.host.Peerstore())
if !ok {
return nil, errors.New("a certified addr book is required")
}
_, err = cab.ConsumePeerRecord(envelope, time.Duration(reg.Ttl))
if err != nil {
log.Errorf("Invalid peer info: %s", err.Error())
continue
}
var record peer.PeerRecord
err = envelope.TypedRecord(&record)
if err != nil {
log.Errorf("Invalid peer record: %s", err.Error())
continue
}
result = append(result, Registration{Peer: peer.AddrInfo{ID: record.PeerID, Addrs: record.Addrs}, Ns: reg.GetNs(), Ttl: int(reg.GetTtl())})
}
return result, nil
@ -238,11 +259,11 @@ func (rp *rendezvousPoint) DiscoverAsync(ctx context.Context, ns string) (<-chan
}
ch := make(chan Registration)
go discoverAsync(ctx, ns, s, ch)
go rp.discoverAsync(ctx, ns, s, ch)
return ch, nil
}
func discoverAsync(ctx context.Context, ns string, s inet.Stream, ch chan Registration) {
func (rp *rendezvousPoint) discoverAsync(ctx context.Context, ns string, s inet.Stream, ch chan Registration) {
defer s.Reset()
defer close(ch)
@ -257,7 +278,7 @@ func discoverAsync(ctx context.Context, ns string, s inet.Stream, ch chan Regist
)
for {
regs, err = discoverQuery(ns, batch, r, w)
regs, err = rp.discoverQuery(ns, batch, r, w)
if err != nil {
// TODO robust error recovery
// - handle closed streams with backoff + new stream

View File

@ -61,7 +61,7 @@ func newRegisterMessage(privKey libp2pCrypto.PrivKey, ns string, pi peer.AddrInf
return nil, err
}
var peerEnvelop *record_pb.Envelope
peerEnvelop := &record_pb.Envelope{}
if err = proto.Unmarshal(envPayload, peerEnvelop); err != nil {
return nil, err
}
@ -89,6 +89,19 @@ func marshalEnvelope(pbEnvelope *record_pb.Envelope) ([]byte, error) {
return proto.Marshal(pbEnvelope)
}
func pbToEnvelope(pbEnvelope *record_pb.Envelope) (*record.Envelope, error) {
if pbEnvelope == nil {
return nil, errors.New("missing envelope information")
}
envelopeBytes, err := proto.Marshal(pbEnvelope)
if err != nil {
return nil, err
}
return record.UnmarshalEnvelope(envelopeBytes)
}
func pbToPeerRecord(pbEnvelope *record_pb.Envelope) (peer.AddrInfo, error) {
if pbEnvelope == nil {
return peer.AddrInfo{}, errors.New("missing envelope information")
@ -99,7 +112,7 @@ func pbToPeerRecord(pbEnvelope *record_pb.Envelope) (peer.AddrInfo, error) {
return peer.AddrInfo{}, err
}
_, rec, err := record.ConsumeEnvelope(envelopeBytes, peer.PeerRecordEnvelopeDomain)
envelope, rec, err := record.ConsumeEnvelope(envelopeBytes, peer.PeerRecordEnvelopeDomain)
if err != nil {
return peer.AddrInfo{}, err
}
@ -109,6 +122,10 @@ func pbToPeerRecord(pbEnvelope *record_pb.Envelope) (peer.AddrInfo, error) {
return peer.AddrInfo{}, errors.New("invalid peer record")
}
if !peerRecord.PeerID.MatchesPublicKey(envelope.PublicKey) {
return peer.AddrInfo{}, errors.New("signing key does not match peer record")
}
return peer.AddrInfo{ID: peerRecord.PeerID, Addrs: peerRecord.Addrs}, nil
}