remove introquery start on dht key/value schema
This commit is contained in:
@@ -35,7 +35,7 @@ type Hash [32]byte
|
|||||||
// return hex.EncodeToString(h[:])
|
// return hex.EncodeToString(h[:])
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func (h Hash) Based32String() string {
|
func (h Hash) String() string {
|
||||||
return enc(h[:])[:52]
|
return enc(h[:])[:52]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
51
pkg/engine/advert/advert.go
Normal file
51
pkg/engine/advert/advert.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package advert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/multiformats/go-multiaddr"
|
||||||
|
|
||||||
|
"git-indra.lan/indra-labs/indra/pkg/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Peer is the root identity document for an Indra peer. It is indexed by the
|
||||||
|
// Identity field, its public key. The slices found below it are derived via
|
||||||
|
// concatenation of strings with the keys and hashing to generate a derived
|
||||||
|
// field index, used to search the DHT for matches.
|
||||||
|
//
|
||||||
|
// The data stored for Peer must be signed with the key claimed by the Identity.
|
||||||
|
// For hidden services the address fields are signed in the DHT by the hidden
|
||||||
|
// service from their introduction solicitation, and the index from the current
|
||||||
|
// set is given by the hidden service.
|
||||||
|
type Peer struct {
|
||||||
|
Identity crypto.PubBytes
|
||||||
|
RelayRate int
|
||||||
|
// Addresses - first is address, nil for hidden services,
|
||||||
|
// hidden services have more than one, 6 or more are kept active.
|
||||||
|
Addresses []*Address
|
||||||
|
Services []Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address entries are stored with an index generated by the combination of the
|
||||||
|
// 8 bit form of the index from the Peer struct field, after the word "address/"
|
||||||
|
// followed by a forward slash, and then hashed. A zero entry can be used to
|
||||||
|
// mark the end for scanning, if the list shrinks.
|
||||||
|
type Address struct {
|
||||||
|
Index byte
|
||||||
|
multiaddr.Multiaddr
|
||||||
|
// Expiry is zero for relay's public address, and something for hidden
|
||||||
|
// services.
|
||||||
|
Expiry time.Time
|
||||||
|
crypto.SigBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service stores a specification for the fee rate and the service port, which
|
||||||
|
// must be a well known port to match with a type of service, eg 80 for web, 53
|
||||||
|
// for DNS, etc. These are also attached to the Peer entry via concatenating
|
||||||
|
// "service/" and for this a 16 bit value allowing use of the full port
|
||||||
|
// range. A zero entry can be used also to mark the end when shrinking the
|
||||||
|
// list to indicate when to stop scanning for more entries.
|
||||||
|
type Service struct {
|
||||||
|
Index uint16
|
||||||
|
Port, RelayRate int
|
||||||
|
}
|
||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
"git-indra.lan/indra-labs/indra/pkg/engine/sess"
|
"git-indra.lan/indra-labs/indra/pkg/engine/sess"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/engine/sessions"
|
"git-indra.lan/indra-labs/indra/pkg/engine/sessions"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/util/slice"
|
"git-indra.lan/indra-labs/indra/pkg/util/slice"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/util/splice"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ng *Engine) SendExit(port uint16, msg slice.Bytes, id nonce.ID,
|
func (ng *Engine) SendExit(port uint16, msg slice.Bytes, id nonce.ID,
|
||||||
@@ -69,41 +68,10 @@ func (ng *Engine) SendHiddenService(id nonce.ID, key *crypto.Prv,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ng *Engine) SendIntroQuery(id nonce.ID, hsk *crypto.Pub,
|
func (ng *Engine) SendHiddenMessage(mp *onions.Message, hook responses.Callback) (id nonce.ID) {
|
||||||
alice, bob *sessions.Data, hook func(in *onions.Intro)) {
|
|
||||||
|
|
||||||
fn := func(id nonce.ID, ifc interface{}, b slice.Bytes) (e error) {
|
|
||||||
s := splice.Load(b, slice.NewCursor())
|
|
||||||
on := onions.Recognise(s)
|
|
||||||
if e = on.Decode(s); fails(e) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var oni *onions.Intro
|
|
||||||
var ok bool
|
|
||||||
if oni, ok = on.(*onions.Intro); !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
hook(oni)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.D.Ln("sending introquery")
|
|
||||||
hops := sess.StandardCircuit()
|
|
||||||
s := make(sessions.Sessions, len(hops))
|
|
||||||
s[2] = bob
|
|
||||||
s[5] = alice
|
|
||||||
se := ng.Manager.SelectHops(hops, s, "sendintroquery")
|
|
||||||
var c sessions.Circuit
|
|
||||||
copy(c[:], se)
|
|
||||||
o := onions.MakeIntroQuery(id, hsk, bob, alice, c, ng.KeySet)
|
|
||||||
res := PostAcctOnion(ng.Manager, o)
|
|
||||||
log.D.Ln(res.ID)
|
|
||||||
ng.Manager.SendWithOneHook(c[0].Node.AddrPort, res, fn, ng.Responses)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ng *Engine) SendMessage(mp *onions.Message, hook responses.Callback) (id nonce.ID) {
|
|
||||||
// Add another two hops for security against unmasking.
|
// Add another two hops for security against unmasking.
|
||||||
preHops := []byte{0, 1}
|
preHops := []byte{0, 1}
|
||||||
oo := ng.Manager.SelectHops(preHops, mp.Forwards[:], "sendmessage")
|
oo := ng.Manager.SelectHops(preHops, mp.Forwards[:], "sendhiddenmessage")
|
||||||
mp.Forwards = [2]*sessions.Data{oo[0], oo[1]}
|
mp.Forwards = [2]*sessions.Data{oo[0], oo[1]}
|
||||||
o := onions.Skins{}.Message(mp, ng.KeySet)
|
o := onions.Skins{}.Message(mp, ng.KeySet)
|
||||||
res := PostAcctOnion(ng.Manager, o)
|
res := PostAcctOnion(ng.Manager, o)
|
||||||
|
|||||||
@@ -182,119 +182,119 @@ out:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEngine_SendIntroQuery(t *testing.T) {
|
// func TestEngine_SendIntroQuery(t *testing.T) {
|
||||||
log2.SetLogLevel(log2.Info)
|
// log2.SetLogLevel(log2.Info)
|
||||||
var clients []*Engine
|
// var clients []*Engine
|
||||||
var e error
|
// var e error
|
||||||
const nCircuits = 10
|
// const nCircuits = 10
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
// ctx, cancel := context.WithCancel(context.Background())
|
||||||
if clients, e = CreateNMockCircuits(nCircuits, nCircuits,
|
// if clients, e = CreateNMockCircuits(nCircuits, nCircuits,
|
||||||
ctx); fails(e) {
|
// ctx); fails(e) {
|
||||||
t.Error(e)
|
// t.Error(e)
|
||||||
t.FailNow()
|
// t.FailNow()
|
||||||
}
|
// }
|
||||||
client := clients[0]
|
// client := clients[0]
|
||||||
// Start up the clients.
|
// // Start up the clients.
|
||||||
for _, v := range clients {
|
// for _, v := range clients {
|
||||||
go v.Start()
|
// go v.Start()
|
||||||
}
|
// }
|
||||||
var wg sync.WaitGroup
|
// var wg sync.WaitGroup
|
||||||
var counter atomic.Int32
|
// var counter atomic.Int32
|
||||||
quit := qu.T()
|
// quit := qu.T()
|
||||||
go func() {
|
// go func() {
|
||||||
for {
|
// for {
|
||||||
select {
|
// select {
|
||||||
case <-time.After(time.Second * 4):
|
// case <-time.After(time.Second * 4):
|
||||||
quit.Q()
|
// quit.Q()
|
||||||
t.Error("MakeHiddenService test failed")
|
// t.Error("MakeHiddenService test failed")
|
||||||
case <-quit:
|
// case <-quit:
|
||||||
for i := 0; i < int(counter.Load()); i++ {
|
// for i := 0; i < int(counter.Load()); i++ {
|
||||||
wg.Done()
|
// wg.Done()
|
||||||
}
|
// }
|
||||||
for _, v := range clients {
|
// for _, v := range clients {
|
||||||
v.Shutdown()
|
// v.Shutdown()
|
||||||
}
|
// }
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}()
|
// }()
|
||||||
for i := 0; i < nCircuits*nCircuits/2; i++ {
|
// for i := 0; i < nCircuits*nCircuits/2; i++ {
|
||||||
wg.Add(1)
|
// wg.Add(1)
|
||||||
counter.Inc()
|
// counter.Inc()
|
||||||
e = clients[0].BuyNewSessions(1000000, func() {
|
// e = clients[0].BuyNewSessions(1000000, func() {
|
||||||
wg.Done()
|
// wg.Done()
|
||||||
counter.Dec()
|
// counter.Dec()
|
||||||
})
|
// })
|
||||||
if fails(e) {
|
// if fails(e) {
|
||||||
wg.Done()
|
// wg.Done()
|
||||||
counter.Dec()
|
// counter.Dec()
|
||||||
}
|
// }
|
||||||
wg.Wait()
|
// wg.Wait()
|
||||||
}
|
// }
|
||||||
var idPrv *crypto.Prv
|
// var idPrv *crypto.Prv
|
||||||
if idPrv, e = crypto.GeneratePrvKey(); fails(e) {
|
// if idPrv, e = crypto.GeneratePrvKey(); fails(e) {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
id := nonce.NewID()
|
// id := nonce.NewID()
|
||||||
introducerHops := client.Manager.GetSessionsAtHop(2)
|
// introducerHops := client.Manager.GetSessionsAtHop(2)
|
||||||
var introducer *sessions.Data
|
// var introducer *sessions.Data
|
||||||
if len(introducerHops) > 1 {
|
// if len(introducerHops) > 1 {
|
||||||
cryptorand.Shuffle(len(introducerHops), func(i, j int) {
|
// cryptorand.Shuffle(len(introducerHops), func(i, j int) {
|
||||||
introducerHops[i], introducerHops[j] = introducerHops[j], introducerHops[i]
|
// introducerHops[i], introducerHops[j] = introducerHops[j], introducerHops[i]
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
introducer = introducerHops[0]
|
// introducer = introducerHops[0]
|
||||||
returnHops := client.Manager.GetSessionsAtHop(5)
|
// returnHops := client.Manager.GetSessionsAtHop(5)
|
||||||
var returner *sessions.Data
|
// var returner *sessions.Data
|
||||||
if len(returnHops) > 1 {
|
// if len(returnHops) > 1 {
|
||||||
cryptorand.Shuffle(len(returnHops), func(i, j int) {
|
// cryptorand.Shuffle(len(returnHops), func(i, j int) {
|
||||||
returnHops[i], returnHops[j] = returnHops[j],
|
// returnHops[i], returnHops[j] = returnHops[j],
|
||||||
returnHops[i]
|
// returnHops[i]
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
returner = returnHops[0]
|
// returner = returnHops[0]
|
||||||
svc := &services.Service{
|
// svc := &services.Service{
|
||||||
Port: 2345,
|
// Port: 2345,
|
||||||
RelayRate: 43523,
|
// RelayRate: 43523,
|
||||||
Transport: transport.NewByteChan(64),
|
// Transport: transport.NewByteChan(64),
|
||||||
}
|
// }
|
||||||
client.SendHiddenService(id, idPrv, time.Now().Add(time.Hour), returner,
|
// client.SendHiddenService(id, idPrv, time.Now().Add(time.Hour), returner,
|
||||||
introducer, svc, func(id nonce.ID, ifc interface{},
|
// introducer, svc, func(id nonce.ID, ifc interface{},
|
||||||
b slice.Bytes) (e error) {
|
// b slice.Bytes) (e error) {
|
||||||
log.I.S("hidden service callback", id, ifc, b.ToBytes())
|
// log.I.S("hidden service callback", id, ifc, b.ToBytes())
|
||||||
return
|
// return
|
||||||
})
|
// })
|
||||||
log2.SetLogLevel(log2.Trace)
|
// log2.SetLogLevel(log2.Trace)
|
||||||
// Now query everyone for the intro.
|
// // Now query everyone for the intro.
|
||||||
idPub := crypto.DerivePub(idPrv)
|
// idPub := crypto.DerivePub(idPrv)
|
||||||
peers := clients[1:]
|
// peers := clients[1:]
|
||||||
log.D.Ln("client address", client.Manager.GetLocalNodeAddressString())
|
// log.D.Ln("client address", client.Manager.GetLocalNodeAddressString())
|
||||||
for i := range peers {
|
// for i := range peers {
|
||||||
wg.Add(1)
|
// wg.Add(1)
|
||||||
counter.Inc()
|
// counter.Inc()
|
||||||
log.T.Ln("peer", i)
|
// log.T.Ln("peer", i)
|
||||||
if len(returnHops) > 1 {
|
// if len(returnHops) > 1 {
|
||||||
cryptorand.Shuffle(len(returnHops), func(i, j int) {
|
// cryptorand.Shuffle(len(returnHops), func(i, j int) {
|
||||||
returnHops[i], returnHops[j] = returnHops[j], returnHops[i]
|
// returnHops[i], returnHops[j] = returnHops[j], returnHops[i]
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
if len(introducerHops) > 1 {
|
// if len(introducerHops) > 1 {
|
||||||
cryptorand.Shuffle(len(introducerHops), func(i, j int) {
|
// cryptorand.Shuffle(len(introducerHops), func(i, j int) {
|
||||||
introducerHops[i], introducerHops[j] = introducerHops[j], introducerHops[i]
|
// introducerHops[i], introducerHops[j] = introducerHops[j], introducerHops[i]
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
client.SendIntroQuery(id, idPub, introducerHops[0], returnHops[0],
|
// client.SendIntroQuery(id, idPub, introducerHops[0], returnHops[0],
|
||||||
func(in *onions.Intro) {
|
// func(in *onions.Intro) {
|
||||||
wg.Done()
|
// wg.Done()
|
||||||
counter.Dec()
|
// counter.Dec()
|
||||||
log.I.Ln("success",
|
// log.I.Ln("success",
|
||||||
in.ID, in.Key.ToBase32Abbreviated(), in.AddrPort)
|
// in.ID, in.Key.ToBase32Abbreviated(), in.AddrPort)
|
||||||
})
|
// })
|
||||||
wg.Wait()
|
// wg.Wait()
|
||||||
}
|
// }
|
||||||
quit.Q()
|
// quit.Q()
|
||||||
cancel()
|
// cancel()
|
||||||
}
|
// }
|
||||||
|
|
||||||
func TestEngine_Message(t *testing.T) {
|
func TestEngine_Message(t *testing.T) {
|
||||||
log2.SetLogLevel(log2.Trace)
|
log2.SetLogLevel(log2.Trace)
|
||||||
@@ -429,7 +429,7 @@ func TestEngine_Message(t *testing.T) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
counter.Inc()
|
counter.Inc()
|
||||||
var ms *onions.Message
|
var ms *onions.Message
|
||||||
client.SendMessage(&onions.Message{
|
client.SendHiddenMessage(&onions.Message{
|
||||||
Address: rd.Address,
|
Address: rd.Address,
|
||||||
ID: nonce.NewID(),
|
ID: nonce.NewID(),
|
||||||
Re: rd.ID,
|
Re: rd.ID,
|
||||||
@@ -446,7 +446,7 @@ func TestEngine_Message(t *testing.T) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
counter.Inc()
|
counter.Inc()
|
||||||
client.SendMessage(&onions.Message{
|
client.SendHiddenMessage(&onions.Message{
|
||||||
Address: ms.Address,
|
Address: ms.Address,
|
||||||
ID: nonce.NewID(),
|
ID: nonce.NewID(),
|
||||||
Re: ms.ID,
|
Re: ms.ID,
|
||||||
|
|||||||
@@ -36,9 +36,7 @@ const (
|
|||||||
PaymentChanBuffers = 8
|
PaymentChanBuffers = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewNode creates a new Node. The Node for a client's self should use true in
|
// NewNode creates a new Node.
|
||||||
// the local parameter to not initialise the peer state ring buffers as it won't
|
|
||||||
// use them.
|
|
||||||
func NewNode(addr *netip.AddrPort, keys *crypto.Keys, tpt tpt.Transport,
|
func NewNode(addr *netip.AddrPort, keys *crypto.Keys, tpt tpt.Transport,
|
||||||
relayRate int) (n *Node, id nonce.ID) {
|
relayRate int) (n *Node, id nonce.ID) {
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ import (
|
|||||||
|
|
||||||
type MyIntros map[crypto.PubBytes]*Introduction
|
type MyIntros map[crypto.PubBytes]*Introduction
|
||||||
|
|
||||||
type KnownIntros map[crypto.PubBytes]*Intro
|
|
||||||
|
|
||||||
type LocalHiddenService struct {
|
type LocalHiddenService struct {
|
||||||
Prv *crypto.Prv
|
Prv *crypto.Prv
|
||||||
CurrentIntros []*Intro
|
CurrentIntros []*Intro
|
||||||
@@ -25,14 +23,12 @@ type Services map[crypto.PubBytes]*LocalHiddenService
|
|||||||
type Hidden struct {
|
type Hidden struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
MyIntros
|
MyIntros
|
||||||
KnownIntros
|
|
||||||
Services
|
Services
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHiddenrouting() *Hidden {
|
func NewHiddenrouting() *Hidden {
|
||||||
return &Hidden{
|
return &Hidden{
|
||||||
MyIntros: make(MyIntros),
|
MyIntros: make(MyIntros),
|
||||||
KnownIntros: make(KnownIntros),
|
|
||||||
Services: make(Services),
|
Services: make(Services),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,12 +68,6 @@ out:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := range hr.KnownIntros {
|
|
||||||
if hr.KnownIntros[i].ID == id {
|
|
||||||
delete(hr.KnownIntros, i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hr.Unlock()
|
hr.Unlock()
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -96,11 +86,6 @@ func (hr *Hidden) FindCloakedHiddenService(key crypto.PubKey) (
|
|||||||
return &i
|
return &i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := range hr.KnownIntros {
|
|
||||||
if crypto.Match(key, i) {
|
|
||||||
return &i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,22 +118,6 @@ func (hr *Hidden) FindIntroductionUnsafe(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hr *Hidden) FindKnownIntro(key crypto.PubBytes) (intro *Intro) {
|
|
||||||
hr.Lock()
|
|
||||||
var ok bool
|
|
||||||
if intro, ok = hr.KnownIntros[key]; ok {
|
|
||||||
}
|
|
||||||
hr.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hr *Hidden) FindKnownIntroUnsafe(key crypto.PubBytes) (intro *Intro) {
|
|
||||||
var ok bool
|
|
||||||
if intro, ok = hr.KnownIntros[key]; ok {
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hr *Hidden) Delete(key crypto.PubBytes) (header *Introduction) {
|
func (hr *Hidden) Delete(key crypto.PubBytes) (header *Introduction) {
|
||||||
hr.Lock()
|
hr.Lock()
|
||||||
var ok bool
|
var ok bool
|
||||||
@@ -159,16 +128,6 @@ func (hr *Hidden) Delete(key crypto.PubBytes) (header *Introduction) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hr *Hidden) DeleteKnownIntro(key crypto.PubBytes) (
|
|
||||||
header *Introduction) {
|
|
||||||
hr.Lock()
|
|
||||||
var ok bool
|
|
||||||
if _, ok = hr.KnownIntros[key]; ok {
|
|
||||||
delete(hr.KnownIntros, key)
|
|
||||||
}
|
|
||||||
hr.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hr *Hidden) AddIntro(pk *crypto.Pub, intro *Introduction) {
|
func (hr *Hidden) AddIntro(pk *crypto.Pub, intro *Introduction) {
|
||||||
hr.Lock()
|
hr.Lock()
|
||||||
|
|||||||
@@ -5,14 +5,11 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gookit/color"
|
|
||||||
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto"
|
"git-indra.lan/indra-labs/indra/pkg/crypto"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
|
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
|
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/engine/coding"
|
"git-indra.lan/indra-labs/indra/pkg/engine/coding"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/engine/magic"
|
"git-indra.lan/indra-labs/indra/pkg/engine/magic"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/engine/node"
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/engine/sess"
|
"git-indra.lan/indra-labs/indra/pkg/engine/sess"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/engine/sessions"
|
"git-indra.lan/indra-labs/indra/pkg/engine/sessions"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/util/slice"
|
"git-indra.lan/indra-labs/indra/pkg/util/slice"
|
||||||
@@ -113,48 +110,6 @@ func (x *Intro) Handle(s *splice.Splice, p Onion, ng Ngin) (e error) {
|
|||||||
valid := x.Validate()
|
valid := x.Validate()
|
||||||
if valid {
|
if valid {
|
||||||
log.T.Ln(ng.Mgr().GetLocalNodeAddressString(), "validated intro", x.ID)
|
log.T.Ln(ng.Mgr().GetLocalNodeAddressString(), "validated intro", x.ID)
|
||||||
kb := x.Key.ToBytes()
|
|
||||||
if _, ok := ng.GetHidden().KnownIntros[x.Key.ToBytes()]; ok {
|
|
||||||
log.D.Ln(ng.Mgr().GetLocalNodeAddressString(), "already have intro")
|
|
||||||
ng.Pending().ProcessAndDelete(x.ID, &kb, s.GetAll())
|
|
||||||
ng.GetHidden().Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.D.F("%s storing intro for %s %s",
|
|
||||||
ng.Mgr().GetLocalNodeAddressString(), x.Key.ToBase32Abbreviated(),
|
|
||||||
x.ID)
|
|
||||||
ng.GetHidden().KnownIntros[x.Key.ToBytes()] = x
|
|
||||||
var ok bool
|
|
||||||
if ok, e = ng.Pending().ProcessAndDelete(x.ID, &kb,
|
|
||||||
s.GetAll()); ok || fails(e) {
|
|
||||||
|
|
||||||
ng.GetHidden().Unlock()
|
|
||||||
log.D.Ln("deleted pending response", x.ID)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.D.F("%s sending out intro to %s at %s to all known peers",
|
|
||||||
ng.Mgr().GetLocalNodeAddressString(), x.Key.ToBase32Abbreviated(),
|
|
||||||
color.Yellow.Sprint(x.AddrPort.String()))
|
|
||||||
sender := ng.Mgr().FindNodeByAddrPort(x.AddrPort)
|
|
||||||
nn := make(map[nonce.ID]*node.Node)
|
|
||||||
ng.Mgr().ForEachNode(func(n *node.Node) bool {
|
|
||||||
if n.ID != sender.ID {
|
|
||||||
nn[n.ID] = n
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
counter := 0
|
|
||||||
for i := range nn {
|
|
||||||
log.T.F("sending intro to %s", color.Yellow.Sprint(nn[i].AddrPort.
|
|
||||||
String()))
|
|
||||||
nn[i].Transport.Send(s.GetAll())
|
|
||||||
counter++
|
|
||||||
if counter < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ng.GetHidden().Unlock()
|
ng.GetHidden().Unlock()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
package onions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto"
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/engine/coding"
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/engine/magic"
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/engine/sess"
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/engine/sessions"
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/util/splice"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
IntroQueryMagic = "intq"
|
|
||||||
IntroQueryLen = magic.Len + nonce.IDLen + crypto.PubKeyLen +
|
|
||||||
3*sha256.Len + nonce.IVLen*3
|
|
||||||
)
|
|
||||||
|
|
||||||
type IntroQuery struct {
|
|
||||||
ID nonce.ID
|
|
||||||
// Ciphers is a set of 3 symmetric ciphers that are to be used in their
|
|
||||||
// given order over the reply message from the service.
|
|
||||||
crypto.Ciphers
|
|
||||||
// Nonces are the nonces to use with the cipher when creating the
|
|
||||||
// encryption for the reply message,
|
|
||||||
// they are common with the crypts in the header.
|
|
||||||
crypto.Nonces
|
|
||||||
// Port identifies the type of service as well as being the port used by
|
|
||||||
// the service to be relayed to. Notice there is no IP address, this is
|
|
||||||
// because Indranet only forwards to exits of decentralised services
|
|
||||||
// also running on the same machine. This service could be a proxy, of
|
|
||||||
// course, if configured this way. This could be done by tunneling from
|
|
||||||
// a local Socks5 proxy into Indranet and the exit node also having
|
|
||||||
// this.
|
|
||||||
Key *crypto.Pub
|
|
||||||
Onion
|
|
||||||
}
|
|
||||||
|
|
||||||
func introQueryGen() coding.Codec { return &IntroQuery{} }
|
|
||||||
func init() { Register(IntroQueryMagic, introQueryGen) }
|
|
||||||
func (x *IntroQuery) Magic() string { return IntroQueryMagic }
|
|
||||||
func (x *IntroQuery) Len() int { return IntroQueryLen + x.Onion.Len() }
|
|
||||||
func (x *IntroQuery) Wrap(inner Onion) { x.Onion = inner }
|
|
||||||
func (x *IntroQuery) GetOnion() interface{} { return x }
|
|
||||||
|
|
||||||
func (x *IntroQuery) Encode(s *splice.Splice) (e error) {
|
|
||||||
log.T.S("encoding", reflect.TypeOf(x),
|
|
||||||
x.ID, x.Key, x.Ciphers, x.Nonces,
|
|
||||||
)
|
|
||||||
return x.Onion.Encode(s.
|
|
||||||
Magic(IntroQueryMagic).
|
|
||||||
ID(x.ID).Ciphers(x.Ciphers).Nonces(x.Nonces).
|
|
||||||
Pubkey(x.Key),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *IntroQuery) Decode(s *splice.Splice) (e error) {
|
|
||||||
if e = magic.TooShort(s.Remaining(), IntroQueryLen-magic.Len,
|
|
||||||
IntroQueryMagic); fails(e) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.ReadID(&x.ID).ReadCiphers(&x.Ciphers).ReadNonces(&x.Nonces).
|
|
||||||
ReadPubkey(&x.Key)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *IntroQuery) Handle(s *splice.Splice, p Onion, ng Ngin) (e error) {
|
|
||||||
ng.GetHidden().Lock()
|
|
||||||
log.D.Ln(ng.Mgr().GetLocalNodeAddressString(), "handling introquery", x.ID,
|
|
||||||
x.Key.ToBase32Abbreviated())
|
|
||||||
var ok bool
|
|
||||||
var il *Intro
|
|
||||||
if il, ok = ng.GetHidden().KnownIntros[x.Key.ToBytes()]; !ok {
|
|
||||||
// if the reply is zeroes the querant knows it needs to retry at a
|
|
||||||
// different relay
|
|
||||||
il = &Intro{}
|
|
||||||
ng.GetHidden().Unlock()
|
|
||||||
log.E.Ln("intro not known")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ng.GetHidden().Unlock()
|
|
||||||
iqr := Encode(il)
|
|
||||||
rb := FormatReply(GetRoutingHeaderFromCursor(s), x.Ciphers, x.Nonces,
|
|
||||||
iqr.GetAll())
|
|
||||||
switch on1 := p.(type) {
|
|
||||||
case *Crypt:
|
|
||||||
sess := ng.Mgr().FindSessionByHeader(on1.ToPriv)
|
|
||||||
if sess != nil {
|
|
||||||
in := sess.Node.RelayRate * s.Len() / 2
|
|
||||||
out := sess.Node.RelayRate * rb.Len() / 2
|
|
||||||
ng.Mgr().DecSession(sess.Header.Bytes, in+out, false, "introquery")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ng.HandleMessage(rb, x)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *IntroQuery) Account(res *sess.Data, sm *sess.Manager, s *sessions.Data, last bool) (skip bool, sd *sessions.Data) {
|
|
||||||
|
|
||||||
res.ID = x.ID
|
|
||||||
res.Billable = append(res.Billable, s.Header.Bytes)
|
|
||||||
skip = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
package onions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto"
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/engine/coding"
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/engine/sessions"
|
|
||||||
log2 "git-indra.lan/indra-labs/indra/pkg/proc/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestOnionSkins_IntroQuery(t *testing.T) {
|
|
||||||
log2.SetLogLevel(log2.Trace)
|
|
||||||
log2.App.Store("")
|
|
||||||
var e error
|
|
||||||
prvs, pubs := crypto.GetCipherSet(t)
|
|
||||||
ciphers := crypto.GenCiphers(prvs, pubs)
|
|
||||||
prv1, _ := crypto.GetTwoPrvKeys(t)
|
|
||||||
pub1 := crypto.DerivePub(prv1)
|
|
||||||
n3 := crypto.Gen3Nonces()
|
|
||||||
ep := &ExitPoint{
|
|
||||||
Routing: &Routing{
|
|
||||||
Sessions: [3]*sessions.Data{},
|
|
||||||
Keys: prvs,
|
|
||||||
Nonces: n3,
|
|
||||||
},
|
|
||||||
ReturnPubs: pubs,
|
|
||||||
}
|
|
||||||
id := nonce.NewID()
|
|
||||||
on := Skins{}.
|
|
||||||
IntroQuery(id, crypto.DerivePub(prv1), ep).
|
|
||||||
End().Assemble()
|
|
||||||
s := Encode(on)
|
|
||||||
s.SetCursor(0)
|
|
||||||
var onc coding.Codec
|
|
||||||
if onc = Recognise(s); onc == nil {
|
|
||||||
t.Error("did not unwrap")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if e = onc.Decode(s); fails(e) {
|
|
||||||
t.Error("did not decode")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
log.D.Ln(s)
|
|
||||||
var ex *IntroQuery
|
|
||||||
var ok bool
|
|
||||||
if ex, ok = onc.(*IntroQuery); !ok {
|
|
||||||
t.Error("did not unwrap expected type")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
for i := range ex.Ciphers {
|
|
||||||
if ex.Ciphers[i] != ciphers[i] {
|
|
||||||
t.Errorf("cipher %d did not unwrap correctly", i)
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := range ex.Nonces {
|
|
||||||
if ex.Nonces[i] != n3[i] {
|
|
||||||
t.Errorf("nonce %d did not unwrap correctly", i)
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !ex.Key.Equals(pub1) {
|
|
||||||
t.Error("HiddenService did not decode correctly")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if ex.ID != id {
|
|
||||||
t.Error("Keys did not decode correctly")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,6 +13,9 @@ type Introduction struct {
|
|||||||
ReplyHeader
|
ReplyHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GossipIntro -
|
||||||
|
// todo: this should update a peer subkey on DHT for
|
||||||
|
// introductions, as well as the link to the hidden service peer data
|
||||||
func GossipIntro(intro *Intro, sm *sess.Manager, c qu.C) {
|
func GossipIntro(intro *Intro, sm *sess.Manager, c qu.C) {
|
||||||
log.D.F("propagating hidden service intro for %s",
|
log.D.F("propagating hidden service intro for %s",
|
||||||
intro.Key.ToBase32Abbreviated())
|
intro.Key.ToBase32Abbreviated())
|
||||||
|
|||||||
@@ -198,16 +198,6 @@ func (o Skins) Intro(id nonce.ID, key *crypto.Prv, ap *netip.AddrPort,
|
|||||||
return append(o, NewIntro(id, key, ap, expires))
|
return append(o, NewIntro(id, key, ap, expires))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Skins) IntroQuery(id nonce.ID, hsk *crypto.Pub, exit *ExitPoint) Skins {
|
|
||||||
return append(o, &IntroQuery{
|
|
||||||
ID: id,
|
|
||||||
Ciphers: crypto.GenCiphers(exit.Keys, exit.ReturnPubs),
|
|
||||||
Nonces: exit.Nonces,
|
|
||||||
Key: hsk,
|
|
||||||
Onion: nop,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o Skins) Message(msg *Message, ks *crypto.KeySet) Skins {
|
func (o Skins) Message(msg *Message, ks *crypto.KeySet) Skins {
|
||||||
return append(o.
|
return append(o.
|
||||||
ForwardCrypt(msg.Forwards[0], ks.Next(), nonce.New()).
|
ForwardCrypt(msg.Forwards[0], ks.Next(), nonce.New()).
|
||||||
@@ -338,16 +328,6 @@ func MakeHiddenService(in *Intro, alice, bob *sessions.Data,
|
|||||||
RoutingHeader(headers.Return)
|
RoutingHeader(headers.Return)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeIntroQuery(id nonce.ID, hsk *crypto.Pub, alice, bob *sessions.Data,
|
|
||||||
c sessions.Circuit, ks *crypto.KeySet) Skins {
|
|
||||||
|
|
||||||
headers := GetHeaders(alice, bob, c, ks)
|
|
||||||
return Skins{}.
|
|
||||||
RoutingHeader(headers.Forward).
|
|
||||||
IntroQuery(id, hsk, headers.ExitPoint()).
|
|
||||||
RoutingHeader(headers.Return)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MakeSession(id nonce.ID, s [5]*Session,
|
func MakeSession(id nonce.ID, s [5]*Session,
|
||||||
client *sessions.Data, hop []*node.Node, ks *crypto.KeySet) Skins {
|
client *sessions.Data, hop []*node.Node, ks *crypto.KeySet) Skins {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user