all ads now properly validated before storing

This commit is contained in:
l0k18
2023-06-17 10:10:00 +01:00
parent 5380d5f01e
commit e315ebd3dd
6 changed files with 132 additions and 102 deletions

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"github.com/indra-labs/indra/pkg/ad"
"github.com/indra-labs/indra/pkg/onions/adload"
"github.com/indra-labs/indra/pkg/util/slice"
"github.com/libp2p/go-libp2p/core/peer"
@@ -67,61 +68,67 @@ func (ng *Engine) HandleAd(p *pubsub.Message, ctx context.Context) (e error) {
if e = c.Decode(s); fails(e) {
return
}
var ok bool
switch c.(type) {
case *adaddress.Ad:
log.D.Ln("received", reflect.TypeOf(c), "from gossip network")
if addr, ok := c.(*adaddress.Ad); !ok {
var addr *adaddress.Ad
if addr, ok = c.(*adaddress.Ad); !ok {
return fmt.Errorf(ErrWrongTypeDecode,
adaddress.Magic, reflect.TypeOf(c).String())
} else {
// If we got to here now we can add to the PeerStore.
log.D.S("new ad for address:", c)
var id peer.ID
if id, e = peer.IDFromPublicKey(addr.Key); fails(e) {
return
}
if e = ng.Listener.Host.
Peerstore().Put(id, "services", s.GetAll().ToBytes()); fails(e) {
return
}
} else if !addr.Validate() {
return errors.New("addr ad failed validation")
}
// If we got to here now we can add to the PeerStore.
log.D.S("new ad for address:", c)
var id peer.ID
if id, e = peer.IDFromPublicKey(addr.Key); fails(e) {
return
}
if e = ng.Listener.Host.
Peerstore().Put(id, "services", s.GetAll().ToBytes()); fails(e) {
return
}
case *adintro.Ad:
log.D.Ln("received", reflect.TypeOf(c), "from gossip network")
if intr, ok := c.(*adintro.Ad); !ok {
var intr *adintro.Ad
if intr, ok = c.(*adintro.Ad); !ok {
return fmt.Errorf(ErrWrongTypeDecode,
adintro.Magic, reflect.TypeOf(c).String())
} else {
// If we got to here now we can add to the PeerStore.
log.D.S("new ad for intro:", c)
var id peer.ID
if id, e = peer.IDFromPublicKey(intr.Key); fails(e) {
return
}
if e = ng.Listener.Host.
Peerstore().Put(id, "services", s.GetAll().ToBytes()); fails(e) {
return
}
} else if !intr.Validate() {
return errors.New("intro ad failed validation")
}
// If we got to here now we can add to the PeerStore.
log.D.S("new ad for intro:", c)
var id peer.ID
if id, e = peer.IDFromPublicKey(intr.Key); fails(e) {
return
}
if e = ng.Listener.Host.
Peerstore().Put(id, "services", s.GetAll().ToBytes()); fails(e) {
return
}
case *adload.Ad:
log.D.Ln("received", reflect.TypeOf(c), "from gossip network")
if lod, ok := c.(*adload.Ad); !ok {
var lod *adload.Ad
if lod, ok = c.(*adload.Ad); !ok {
return fmt.Errorf(ErrWrongTypeDecode,
adaddress.Magic, reflect.TypeOf(c).String())
} else {
// If we got to here now we can add to the PeerStore.
log.D.S("new ad for load:", c)
var id peer.ID
if id, e = peer.IDFromPublicKey(lod.Key); fails(e) {
return
}
if e = ng.Listener.Host.
Peerstore().Put(id, "services", s.GetAll().ToBytes()); fails(e) {
return
}
} else if !lod.Validate() {
return errors.New("load ad failed validation")
}
// If we got to here now we can add to the PeerStore.
log.D.S("new ad for load:", c)
var id peer.ID
if id, e = peer.IDFromPublicKey(lod.Key); fails(e) {
return
}
if e = ng.Listener.Host.
Peerstore().Put(id, "services", s.GetAll().ToBytes()); fails(e) {
return
}
case *adpeer.Ad:
log.D.Ln("received", reflect.TypeOf(c), "from gossip network")
var ok bool
var pa *adpeer.Ad
if pa, ok = c.(*adpeer.Ad); !ok {
return fmt.Errorf(ErrWrongTypeDecode,
@@ -141,21 +148,61 @@ func (ng *Engine) HandleAd(p *pubsub.Message, ctx context.Context) (e error) {
}
case *adservices.Ad:
log.D.Ln("received", reflect.TypeOf(c), "from gossip network")
if serv, ok := c.(*adservices.Ad); !ok {
var sa *adservices.Ad
if sa, ok = c.(*adservices.Ad); !ok {
return fmt.Errorf(ErrWrongTypeDecode,
adservices.Magic, reflect.TypeOf(c).String())
} else {
// If we got to here now we can add to the PeerStore.
log.D.S("new ad for services:", c)
var id peer.ID
if id, e = peer.IDFromPublicKey(serv.Key); fails(e) {
return
}
if e = ng.Listener.Host.
Peerstore().Put(id, "services", s.GetAll().ToBytes()); fails(e) {
return
}
} else if !sa.Validate() {
return errors.New("services ad failed validation")
}
// If we got to here now we can add to the PeerStore.
log.D.S("new ad for services:", c)
var id peer.ID
if id, e = peer.IDFromPublicKey(sa.Key); fails(e) {
return
}
if e = ng.Listener.Host.
Peerstore().Put(id, "services", s.GetAll().ToBytes()); fails(e) {
return
}
}
return
}
func (ng *Engine) GetPeerRecord(id peer.ID, key string) (add ad.Ad, e error) {
var a interface{}
if a, e = ng.Listener.Host.Peerstore().Get(id, key); fails(e) {
return
}
var ok bool
var adb slice.Bytes
if adb, ok = a.(slice.Bytes); !ok {
e = errors.New("peer record did not decode slice.Bytes")
return
}
s := splice.NewFrom(adb)
c := reg.Recognise(s)
if c == nil {
e = errors.New("message not recognised")
return
}
if e = c.Decode(s); fails(e) {
return
}
if add, ok = c.(ad.Ad); !ok {
e = errors.New("peer record did not decode as Ad")
}
return
}
func (ng *Engine) ClearPeerRecord(id peer.ID, key string) (add ad.Ad, e error) {
if _, e = ng.Listener.Host.Peerstore().Get(id, key); fails(e) {
return
}
if e = ng.Listener.Host.
Peerstore().Put(id, key, []byte{}); fails(e) {
return
}
return
}

View File

@@ -87,11 +87,11 @@ func (x *Ad) Len() int { return Len }
func (x *Ad) Magic() string { return Magic }
func (x *Ad) Splice(s *splice.Splice) {
x.SpliceWithoutSig(s)
x.SpliceNoSig(s)
s.Signature(x.Sig)
}
func (x *Ad) SpliceWithoutSig(s *splice.Splice) {
func (x *Ad) SpliceNoSig(s *splice.Splice) {
var e error
var ap netip.AddrPort
if ap, e = multi.AddrToAddrPort(x.Addr); fails(e) {
@@ -107,13 +107,13 @@ func (x *Ad) SpliceWithoutSig(s *splice.Splice) {
func (x *Ad) Validate() bool {
s := splice.New(Len - magic.Len)
x.SpliceWithoutSig(s)
x.SpliceNoSig(s)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
key, e := x.Sig.Recover(hash)
if fails(e) {
return false
}
if key.Equals(x.Key) {
if key.Equals(x.Key) && x.Expiry.After(time.Now()) {
return true
}
return false
@@ -133,7 +133,7 @@ func New(id nonce.ID, key *crypto.Prv,
Addr: ma,
}
s := splice.New(Len)
peerAd.SpliceWithoutSig(s)
peerAd.SpliceNoSig(s)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
var e error
if peerAd.Sig, e = crypto.Sign(key, hash); fails(e) {

View File

@@ -125,25 +125,24 @@ func New(
) (in *Ad) {
pk := crypto.DerivePub(key)
s := splice.New(Len)
IntroSplice(s, id, pk, ap, relayRate, port, expires)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
var e error
var sign crypto.SigBytes
if sign, e = crypto.Sign(key, hash); fails(e) {
return nil
}
in = &Ad{
Ad: adproto.Ad{
ID: id,
Key: pk,
Expiry: time.Now().Add(adproto.TTL),
Sig: sign,
Expiry: expires,
},
AddrPort: ap,
RelayRate: relayRate,
Port: port,
}
s := splice.New(in.Len())
in.SpliceNoSig(s)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
var e error
if in.Sig, e = crypto.Sign(key, hash); fails(e) {
return nil
}
return
}

View File

@@ -7,7 +7,6 @@ import (
"github.com/indra-labs/indra/pkg/engine/coding"
"github.com/indra-labs/indra/pkg/engine/magic"
"github.com/indra-labs/indra/pkg/engine/sess"
"github.com/indra-labs/indra/pkg/onions/adintro"
"github.com/indra-labs/indra/pkg/onions/adproto"
"github.com/indra-labs/indra/pkg/onions/reg"
log2 "github.com/indra-labs/indra/pkg/proc/log"
@@ -24,7 +23,7 @@ var (
const (
Magic = "load"
Len = adproto.Len +1
Len = adproto.Len + 1
)
// Ad stores a specification for the fee rate and existence of a peer.
@@ -39,24 +38,22 @@ var _ coding.Codec = &Ad{}
func New(id nonce.ID, key *crypto.Prv, load byte,
expiry time.Time) (sv *Ad) {
s := splice.New(adintro.Len)
k := crypto.DerivePub(key)
Splice(s, id, k, load, expiry)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
var e error
var sign crypto.SigBytes
if sign, e = crypto.Sign(key, hash); fails(e) {
return nil
}
sv = &Ad{
Ad: adproto.Ad{
ID: id,
Key: k,
Expiry: time.Now().Add(adproto.TTL),
Sig: sign,
Expiry: expiry,
},
Load: load,
}
s := splice.New(sv.Len())
sv.SpliceNoSig(s)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
var e error
if sv.Sig, e = crypto.Sign(key, hash); fails(e) {
return nil
}
return
}
@@ -83,17 +80,6 @@ func (x *Ad) Len() int { return Len }
func (x *Ad) Magic() string { return "" }
func (x *Ad) Sign(prv *crypto.Prv) (e error) {
s := splice.New(x.Len())
x.SpliceNoSig(s)
var b crypto.SigBytes
if b, e = crypto.Sign(prv, sha256.Single(s.GetUntil(s.GetCursor()))); fails(e) {
return
}
copy(x.Sig[:], b[:])
return nil
}
func (x *Ad) Splice(s *splice.Splice) {
x.SpliceNoSig(s)
s.Signature(x.Sig)
@@ -104,14 +90,14 @@ func (x *Ad) SpliceNoSig(s *splice.Splice) {
}
func (x *Ad) Validate() (valid bool) {
s := splice.New(adintro.Len - magic.Len)
s := splice.New(x.Len() - magic.Len)
x.SpliceNoSig(s)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
key, e := x.Sig.Recover(hash)
if fails(e) {
return false
}
if key.Equals(x.Key) {
if key.Equals(x.Key) && x.Expiry.After(time.Now()) {
return true
}
return false

View File

@@ -76,11 +76,11 @@ func (x *Ad) Len() int { return Len }
func (x *Ad) Magic() string { return Magic }
func (x *Ad) Splice(s *splice.Splice) {
x.SpliceWithoutSig(s)
x.SpliceNoSig(s)
s.Signature(x.Sig)
}
func (x *Ad) SpliceWithoutSig(s *splice.Splice) {
func (x *Ad) SpliceNoSig(s *splice.Splice) {
s.Magic(Magic).
ID(x.ID).
Pubkey(x.Key).
@@ -89,7 +89,7 @@ func (x *Ad) SpliceWithoutSig(s *splice.Splice) {
func (x *Ad) Validate() bool {
s := splice.New(Len)
x.SpliceWithoutSig(s)
x.SpliceNoSig(s)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
key, e := x.Sig.Recover(hash)
if fails(e) {
@@ -111,7 +111,7 @@ func New(id nonce.ID, key *crypto.Prv,
Expiry: expiry,
}
s := splice.New(Len - magic.Len)
protoAd.SpliceWithoutSig(s)
protoAd.SpliceNoSig(s)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
var e error
if protoAd.Sig, e = crypto.Sign(key, hash); fails(e) {

View File

@@ -49,24 +49,22 @@ var _ coding.Codec = &Ad{}
func New(id nonce.ID, key *crypto.Prv, services []Service,
expiry time.Time) (sv *Ad) {
s := splice.New(adintro.Len)
k := crypto.DerivePub(key)
ServiceSplice(s, id, k, services, expiry)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
var e error
var sign crypto.SigBytes
if sign, e = crypto.Sign(key, hash); fails(e) {
return nil
}
sv = &Ad{
Ad: adproto.Ad{
ID: id,
Key: k,
Expiry: time.Now().Add(adproto.TTL),
Sig: sign,
},
Services: services,
}
s := splice.New(adintro.Len)
sv.SpliceNoSig(s)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
var e error
if sv.Sig, e = crypto.Sign(key, hash); fails(e) {
return nil
}
return
}