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[:])
|
||||
// }
|
||||
|
||||
func (h Hash) Based32String() string {
|
||||
func (h Hash) String() string {
|
||||
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/sessions"
|
||||
"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,
|
||||
@@ -69,41 +68,10 @@ func (ng *Engine) SendHiddenService(id nonce.ID, key *crypto.Prv,
|
||||
return
|
||||
}
|
||||
|
||||
func (ng *Engine) SendIntroQuery(id nonce.ID, hsk *crypto.Pub,
|
||||
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) {
|
||||
func (ng *Engine) SendHiddenMessage(mp *onions.Message, hook responses.Callback) (id nonce.ID) {
|
||||
// Add another two hops for security against unmasking.
|
||||
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]}
|
||||
o := onions.Skins{}.Message(mp, ng.KeySet)
|
||||
res := PostAcctOnion(ng.Manager, o)
|
||||
|
||||
@@ -182,119 +182,119 @@ out:
|
||||
}
|
||||
}
|
||||
|
||||
func TestEngine_SendIntroQuery(t *testing.T) {
|
||||
log2.SetLogLevel(log2.Info)
|
||||
var clients []*Engine
|
||||
var e error
|
||||
const nCircuits = 10
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
if clients, e = CreateNMockCircuits(nCircuits, nCircuits,
|
||||
ctx); fails(e) {
|
||||
t.Error(e)
|
||||
t.FailNow()
|
||||
}
|
||||
client := clients[0]
|
||||
// Start up the clients.
|
||||
for _, v := range clients {
|
||||
go v.Start()
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
var counter atomic.Int32
|
||||
quit := qu.T()
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 4):
|
||||
quit.Q()
|
||||
t.Error("MakeHiddenService test failed")
|
||||
case <-quit:
|
||||
for i := 0; i < int(counter.Load()); i++ {
|
||||
wg.Done()
|
||||
}
|
||||
for _, v := range clients {
|
||||
v.Shutdown()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
for i := 0; i < nCircuits*nCircuits/2; i++ {
|
||||
wg.Add(1)
|
||||
counter.Inc()
|
||||
e = clients[0].BuyNewSessions(1000000, func() {
|
||||
wg.Done()
|
||||
counter.Dec()
|
||||
})
|
||||
if fails(e) {
|
||||
wg.Done()
|
||||
counter.Dec()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
var idPrv *crypto.Prv
|
||||
if idPrv, e = crypto.GeneratePrvKey(); fails(e) {
|
||||
return
|
||||
}
|
||||
id := nonce.NewID()
|
||||
introducerHops := client.Manager.GetSessionsAtHop(2)
|
||||
var introducer *sessions.Data
|
||||
if len(introducerHops) > 1 {
|
||||
cryptorand.Shuffle(len(introducerHops), func(i, j int) {
|
||||
introducerHops[i], introducerHops[j] = introducerHops[j], introducerHops[i]
|
||||
})
|
||||
}
|
||||
introducer = introducerHops[0]
|
||||
returnHops := client.Manager.GetSessionsAtHop(5)
|
||||
var returner *sessions.Data
|
||||
if len(returnHops) > 1 {
|
||||
cryptorand.Shuffle(len(returnHops), func(i, j int) {
|
||||
returnHops[i], returnHops[j] = returnHops[j],
|
||||
returnHops[i]
|
||||
})
|
||||
}
|
||||
returner = returnHops[0]
|
||||
svc := &services.Service{
|
||||
Port: 2345,
|
||||
RelayRate: 43523,
|
||||
Transport: transport.NewByteChan(64),
|
||||
}
|
||||
client.SendHiddenService(id, idPrv, time.Now().Add(time.Hour), returner,
|
||||
introducer, svc, func(id nonce.ID, ifc interface{},
|
||||
b slice.Bytes) (e error) {
|
||||
log.I.S("hidden service callback", id, ifc, b.ToBytes())
|
||||
return
|
||||
})
|
||||
log2.SetLogLevel(log2.Trace)
|
||||
// Now query everyone for the intro.
|
||||
idPub := crypto.DerivePub(idPrv)
|
||||
peers := clients[1:]
|
||||
log.D.Ln("client address", client.Manager.GetLocalNodeAddressString())
|
||||
for i := range peers {
|
||||
wg.Add(1)
|
||||
counter.Inc()
|
||||
log.T.Ln("peer", i)
|
||||
if len(returnHops) > 1 {
|
||||
cryptorand.Shuffle(len(returnHops), func(i, j int) {
|
||||
returnHops[i], returnHops[j] = returnHops[j], returnHops[i]
|
||||
})
|
||||
}
|
||||
if len(introducerHops) > 1 {
|
||||
cryptorand.Shuffle(len(introducerHops), func(i, j int) {
|
||||
introducerHops[i], introducerHops[j] = introducerHops[j], introducerHops[i]
|
||||
})
|
||||
}
|
||||
client.SendIntroQuery(id, idPub, introducerHops[0], returnHops[0],
|
||||
func(in *onions.Intro) {
|
||||
wg.Done()
|
||||
counter.Dec()
|
||||
log.I.Ln("success",
|
||||
in.ID, in.Key.ToBase32Abbreviated(), in.AddrPort)
|
||||
})
|
||||
wg.Wait()
|
||||
}
|
||||
quit.Q()
|
||||
cancel()
|
||||
}
|
||||
// func TestEngine_SendIntroQuery(t *testing.T) {
|
||||
// log2.SetLogLevel(log2.Info)
|
||||
// var clients []*Engine
|
||||
// var e error
|
||||
// const nCircuits = 10
|
||||
// ctx, cancel := context.WithCancel(context.Background())
|
||||
// if clients, e = CreateNMockCircuits(nCircuits, nCircuits,
|
||||
// ctx); fails(e) {
|
||||
// t.Error(e)
|
||||
// t.FailNow()
|
||||
// }
|
||||
// client := clients[0]
|
||||
// // Start up the clients.
|
||||
// for _, v := range clients {
|
||||
// go v.Start()
|
||||
// }
|
||||
// var wg sync.WaitGroup
|
||||
// var counter atomic.Int32
|
||||
// quit := qu.T()
|
||||
// go func() {
|
||||
// for {
|
||||
// select {
|
||||
// case <-time.After(time.Second * 4):
|
||||
// quit.Q()
|
||||
// t.Error("MakeHiddenService test failed")
|
||||
// case <-quit:
|
||||
// for i := 0; i < int(counter.Load()); i++ {
|
||||
// wg.Done()
|
||||
// }
|
||||
// for _, v := range clients {
|
||||
// v.Shutdown()
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
// }()
|
||||
// for i := 0; i < nCircuits*nCircuits/2; i++ {
|
||||
// wg.Add(1)
|
||||
// counter.Inc()
|
||||
// e = clients[0].BuyNewSessions(1000000, func() {
|
||||
// wg.Done()
|
||||
// counter.Dec()
|
||||
// })
|
||||
// if fails(e) {
|
||||
// wg.Done()
|
||||
// counter.Dec()
|
||||
// }
|
||||
// wg.Wait()
|
||||
// }
|
||||
// var idPrv *crypto.Prv
|
||||
// if idPrv, e = crypto.GeneratePrvKey(); fails(e) {
|
||||
// return
|
||||
// }
|
||||
// id := nonce.NewID()
|
||||
// introducerHops := client.Manager.GetSessionsAtHop(2)
|
||||
// var introducer *sessions.Data
|
||||
// if len(introducerHops) > 1 {
|
||||
// cryptorand.Shuffle(len(introducerHops), func(i, j int) {
|
||||
// introducerHops[i], introducerHops[j] = introducerHops[j], introducerHops[i]
|
||||
// })
|
||||
// }
|
||||
// introducer = introducerHops[0]
|
||||
// returnHops := client.Manager.GetSessionsAtHop(5)
|
||||
// var returner *sessions.Data
|
||||
// if len(returnHops) > 1 {
|
||||
// cryptorand.Shuffle(len(returnHops), func(i, j int) {
|
||||
// returnHops[i], returnHops[j] = returnHops[j],
|
||||
// returnHops[i]
|
||||
// })
|
||||
// }
|
||||
// returner = returnHops[0]
|
||||
// svc := &services.Service{
|
||||
// Port: 2345,
|
||||
// RelayRate: 43523,
|
||||
// Transport: transport.NewByteChan(64),
|
||||
// }
|
||||
// client.SendHiddenService(id, idPrv, time.Now().Add(time.Hour), returner,
|
||||
// introducer, svc, func(id nonce.ID, ifc interface{},
|
||||
// b slice.Bytes) (e error) {
|
||||
// log.I.S("hidden service callback", id, ifc, b.ToBytes())
|
||||
// return
|
||||
// })
|
||||
// log2.SetLogLevel(log2.Trace)
|
||||
// // Now query everyone for the intro.
|
||||
// idPub := crypto.DerivePub(idPrv)
|
||||
// peers := clients[1:]
|
||||
// log.D.Ln("client address", client.Manager.GetLocalNodeAddressString())
|
||||
// for i := range peers {
|
||||
// wg.Add(1)
|
||||
// counter.Inc()
|
||||
// log.T.Ln("peer", i)
|
||||
// if len(returnHops) > 1 {
|
||||
// cryptorand.Shuffle(len(returnHops), func(i, j int) {
|
||||
// returnHops[i], returnHops[j] = returnHops[j], returnHops[i]
|
||||
// })
|
||||
// }
|
||||
// if len(introducerHops) > 1 {
|
||||
// cryptorand.Shuffle(len(introducerHops), func(i, j int) {
|
||||
// introducerHops[i], introducerHops[j] = introducerHops[j], introducerHops[i]
|
||||
// })
|
||||
// }
|
||||
// client.SendIntroQuery(id, idPub, introducerHops[0], returnHops[0],
|
||||
// func(in *onions.Intro) {
|
||||
// wg.Done()
|
||||
// counter.Dec()
|
||||
// log.I.Ln("success",
|
||||
// in.ID, in.Key.ToBase32Abbreviated(), in.AddrPort)
|
||||
// })
|
||||
// wg.Wait()
|
||||
// }
|
||||
// quit.Q()
|
||||
// cancel()
|
||||
// }
|
||||
|
||||
func TestEngine_Message(t *testing.T) {
|
||||
log2.SetLogLevel(log2.Trace)
|
||||
@@ -429,7 +429,7 @@ func TestEngine_Message(t *testing.T) {
|
||||
wg.Add(1)
|
||||
counter.Inc()
|
||||
var ms *onions.Message
|
||||
client.SendMessage(&onions.Message{
|
||||
client.SendHiddenMessage(&onions.Message{
|
||||
Address: rd.Address,
|
||||
ID: nonce.NewID(),
|
||||
Re: rd.ID,
|
||||
@@ -446,7 +446,7 @@ func TestEngine_Message(t *testing.T) {
|
||||
wg.Wait()
|
||||
wg.Add(1)
|
||||
counter.Inc()
|
||||
client.SendMessage(&onions.Message{
|
||||
client.SendHiddenMessage(&onions.Message{
|
||||
Address: ms.Address,
|
||||
ID: nonce.NewID(),
|
||||
Re: ms.ID,
|
||||
|
||||
@@ -36,9 +36,7 @@ const (
|
||||
PaymentChanBuffers = 8
|
||||
)
|
||||
|
||||
// NewNode creates a new Node. The Node for a client's self should use true in
|
||||
// the local parameter to not initialise the peer state ring buffers as it won't
|
||||
// use them.
|
||||
// NewNode creates a new Node.
|
||||
func NewNode(addr *netip.AddrPort, keys *crypto.Keys, tpt tpt.Transport,
|
||||
relayRate int) (n *Node, id nonce.ID) {
|
||||
|
||||
|
||||
@@ -10,8 +10,6 @@ import (
|
||||
|
||||
type MyIntros map[crypto.PubBytes]*Introduction
|
||||
|
||||
type KnownIntros map[crypto.PubBytes]*Intro
|
||||
|
||||
type LocalHiddenService struct {
|
||||
Prv *crypto.Prv
|
||||
CurrentIntros []*Intro
|
||||
@@ -25,15 +23,13 @@ type Services map[crypto.PubBytes]*LocalHiddenService
|
||||
type Hidden struct {
|
||||
sync.Mutex
|
||||
MyIntros
|
||||
KnownIntros
|
||||
Services
|
||||
}
|
||||
|
||||
func NewHiddenrouting() *Hidden {
|
||||
return &Hidden{
|
||||
MyIntros: make(MyIntros),
|
||||
KnownIntros: make(KnownIntros),
|
||||
Services: make(Services),
|
||||
MyIntros: make(MyIntros),
|
||||
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()
|
||||
|
||||
}
|
||||
@@ -96,11 +86,6 @@ func (hr *Hidden) FindCloakedHiddenService(key crypto.PubKey) (
|
||||
return &i
|
||||
}
|
||||
}
|
||||
for i := range hr.KnownIntros {
|
||||
if crypto.Match(key, i) {
|
||||
return &i
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -133,22 +118,6 @@ func (hr *Hidden) FindIntroductionUnsafe(
|
||||
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) {
|
||||
hr.Lock()
|
||||
var ok bool
|
||||
@@ -159,16 +128,6 @@ func (hr *Hidden) Delete(key crypto.PubBytes) (header *Introduction) {
|
||||
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) {
|
||||
hr.Lock()
|
||||
|
||||
@@ -5,14 +5,11 @@ import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/gookit/color"
|
||||
|
||||
"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/node"
|
||||
"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/slice"
|
||||
@@ -113,48 +110,6 @@ func (x *Intro) Handle(s *splice.Splice, p Onion, ng Ngin) (e error) {
|
||||
valid := x.Validate()
|
||||
if valid {
|
||||
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()
|
||||
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
|
||||
}
|
||||
|
||||
// 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) {
|
||||
log.D.F("propagating hidden service intro for %s",
|
||||
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))
|
||||
}
|
||||
|
||||
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 {
|
||||
return append(o.
|
||||
ForwardCrypt(msg.Forwards[0], ks.Next(), nonce.New()).
|
||||
@@ -338,16 +328,6 @@ func MakeHiddenService(in *Intro, alice, bob *sessions.Data,
|
||||
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,
|
||||
client *sessions.Data, hop []*node.Node, ks *crypto.KeySet) Skins {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user