[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnunet-go] branch master updated: Identity service added to zone master
From: |
gnunet |
Subject: |
[gnunet-go] branch master updated: Identity service added to zone master. |
Date: |
Wed, 26 Oct 2022 18:01:38 +0200 |
This is an automated email from the git hooks/post-receive script.
bernd-fix pushed a commit to branch master
in repository gnunet-go.
The following commit(s) were added to refs/heads/master by this push:
new bcc6ce0 Identity service added to zone master.
bcc6ce0 is described below
commit bcc6ce0be0d9c240dce80c42af5b56e8ee805aff
Author: Bernd Fix <brf@hoi-polloi.org>
AuthorDate: Wed Oct 26 17:59:46 2022 +0200
Identity service added to zone master.
---
src/gnunet/cmd/zonemaster-go/main.go | 14 +-
src/gnunet/config/gnunet-config.json | 2 +-
src/gnunet/crypto/gns.go | 158 ++++---
src/gnunet/crypto/gns_edkey.go | 15 +-
src/gnunet/crypto/gns_edkey_test.go | 4 +
src/gnunet/crypto/gns_pkey.go | 21 +-
src/gnunet/crypto/gns_test.go | 51 +--
.../zonemaster/rpc.go => enums/results.go} | 15 +-
src/gnunet/go.mod | 4 +-
src/gnunet/go.sum | 4 +-
src/gnunet/message/factory.go | 32 ++
src/gnunet/message/message.go | 3 +
src/gnunet/message/msg_core.go | 5 +-
src/gnunet/message/msg_dht.go | 15 +
src/gnunet/message/msg_dht_p2p.go | 61 ++-
src/gnunet/message/msg_gns.go | 8 +-
src/gnunet/message/msg_hello.go | 41 +-
src/gnunet/message/msg_identity.go | 473 +++++++++++++++++++++
src/gnunet/message/msg_namecache.go | 18 +-
src/gnunet/message/msg_namestore.go | 57 ++-
src/gnunet/message/msg_revocation.go | 16 +-
src/gnunet/message/msg_transport.go | 27 ++
src/gnunet/service/connection.go | 3 +
src/gnunet/service/dht/blocks/gns.go | 7 +-
src/gnunet/service/dht/blocks/gns_test.go | 75 ++--
src/gnunet/service/namecache/module.go | 2 +-
src/gnunet/service/revocation/pow_test.go | 8 +-
src/gnunet/service/store/store_zonemaster.go | 201 ++++++++-
src/gnunet/service/store/store_zonemaster.sql | 30 +-
src/gnunet/service/zonemaster/gui.go | 46 +-
src/gnunet/service/zonemaster/gui.htpl | 4 +-
src/gnunet/service/zonemaster/gui_css.htpl | 27 +-
src/gnunet/service/zonemaster/gui_new.htpl | 6 +-
src/gnunet/service/zonemaster/gui_rr.htpl | 40 +-
src/gnunet/service/zonemaster/records.go | 25 +-
src/gnunet/service/zonemaster/rpc.go | 2 +-
src/gnunet/service/zonemaster/service.go | 186 ++++++--
src/gnunet/service/zonemaster/service_identity.go | 135 ++++++
src/gnunet/service/zonemaster/service_namestore.go | 90 ++++
src/gnunet/service/zonemaster/zonemaster.go | 137 +++---
src/gnunet/transport/reader_writer.go | 5 +-
41 files changed, 1702 insertions(+), 371 deletions(-)
diff --git a/src/gnunet/cmd/zonemaster-go/main.go
b/src/gnunet/cmd/zonemaster-go/main.go
index 1e4b985..6380db0 100644
--- a/src/gnunet/cmd/zonemaster-go/main.go
+++ b/src/gnunet/cmd/zonemaster-go/main.go
@@ -73,13 +73,11 @@ func main() {
config.Cfg.ZoneMaster.GUI = gui
}
- // start a new namestore service under zonemaster umbrella
+ // start services under zonemaster umbrella
ctx, cancel := context.WithCancel(context.Background())
- srv, ok := zonemaster.NewService(ctx, nil).(*zonemaster.Service)
- if !ok {
- logger.Println(logger.ERROR, "[zonemaster] Failed to create
service")
- return
- }
+ srv := zonemaster.NewService(ctx, nil)
+ go srv.Run(ctx)
+
// start UDS listener if service is specified
if config.Cfg.ZoneMaster.Service != nil {
sockHdlr := service.NewSocketHandler("zonemaster", srv)
@@ -89,10 +87,6 @@ func main() {
}
}
- // start a new ZONEMASTER (background service with HTTPS backend)
- zm := zonemaster.NewZoneMaster(config.Cfg, srv)
- go zm.Run(ctx)
-
// handle command-line arguments for RPC
if len(rpcEndp) > 0 {
parts := strings.Split(rpcEndp, ":")
diff --git a/src/gnunet/config/gnunet-config.json
b/src/gnunet/config/gnunet-config.json
index 5e9ec99..cd19450 100644
--- a/src/gnunet/config/gnunet-config.json
+++ b/src/gnunet/config/gnunet-config.json
@@ -91,7 +91,7 @@
},
"gui": "127.0.0.1:8100",
"service": {
- "socket": "${RT_USER}/gnunet-service-namestore-go.sock",
+ "socket": "${RT_USER}/gnunet-service-zonemaster-go.sock",
"params": {
"perm": "0770"
}
diff --git a/src/gnunet/crypto/gns.go b/src/gnunet/crypto/gns.go
index 301acb1..a1c26f6 100644
--- a/src/gnunet/crypto/gns.go
+++ b/src/gnunet/crypto/gns.go
@@ -129,6 +129,10 @@ type ZoneKeyImpl interface {
type ZonePrivateImpl interface {
ZoneAbstractImpl
+ // Prepare a random byte array to be used as a random
+ // private key of given type.
+ Prepare(rnd []byte) []byte
+
// Derive a private key from this zone key based on a big integer
// (key blinding). Returns the derived key and the blinding value.
Derive(h *math.Int) (ZonePrivateImpl, *math.Int, error)
@@ -211,46 +215,80 @@ func GetImplementation(ztype enums.GNSType)
*ZoneImplementation {
// ZonePrivate represents the possible types of private zone keys (PKEY,
EDKEY,...)
type ZonePrivate struct {
- ZoneKey
+ Type enums.GNSType `json:"type" order:"big"`
+ KeyData []byte `json:"key" size:"(KeySize)"`
impl ZonePrivateImpl // reference to implementation
}
-// NewZonePrivate returns a new initialized ZonePrivate instance. If no data is
-// provided, a new random key is created
-func NewZonePrivate(ztype enums.GNSType, d []byte) (zp *ZonePrivate, err
error) {
+// NewZonePrivate returns a new initialized ZonePrivate instance of given
ztype.
+// If no data is provided, a new random key is created. If data is provided, it
+// must be in the correct format specified by a ZonePrivate implementation.
+func NewZonePrivate(ztype enums.GNSType, zdata []byte) (zp *ZonePrivate, err
error) {
// get factory for given zone type
impl, ok := zoneImpl[ztype]
if !ok {
return nil, ErrNoImplementation
}
+ prvImpl := impl.NewPrivate()
+
// init data available?
- if d == nil {
+ if zdata == nil {
// no: create random seed
- d = make([]byte, impl.PrivateSize)
- if _, err = rand.Read(d); err != nil {
+ zdata = make([]byte, impl.PrivateSize)
+ if _, err = rand.Read(zdata); err != nil {
return
}
+ zdata = prvImpl.Prepare(zdata)
}
// assemble private zone key
zp = &ZonePrivate{
- ZoneKey{
- ztype,
- nil,
- nil,
- },
- nil,
+ Type: ztype,
+ KeyData: zdata,
+ impl: prvImpl,
}
- zp.impl = impl.NewPrivate()
- if err = zp.impl.Init(d); err != nil {
- return
+ err = zp.impl.Init(zdata)
+ return
+}
+
+// Init is called to setup internal state after unmarshalling object
+func (zp *ZonePrivate) Init() (err error) {
+ // check for initialized key
+ if zp.impl == nil {
+ impl, ok := zoneImpl[zp.Type]
+ if !ok {
+ return ErrNoImplementation
+ }
+ zp.impl = impl.NewPrivate()
+ err = zp.impl.Init(zp.KeyData)
}
- zp.ZoneKey.KeyData = zp.impl.Public().Bytes()
- zp.ZoneKey.impl = impl.NewPublic()
- err = zp.ZoneKey.impl.Init(zp.ZoneKey.KeyData)
return
}
+// Null returns a "NULL" ZonePrivate for a given key
+func NullZonePrivate(ztype enums.GNSType) (*ZonePrivate, uint16) {
+ // get factory for given zone type
+ impl, ok := zoneImpl[ztype]
+ if !ok {
+ return nil, 0
+ }
+ kd := make([]byte, impl.PrivateSize)
+ zp := &ZonePrivate{
+ Type: ztype, // need key type for length calculation
+ KeyData: kd, // untyped key data (all 0)
+ impl: nil, // no implementation!
+ }
+ return zp, uint16(len(zp.KeyData) + 4)
+}
+
+// Bytes returns the binary representation
+func (zp *ZonePrivate) Bytes() []byte {
+ buf := new(bytes.Buffer)
+ _ = binary.Write(buf, binary.BigEndian, zp.Type)
+ _, _ = buf.Write(zp.KeyData)
+ return buf.Bytes()
+}
+
// KeySize returns the number of bytes of a key representation.
// This method is used during serialization (Unmarshal).
func (zp *ZonePrivate) KeySize() uint {
@@ -263,7 +301,7 @@ func (zp *ZonePrivate) KeySize() uint {
// Derive key (key blinding)
func (zp *ZonePrivate) Derive(label, context string) (dzp *ZonePrivate, h
*math.Int, err error) {
// calculate derived key
- key := zp.Public().Bytes()
+ key := zp.Public().KeyData
h = deriveH(key, label, context)
var derived ZonePrivateImpl
if derived, h, err = zp.impl.Derive(h); err != nil {
@@ -271,15 +309,10 @@ func (zp *ZonePrivate) Derive(label, context string) (dzp
*ZonePrivate, h *math.
}
// assemble derived pivate key
dzp = &ZonePrivate{
- ZoneKey{
- zp.Type,
- nil,
- nil,
- },
- derived,
+ Type: zp.Type,
+ KeyData: derived.Bytes(),
+ impl: derived,
}
- dzp.ZoneKey.KeyData = derived.Public().Bytes()
- err = dzp.Init()
return
}
@@ -290,7 +323,12 @@ func (zp *ZonePrivate) Sign(data []byte) (sig
*ZoneSignature, err error) {
// Public returns the associated public key
func (zp *ZonePrivate) Public() *ZoneKey {
- return &zp.ZoneKey
+ impl := zp.impl.Public()
+ return &ZoneKey{
+ Type: zp.Type,
+ KeyData: impl.Bytes(),
+ impl: impl,
+ }
}
// ID returns the human-readable zone private key.
@@ -310,7 +348,7 @@ type ZoneKey struct {
impl ZoneKeyImpl // reference to implementation
}
-// Init a zone key where only the attributes have been read/deserialized.
+// Init is called to setup internal state after unmarshalling object
func (zk *ZoneKey) Init() (err error) {
if zk.impl == nil {
// initialize implementation
@@ -335,6 +373,14 @@ func NewZoneKey(d []byte) (zk *ZoneKey, err error) {
return
}
+// Bytes returns the binary representation (can be used with 'init()')
+func (zk *ZoneKey) Bytes() []byte {
+ buf := new(bytes.Buffer)
+ _ = binary.Write(buf, binary.BigEndian, zk.Type)
+ _, _ = buf.Write(zk.KeyData)
+ return buf.Bytes()
+}
+
// KeySize returns the number of bytes of a key representation.
// This method is used during serialization (Unmarshal).
func (zk *ZoneKey) KeySize() uint {
@@ -346,7 +392,7 @@ func (zk *ZoneKey) KeySize() uint {
// Derive key (key blinding)
func (zk *ZoneKey) Derive(label, context string) (dzk *ZoneKey, h *math.Int,
err error) {
- key := zk.Bytes()
+ key := zk.KeyData
h = deriveH(key, label, context)
var derived ZoneKeyImpl
if derived, h, err = zk.impl.Derive(h); err != nil {
@@ -388,12 +434,6 @@ func (zk *ZoneKey) ID() string {
return zk.impl.ID()
}
-// Bytes returns all bytes of a zone key
-func (zk *ZoneKey) Bytes() []byte {
- data, _ := data.Marshal(zk)
- return data
-}
-
// Equal checks if two zone keys are equal
func (zk *ZoneKey) Equal(k *ZoneKey) bool {
return bytes.Equal(zk.KeyData, k.KeyData)
@@ -420,23 +460,26 @@ type ZoneSignature struct {
impl ZoneSigImpl // reference to implementation
}
+// Init is called to setup internal state after unmarshalling object
func (zs *ZoneSignature) Init() (err error) {
- // initialize implementations
- impl, ok := zoneImpl[zs.Type]
- if !ok {
- err = ErrUnknownZoneType
- return
- }
- // set signature implementation
- sig := impl.NewSignature()
- if err = sig.Init(zs.Signature); err != nil {
- return
+ if zs.impl == nil {
+ // initialize implementations
+ impl, ok := zoneImpl[zs.Type]
+ if !ok {
+ err = ErrUnknownZoneType
+ return
+ }
+ // set signature implementation
+ sig := impl.NewSignature()
+ if err = sig.Init(zs.Signature); err != nil {
+ return
+ }
+ zs.impl = sig
+ // set public key implementation
+ zk := impl.NewPublic()
+ err = zk.Init(zs.KeyData)
+ zs.ZoneKey.impl = zk
}
- zs.impl = sig
- // set public key implementation
- zk := impl.NewPublic()
- err = zk.Init(zs.KeyData)
- zs.ZoneKey.impl = zk
return
}
@@ -460,6 +503,11 @@ func (zs *ZoneSignature) SigSize() uint {
return 0
}
+// Bytes returns the binary representation (can be used with 'init()')
+func (zs *ZoneSignature) Bytes() []byte {
+ return zs.impl.Bytes()
+}
+
// Key returns the associated zone key object
func (zs *ZoneSignature) Key() *ZoneKey {
return &zs.ZoneKey
@@ -486,10 +534,10 @@ func deriveH(key []byte, label, context string) *math.Int
{
return math.NewIntFromBytes(b)
}
-// convert (type|data) to GNUnet identifier
-func asID(t enums.GNSType, data []byte) string {
+// convert (type|data) to bytes
+func asBytes(t enums.GNSType, data []byte) []byte {
buf := new(bytes.Buffer)
_ = binary.Write(buf, binary.BigEndian, t)
_, _ = buf.Write(data)
- return util.EncodeBinaryToString(buf.Bytes())
+ return buf.Bytes()
}
diff --git a/src/gnunet/crypto/gns_edkey.go b/src/gnunet/crypto/gns_edkey.go
index 08dbc55..0054ca5 100644
--- a/src/gnunet/crypto/gns_edkey.go
+++ b/src/gnunet/crypto/gns_edkey.go
@@ -79,8 +79,8 @@ func (pk *EDKEYPublicImpl) Bytes() []byte {
// Derive a public key from this key based on a big integer
// (key blinding). Returns the derived key and the blinding value.
func (pk *EDKEYPublicImpl) Derive(h *math.Int) (dPk ZoneKeyImpl, hOut
*math.Int, err error) {
- // limit to allowed value range
- hOut = h.Mod(ed25519.GetCurve().N)
+ // limit to allowed value range (see LSD0001 spec)
+ hOut = h.SetBit(255, 0)
derived := pk.pub.Mult(hOut)
dPk = &EDKEYPublicImpl{
pk.ztype,
@@ -162,7 +162,7 @@ func (pk *EDKEYPublicImpl) BlockKey(label string, expire
util.AbsoluteTime) (ske
// ID returns the GNUnet identifier for a public zone key
func (pk *EDKEYPublicImpl) ID() string {
- return asID(enums.GNS_TYPE_EDKEY, pk.pub.Bytes())
+ return util.EncodeBinaryToString(asBytes(enums.GNS_TYPE_EDKEY,
pk.pub.Bytes()))
}
//----------------------------------------------------------------------
@@ -187,6 +187,11 @@ func (pk *EDKEYPrivateImpl) Init(data []byte) error {
return nil
}
+// Prepare a random byte array to be used as a random private EDKEY
+func (pk *EDKEYPrivateImpl) Prepare(rnd []byte) []byte {
+ return rnd
+}
+
// Bytes returns a binary representation of the instance suitable for
// consumption in 'Init()'.
func (pk *EDKEYPrivateImpl) Bytes() []byte {
@@ -201,7 +206,7 @@ func (pk *EDKEYPrivateImpl) Public() ZoneKeyImpl {
// Derive a public key from this key based on a big integer
// (key blinding). Returns the derived key and the blinding value.
func (pk *EDKEYPrivateImpl) Derive(h *math.Int) (dPk ZonePrivateImpl, hOut
*math.Int, err error) {
- // limit to allowed value range
+ // limit to allowed value range (see LSD0001 spec)
hOut = h.SetBit(255, 0)
// derive private key
derived := pk.prv.Mult(hOut)
@@ -243,7 +248,7 @@ func (pk *EDKEYPrivateImpl) Sign(data []byte) (sig
*ZoneSignature, err error) {
// ID returns the GNUnet identifier for a private zone key
func (pk *EDKEYPrivateImpl) ID() string {
- return asID(enums.GNS_TYPE_EDKEY, pk.seed)
+ return util.EncodeBinaryToString(asBytes(enums.GNS_TYPE_EDKEY, pk.seed))
}
//----------------------------------------------------------------------
diff --git a/src/gnunet/crypto/gns_edkey_test.go
b/src/gnunet/crypto/gns_edkey_test.go
index aa9728f..b5ba700 100644
--- a/src/gnunet/crypto/gns_edkey_test.go
+++ b/src/gnunet/crypto/gns_edkey_test.go
@@ -20,6 +20,7 @@ package crypto
import (
"bytes"
+ "encoding/hex"
"gnunet/enums"
"testing"
)
@@ -50,7 +51,10 @@ func TestDeriveEDKEY(t *testing.T) {
if err != nil {
t.Fatal(err)
}
+ // check resuts
if !bytes.Equal(dzp.Public().Bytes(), dzk.Bytes()) {
+ t.Logf("dzp.Public = %s",
hex.EncodeToString(dzp.Public().Bytes()))
+ t.Logf("dzk = %s", hex.EncodeToString(dzk.Bytes()))
t.Fatal("derive mismatch")
}
}
diff --git a/src/gnunet/crypto/gns_pkey.go b/src/gnunet/crypto/gns_pkey.go
index 8184483..d2c08ba 100644
--- a/src/gnunet/crypto/gns_pkey.go
+++ b/src/gnunet/crypto/gns_pkey.go
@@ -158,7 +158,7 @@ func (pk *PKEYPublicImpl) cipher(encrypt bool, data []byte,
label string, expire
// ID returns the GNUnet identifier for a public zone key
func (pk *PKEYPublicImpl) ID() string {
- return asID(enums.GNS_TYPE_PKEY, pk.pub.Bytes())
+ return util.EncodeBinaryToString(asBytes(enums.GNS_TYPE_PKEY,
pk.pub.Bytes()))
}
//----------------------------------------------------------------------
@@ -173,15 +173,25 @@ type PKEYPrivateImpl struct {
}
// Init instance from binary data. The data represents a big integer
-// (in big-endian notation) for the private scalar d.
+// (in little-endian notation) for the private scalar d (clamped).
func (pk *PKEYPrivateImpl) Init(data []byte) error {
- d := math.NewIntFromBytes(data)
+ // generate key material
+ d := math.NewIntFromBytes(util.Reverse(data))
pk.prv = ed25519.NewPrivateKeyFromD(d)
pk.ztype = enums.GNS_TYPE_PKEY
pk.pub = pk.prv.Public()
return nil
}
+// Prepare a random byte array to be used as a random private PKEY
+func (pk *PKEYPrivateImpl) Prepare(rnd []byte) []byte {
+ // clamp little-endian skalar
+ d := util.Clone(rnd)
+ d[31] = (d[31] & 0x3f) | 0x40
+ d[0] &= 0xf8
+ return d
+}
+
// Bytes returns a binary representation of the instance suitable for
// consumption in 'Init()'.
func (pk *PKEYPrivateImpl) Bytes() []byte {
@@ -232,8 +242,11 @@ func (pk *PKEYPrivateImpl) Sign(data []byte) (sig
*ZoneSignature, err error) {
}
// ID returns the GNUnet identifier for a private zone key
+// (little-endian big integer)
func (pk *PKEYPrivateImpl) ID() string {
- return asID(enums.GNS_TYPE_PKEY, pk.prv.D.Bytes())
+ return util.EncodeBinaryToString(asBytes(
+ enums.GNS_TYPE_PKEY,
+ util.Reverse(pk.prv.D.Bytes())))
}
//----------------------------------------------------------------------
diff --git a/src/gnunet/crypto/gns_test.go b/src/gnunet/crypto/gns_test.go
index 2cccb4d..f910dcf 100644
--- a/src/gnunet/crypto/gns_test.go
+++ b/src/gnunet/crypto/gns_test.go
@@ -202,12 +202,13 @@ func TestVerifyBlock(t *testing.T) {
func TestDeriveH(t *testing.T) {
var (
D = []byte{
- // private scalar (big-endian)
- 0x74, 0x50, 0xf7, 0x1d, 0xef, 0x64, 0x11, 0xe0,
- 0xab, 0x0e, 0x6a, 0x1d, 0xfd, 0x1d, 0x9c, 0xcd,
- 0x0e, 0xaf, 0x71, 0x95, 0x24, 0x94, 0xcc, 0xf5,
- 0x1b, 0x85, 0xff, 0xac, 0x5d, 0xb0, 0x93, 0xc8,
+ // private scalar (clamped little-endian)
+ 0xc8, 0x93, 0xb0, 0x5d, 0xac, 0xff, 0x85, 0x1b,
+ 0xf5, 0xcc, 0x94, 0x24, 0x95, 0x71, 0xaf, 0x0e,
+ 0xcd, 0x9c, 0x1d, 0xfd, 0x1d, 0x6a, 0x0e, 0xab,
+ 0xe0, 0x11, 0x64, 0xef, 0x1d, 0xf7, 0x50, 0x74,
}
+
PUB = []byte{
// zone type
0x00, 0x01, 0x00, 0x00,
@@ -223,29 +224,19 @@ func TestDeriveH(t *testing.T) {
CONTEXT = "gns"
H = []byte{
- 0x06, 0x5b, 0xb7, 0x42, 0x12, 0xa1, 0xae, 0xc3,
- 0x59, 0x68, 0xdd, 0xdb, 0xca, 0xa3, 0x48, 0xfc,
- 0xb0, 0xcd, 0x89, 0xd4, 0xcf, 0x9a, 0xe0, 0xfe,
- 0xd1, 0xf9, 0xab, 0x6b, 0xd4, 0x28, 0xf4, 0x95,
+ 0x07, 0x1e, 0xfc, 0xa7, 0xdb, 0x28, 0x50, 0xbd,
+ 0x6f, 0x35, 0x4e, 0xbf, 0xe3, 0x8c, 0x5b, 0xbf,
+ 0xd6, 0xba, 0x2f, 0x80, 0x5c, 0xd8, 0xd3, 0xb5,
+ 0x4e, 0xdd, 0x7f, 0x3d, 0xd0, 0x73, 0x0d, 0x1a,
}
Q = []byte{
- // zone type
+ // zone type (PKEY)
0x00, 0x01, 0x00, 0x00,
// derived public key data
- 0xb1, 0x0e, 0x88, 0xd5, 0x17, 0x02, 0xf3, 0x3d,
- 0xc9, 0xcb, 0xa1, 0xe9, 0x16, 0x65, 0x9c, 0x44,
- 0x47, 0x9c, 0xc8, 0xdb, 0x83, 0x32, 0xd1, 0xd1,
- 0xc5, 0x03, 0xdb, 0x50, 0x0e, 0xbd, 0x2d, 0x67,
- }
- QUERY = []byte{
- 0xa9, 0x47, 0x81, 0x8a, 0xaf, 0x45, 0x94, 0xda,
- 0x89, 0x41, 0xfa, 0x29, 0x77, 0x53, 0x94, 0x9d,
- 0xcb, 0xc5, 0xfb, 0x41, 0xea, 0x77, 0xc6, 0x25,
- 0x11, 0x3a, 0x59, 0x09, 0x32, 0xfe, 0xeb, 0xb4,
- 0x59, 0x98, 0x69, 0xe2, 0x83, 0xe9, 0xdb, 0xd9,
- 0xc7, 0x24, 0xeb, 0xf2, 0xd5, 0x30, 0x3b, 0x73,
- 0xd7, 0xda, 0x9a, 0x2c, 0xd1, 0xd7, 0x95, 0x70,
- 0xc5, 0x9d, 0x71, 0xb8, 0x32, 0x68, 0xc9, 0xd1,
+ 0x9f, 0x27, 0xad, 0x25, 0xb5, 0x95, 0x4a, 0x46,
+ 0x7b, 0xc6, 0x5a, 0x67, 0x6b, 0x7a, 0x6d, 0x23,
+ 0xb2, 0xef, 0x30, 0x0f, 0x7f, 0xc7, 0x00, 0x58,
+ 0x05, 0x9e, 0x7f, 0x29, 0xe5, 0x94, 0xb5, 0xc1,
}
)
@@ -255,7 +246,7 @@ func TestDeriveH(t *testing.T) {
t.Fatal(err)
}
- // derive and checkpublic key
+ // derive and check public key
pub := prv.Public()
if !bytes.Equal(pub.Bytes(), PUB) {
t.Fatal("wrong public key")
@@ -290,16 +281,6 @@ func TestDeriveH(t *testing.T) {
}
t.Fatal("x-coordinate mismatch")
}
-
- // test query
- out := sha512.Sum512(dpub.Bytes())
- if !bytes.Equal(out[:], QUERY) {
- if testing.Verbose() {
- t.Log("query(computed) = " + hex.EncodeToString(out[:]))
- t.Log("query(expected) = " + hex.EncodeToString(QUERY))
- }
- t.Fatal("Query mismatch")
- }
}
func TestHKDF_gnunet(t *testing.T) {
diff --git a/src/gnunet/service/zonemaster/rpc.go b/src/gnunet/enums/results.go
similarity index 76%
copy from src/gnunet/service/zonemaster/rpc.go
copy to src/gnunet/enums/results.go
index 2060e56..ea93b0e 100644
--- a/src/gnunet/service/zonemaster/rpc.go
+++ b/src/gnunet/enums/results.go
@@ -16,9 +16,16 @@
//
// SPDX-License-Identifier: AGPL3.0-or-later
-package zonemaster
+//nolint:stylecheck // allow non-camel-case for constants
+package enums
-import "gnunet/service"
+// ResultCode type
+type ResultCode int32
-func (s *Service) InitRPC(rpc *service.JRPCServer) {
-}
+// ResultCode values
+const (
+ RC_SYSERR ResultCode = -1
+ RC_NO ResultCode = 0
+ RC_YES ResultCode = 1
+ RC_OK ResultCode = 1
+)
diff --git a/src/gnunet/go.mod b/src/gnunet/go.mod
index 185eaad..6e0021b 100644
--- a/src/gnunet/go.mod
+++ b/src/gnunet/go.mod
@@ -3,7 +3,7 @@ module gnunet
go 1.18
require (
- github.com/bfix/gospel v1.2.20
+ github.com/bfix/gospel v1.2.21
github.com/go-redis/redis/v8 v8.11.5
github.com/go-sql-driver/mysql v1.6.0
github.com/gorilla/mux v1.8.0
@@ -24,4 +24,4 @@ require (
golang.org/x/tools v0.1.11 // indirect
)
-// replace github.com/bfix/gospel v1.2.20 => ../gospel
+// replace github.com/bfix/gospel v1.2.21 => ../gospel
diff --git a/src/gnunet/go.sum b/src/gnunet/go.sum
index a8e3d7e..26ce2b7 100644
--- a/src/gnunet/go.sum
+++ b/src/gnunet/go.sum
@@ -1,5 +1,5 @@
-github.com/bfix/gospel v1.2.20 h1:e/IxmTiC579jIQlIxpMzCX/MIKHNsBzJ1WdMKheCgBw=
-github.com/bfix/gospel v1.2.20/go.mod
h1:cdu63bA9ZdfeDoqZ+vnWOcbY9Puwdzmf5DMxMGMznRI=
+github.com/bfix/gospel v1.2.21 h1:rgllMlR+2AZt6+x0uaBF67a+pM7fJxHiO93amhKXZNU=
+github.com/bfix/gospel v1.2.21/go.mod
h1:cdu63bA9ZdfeDoqZ+vnWOcbY9Puwdzmf5DMxMGMznRI=
github.com/cespare/xxhash/v2 v2.1.2
h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod
h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f
h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
diff --git a/src/gnunet/message/factory.go b/src/gnunet/message/factory.go
index 82af6e9..e3a2943 100644
--- a/src/gnunet/message/factory.go
+++ b/src/gnunet/message/factory.go
@@ -31,6 +31,7 @@ func NewEmptyMessage(msgType enums.MsgType) (Message, error) {
//------------------------------------------------------------------
// Transport
//------------------------------------------------------------------
+
case enums.MSG_TRANSPORT_TCP_WELCOME:
return NewTransportTCPWelcomeMsg(nil), nil
case enums.MSG_HELLO:
@@ -53,12 +54,14 @@ func NewEmptyMessage(msgType enums.MsgType) (Message,
error) {
//------------------------------------------------------------------
// Core
//------------------------------------------------------------------
+
case enums.MSG_CORE_EPHEMERAL_KEY:
return NewEphemeralKeyMsg(), nil
//------------------------------------------------------------------
// DHT
//------------------------------------------------------------------
+
case enums.MSG_DHT_CLIENT_PUT:
return NewDHTClientPutMsg(nil, 0, nil), nil
case enums.MSG_DHT_CLIENT_GET:
@@ -73,6 +76,7 @@ func NewEmptyMessage(msgType enums.MsgType) (Message, error) {
//------------------------------------------------------------------
// DHT-P2P
//------------------------------------------------------------------
+
case enums.MSG_DHT_P2P_HELLO:
return NewDHTP2PHelloMsg(), nil
case enums.MSG_DHT_P2P_GET:
@@ -85,6 +89,7 @@ func NewEmptyMessage(msgType enums.MsgType) (Message, error) {
//------------------------------------------------------------------
// GNS
//------------------------------------------------------------------
+
case enums.MSG_GNS_LOOKUP:
return NewGNSLookupMsg(), nil
case enums.MSG_GNS_LOOKUP_RESULT:
@@ -93,6 +98,7 @@ func NewEmptyMessage(msgType enums.MsgType) (Message, error) {
//------------------------------------------------------------------
// Namecache
//------------------------------------------------------------------
+
case enums.MSG_NAMECACHE_LOOKUP_BLOCK:
return NewNamecacheLookupMsg(nil), nil
case enums.MSG_NAMECACHE_LOOKUP_BLOCK_RESPONSE:
@@ -105,6 +111,7 @@ func NewEmptyMessage(msgType enums.MsgType) (Message,
error) {
//------------------------------------------------------------------
// Revocation
//------------------------------------------------------------------
+
case enums.MSG_REVOCATION_QUERY:
return NewRevocationQueryMsg(nil), nil
case enums.MSG_REVOCATION_QUERY_RESPONSE:
@@ -114,9 +121,33 @@ func NewEmptyMessage(msgType enums.MsgType) (Message,
error) {
case enums.MSG_REVOCATION_REVOKE_RESPONSE:
return NewRevocationRevokeResponseMsg(false), nil
+ //------------------------------------------------------------------
+ // Identity service
+ //------------------------------------------------------------------
+
+ case enums.MSG_IDENTITY_START:
+ return NewIdentityStartMsg(), nil
+ case enums.MSG_IDENTITY_RESULT_CODE:
+ return NewIdentityResultCodeMsg(enums.RC_OK, ""), nil
+ case enums.MSG_IDENTITY_UPDATE:
+ return NewIdentityUpdateMsg("", nil), nil
+ case enums.MSG_IDENTITY_CREATE:
+ return NewIdentityCreateMsg(nil, ""), nil
+ case enums.MSG_IDENTITY_RENAME:
+ return NewIdentityRenameMsg("", ""), nil
+ case enums.MSG_IDENTITY_DELETE:
+ return NewIdentityDeleteMsg(""), nil
+ case enums.MSG_IDENTITY_LOOKUP:
+ return NewIdentityLookupMsg(""), nil
+ case enums.MSG_IDENTITY_GET_DEFAULT:
+ return NewIdentityGetDefaultMsg(""), nil
+ case enums.MSG_IDENTITY_SET_DEFAULT:
+ return NewIdentitySetDefaultMsg(nil, ""), nil
+
//------------------------------------------------------------------
// Namestore service
//------------------------------------------------------------------
+
case enums.MSG_NAMESTORE_ZONE_ITERATION_START:
return NewNamestoreZoneIterStartMsg(nil), nil
case enums.MSG_NAMESTORE_ZONE_ITERATION_NEXT:
@@ -130,6 +161,7 @@ func NewEmptyMessage(msgType enums.MsgType) (Message,
error) {
case enums.MSG_NAMESTORE_MONITOR_START:
case enums.MSG_NAMESTORE_MONITOR_SYNC:
case enums.MSG_NAMESTORE_RECORD_RESULT:
+ return NewNamestoreRecordResultMsg(nil, ""), nil
case enums.MSG_NAMESTORE_MONITOR_NEXT:
}
return nil, fmt.Errorf("unknown message type %d", msgType)
diff --git a/src/gnunet/message/message.go b/src/gnunet/message/message.go
index 946dd6e..7e9b2d1 100644
--- a/src/gnunet/message/message.go
+++ b/src/gnunet/message/message.go
@@ -43,6 +43,9 @@ type Message interface {
// String returns a human-readable message
String() string
+
+ // Init called after unmarshalling a message to setup internal state
+ Init() error
}
//----------------------------------------------------------------------
diff --git a/src/gnunet/message/msg_core.go b/src/gnunet/message/msg_core.go
index 6ebb30e..227b901 100644
--- a/src/gnunet/message/msg_core.go
+++ b/src/gnunet/message/msg_core.go
@@ -45,7 +45,7 @@ type EphKeyBlock struct {
type EphemeralKeyMsg struct {
MsgHeader
SenderStatus uint32 `order:"big"` // enum PeerStateMachine
- Signature *util.PeerSignature `` // EdDSA signature
+ Signature *util.PeerSignature `init:"Init"` // EdDSA signature
SignedBlock *EphKeyBlock
}
@@ -68,6 +68,9 @@ func NewEphemeralKeyMsg() *EphemeralKeyMsg {
}
}
+// Init called after unmarshalling a message to setup internal state
+func (m *EphemeralKeyMsg) Init() error { return nil }
+
// String returns a human-readable representation of the message.
func (m *EphemeralKeyMsg) String() string {
return
fmt.Sprintf("EphKeyMsg{peer=%s,ephkey=%s,create=%s,expire=%s,status=%d}",
diff --git a/src/gnunet/message/msg_dht.go b/src/gnunet/message/msg_dht.go
index 0f8b9cc..2e99d40 100644
--- a/src/gnunet/message/msg_dht.go
+++ b/src/gnunet/message/msg_dht.go
@@ -67,6 +67,9 @@ func (m *DHTClientPutMsg) String() string {
m.BType, m.Expire, m.Options, m.ReplLevel, m.Key)
}
+// Init called after unmarshalling a message to setup internal state
+func (m *DHTClientPutMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// DHT_CLIENT_GET
//----------------------------------------------------------------------
@@ -113,6 +116,9 @@ func (m *DHTClientGetMsg) String() string {
m.ID, m.BType, m.Options, m.ReplLevel, m.Key)
}
+// Init called after unmarshalling a message to setup internal state
+func (m *DHTClientGetMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// DHT_CLIENT_RESULT
//----------------------------------------------------------------------
@@ -153,6 +159,9 @@ func (m *DHTClientResultMsg) String() string {
return fmt.Sprintf("DHTClientResultMsg{id:%d,type=%s,expire=%s}", m.ID,
m.BType, m.Expire)
}
+// Init called after unmarshalling a message to setup internal state
+func (m *DHTClientResultMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// DHT_CLIENT_GET_STOP
//----------------------------------------------------------------------
@@ -183,6 +192,9 @@ func (m *DHTClientGetStopMsg) String() string {
return fmt.Sprintf("DHTClientGetStopMsg{Id:%d,Key=%s}", m.ID, m.Key)
}
+// Init called after unmarshalling a message to setup internal state
+func (m *DHTClientGetStopMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// DHT_CLIENT_GET_RESULTS_KNOWN
//----------------------------------------------------------------------
@@ -220,3 +232,6 @@ func (m *DHTClientGetResultsKnownMsg) String() string {
return fmt.Sprintf("DHTClientGetResultsKnownMsg{Id:%d,Key=%s,Num=%d}",
m.ID, m.Key.Data, len(m.Known))
}
+
+// Init called after unmarshalling a message to setup internal state
+func (m *DHTClientGetResultsKnownMsg) Init() error { return nil }
diff --git a/src/gnunet/message/msg_dht_p2p.go
b/src/gnunet/message/msg_dht_p2p.go
index d4a474c..f7c24fd 100644
--- a/src/gnunet/message/msg_dht_p2p.go
+++ b/src/gnunet/message/msg_dht_p2p.go
@@ -76,6 +76,9 @@ func NewDHTP2PGetMsg() *DHTP2PGetMsg {
}
}
+// Init called after unmarshalling a message to setup internal state
+func (m *DHTP2PGetMsg) Init() (err error) { return nil }
+
// String returns a human-readable representation of the message.
func (m *DHTP2PGetMsg) String() string {
return fmt.Sprintf("DHTP2PGetMsg{btype=%s,hops=%d,flags=%s}",
@@ -167,6 +170,11 @@ func (m *DHTP2PPutMsg) IsUsed(field string) bool {
return false
}
+// Init called after unmarshalling a message to setup internal state
+func (m *DHTP2PPutMsg) Init() (err error) {
+ return nil
+}
+
//----------------------------------------------------------------------
// Update message (forwarding)
@@ -287,17 +295,17 @@ func (m *DHTP2PPutMsg) String() string {
// DHTP2PResultMsg wire layout
type DHTP2PResultMsg struct {
MsgHeader
- BType enums.BlockType `order:"big"` // Block type of
result
- Reserved uint16 `order:"big"` // Reserved
- Flags uint16 `order:"big"` // Message flags
- PutPathL uint16 `order:"big"` // size of PUTPATH
field
- GetPathL uint16 `order:"big"` // size of GETPATH
field
- Expire util.AbsoluteTime `` // expiration date
- Query *crypto.HashCode `` // Query key for
block
- TruncOrigin *util.PeerID `opt:"(IsUsed)"` // truncated origin
(if TRUNCATED flag set)
- PathList []*path.Entry `size:"(NumPath)"` // PATH
- LastSig *util.PeerSignature `opt:"(IsUsed)"` // signature of last
hop (if RECORD_ROUTE flag is set)
- Block []byte `size:"*"` // block data
+ BType enums.BlockType `order:"big"` // Block
type of result
+ Reserved uint16 `order:"big"` // Reserved
+ Flags uint16 `order:"big"` // Message
flags
+ PutPathL uint16 `order:"big"` // size of
PUTPATH field
+ GetPathL uint16 `order:"big"` // size of
GETPATH field
+ Expire util.AbsoluteTime `` //
expiration date
+ Query *crypto.HashCode `` // Query
key for block
+ TruncOrigin *util.PeerID `opt:"(IsUsed)"` //
truncated origin (if TRUNCATED flag set)
+ PathList []*path.Entry `size:"(NumPath)"` // PATH
+ LastSig *util.PeerSignature `opt:"(IsUsed)" init:"Init"` //
signature of last hop (if RECORD_ROUTE flag is set)
+ Block []byte `size:"*"` // block
data
}
// NewDHTP2PResultMsg creates a new empty DHTP2PResultMsg
@@ -330,6 +338,11 @@ func (m *DHTP2PResultMsg) NumPath(field string) uint {
return uint(m.GetPathL + m.PutPathL)
}
+// Init called after unmarshalling a message to setup internal state
+func (m *DHTP2PResultMsg) Init() (err error) {
+ return nil
+}
+
//----------------------------------------------------------------------
// Path handling (get/set path in message)
//----------------------------------------------------------------------
@@ -471,9 +484,12 @@ type DHTP2PHelloMsg struct {
MsgHeader
Reserved uint16 `order:"big"` // Reserved for further use
NumAddr uint16 `order:"big"` // Number of addresses in
list
- Signature *util.PeerSignature `` // Signature
+ Signature *util.PeerSignature `init:"Init"` // Signature
Expire util.AbsoluteTime `` // expiration time
AddrList []byte `size:"*"` // List of end-point
addresses (HelloAddress)
+
+ // transient state
+ addresses []*util.Address // list of converted addresses
}
// NewHelloMsgDHT creates an empty DHT_P2P_HELLO message.
@@ -492,8 +508,12 @@ func NewDHTP2PHelloMsg() *DHTP2PHelloMsg {
}
}
-// Addresses returns the list of HelloAddress
-func (m *DHTP2PHelloMsg) Addresses() (list []*util.Address, err error) {
+// Init called after unmarshalling a message to setup internal state
+func (m *DHTP2PHelloMsg) Init() (err error) {
+ if m.addresses != nil {
+ return
+ }
+ m.addresses = make([]*util.Address, 0)
var addr *util.Address
var as string
num, pos := 0, 0
@@ -506,16 +526,25 @@ func (m *DHTP2PHelloMsg) Addresses() (list
[]*util.Address, err error) {
return
}
addr.Expire = m.Expire
- list = append(list, addr)
+ m.addresses = append(m.addresses, addr)
num++
}
// check numbers
if num != int(m.NumAddr) {
- logger.Printf(logger.WARN, "[DHTP2PHelloMsg] Number of
addresses does not match (got %d, expected %d)", num, m.NumAddr)
+ err = errors.New("number of addresses does not match")
}
return
}
+// Addresses returns the list of HelloAddress
+func (m *DHTP2PHelloMsg) Addresses() (list []*util.Address, err error) {
+ if m.addresses == nil {
+ err = errors.New("no addresses available")
+ return
+ }
+ return m.addresses, nil
+}
+
// SetAddresses adds addresses to the HELLO message.
func (m *DHTP2PHelloMsg) SetAddresses(list []*util.Address) {
// write addresses as blob and track earliest expiration
diff --git a/src/gnunet/message/msg_gns.go b/src/gnunet/message/msg_gns.go
index 1c7f9af..64f58a4 100644
--- a/src/gnunet/message/msg_gns.go
+++ b/src/gnunet/message/msg_gns.go
@@ -37,7 +37,7 @@ import (
type LookupMsg struct {
MsgHeader
ID uint32 `order:"big"` // Unique identifier for this
request (for key collisions).
- Zone *crypto.ZoneKey `` // Zone that is to be used for
lookup
+ Zone *crypto.ZoneKey `init:"Init"` // Zone that is to be used for
lookup
Options uint16 `order:"big"` // Local options for where to
look for results
Reserved uint16 `order:"big"` // Always 0
RType enums.GNSType `order:"big"` // the type of record to look up
@@ -81,6 +81,9 @@ func (m *LookupMsg) String() string {
m.ID, m.Zone.ID(), m.Options, m.RType, m.GetName())
}
+// Init called after unmarshalling a message to setup internal state
+func (m *LookupMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// GNS_LOOKUP_RESULT
//----------------------------------------------------------------------
@@ -124,3 +127,6 @@ func (m *LookupResultMsg) String() string {
func (m *LookupResultMsg) Header() *MsgHeader {
return &MsgHeader{m.MsgSize, m.MsgType}
}
+
+// Init called after unmarshalling a message to setup internal state
+func (m *LookupResultMsg) Init() error { return nil }
diff --git a/src/gnunet/message/msg_hello.go b/src/gnunet/message/msg_hello.go
index 4cc8712..73f2d9e 100644
--- a/src/gnunet/message/msg_hello.go
+++ b/src/gnunet/message/msg_hello.go
@@ -145,6 +145,32 @@ type HelloMsg struct {
FriendsOnly uint32 `order:"big"` // Do not gossip this HELLO
message
Peer *util.PeerID `` // peer identifier for addresses
AddrList []byte `size:"*"` // List of end-point addresses
(HelloAddress)
+
+ // transient state
+ addresses []*HelloAddress // list of converted addresses
+}
+
+// Init called after unmarshalling a message to setup internal state
+func (m *HelloMsg) Init() (err error) {
+ // check for initialized state
+ if m.addresses != nil {
+ return nil
+ }
+ // convert addresses
+ m.addresses = make([]*HelloAddress, 0)
+ rdr := bytes.NewReader(m.AddrList)
+ var addr *HelloAddress
+ for {
+ // parse address from stream
+ if addr, err = ParseHelloAddr(rdr); err != nil {
+ // end of stream: no more addresses
+ if err == io.EOF {
+ err = nil
+ }
+ return
+ }
+ m.addresses = append(m.addresses, addr)
+ }
}
// NewHelloMsg creates a new HELLO msg for a given peer.
@@ -164,19 +190,10 @@ func NewHelloMsg(peer *util.PeerID) *HelloMsg {
// Addresses returns the list of HelloAddress
func (m *HelloMsg) Addresses() (list []*HelloAddress, err error) {
- rdr := bytes.NewReader(m.AddrList)
- var addr *HelloAddress
- for {
- // parse address from stream
- if addr, err = ParseHelloAddr(rdr); err != nil {
- // end of stream: no more addresses
- if err == io.EOF {
- err = nil
- }
- return
- }
- list = append(list, addr)
+ if m.addresses == nil {
+ return
}
+ return m.addresses, nil
}
// String returns a human-readable representation of the message.
diff --git a/src/gnunet/message/msg_identity.go
b/src/gnunet/message/msg_identity.go
new file mode 100644
index 0000000..fb8bba5
--- /dev/null
+++ b/src/gnunet/message/msg_identity.go
@@ -0,0 +1,473 @@
+// This file is part of gnunet-go, a GNUnet-implementation in Golang.
+// Copyright (C) 2019-2022 Bernd Fix >Y<
+//
+// gnunet-go is free software: you can redistribute it and/or modify it
+// under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// gnunet-go is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// SPDX-License-Identifier: AGPL3.0-or-later
+
+package message
+
+import (
+ "fmt"
+ "gnunet/crypto"
+ "gnunet/enums"
+ "gnunet/util"
+)
+
+//----------------------------------------------------------------------
+// MSG_IDENTITY_START
+//
+// Start client connection for update notification. Triggers sending
+// all identities as update messages to client.
+//----------------------------------------------------------------------
+
+// IdentityStartMsg to initiate session.
+type IdentityStartMsg struct {
+ MsgHeader
+}
+
+// NewIdentityStartMsg creates an empty message
+func NewIdentityStartMsg() *IdentityStartMsg {
+ return &IdentityStartMsg{
+ MsgHeader: MsgHeader{4, enums.MSG_IDENTITY_START},
+ }
+}
+
+// Init called after unmarshalling a message to setup internal state
+func (msg *IdentityStartMsg) Init() error { return nil }
+
+// String returns a human-readable representation of the message.
+func (msg *IdentityStartMsg) String() string {
+ return "IdentityStartMsg{}"
+}
+
+//----------------------------------------------------------------------
+// MSG_IDENTITY_UPDATE
+//
+// IdentityStore changed (send to all clients with started session)
+//----------------------------------------------------------------------
+
+// IdentityUpdateMsg notifies about changes in identity store
+type IdentityUpdateMsg struct {
+ MsgHeader
+
+ NameLen uint16 `order:"big"`
+ EOL uint16 `order:"big"`
+ ZoneKey *crypto.ZonePrivate `init:"Init"`
+ Name_ []byte `size:"NameLen"`
+
+ // transient state
+ name string
+}
+
+// NewIdentityUpdateMsg creates an update message. If the zone key is nil,
+// a End-Of-List is triggered so the client knows we are done.
+func NewIdentityUpdateMsg(name string, zk *crypto.ZonePrivate)
*IdentityUpdateMsg {
+ msg := &IdentityUpdateMsg{
+ MsgHeader: MsgHeader{8, enums.MSG_IDENTITY_UPDATE},
+ }
+ if zk == nil {
+ // tag end-of-list
+ msg.EOL = uint16(enums.RC_YES)
+ var size uint16
+ // assemble an empty zonekey
+ msg.ZoneKey, size = crypto.NullZonePrivate(enums.GNS_TYPE_PKEY)
+ msg.MsgSize += size
+ } else {
+ msg.name = name
+ msg.Name_ = util.WriteCString(name)
+ msg.NameLen = uint16(len(msg.Name_))
+ msg.MsgSize += msg.NameLen
+ msg.ZoneKey = zk
+ msg.MsgSize += uint16(zk.KeySize() + 4)
+ }
+ return msg
+}
+
+// Init called after unmarshalling a message to setup internal state
+func (msg *IdentityUpdateMsg) Init() error {
+ msg.name, _ = util.ReadCString(msg.Name_, 0)
+ return nil
+}
+
+// String returns a human-readable representation of the message.
+func (msg *IdentityUpdateMsg) String() string {
+ if msg.EOL == uint16(enums.RC_OK) {
+ return "IdentityUpdateMsg{end-of-list}"
+ }
+ return fmt.Sprintf("IdentityUpdateMsg{'%s'@%s}", msg.Name(),
msg.ZoneKey.ID())
+}
+
+// Name of the new identity
+func (msg *IdentityUpdateMsg) Name() string {
+ return msg.name
+}
+
+//----------------------------------------------------------------------
+// MSG_IDENTITY_RESULT_CODE
+//
+// Returned by CREATE and RENAME (and by GET_DEFAULT on failure).
+//----------------------------------------------------------------------
+
+// IdentityResultCodeMsg is a response message
+type IdentityResultCodeMsg struct {
+ MsgHeader
+
+ ResultCode enums.ResultCode `order:"big"`
+ Error string `opt:"(OnError)"`
+}
+
+// OnError returns true if an error message is attached
+func (msg *IdentityResultCodeMsg) OnError() bool {
+ return msg.ResultCode != enums.RC_OK
+}
+
+// Init called after unmarshalling a message to setup internal state
+func (msg *IdentityResultCodeMsg) Init() error { return nil }
+
+// NewIdentityResultCodeMsg creates a new default message.
+func NewIdentityResultCodeMsg(rc enums.ResultCode, err string)
*IdentityResultCodeMsg {
+ msg := &IdentityResultCodeMsg{
+ MsgHeader: MsgHeader{
+ MsgSize: 8,
+ MsgType: enums.MSG_IDENTITY_RESULT_CODE,
+ },
+ ResultCode: rc,
+ }
+ if rc != enums.RC_OK {
+ msg.Error = err
+ msg.MsgSize += uint16(len(err) + 1)
+ }
+ return msg
+}
+
+// String returns a human-readable representation of the message.
+func (msg *IdentityResultCodeMsg) String() string {
+ return fmt.Sprintf("IdentityResultCodeMsg{rc=%d,err='%s'}",
msg.ResultCode, msg.Error)
+}
+
+//----------------------------------------------------------------------
+// MSG_IDENTITY_CREATE
+//
+// Create new identity with service association
+//----------------------------------------------------------------------
+
+// IdentityCreateMsg to create a new identity for given service
+type IdentityCreateMsg struct {
+ MsgHeader
+
+ NameLen uint16 `order:"big"`
+ Reserved uint16 `order:"big"`
+ ZoneKey *crypto.ZonePrivate `init:"Init"`
+ Name_ []byte `size:"NameLen"`
+
+ // transient state
+ name string
+}
+
+// Init called after unmarshalling a message to setup internal state
+func (msg *IdentityCreateMsg) Init() error {
+ msg.name, _ = util.ReadCString(msg.Name_, 0)
+ return nil
+}
+
+// NewIdentityCreateMsg creates a new default message.
+func NewIdentityCreateMsg(zk *crypto.ZonePrivate, name string)
*IdentityCreateMsg {
+ var size uint16
+ if zk == nil {
+ zk, size = crypto.NullZonePrivate(enums.GNS_TYPE_PKEY)
+ } else {
+ size = uint16(zk.KeySize() + 4)
+ }
+ msg := &IdentityCreateMsg{
+ MsgHeader: MsgHeader{
+ MsgSize: size + 8,
+ MsgType: enums.MSG_IDENTITY_CREATE,
+ },
+ ZoneKey: zk,
+ }
+ if len(name) > 0 {
+ msg.Name_ = util.WriteCString(name)
+ msg.MsgSize += uint16(len(msg.Name_))
+ msg.name = name
+ }
+ return msg
+}
+
+// String returns a human-readable representation of the message.
+func (msg *IdentityCreateMsg) String() string {
+ return fmt.Sprintf("IdentityCreateMsg{name='%s',key=%s}", msg.name,
msg.ZoneKey.ID())
+}
+
+// Name of the new identity
+func (msg *IdentityCreateMsg) Name() string {
+ return msg.name
+}
+
+//----------------------------------------------------------------------
+// MSG_IDENTITY_RENAME
+//
+// Rename identity
+//----------------------------------------------------------------------
+
+// IdentitRenameMsg to rename an identity
+type IdentityRenameMsg struct {
+ MsgHeader
+
+ OldNameLen uint16 `order:"big"`
+ NewNameLen uint16 `order:"big"`
+ OldName_ []byte `size:"OldNameLen"`
+ NewName_ []byte `size:"NewNameLen"`
+
+ // transient state
+ oldName string
+ newName string
+}
+
+// Init called after unmarshalling a message to setup internal state
+func (msg *IdentityRenameMsg) Init() error {
+ msg.oldName, _ = util.ReadCString(msg.OldName_, 0)
+ msg.newName, _ = util.ReadCString(msg.NewName_, 0)
+ return nil
+}
+
+// NewIdentityRenameMsg renames an identity
+func NewIdentityRenameMsg(oldName, newName string) *IdentityRenameMsg {
+ msg := &IdentityRenameMsg{
+ MsgHeader: MsgHeader{
+ MsgSize: 8,
+ MsgType: enums.MSG_IDENTITY_RENAME,
+ },
+ }
+ if len(oldName) > 0 {
+ msg.OldName_ = util.WriteCString(oldName)
+ msg.MsgSize += uint16(len(msg.OldName_))
+ msg.oldName = oldName
+ }
+ if len(newName) > 0 {
+ msg.NewName_ = util.WriteCString(newName)
+ msg.MsgSize += uint16(len(msg.NewName_))
+ msg.newName = newName
+ }
+ return msg
+}
+
+// String returns a human-readable representation of the message.
+func (msg *IdentityRenameMsg) String() string {
+ return fmt.Sprintf("IdentityRenameMsg{'%s'->'%s'}", msg.oldName,
msg.newName)
+}
+
+// OldName of the identity
+func (msg *IdentityRenameMsg) OldName() string {
+ return msg.oldName
+}
+
+// NewName of the identity
+func (msg *IdentityRenameMsg) NewName() string {
+ return msg.newName
+}
+
+//----------------------------------------------------------------------
+// MSG_IDENTITY_DELETE
+//
+// Remove named identity
+//----------------------------------------------------------------------
+
+// IdentityDeleteMsg requests the deletion of an identity
+type IdentityDeleteMsg struct {
+ MsgHeader
+
+ NameLen uint16 `order:"big"`
+ Reserved uint16 `order:"big"`
+ Name_ []byte `size:"NameLen"`
+
+ // transient state
+ name string
+}
+
+// Init called after unmarshalling a message to setup internal state
+func (msg *IdentityDeleteMsg) Init() error {
+ msg.name, _ = util.ReadCString(msg.Name_, 0)
+ return nil
+}
+
+// NewIdentityDeleteMsg renames an identity
+func NewIdentityDeleteMsg(name string) *IdentityDeleteMsg {
+ msg := &IdentityDeleteMsg{
+ MsgHeader: MsgHeader{
+ MsgSize: 8,
+ MsgType: enums.MSG_IDENTITY_DELETE,
+ },
+ }
+ if len(name) > 0 {
+ msg.Name_ = util.WriteCString(name)
+ msg.MsgSize += uint16(len(msg.Name_))
+ msg.name = name
+ }
+ return msg
+}
+
+// String returns a human-readable representation of the message.
+func (msg *IdentityDeleteMsg) String() string {
+ return fmt.Sprintf("IdentityDeleteMsg{name='%s'}", msg.name)
+}
+
+// Name of the removed identity
+func (msg *IdentityDeleteMsg) Name() string {
+ return msg.name
+}
+
+//----------------------------------------------------------------------
+// MSG_IDENTITY_LOOKUP
+//
+// Return default identity
+//----------------------------------------------------------------------
+
+// IdentityLookupMsg to lookup named identity
+type IdentityLookupMsg struct {
+ MsgHeader
+
+ Name string
+}
+
+// Init called after unmarshalling a message to setup internal state
+func (msg *IdentityLookupMsg) Init() error {
+ return nil
+}
+
+// NewIdentityLookupMsg renames an identity
+func NewIdentityLookupMsg(name string) *IdentityLookupMsg {
+ return &IdentityLookupMsg{
+ MsgHeader: MsgHeader{
+ MsgSize: uint16(len(name) + 9),
+ MsgType: enums.MSG_IDENTITY_DELETE,
+ },
+ Name: name,
+ }
+}
+
+// String returns a human-readable representation of the message.
+func (msg *IdentityLookupMsg) String() string {
+ return fmt.Sprintf("IdentityLookupMsg{name='%s'}", msg.Name)
+}
+
+//----------------------------------------------------------------------
+// MSG_IDENTITY_GET_DEFAULT
+//
+// Get the default identity for named subsystem
+//----------------------------------------------------------------------
+
+// IdentityGetDefault to retrieve the default identity for a service
+type IdentityGetDefaultMsg struct {
+ MsgHeader
+
+ SrvLen uint16 `order:"big"`
+ Reserved uint16 `order:"big"`
+ Service_ []byte `size:"SrvLen"`
+
+ // transient state
+ service string
+}
+
+// Init called after unmarshalling a message to setup internal state
+func (msg *IdentityGetDefaultMsg) Init() error {
+ msg.service, _ = util.ReadCString(msg.Service_, 0)
+ return nil
+}
+
+// NewIdentityGetDefaultMsg creates a new message
+func NewIdentityGetDefaultMsg(svc string) *IdentityGetDefaultMsg {
+ msg := &IdentityGetDefaultMsg{
+ MsgHeader: MsgHeader{
+ MsgSize: 8,
+ MsgType: enums.MSG_IDENTITY_DELETE,
+ },
+ }
+ if len(svc) > 0 {
+ msg.Service_ = util.WriteCString(svc)
+ msg.MsgSize += uint16(len(msg.Service_))
+ msg.service = svc
+ }
+ return msg
+}
+
+// String returns a human-readable representation of the message.
+func (msg *IdentityGetDefaultMsg) String() string {
+ return fmt.Sprintf("IdentityGetDefaultMsg{svc='%s'}", msg.service)
+}
+
+// Service name
+func (msg *IdentityGetDefaultMsg) Service() string {
+ return msg.service
+}
+
+//----------------------------------------------------------------------
+// MSG_IDENTITY_SET_DEFAULT
+//
+// Set default identity for named subsystem
+//----------------------------------------------------------------------
+
+// IdentitySetDefaultMsg sets a default identity (key) for a service
+type IdentitySetDefaultMsg struct {
+ MsgHeader
+
+ SrvLen uint16 `order:"big"`
+ Reserved uint16 `order:"big"`
+ ZoneKey *crypto.ZonePrivate `init:"Init"`
+ Service_ []byte `size:"SrvLen"`
+
+ // transient state
+ service string
+}
+
+// Init called after unmarshalling a message to setup internal state
+func (msg *IdentitySetDefaultMsg) Init() error {
+ msg.service, _ = util.ReadCString(msg.Service_, 0)
+ return nil
+}
+
+// NewIdentitySetDefaultMsg renames an identity
+func NewIdentitySetDefaultMsg(zk *crypto.ZonePrivate, svc string)
*IdentitySetDefaultMsg {
+ msg := &IdentitySetDefaultMsg{
+ MsgHeader: MsgHeader{
+ MsgSize: 8,
+ MsgType: enums.MSG_IDENTITY_DELETE,
+ },
+ }
+ if zk == nil {
+ // assemble an empty zonekey
+ var size uint16
+ msg.ZoneKey, size = crypto.NullZonePrivate(enums.GNS_TYPE_PKEY)
+ msg.MsgSize += size
+ } else {
+ msg.ZoneKey = zk
+ msg.MsgSize += uint16(zk.KeySize() + 4)
+ }
+ if len(svc) > 0 {
+ msg.Service_ = util.WriteCString(svc)
+ msg.MsgSize += uint16(len(msg.Service_))
+ msg.service = svc
+ }
+ return msg
+}
+
+// String returns a human-readable representation of the message.
+func (msg *IdentitySetDefaultMsg) String() string {
+ return fmt.Sprintf("IdentitySetDefaultMsg{key=%s,svc='%s'}",
msg.ZoneKey.ID(), msg.service)
+}
+
+// Service name
+func (msg *IdentitySetDefaultMsg) Service() string {
+ return msg.service
+}
diff --git a/src/gnunet/message/msg_namecache.go
b/src/gnunet/message/msg_namecache.go
index 53b2f4c..61309aa 100644
--- a/src/gnunet/message/msg_namecache.go
+++ b/src/gnunet/message/msg_namecache.go
@@ -67,6 +67,9 @@ func NewNamecacheLookupMsg(query *crypto.HashCode)
*NamecacheLookupMsg {
}
}
+// Init called after unmarshalling a message to setup internal state
+func (m *NamecacheLookupMsg) Init() error { return nil }
+
// String returns a human-readable representation of the message.
func (m *NamecacheLookupMsg) String() string {
return fmt.Sprintf("NamecacheLookupMsg{Id=%d,Query=%s}",
@@ -81,11 +84,14 @@ func (m *NamecacheLookupMsg) String() string {
type NamecacheLookupResultMsg struct {
GenericNamecacheMsg
- Expire util.AbsoluteTime `` // Expiration time
- DerivedKeySig *crypto.ZoneSignature `` // Derived public key
- EncData []byte `size:"*"` // Encrypted block data
+ Expire util.AbsoluteTime `` // Expiration time
+ DerivedKeySig *crypto.ZoneSignature `init:"Init"` // Derived public key
+ EncData []byte `size:"*"` // Encrypted block
data
}
+// Init called after unmarshalling a message to setup internal state
+func (m *NamecacheLookupResultMsg) Init() error { return nil }
+
// NewNamecacheLookupResultMsg creates a new default message.
func NewNamecacheLookupResultMsg() *NamecacheLookupResultMsg {
return &NamecacheLookupResultMsg{
@@ -116,6 +122,9 @@ type NamecacheCacheMsg struct {
EncData []byte `size:"*"` // Encrypted block data
}
+// Init called after unmarshalling a message to setup internal state
+func (m *NamecacheCacheMsg) Init() error { return nil }
+
// Size returns buffer sizes for fields
func (m *NamecacheCacheMsg) FldSize(field string) uint {
switch field {
@@ -174,6 +183,9 @@ func NewNamecacheCacheResponseMsg()
*NamecacheCacheResponseMsg {
}
}
+// Init called after unmarshalling a message to setup internal state
+func (m *NamecacheCacheResponseMsg) Init() error { return nil }
+
// String returns a human-readable representation of the message.
func (m *NamecacheCacheResponseMsg) String() string {
return fmt.Sprintf("NamecacheCacheResponseMsg{id=%d,result=%d}",
diff --git a/src/gnunet/message/msg_namestore.go
b/src/gnunet/message/msg_namestore.go
index a682ef1..f03ef2c 100644
--- a/src/gnunet/message/msg_namestore.go
+++ b/src/gnunet/message/msg_namestore.go
@@ -52,7 +52,7 @@ func newGenericNamestoreMsg(size uint16, mtype enums.MsgType)
GenericNamestoreMs
type NamestoreZoneIterStartMsg struct {
GenericNamestoreMsg
- ZoneKey *crypto.ZonePrivate // private zone key
+ ZoneKey *crypto.ZonePrivate `init:"Init"` // private zone key
}
// NewNamecacheCacheMsg creates a new default message.
@@ -63,6 +63,9 @@ func NewNamestoreZoneIterStartMsg(zone *crypto.ZonePrivate)
*NamestoreZoneIterSt
}
}
+// Init called after unmarshalling a message to setup internal state
+func (m *NamestoreZoneIterStartMsg) Init() error { return nil }
+
// String returns a human-readable representation of the message.
func (m *NamestoreZoneIterStartMsg) String() string {
return fmt.Sprintf("NamestoreZoneIterStartMsg{id=%d,zone=%s}", m.ID,
m.ZoneKey.ID())
@@ -82,6 +85,9 @@ func NewNamestoreZoneIterNextMsg() *NamestoreZoneIterNextMsg {
return &NamestoreZoneIterNextMsg{}
}
+// Init called after unmarshalling a message to setup internal state
+func (m *NamestoreZoneIterNextMsg) Init() error { return nil }
+
// String returns a human-readable representation of the message.
func (m *NamestoreZoneIterNextMsg) String() string {
return fmt.Sprintf("NamestoreZoneIterNextMsg{id=%d,limit=%d}", m.ID,
m.Limit)
@@ -95,6 +101,42 @@ type NamestoreZoneIterStopMsg struct {
GenericNamestoreMsg
}
+//----------------------------------------------------------------------
+// MSG_NAMESTORE_RECORD_RESULT
+//----------------------------------------------------------------------
+
+type NamestoreRecordResultMsg struct {
+ GenericNamestoreMsg
+
+ Expire util.AbsoluteTime `` // expiration date
+ NameLen uint16 `order:"big"` // length of name
+ RdLen uint16 `order:"big"` // size of record data
+ RdCount uint16 `order:"big"` // number of records
+ Reserved uint16 `order:"big"` // alignment
+ ZoneKey *crypto.ZonePrivate `init:"Init"` // private zone key
+ Name []byte `size:"NameLen"` // name string
+ Records []byte `size:"RdLen"` // serialized record data
+}
+
+func NewNamestoreRecordResultMsg(zk *crypto.ZonePrivate, label string)
*NamestoreRecordResultMsg {
+ return &NamestoreRecordResultMsg{
+ Expire: util.AbsoluteTimeNever(),
+ ZoneKey: zk,
+ NameLen: uint16(len(label)),
+ Name: []byte(label),
+ RdLen: 0,
+ RdCount: 0,
+ }
+}
+
+// Init called after unmarshalling a message to setup internal state
+func (m *NamestoreRecordResultMsg) Init() error { return nil }
+
+// String returns a human-readable representation of the message.
+func (m *NamestoreRecordResultMsg) String() string {
+ return
fmt.Sprintf("NamestoreRecordResultMsg{id=%d,zone=%s,label='%s'}", m.ID,
m.ZoneKey.ID(), string(m.Name))
+}
+
//----------------------------------------------------------------------
//----------------------------------------------------------------------
@@ -154,19 +196,6 @@ type NamestoreZoneToNameRespMsg struct {
Records []byte `size:"RdLen"` // serialized record data
}
-type NamestoreRecordResultMsg struct {
- GenericNamestoreMsg
-
- Expire util.AbsoluteTime `` // expiration date
- NameLen uint16 `order:"big"` // length of name
- RdLen uint16 `order:"big"` // size of record data
- RdCount uint16 `order:"big"` // number of records
- Reserved uint16 `order:"big"` // alignment
- ZoneKey *crypto.ZonePrivate // private zone key
- Name []byte `size:"NameLen"` // name string
- Records []byte `size:"RdLen"` // serialized record data
-}
-
type NamestoreTxControlMsg struct {
GenericNamestoreMsg
diff --git a/src/gnunet/message/msg_revocation.go
b/src/gnunet/message/msg_revocation.go
index aaef0d4..1fa891e 100644
--- a/src/gnunet/message/msg_revocation.go
+++ b/src/gnunet/message/msg_revocation.go
@@ -34,7 +34,7 @@ import (
type RevocationQueryMsg struct {
MsgHeader
Reserved uint32 `order:"big"` // Reserved for future use
- Zone *crypto.ZoneKey // Zone that is to be checked for revocation
+ Zone *crypto.ZoneKey `init:"Init"` // Zone that is to be checked
for revocation
}
// NewRevocationQueryMsg creates a new message for a given zone.
@@ -46,6 +46,9 @@ func NewRevocationQueryMsg(zkey *crypto.ZoneKey)
*RevocationQueryMsg {
}
}
+// Init called after unmarshalling a message to setup internal state
+func (m *RevocationQueryMsg) Init() error { return nil }
+
// String returns a human-readable representation of the message.
func (m *RevocationQueryMsg) String() string {
return fmt.Sprintf("RevocationQueryMsg{zone=%s}", m.Zone.ID())
@@ -73,6 +76,9 @@ func NewRevocationQueryResponseMsg(revoked bool)
*RevocationQueryResponseMsg {
}
}
+// Init called after unmarshalling a message to setup internal state
+func (m *RevocationQueryResponseMsg) Init() error { return nil }
+
// String returns a human-readable representation of the message.
func (m *RevocationQueryResponseMsg) String() string {
return fmt.Sprintf("RevocationQueryResponseMsg{valid=%d}", m.Valid)
@@ -88,7 +94,7 @@ type RevocationRevokeMsg struct {
Timestamp util.AbsoluteTime `` // Timestamp
of revocation creation
TTL util.RelativeTime `` // TTL of
revocation
PoWs []uint64 `size:"32" order:"big"` // (Sorted)
list of PoW values
- ZoneKeySig *crypto.ZoneSignature `` // public zone
key (with signature) to be revoked
+ ZoneKeySig *crypto.ZoneSignature `init:"Init"` // public zone
key (with signature) to be revoked
}
// NewRevocationRevokeMsg creates a new message for a given zone.
@@ -102,6 +108,9 @@ func NewRevocationRevokeMsg(zsig *crypto.ZoneSignature)
*RevocationRevokeMsg {
}
}
+// Init called after unmarshalling a message to setup internal state
+func (m *RevocationRevokeMsg) Init() error { return nil }
+
// String returns a human-readable representation of the message.
func (m *RevocationRevokeMsg) String() string {
return fmt.Sprintf("RevocationRevokeMsg{zone=%s,expire=%s}",
@@ -130,6 +139,9 @@ func NewRevocationRevokeResponseMsg(success bool)
*RevocationRevokeResponseMsg {
}
}
+// Init called after unmarshalling a message to setup internal state
+func (m *RevocationRevokeResponseMsg) Init() error { return nil }
+
// String returns a human-readable representation of the message.
func (m *RevocationRevokeResponseMsg) String() string {
return fmt.Sprintf("RevocationRevokeResponseMsg{success=%v}", m.Success
== 1)
diff --git a/src/gnunet/message/msg_transport.go
b/src/gnunet/message/msg_transport.go
index 5369ca7..e02e3e6 100644
--- a/src/gnunet/message/msg_transport.go
+++ b/src/gnunet/message/msg_transport.go
@@ -57,6 +57,9 @@ func (m *TransportTCPWelcomeMsg) String() string {
return fmt.Sprintf("TransportTcpWelcomeMsg{peer=%s}", m.PeerID)
}
+// Init called after unmarshalling a message to setup internal state
+func (m *TransportTCPWelcomeMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// TRANSPORT_PING
//
@@ -105,6 +108,9 @@ func (m *TransportPingMsg) String() string {
m.Target, a, m.Challenge)
}
+// Init called after unmarshalling a message to setup internal state
+func (m *TransportPingMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// TRANSPORT_PONG
//
@@ -206,6 +212,9 @@ func (m *TransportPongMsg) Verify(pub *ed25519.PublicKey)
(bool, error) {
return pub.EdVerify(data, sig)
}
+// Init called after unmarshalling a message to setup internal state
+func (m *TransportPongMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// TRANSPORT_SESSION_ACK
//----------------------------------------------------------------------
@@ -227,6 +236,9 @@ func (m *SessionAckMsg) String() string {
return "SessionAck{}"
}
+// Init called after unmarshalling a message to setup internal state
+func (m *SessionAckMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// TRANSPORT_SESSION_SYN
//----------------------------------------------------------------------
@@ -252,6 +264,9 @@ func (m *SessionSynMsg) String() string {
return fmt.Sprintf("SessionSyn{timestamp=%s}", m.Timestamp)
}
+// Init called after unmarshalling a message to setup internal state
+func (m *SessionSynMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// TRANSPORT_SESSION_SYN_ACK
//----------------------------------------------------------------------
@@ -277,6 +292,9 @@ func (m *SessionSynAckMsg) String() string {
return fmt.Sprintf("SessionSynAck{timestamp=%s}", m.Timestamp)
}
+// Init called after unmarshalling a message to setup internal state
+func (m *SessionSynAckMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// TRANSPORT_SESSION_QUOTA
//----------------------------------------------------------------------
@@ -303,6 +321,9 @@ func (m *SessionQuotaMsg) String() string {
return fmt.Sprintf("SessionQuotaMsg{%sB/s}",
util.Scale1024(uint64(m.Quota)))
}
+// Init called after unmarshalling a message to setup internal state
+func (m *SessionQuotaMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// TRANSPORT_SESSION_KEEPALIVE
//----------------------------------------------------------------------
@@ -327,6 +348,9 @@ func (m *SessionKeepAliveMsg) String() string {
return fmt.Sprintf("SessionKeepAliveMsg{%d}", m.Nonce)
}
+// Init called after unmarshalling a message to setup internal state
+func (m *SessionKeepAliveMsg) Init() error { return nil }
+
//----------------------------------------------------------------------
// TRANSPORT_SESSION_KEEPALIVE_RESPONSE
//----------------------------------------------------------------------
@@ -350,3 +374,6 @@ func NewSessionKeepAliveRespMsg(nonce uint32)
*SessionKeepAliveRespMsg {
func (m *SessionKeepAliveRespMsg) String() string {
return fmt.Sprintf("SessionKeepAliveRespMsg{%d}", m.Nonce)
}
+
+// Init called after unmarshalling a message to setup internal state
+func (m *SessionKeepAliveRespMsg) Init() error { return nil }
diff --git a/src/gnunet/service/connection.go b/src/gnunet/service/connection.go
index fbc24d0..a008bdb 100644
--- a/src/gnunet/service/connection.go
+++ b/src/gnunet/service/connection.go
@@ -134,6 +134,9 @@ func (s *Connection) Receive(ctx context.Context)
(message.Message, error) {
if err = data.Unmarshal(msg, s.buf[:mh.MsgSize]); err != nil {
return nil, err
}
+ if err = msg.Init(); err != nil {
+ return nil, err
+ }
return msg, nil
}
diff --git a/src/gnunet/service/dht/blocks/gns.go
b/src/gnunet/service/dht/blocks/gns.go
index 0c32085..b504bc5 100644
--- a/src/gnunet/service/dht/blocks/gns.go
+++ b/src/gnunet/service/dht/blocks/gns.go
@@ -235,7 +235,7 @@ func NewRecordSet() *RecordSet {
return &RecordSet{
Count: 0,
Records: make([]*ResourceRecord, 0),
- Padding: make([]byte, 0),
+ Padding: nil,
}
}
@@ -273,6 +273,11 @@ func (rs *RecordSet) Expire() util.AbsoluteTime {
// Bytes returns the binary representation
func (rs *RecordSet) Bytes() []byte {
+ // make sure padding exists
+ if rs.Padding == nil {
+ rs.SetPadding()
+ }
+ // unmarshal record set
buf, err := data.Marshal(rs)
if err != nil {
return nil
diff --git a/src/gnunet/service/dht/blocks/gns_test.go
b/src/gnunet/service/dht/blocks/gns_test.go
index 260d83b..bc1703b 100644
--- a/src/gnunet/service/dht/blocks/gns_test.go
+++ b/src/gnunet/service/dht/blocks/gns_test.go
@@ -31,41 +31,41 @@ import (
func TestGNSBlock(t *testing.T) {
var (
- ZONEKEY =
"000G054G4G3HWZP2WFNVS1XJ4VXWY85G49AVYBZ7TV4EWP5J5V59H5QN40"
+ ZONEKEY =
"000G051J6AZ48NAJP94HD6CNBXNN9C85YT8GYVVXFKGY2516YGF7HRXKR4"
LABEL = "@"
QKEY = []byte{
- 0xb6, 0x48, 0xfd, 0x0c, 0x4a, 0x6c, 0xaa, 0x87,
- 0x33, 0x2f, 0xf5, 0x12, 0x90, 0xe4, 0xbd, 0x55,
- 0x0f, 0x8c, 0xe7, 0x9b, 0xc9, 0x5b, 0x3a, 0xfb,
- 0xbb, 0xe2, 0xd7, 0x33, 0xbc, 0x32, 0xc9, 0x7d,
- 0xc5, 0x4a, 0x56, 0x22, 0xbf, 0xfa, 0x49, 0x1a,
- 0x60, 0xd6, 0xdb, 0x77, 0x5d, 0x3d, 0x18, 0x99,
- 0x5b, 0x4f, 0xc3, 0x7d, 0x86, 0x00, 0x15, 0x76,
- 0x42, 0x03, 0x98, 0xcc, 0xdf, 0x83, 0x4d, 0x21,
+ 0xb5, 0xbb, 0xf8, 0x43, 0xfa, 0x6f, 0x7d, 0x53,
+ 0xb9, 0x84, 0x9a, 0xa1, 0x61, 0xc9, 0x44, 0x4f,
+ 0x29, 0x68, 0x98, 0x02, 0x36, 0x26, 0xc5, 0xd2,
+ 0xd3, 0x06, 0x21, 0x99, 0xf7, 0x39, 0x06, 0x46,
+ 0xdb, 0x32, 0x07, 0xa6, 0x0d, 0xd2, 0xea, 0x03,
+ 0xce, 0x74, 0x93, 0x86, 0x78, 0x3a, 0x70, 0xaa,
+ 0xa0, 0x75, 0xf1, 0x18, 0xf7, 0xb3, 0xc6, 0x0b,
+ 0x12, 0x98, 0xbb, 0x1b, 0x58, 0x53, 0xe6, 0x87,
}
BLK = []byte{
- 0x00, 0x01, 0x00, 0x14, 0xe0, 0x6b, 0xea, 0x2b,
- 0x1b, 0xd6, 0xc6, 0x9a, 0xd4, 0x30, 0xa5, 0x0f,
- 0x81, 0x16, 0x89, 0xe1, 0x9f, 0xca, 0x1f, 0x86,
- 0x3f, 0x83, 0x6e, 0xe6, 0xa7, 0x54, 0x97, 0xde,
- 0xf2, 0xc4, 0x2a, 0x84, 0xb6, 0x89, 0xe6, 0x7e,
- 0xff, 0x0c, 0xae, 0x84, 0xe6, 0xb1, 0x6c, 0x72,
- 0x83, 0x09, 0x68, 0x5b, 0x2f, 0xa2, 0x9f, 0xbe,
- 0xfa, 0xef, 0x43, 0x52, 0x20, 0x48, 0xe5, 0x57,
- 0x1e, 0x65, 0x21, 0x86, 0xd4, 0x9f, 0x96, 0x51,
- 0x4f, 0xa9, 0x6d, 0xa9, 0x98, 0xaa, 0x2d, 0xf6,
- 0x92, 0xd7, 0x86, 0x36, 0xc0, 0x84, 0x90, 0x00,
- 0x42, 0x2e, 0x4e, 0xc1, 0xaf, 0x6f, 0xe0, 0x7e,
- 0x71, 0xe3, 0xc4, 0x0d, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0x00, 0x00, 0x0f, 0x00, 0x06, 0x08, 0x00,
- 0xb5, 0x99, 0x2a, 0x00, 0xd0, 0x7a, 0x2b, 0x9e,
- 0x02, 0x45, 0x54, 0x0d, 0x65, 0x26, 0xa1, 0x05,
- 0x80, 0x26, 0xce, 0xc2, 0x70, 0xd5, 0x22, 0x38,
- 0x80, 0x9a, 0xed, 0x63, 0x2f, 0x96, 0x60, 0x4d,
- 0x02, 0x59, 0xd0, 0x9a, 0x4e, 0x71, 0xfa, 0x30,
- 0xd6, 0xf9, 0xf4, 0x84, 0x5d, 0xb8, 0x60, 0xa4,
- 0xdf, 0xea, 0x34, 0x06, 0x3f, 0x6f, 0x76, 0x9e,
+ 0x00, 0x01, 0x00, 0x14, 0x64, 0x0e, 0x2f, 0x4b,
+ 0x8e, 0x7e, 0x7f, 0x54, 0x43, 0xb4, 0x7c, 0xdc,
+ 0x84, 0xd4, 0x89, 0xfc, 0x87, 0x6e, 0x08, 0x6c,
+ 0xd9, 0x55, 0xab, 0xc6, 0x0a, 0x7d, 0xfe, 0x1b,
+ 0xfe, 0x88, 0xa7, 0x13, 0x72, 0x2b, 0xfa, 0xb1,
+ 0x70, 0xc4, 0x8c, 0xeb, 0xe3, 0x2b, 0x08, 0x9f,
+ 0x07, 0xea, 0x77, 0x51, 0x2d, 0xf1, 0x02, 0x89,
+ 0x73, 0xa8, 0xd0, 0xe0, 0x94, 0x2a, 0x16, 0x05,
+ 0xdb, 0x06, 0x0e, 0xd4, 0x0f, 0xdc, 0xac, 0x48,
+ 0xde, 0x05, 0x2c, 0x0f, 0x29, 0x81, 0xd6, 0x70,
+ 0x17, 0x95, 0x76, 0x79, 0x75, 0xce, 0x0d, 0x4b,
+ 0x98, 0xd7, 0xe5, 0x44, 0x70, 0x3b, 0xbd, 0x50,
+ 0xba, 0xfa, 0x5d, 0x01, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x0f, 0x00, 0x06, 0x09, 0x70,
+ 0x48, 0xa4, 0xa2, 0x00, 0x45, 0xb0, 0xd0, 0xdc,
+ 0x1d, 0x60, 0xd8, 0x1c, 0x4f, 0xd3, 0x50, 0xc4,
+ 0x73, 0x20, 0xc6, 0xd5, 0x28, 0x19, 0x8e, 0xa6,
+ 0x89, 0x56, 0x9f, 0x8c, 0x48, 0xf4, 0xd6, 0x76,
+ 0xf4, 0xb9, 0x70, 0xbd, 0x01, 0x2e, 0xd1, 0x4f,
+ 0x84, 0x96, 0x1b, 0xbf, 0x6c, 0xe4, 0xdb, 0x7a,
+ 0x32, 0xc1, 0x50, 0xc4, 0xb1, 0x6b, 0x08, 0x59,
}
)
// unmarshal block
@@ -89,7 +89,10 @@ func TestGNSBlock(t *testing.T) {
query := NewGNSQuery(zk, LABEL)
// check query key
- if !bytes.Equal(QKEY, query.Key().Data) {
+ qkey := query.Key().Data
+ if !bytes.Equal(QKEY, qkey) {
+ t.Logf("expected: %s", hex.EncodeToString(QKEY))
+ t.Logf("got: %s", hex.EncodeToString(qkey))
t.Fatal("query key mismatch")
}
@@ -125,11 +128,11 @@ func TestGNSBlock(t *testing.T) {
func TestRecordsetPKEY(t *testing.T) {
var (
D = []byte{
- // PKEY private scalar
- 0x50, 0xd7, 0xb6, 0x52, 0xa4, 0xef, 0xea, 0xdf,
- 0xf3, 0x73, 0x96, 0x90, 0x97, 0x85, 0xe5, 0x95,
- 0x21, 0x71, 0xa0, 0x21, 0x78, 0xc8, 0xe7, 0xd4,
- 0x50, 0xfa, 0x90, 0x79, 0x25, 0xfa, 0xfd, 0x98,
+ // PKEY private scalar (clamped little-endian)
+ 0x98, 0xfd, 0xfa, 0x25, 0x79, 0x90, 0xfa, 0x50,
+ 0xd4, 0xe7, 0xc8, 0x78, 0x21, 0xa0, 0x71, 0x21,
+ 0x95, 0xe5, 0x85, 0x97, 0x90, 0x96, 0x73, 0xf3,
+ 0xdf, 0xea, 0xef, 0xa4, 0x52, 0xb6, 0xd7, 0x50,
}
ZKEY = []byte{
// zone type
diff --git a/src/gnunet/service/namecache/module.go
b/src/gnunet/service/namecache/module.go
index 0e8053a..ee3a325 100644
--- a/src/gnunet/service/namecache/module.go
+++ b/src/gnunet/service/namecache/module.go
@@ -77,7 +77,7 @@ func (m *Module) Get(ctx context.Context, query
*blocks.GNSQuery) (block *blocks
return
}
if len(e) != 1 {
- err = errors.New("only one DHT entry exppected")
+ err = errors.New("only one namecache entry expected")
} else {
err = blocks.Unwrap(e[0].Blk, block)
}
diff --git a/src/gnunet/service/revocation/pow_test.go
b/src/gnunet/service/revocation/pow_test.go
index 41c17b4..a3bd5e6 100644
--- a/src/gnunet/service/revocation/pow_test.go
+++ b/src/gnunet/service/revocation/pow_test.go
@@ -13,7 +13,7 @@ import (
// Test revocation with test vector defined in the RFC draft.
func TestRevocationRFC(t *testing.T) {
var (
- D =
"6fea32c05af58bfa979553d188605fd57d8bf9cc263b78d5f7478c07b998ed70"
+ D =
"70ed98b9078c47f7d5783b26ccf98b7dd55f6088d1539597fa8bf55ac032ea6f"
ZKEY =
"000100002ca223e879ecc4bbdeb5da17319281d63b2e3b6955f1c3775c804a98d5f8ddaa"
PROOF = "" +
"0005d66da3598127" +
@@ -86,7 +86,11 @@ func TestRevocationRFC(t *testing.T) {
if err = data.Unmarshal(revData, revD); err != nil {
t.Fatal(err)
}
- if !bytes.Equal(revData.ZoneKeySig.Bytes(), zkey) {
+ if err = revData.ZoneKeySig.Init(); err != nil {
+ t.Fatal(err)
+ }
+ // check sigature
+ if !bytes.Equal(revData.ZoneKeySig.ZoneKey.Bytes(), zkey) {
t.Logf("zkey = %s\n",
hex.EncodeToString(revData.ZoneKeySig.Bytes()))
t.Logf("ZKEY = %s\n", hex.EncodeToString(zkey))
t.Fatal("Wrong zone key in test revocation")
diff --git a/src/gnunet/service/store/store_zonemaster.go
b/src/gnunet/service/store/store_zonemaster.go
index 44b1a68..1338c01 100644
--- a/src/gnunet/service/store/store_zonemaster.go
+++ b/src/gnunet/service/store/store_zonemaster.go
@@ -32,11 +32,15 @@ import (
)
//============================================================
-// Local zone records stored in SQLite3 database
+// Local identities and zone records (SQLite3 database)
+// Identities are named ZonePrivate keys that are associated
+// with a GNUnet subsystem (like GNS, CADET and others).
+// Identities for the subsystem "gns" are called zones and
+// are collections of labeled resource record sets. All other
+// identities are usuall called "egos".
//============================================================
// Zone is the definition of a local GNS zone
-// and is stored in a SQL database for faster access.
type Zone struct {
ID int64 // database identifier
Name string // zone name
@@ -59,6 +63,23 @@ func NewZone(name string, sk *crypto.ZonePrivate) *Zone {
//----------------------------------------------------------------------
+// Identity is a Zone associated with a service
+type Identity struct {
+ Zone
+
+ Svc string // associated service
+}
+
+// NewIdentity creates an initialize instance for database access
+func NewIdentity(name string, sk *crypto.ZonePrivate, svc string) *Identity {
+ return &Identity{
+ Zone: *NewZone(name, sk),
+ Svc: svc,
+ }
+}
+
+//----------------------------------------------------------------------
+
type Label struct {
ID int64 // database id of label
Zone int64 // database ID of parent zone
@@ -136,7 +157,7 @@ func OpenZoneDB(fname string) (db *ZoneDB, err error) {
return
}
// check for initialized database
- res := db.conn.QueryRow("select name from sqlite_master where
type='table' and name='zones'")
+ res := db.conn.QueryRow("select name from sqlite_master where
type='table' and name='identities'")
var s string
if res.Scan(&s) != nil {
// initialize database
@@ -152,6 +173,152 @@ func (db *ZoneDB) Close() error {
return db.conn.Close()
}
+//----------------------------------------------------------------------
+// Identity handling
+//----------------------------------------------------------------------
+
+// SetIdentity inserts, updates or deletes a zone in the database.
+// The function does not change timestamps which are in the
+// responsibility of the caller.
+// - insert: Identity.ID is nil (0)
+// - update: Identity.Name is set
+// - remove: otherwise
+func (db *ZoneDB) SetIdentity(id *Identity) error {
+ // GNS zones are handled by Zone instances
+ if id.Svc == "gns" {
+ return db.SetZone(&id.Zone)
+ }
+ // check for identity insert
+ if id.ID == 0 {
+ stmt := "insert into
identities(svc,name,created,modified,ztype,zdata) values(?,?,?,?,?,?)"
+ result, err := db.conn.Exec(stmt,
+ id.Svc, id.Name, id.Created.Val, id.Modified.Val,
id.Key.Type, id.Key.KeyData)
+ if err != nil {
+ return err
+ }
+ id.ID, err = result.LastInsertId()
+ return err
+ }
+ // check for identity update (name and service only only)
+ if len(id.Name) > 0 {
+ stmt := "update identities set svc=?,name=?,modified=? where
id=?"
+ result, err := db.conn.Exec(stmt, id.Svc, id.Name,
id.Modified.Val, id.ID)
+ if err != nil {
+ return err
+ }
+ var num int64
+ if num, err = result.RowsAffected(); err == nil {
+ if num != 1 {
+ err = errors.New("update identity failed")
+ }
+ }
+ return err
+ }
+ // remove identity from database
+ _, err := db.conn.Exec("delete from identities where id=?", id.ID)
+ return err
+}
+
+// GetIdentity gets an identifier with given database id
+func (db *ZoneDB) GetIdentity(id int64) (ident *Identity, err error) {
+ // assemble identity from database row
+ stmt := "select svc,name,created,modified,ztype,zdata from identities
where id=?"
+ ident = new(Identity)
+ ident.ID = id
+ row := db.conn.QueryRow(stmt, id)
+ var ztype enums.GNSType
+ var zdata []byte
+ if err = row.Scan(&ident.Svc, &ident.Name, &ident.Created.Val,
&ident.Modified.Val, &ztype, &zdata); err == nil {
+ // reconstruct private zone key
+ ident.Key, err = crypto.NewZonePrivate(ztype, zdata)
+ }
+ return
+}
+
+// GetIdentity gets an identifier with given (name,svc)
+func (db *ZoneDB) GetIdentityByName(name, svc string) (ident *Identity, err
error) {
+ // assemble identity from database row
+ var row *sql.Row
+ stmt := "select id,created,modified,ztype,zdata from identities where
name=?"
+ if len(svc) > 0 {
+ stmt += " and svc=?"
+ row = db.conn.QueryRow(stmt, name, svc)
+ } else {
+ row = db.conn.QueryRow(stmt, name)
+ }
+ ident = new(Identity)
+ ident.Name = name
+ ident.Svc = svc
+ var ztype enums.GNSType
+ var zdata []byte
+ if err = row.Scan(&ident.ID, &ident.Created.Val, &ident.Modified.Val,
&ztype, &zdata); err == nil {
+ // reconstruct private zone key
+ ident.Key, err = crypto.NewZonePrivate(ztype, zdata)
+ }
+ return
+}
+
+func (db *ZoneDB) GetIdentities(filter string, args ...any) (list []*Identity,
err error) {
+ // assemble query
+ stmt := "select id,name,svc,created,modified,ztype,zdata from
identities"
+ if len(filter) > 0 {
+ stmt += " where " + fmt.Sprintf(filter, args...)
+ }
+ // select zones
+ var rows *sql.Rows
+ if rows, err = db.conn.Query(stmt); err != nil {
+ return
+ }
+ // process zones
+ defer rows.Close()
+ for rows.Next() {
+ // assemble identity from database row
+ i := new(Identity)
+ var ztype enums.GNSType
+ var zdata []byte
+ if err = rows.Scan(&i.ID, &i.Name, &i.Svc, &i.Created.Val,
&i.Modified.Val, &ztype, &zdata); err != nil {
+ // terminate on error; return list so far
+ return
+ }
+ // reconstruct private key
+ if i.Key, err = crypto.NewZonePrivate(ztype, zdata); err != nil
{
+ return
+ }
+ // append to result list
+ list = append(list, i)
+ }
+ return
+}
+
+func (db *ZoneDB) GetDefaultIdentity(svc string) (ident *Identity, err error) {
+ // assemble identity from database row
+ stmt := "select id,name,created,modified,ztype,zdata from v_defaults
where svc=?"
+ row := db.conn.QueryRow(stmt, svc)
+ ident = new(Identity)
+ ident.Svc = svc
+ var ztype enums.GNSType
+ var zdata []byte
+ if err = row.Scan(&ident.ID, &ident.Name, &ident.Created.Val,
&ident.Modified.Val, &ztype, &zdata); err == nil {
+ // reconstruct private zone key
+ ident.Key, err = crypto.NewZonePrivate(ztype, zdata)
+ }
+ return
+}
+
+func (db *ZoneDB) SetDefaultIdentity(zk *crypto.ZonePrivate, svc string) (err
error) {
+ // get database id of identity
+ stmt := "select id from identities where zdata=?"
+ row := db.conn.QueryRow(stmt, zk.KeyData)
+ var id int64
+ if err = row.Scan(&id); err != nil {
+ return
+ }
+ // set default
+ stmt = "insert into defaults(svc,ident) values(?,?) on conflict(svc) do
update set ident=?"
+ _, err = db.conn.Exec(stmt, svc, id, id)
+ return
+}
+
//----------------------------------------------------------------------
// Zone handling
//----------------------------------------------------------------------
@@ -165,7 +332,7 @@ func (db *ZoneDB) Close() error {
func (db *ZoneDB) SetZone(z *Zone) error {
// check for zone insert
if z.ID == 0 {
- stmt := "insert into zones(name,created,modified,ztype,zdata)
values(?,?,?,?,?)"
+ stmt := "insert into
identities(svc,name,created,modified,ztype,zdata) values('gns',?,?,?,?,?)"
result, err := db.conn.Exec(stmt, z.Name, z.Created.Val,
z.Modified.Val, z.Key.Type, z.Key.KeyData)
if err != nil {
return err
@@ -175,7 +342,7 @@ func (db *ZoneDB) SetZone(z *Zone) error {
}
// check for zone update (name only)
if len(z.Name) > 0 {
- stmt := "update zones set name=?,modified=? where id=?"
+ stmt := "update identities set name=?,modified=? where id=? and
svc='gns'"
result, err := db.conn.Exec(stmt, z.Name, z.Modified.Val, z.ID)
if err != nil {
return err
@@ -202,6 +369,7 @@ func (db *ZoneDB) GetZone(id int64) (zone *Zone, err error)
{
// assemble zone from database row
stmt := "select name,created,modified,ztype,zdata from zones where id=?"
zone = new(Zone)
+ zone.ID = id
var ztype enums.GNSType
var zdata []byte
row := db.conn.QueryRow(stmt, id)
@@ -329,6 +497,29 @@ func (db *ZoneDB) GetLabels(filter string, args ...any)
(list []*Label, err erro
return
}
+func (db *ZoneDB) GetLabelIDs(zk *crypto.ZonePrivate) (list []int64, err
error) {
+ // get zone database id
+ row := db.conn.QueryRow("select id from zones where ztype=? and
zdata=?", zk.Type, zk.KeyData)
+ var zid int64
+ if err = row.Scan(&zid); err != nil {
+ return
+ }
+ // select all labels for zone
+ var rows *sql.Rows
+ if rows, err = db.conn.Query("select id from labels where zid=?", zid);
err != nil {
+ return
+ }
+ defer rows.Close()
+ var id int64
+ for rows.Next() {
+ if err = rows.Scan(&id); err != nil {
+ return
+ }
+ list = append(list, id)
+ }
+ return
+}
+
//----------------------------------------------------------------------
// Record handling
//----------------------------------------------------------------------
diff --git a/src/gnunet/service/store/store_zonemaster.sql
b/src/gnunet/service/store/store_zonemaster.sql
index 169fefd..69b8ab5 100644
--- a/src/gnunet/service/store/store_zonemaster.sql
+++ b/src/gnunet/service/store/store_zonemaster.sql
@@ -16,15 +16,37 @@
--
-- SPDX-License-Identifier: AGPL3.0-or-later
-create table zones (
+create table identities (
id integer primary key autoincrement,
- name text unique,
+ svc text,
+ name text,
created integer,
modified integer,
- ztype integer,
- zdata blob
+ ztype integer,
+ zdata blob,
+ unique (svc,name)
);
+create table defaults (
+ svc text unique,
+ ident integer references identities(id)
+);
+
+create view v_defaults as select
+ i.id as id,
+ d.svc as svc,
+ i.name as name,
+ i.created as created,
+ i.modified as modified,
+ i.ztype as ztype,
+ i.zdata as zdata
+from identities i, defaults d
+where i.id = d.ident;
+
+create view zones as select
+ id, name, created, modified, ztype, zdata
+from identities
+where svc = 'gns';
create table labels (
id integer primary key autoincrement,
diff --git a/src/gnunet/service/zonemaster/gui.go
b/src/gnunet/service/zonemaster/gui.go
index 3885d01..5a2f17d 100644
--- a/src/gnunet/service/zonemaster/gui.go
+++ b/src/gnunet/service/zonemaster/gui.go
@@ -21,10 +21,10 @@ package zonemaster
import (
"bytes"
"context"
- "crypto/rand"
"embed"
"errors"
"fmt"
+ "gnunet/config"
"gnunet/crypto"
"gnunet/enums"
"gnunet/service/gns/rr"
@@ -122,6 +122,13 @@ func (zm *ZoneMaster) startGUI(ctx context.Context) {
"rrdata": func(t enums.GNSType, buf []byte) string {
return guiRRdata(t, buf)
},
+ "tabSetList": func(num int) (list map[int]int) {
+ list = make(map[int]int)
+ for i := 0; i < num; i++ {
+ list[i+1] = 2*i + 1
+ }
+ return
+ },
})
if _, err := tpl.ParseFS(fsys, "*.htpl"); err != nil {
logger.Println(logger.ERROR, "[zonemaster] GUI templates
failed: "+err.Error())
@@ -136,7 +143,7 @@ func (zm *ZoneMaster) startGUI(ctx context.Context) {
router.HandleFunc("/action/{cmd}/{mode}/{id}", zm.action)
router.HandleFunc("/", zm.dashboard)
srv := &http.Server{
- Addr: zm.cfg.ZoneMaster.GUI,
+ Addr: config.Cfg.ZoneMaster.GUI,
ReadTimeout: 10 * time.Second,
ReadHeaderTimeout: 5 * time.Second,
Handler: router,
@@ -205,17 +212,17 @@ func (zm *ZoneMaster) actionNew(w http.ResponseWriter, r
*http.Request, mode str
// new zone
case "zone":
name := r.FormValue("name")
- // create private key
- seed := make([]byte, 32)
- if _, err = rand.Read(seed); err != nil {
- return
- }
- var zp *crypto.ZonePrivate
- kt := enums.GNS_TYPE_PKEY
- if r.FormValue("keytype") == "EDKEY" {
+ // get key type
+ var kt enums.GNSType
+ switch r.FormValue("keytype") {
+ case "EDKEY":
kt = enums.GNS_TYPE_EDKEY
+ case "PKEY":
+ kt = enums.GNS_TYPE_PKEY
}
- zp, err = crypto.NewZonePrivate(kt, seed)
+ // cretae private key
+ var zp *crypto.ZonePrivate
+ zp, err = crypto.NewZonePrivate(kt, nil)
if err != nil {
return
}
@@ -366,7 +373,7 @@ func (zm *ZoneMaster) updRec(w http.ResponseWriter, r
*http.Request, id int64) e
}
//----------------------------------------------------------------------
-// Create new zone. label or resource record
+// Create new zone, label or resource record
//----------------------------------------------------------------------
type NewEditData struct {
@@ -630,8 +637,15 @@ func (zm *ZoneMaster) remove(w http.ResponseWriter, r
*http.Request) {
// Helper methods
//======================================================================
+// MainData for the template "main"
+type MainData struct {
+ Content string // Page content
+ Params any // reference to parameters
+ NumRR int // number of RR types supported
+}
+
// render a webpage with given data and template reference
-func renderPage(w io.Writer, data interface{}, page string) {
+func renderPage(w io.Writer, data any, page string) {
// create content section
t := tpl.Lookup(page)
if t == nil {
@@ -649,7 +663,11 @@ func renderPage(w io.Writer, data interface{}, page
string) {
_, _ = io.WriteString(w, "No main template found")
return
}
- if err := t.Execute(w, content.String()); err != nil {
+ md := new(MainData)
+ md.Params = data
+ md.Content = content.String()
+ md.NumRR = len(rrtypes)
+ if err := t.Execute(w, md); err != nil {
_, _ = io.WriteString(w, err.Error())
}
}
diff --git a/src/gnunet/service/zonemaster/gui.htpl
b/src/gnunet/service/zonemaster/gui.htpl
index ffa9720..de51ee3 100644
--- a/src/gnunet/service/zonemaster/gui.htpl
+++ b/src/gnunet/service/zonemaster/gui.htpl
@@ -3,12 +3,12 @@
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1,
shrink-to-fit=no">
- {{template "css"}}
+ {{template "css" .NumRR}}
</head>
<body>
<h1>GNUnet Zone Master</h1>
<hr/>
- {{.}}
+ {{.Content}}
<script>
function notify(msg) {
if ('Notification' in window) {
diff --git a/src/gnunet/service/zonemaster/gui_css.htpl
b/src/gnunet/service/zonemaster/gui_css.htpl
index b31e714..8a26b30 100644
--- a/src/gnunet/service/zonemaster/gui_css.htpl
+++ b/src/gnunet/service/zonemaster/gui_css.htpl
@@ -165,9 +165,6 @@
.nested {
display: none;
}
- .active {
- display: block;
- }
.tabset > input[type="radio"] {
position: absolute;
left: -200vw;
@@ -175,26 +172,10 @@
.tabset .tab-panel {
display: none;
}
- .tabset > input:first-child:checked ~ .tab-panels > .tab-panel:first-child,
- .tabset > input:nth-child(3):checked ~ .tab-panels >
.tab-panel:nth-child(2),
- .tabset > input:nth-child(5):checked ~ .tab-panels >
.tab-panel:nth-child(3),
- .tabset > input:nth-child(7):checked ~ .tab-panels >
.tab-panel:nth-child(4),
- .tabset > input:nth-child(9):checked ~ .tab-panels >
.tab-panel:nth-child(5),
- .tabset > input:nth-child(11):checked ~ .tab-panels >
.tab-panel:nth-child(6),
- .tabset > input:nth-child(13):checked ~ .tab-panels >
.tab-panel:nth-child(7),
- .tabset > input:nth-child(15):checked ~ .tab-panels >
.tab-panel:nth-child(8),
- .tabset > input:nth-child(17):checked ~ .tab-panels >
.tab-panel:nth-child(9),
- .tabset > input:nth-child(19):checked ~ .tab-panels >
.tab-panel:nth-child(10),
- .tabset > input:nth-child(21):checked ~ .tab-panels >
.tab-panel:nth-child(11),
- .tabset > input:nth-child(23):checked ~ .tab-panels >
.tab-panel:nth-child(12),
- .tabset > input:nth-child(25):checked ~ .tab-panels >
.tab-panel:nth-child(13),
- .tabset > input:nth-child(27):checked ~ .tab-panels >
.tab-panel:nth-child(14),
- .tabset > input:nth-child(29):checked ~ .tab-panels >
.tab-panel:nth-child(15),
- .tabset > input:nth-child(31):checked ~ .tab-panels >
.tab-panel:nth-child(16),
- .tabset > input:nth-child(33):checked ~ .tab-panels >
.tab-panel:nth-child(17),
- .tabset > input:nth-child(35):checked ~ .tab-panels >
.tab-panel:nth-child(18),
- .tabset > input:nth-child(37):checked ~ .tab-panels >
.tab-panel:nth-child(19),
- .tabset > input:nth-child(39):checked ~ .tab-panels >
.tab-panel:nth-child(20) {
+ {{range $i,$j := tabSetList .}}
+ .tabset > input:nth-child({{$j}}):checked ~ .tab-panels >
.tab-panel:nth-child({{$i}}),
+ {{end}}
+ .active {
display: block;
}
.tabset > label {
diff --git a/src/gnunet/service/zonemaster/gui_new.htpl
b/src/gnunet/service/zonemaster/gui_new.htpl
index f470de9..81d32e8 100644
--- a/src/gnunet/service/zonemaster/gui_new.htpl
+++ b/src/gnunet/service/zonemaster/gui_new.htpl
@@ -31,7 +31,7 @@
alert("Empty zone name not allowed");
return false;
}
- for (var i = 0; i < names.length; i++) {
+ for (var i = 0; i < zone_names.length; i++) {
if (zone_names[i] == name) {
alert("Zone name already used");
return false;
@@ -45,7 +45,7 @@
{{define "new_label"}}
<div>
<h3>Creating a new GNS label for zone "{{index .Params "zone"}}":</h3>
- <form action="/action/new/label/{{.Ref}}"
onsubmit="return(label_validate());">
+ <form action="/action/new/label/{{.Ref}}" method="post"
onsubmit="return(label_validate());">
<table>
<tr>
<td align="right">Name:</td>
@@ -68,7 +68,7 @@
alert("Empty labels not allowed");
return false;
}
- for (var i = 0; i < names.length; i++) {
+ for (var i = 0; i < label_names.length; i++) {
if (label_names[i] == name) {
alert("Label already used");
return false;
diff --git a/src/gnunet/service/zonemaster/gui_rr.htpl
b/src/gnunet/service/zonemaster/gui_rr.htpl
index 360a734..00b9148 100644
--- a/src/gnunet/service/zonemaster/gui_rr.htpl
+++ b/src/gnunet/service/zonemaster/gui_rr.htpl
@@ -1,19 +1,19 @@
{{define "RRCommon"}}
- <input type="hidden" name="lid" value="{{index . "lid"}}">
- {{range $k, $v := .}}
+ <input type="hidden" name="lid" value="{{index .Params "lid"}}">
+ {{range $k, $v := .Params}}
<input type="hidden" name="old_{{$k}}" value="{{$v}}">
{{end}}
- {{$pf := index . "prefix"}}
+ {{$pf := index .Params "prefix"}}
<tr>
<td align="right" valign="top"><b>Expires:</b></td>
<td>
Never <input type="checkbox" class="alternate" name="{{$pf}}never"
- {{if eq "on" (index . (print $pf
"never"))}}checked="checked"{{end}}
+ {{if eq "on" (index .Params (print $pf
"never"))}}checked="checked"{{end}}
>
<div class="alternate">
At given date and time:
<input type="datetime-local" id="{{$pf}}expires"
name="{{$pf}}expires" required
- value="{{index . (print $pf "expires")}}"
+ value="{{index .Params (print $pf "expires")}}"
>
</div>
</td>
@@ -22,13 +22,13 @@
<td align="right" valign="top"><b>Flags:</b></td>
<td>
<input type="checkbox" name="{{$pf}}private"
- {{if eq "on" (index . (print $pf
"private"))}}checked="checked" class="disabled"{{end}}
+ {{if eq "on" (index .Params (print $pf
"private"))}}checked="checked" class="disabled"{{end}}
> Private<br>
<input type="checkbox" name="{{$pf}}shadow"
- {{if eq "on" (index . (print $pf "shadow"))}}checked="checked"
class="disabled"{{end}}
+ {{if eq "on" (index .Params (print $pf
"shadow"))}}checked="checked" class="disabled"{{end}}
> Shadow<br>
<input type="checkbox" name="{{$pf}}suppl"
- {{if eq "on" (index . (print $pf "suppl"))}}checked="checked"
class="disabled"{{end}}
+ {{if eq "on" (index .Params (print $pf
"suppl"))}}checked="checked" class="disabled"{{end}}
> Supplemental<br>
</td>
</tr>
@@ -68,7 +68,7 @@
>
</td>
</tr>
- {{template "RRCommon" .Params}}
+ {{template "RRCommon" .}}
<tr><td/><td><button id="submit">{{.Button}}
record</button></td></tr>
</table>
</form>
@@ -98,7 +98,7 @@
>
</td>
</tr>
- {{template "RRCommon" .Params}}
+ {{template "RRCommon" .}}
<tr><td/><td><button id="submit">{{.Button}}
record</button></td></tr>
</table>
</form>
@@ -125,7 +125,7 @@
>
</td>
</tr>
- {{template "RRCommon" .Params}}
+ {{template "RRCommon" .}}
<tr><td/><td><button id="submit">{{.Button}}
record</button></td></tr>
</table>
</form>
@@ -145,7 +145,7 @@
>
</td>
</tr>
- {{template "RRCommon" .Params}}
+ {{template "RRCommon" .}}
<tr><td/><td><button id="submit">{{.Button}}
record</button></td></tr>
</table>
</form>
@@ -165,7 +165,7 @@
>
</td>
</tr>
- {{template "RRCommon" .Params}}
+ {{template "RRCommon" .}}
<tr><td/><td><button id="submit">{{.Button}}
record</button></td></tr>
</table>
</form>
@@ -200,7 +200,7 @@
>
</td>
</tr>
- {{template "RRCommon" .Params}}
+ {{template "RRCommon" .}}
<tr><td/><td><button id="submit">{{.Button}}
record</button></td></tr>
</table>
</form>
@@ -302,7 +302,7 @@
</div>
</td>
</tr>
- {{template "RRCommon" .Params}}
+ {{template "RRCommon" .}}
<tr><td/><td><button id="submit">{{.Button}}
record</button></td></tr>
</table>
</form>
@@ -323,7 +323,7 @@
>
</td>
</tr>
- {{template "RRCommon" .Params}}
+ {{template "RRCommon" .}}
<tr><td/><td><button id="submit">{{.Button}}
record</button></td></tr>
</table>
</form>
@@ -344,7 +344,7 @@
>
</td>
</tr>
- {{template "RRCommon" .Params}}
+ {{template "RRCommon" .}}
<tr><td/><td><button id="submit">{{.Button}}
record</button></td></tr>
</table>
</form>
@@ -364,7 +364,7 @@
>
</td>
</tr>
- {{template "RRCommon" .Params}}
+ {{template "RRCommon" .}}
<tr><td/><td><button id="submit">{{.Button}}
record</button></td></tr>
</table>
</form>
@@ -384,7 +384,7 @@
>
</td>
</tr>
- {{template "RRCommon" .Params}}
+ {{template "RRCommon" .}}
<tr><td/><td><button id="submit">{{.Button}}
record</button></td></tr>
</table>
</form>
@@ -413,7 +413,7 @@
>
</td>
</tr>
- {{template "RRCommon" .Params}}
+ {{template "RRCommon" .}}
<tr><td/><td><button id="submit">{{.Button}}
record</button></td></tr>
</table>
</form>
diff --git a/src/gnunet/service/zonemaster/records.go
b/src/gnunet/service/zonemaster/records.go
index 3015893..a10ee05 100644
--- a/src/gnunet/service/zonemaster/records.go
+++ b/src/gnunet/service/zonemaster/records.go
@@ -22,8 +22,11 @@ import (
"encoding/hex"
"errors"
"fmt"
+ "gnunet/crypto"
"gnunet/enums"
+ "gnunet/service/dht/blocks"
"gnunet/service/gns/rr"
+ "gnunet/service/store"
"gnunet/util"
"net"
"time"
@@ -330,7 +333,7 @@ func Map2RRData(t enums.GNSType, set map[string]string)
(buf []byte, err error)
}
//======================================================================
-// Get list of allowed new RRs given a set of existing RRs.
+// ResourceRecord helpers
//======================================================================
// Create a list of compatible record types from list of
@@ -346,3 +349,23 @@ func compatibleRR(in []*enums.GNSSpec, label string) (out
[]*enums.GNSSpec) {
}
return
}
+
+// get a list of resource records for a given label in a zone.
+func (zm *ZoneMaster) getRecords(zk *crypto.ZoneKey, label int64) (rs
*blocks.RecordSet, expire util.AbsoluteTime, err error) {
+ // collect records for zone label
+ var recs []*store.Record
+ if recs, err = zm.zdb.GetRecords("lid=%d", label); err != nil {
+ return
+ }
+ // assemble record set and find earliest expiration
+ expire = util.AbsoluteTimeNever()
+ rs = blocks.NewRecordSet()
+ for _, r := range recs {
+ if r.Expire.Compare(expire) < 0 {
+ expire = r.Expire
+ }
+ rs.AddRecord(&r.ResourceRecord)
+ }
+ // do not add padding yet as record set may be filtered before use.
+ return
+}
diff --git a/src/gnunet/service/zonemaster/rpc.go
b/src/gnunet/service/zonemaster/rpc.go
index 2060e56..4df5b21 100644
--- a/src/gnunet/service/zonemaster/rpc.go
+++ b/src/gnunet/service/zonemaster/rpc.go
@@ -20,5 +20,5 @@ package zonemaster
import "gnunet/service"
-func (s *Service) InitRPC(rpc *service.JRPCServer) {
+func (zm *ZoneMaster) InitRPC(rpc *service.JRPCServer) {
}
diff --git a/src/gnunet/service/zonemaster/service.go
b/src/gnunet/service/zonemaster/service.go
index c73857f..5725ec8 100644
--- a/src/gnunet/service/zonemaster/service.go
+++ b/src/gnunet/service/zonemaster/service.go
@@ -25,7 +25,7 @@ import (
"gnunet/config"
"gnunet/core"
- "gnunet/crypto"
+ "gnunet/enums"
"gnunet/message"
"gnunet/service"
"gnunet/service/dht/blocks"
@@ -35,43 +35,20 @@ import (
"github.com/bfix/gospel/logger"
)
-type ZoneIterator struct {
- zk *crypto.ZonePrivate
-}
-
//----------------------------------------------------------------------
-// "GNUnet Zonemaster" service implementation:
-// The zonemaster service handles Namestore messages
+// "GNUnet Zonemaster" socket service implementation:
+// Zonemaster handles Namestore and Identity messages.
//----------------------------------------------------------------------
-// Service implements a GNS service
-type Service struct {
- Module
-
- ZoneIters *util.Map[uint32, *ZoneIterator]
-}
-
-// NewService creates a new GNS service instance
-func NewService(ctx context.Context, c *core.Core) service.Service {
- // instantiate service
- mod := NewModule(ctx, c)
- srv := &Service{
- Module: *mod,
- ZoneIters: util.NewMap[uint32, *ZoneIterator](),
- }
- // set external function references (external services)
- srv.StoreLocal = srv.StoreNamecache
- srv.StoreRemote = srv.StoreDHT
-
- return srv
-}
-
// ServeClient processes a client channel.
-func (s *Service) ServeClient(ctx context.Context, id int, mc
*service.Connection) {
+func (zm *ZoneMaster) ServeClient(ctx context.Context, id int, mc
*service.Connection) {
reqID := 0
var cancel context.CancelFunc
ctx, cancel = context.WithCancel(ctx)
+ // inform sub-service about new session
+ zm.identity.NewSession(id, mc)
+
for {
// receive next message from client
reqID++
@@ -89,33 +66,158 @@ func (s *Service) ServeClient(ctx context.Context, id int,
mc *service.Connectio
}
logger.Printf(logger.INFO, "[zonemaster:%d:%d] Received
request: %v\n", id, reqID, msg)
+ // context with values
+ values := make(util.ParameterSet)
+ values["id"] = id
+ values["label"] = fmt.Sprintf(":%d:%d", id, reqID)
+ valueCtx := context.WithValue(ctx, core.CtxKey("params"),
values)
+
// handle message
- valueCtx := context.WithValue(ctx, core.CtxKey("label"),
fmt.Sprintf(":%d:%d", id, reqID))
- s.HandleMessage(valueCtx, nil, msg, mc)
+ zm.HandleMessage(valueCtx, nil, msg, mc)
}
+ // inform sub.services about closed session
+ zm.identity.CloseSession(id)
+
// close client connection
mc.Close()
// cancel all tasks running for this session/connection
- logger.Printf(logger.INFO, "[zonemaster:%d] Start closing
session...\n", id)
+ logger.Printf(logger.INFO, "[zonemaster:%d] Closing session...\n", id)
cancel()
}
// Handle a single incoming message
-func (s *Service) HandleMessage(ctx context.Context, sender *util.PeerID, msg
message.Message, back transport.Responder) bool {
+func (zm *ZoneMaster) HandleMessage(ctx context.Context, sender *util.PeerID,
msg message.Message, back transport.Responder) bool {
// assemble log label
- label := ""
- if v := ctx.Value("label"); v != nil {
- label, _ = v.(string)
+ var id int
+ var label string
+ if v := ctx.Value(core.CtxKey("params")); v != nil {
+ if ps, ok := v.(util.ParameterSet); ok {
+ label, _ = util.GetParam[string](ps, "label")
+ id, _ = util.GetParam[int](ps, "id")
+ }
}
// perform lookup
switch m := msg.(type) {
+ //------------------------------------------------------------------
+ // Identity service
+ //------------------------------------------------------------------
+
+ // start identity update listener
+ case *message.IdentityStartMsg:
+ if err := zm.identity.Start(ctx, id); err != nil {
+ logger.Printf(logger.ERROR, "[zonemaster%s] Identity
session for %d failed: %v\n", label, id, err)
+ return false
+ }
+
+ // create a new identity with given private key
+ case *message.IdentityCreateMsg:
+ if err := zm.identity.Create(ctx, id, m.ZoneKey, m.Name()); err
!= nil {
+ logger.Printf(logger.ERROR, "[zonemaster%s] Identity
create failed: %v\n", label, err)
+ return false
+ }
+
+ // rename identity
+ case *message.IdentityRenameMsg:
+ id, err := zm.zdb.GetIdentityByName(m.OldName(),
IDENT_DEFAULT_SERVICE)
+ if err != nil {
+ logger.Printf(logger.ERROR, "[zonemaster%s] Identity
lookup failed: %v\n", label, err)
+ return false
+ }
+ // change name
+ id.Name = m.NewName()
+ err = zm.zdb.SetIdentity(id)
+
+ // send response
+ rc := enums.RC_OK
+ msg := ""
+ if err != nil {
+ rc = enums.RC_NO
+ msg = err.Error()
+ }
+ resp := message.NewIdentityResultCodeMsg(rc, msg)
+ if err = back.Send(ctx, resp); err != nil {
+ logger.Printf(logger.ERROR, "[identity:%s] Can't send
response (%v): %v\n", label, resp, err)
+ }
+
+ // delete identity
+ case *message.IdentityDeleteMsg:
+ id, err := zm.zdb.GetIdentityByName(m.Name(),
IDENT_DEFAULT_SERVICE)
+ if err != nil {
+ logger.Printf(logger.ERROR, "[zonemaster%s] Identity
lookup failed: %v\n", label, err)
+ return false
+ }
+ // delete in database
+ id.Name = ""
+ err = zm.zdb.SetIdentity(id)
+
+ // send response
+ rc := enums.RC_OK
+ msg := ""
+ if err != nil {
+ rc = enums.RC_NO
+ msg = err.Error()
+ }
+ resp := message.NewIdentityResultCodeMsg(rc, msg)
+ if err = back.Send(ctx, resp); err != nil {
+ logger.Printf(logger.ERROR, "[identity:%s] Can't send
response (%v): %v\n", label, resp, err)
+ }
+
+ // lookup identity
+ case *message.IdentityLookupMsg:
+ id, err := zm.zdb.GetIdentityByName(m.Name,
IDENT_DEFAULT_SERVICE)
+ if err != nil {
+ logger.Printf(logger.ERROR, "[zonemaster%s] Identity
lookup failed: %v\n", label, err)
+ return false
+ }
+ resp := message.NewIdentityUpdateMsg(id.Name, id.Key)
+ logger.Printf(logger.DBG, "[identity:%s] Sending %v", label,
resp)
+ if err = back.Send(ctx, resp); err != nil {
+ logger.Printf(logger.ERROR, "[identity:%s] Can't send
response (%v): %v\n", label, resp, err)
+ }
+
+ // get default identity for service
+ case *message.IdentityGetDefaultMsg:
+ id, err := zm.zdb.GetDefaultIdentity(m.Service())
+ if err != nil {
+ logger.Printf(logger.ERROR, "[zonemaster%s] Identity
lookup failed: %v\n", label, err)
+ return false
+ }
+ resp := message.NewIdentityUpdateMsg(id.Name, id.Key)
+ logger.Printf(logger.DBG, "[identity:%s] Sending %v", label,
resp)
+ if err = back.Send(ctx, resp); err != nil {
+ logger.Printf(logger.ERROR, "[identity:%s] Can't send
response (%v): %v\n", label, resp, err)
+ }
+
+ // set default identity for service
+ case *message.IdentitySetDefaultMsg:
+ err := zm.zdb.SetDefaultIdentity(m.ZoneKey, m.Service())
+
+ // send response
+ rc := enums.RC_OK
+ msg := ""
+ if err != nil {
+ rc = enums.RC_NO
+ msg = err.Error()
+ }
+ resp := message.NewIdentityResultCodeMsg(rc, msg)
+ if err = back.Send(ctx, resp); err != nil {
+ logger.Printf(logger.ERROR, "[identity:%s] Can't send
response (%v): %v\n", label, resp, err)
+ }
+
+ //------------------------------------------------------------------
+ // Namestore service
+ //------------------------------------------------------------------
+
// start new zone iteration
case *message.NamestoreZoneIterStartMsg:
- zi := new(ZoneIterator)
- zi.zk = m.ZoneKey
- s.ZoneIters.Put(m.ID, zi, 0)
+ iter := zm.namestore.NewIterator(m.ID, m.ZoneKey)
+ resp := iter.Next()
+ if err := back.Send(ctx, resp); err != nil {
+ logger.Printf(logger.ERROR, "[zonemaster%s] Can't send
response (%v)\n", label, resp)
+ return false
+ }
default:
//----------------------------------------------------------
@@ -128,7 +230,7 @@ func (s *Service) HandleMessage(ctx context.Context, sender
*util.PeerID, msg me
}
// storeDHT stores a GNS block in the DHT.
-func (s *Service) StoreDHT(ctx context.Context, query blocks.Query, block
blocks.Block) (err error) {
+func (zm *ZoneMaster) StoreDHT(ctx context.Context, query blocks.Query, block
blocks.Block) (err error) {
// assemble DHT request
req := message.NewDHTP2PPutMsg(block)
req.Flags = query.Flags()
@@ -140,7 +242,7 @@ func (s *Service) StoreDHT(ctx context.Context, query
blocks.Query, block blocks
}
// storeNamecache stores a GNS block in the local namecache.
-func (s *Service) StoreNamecache(ctx context.Context, query *blocks.GNSQuery,
block *blocks.GNSBlock) (err error) {
+func (zm *ZoneMaster) StoreNamecache(ctx context.Context, query
*blocks.GNSQuery, block *blocks.GNSBlock) (err error) {
// assemble Namecache request
req := message.NewNamecacheCacheMsg(block)
diff --git a/src/gnunet/service/zonemaster/service_identity.go
b/src/gnunet/service/zonemaster/service_identity.go
new file mode 100644
index 0000000..b7777be
--- /dev/null
+++ b/src/gnunet/service/zonemaster/service_identity.go
@@ -0,0 +1,135 @@
+// This file is part of gnunet-go, a GNUnet-implementation in Golang.
+// Copyright (C) 2019-2022 Bernd Fix >Y<
+//
+// gnunet-go is free software: you can redistribute it and/or modify it
+// under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// gnunet-go is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// SPDX-License-Identifier: AGPL3.0-or-later
+
+package zonemaster
+
+import (
+ "context"
+ "fmt"
+ "gnunet/crypto"
+ "gnunet/enums"
+ "gnunet/message"
+ "gnunet/service/store"
+ "gnunet/transport"
+ "gnunet/util"
+
+ "github.com/bfix/gospel/logger"
+)
+
+//nolint:stylecheck // my style is my style...
+const (
+ IDENT_DEFAULT_SERVICE = "ego"
+)
+
+//----------------------------------------------------------------------
+// "GNUnet Identity" service implementation:
+//----------------------------------------------------------------------
+
+type IdentitySession struct {
+ id int
+ updates bool
+ back transport.Responder
+}
+
+type Identity struct{}
+
+type IdentityService struct {
+ zm *ZoneMaster // reference to main service
+ clients *util.Map[int, *IdentitySession] // client sessions
+}
+
+func NewIdentityService(zm *ZoneMaster) *IdentityService {
+ srv := new(IdentityService)
+ srv.zm = zm
+ srv.clients = util.NewMap[int, *IdentitySession]()
+ return srv
+}
+
+func (ident *IdentityService) NewSession(id int, back transport.Responder) {
+ sess := &IdentitySession{
+ id: id,
+ updates: false,
+ back: back,
+ }
+ ident.clients.Put(id, sess, 0)
+}
+
+func (ident *IdentityService) CloseSession(id int) {
+ ident.clients.Delete(id, 0)
+}
+
+func (ident *IdentityService) FollowUpdates(id int) *IdentitySession {
+ if sess, ok := ident.clients.Get(id, 0); ok {
+ sess.updates = true
+ return sess
+ }
+ return nil
+}
+
+func (ident *IdentityService) Start(ctx context.Context, id int) (err error) {
+ // flag client as update receiver
+ sess := ident.FollowUpdates(id)
+ if sess == nil {
+ err = fmt.Errorf("no session available for client %d", id)
+ return
+ }
+ // initial update is to send all existing identites
+ var list []*store.Identity
+ if list, err = ident.zm.zdb.GetIdentities(""); err != nil {
+ return
+ }
+ for _, ident := range list {
+ resp := message.NewIdentityUpdateMsg(ident.Name, ident.Key)
+ logger.Printf(logger.DBG, "[identity:%d] Sending %v", id, resp)
+ if err = sess.back.Send(ctx, resp); err != nil {
+ logger.Printf(logger.ERROR, "[identity:%d] Can't send
response (%v): %v\n", id, resp, err)
+ return
+ }
+ }
+ // terminate with EOL
+ resp := message.NewIdentityUpdateMsg("", nil)
+ if err = sess.back.Send(ctx, resp); err != nil {
+ logger.Printf(logger.ERROR, "[identity:%d] Can't send response
(%v): %v\n", id, resp, err)
+ return
+ }
+ return
+}
+
+func (ident *IdentityService) Create(ctx context.Context, cid int, zk
*crypto.ZonePrivate, name string) (err error) {
+ // get client session
+ sess, ok := ident.clients.Get(cid, 0)
+ if !ok {
+ err = fmt.Errorf("no session available for client %d", cid)
+ return
+ }
+ // add identity
+ id := store.NewIdentity(name, zk, IDENT_DEFAULT_SERVICE)
+ err = ident.zm.zdb.SetIdentity(id)
+ rc := enums.RC_OK
+ msg := ""
+ if err != nil {
+ rc = enums.RC_NO
+ msg = err.Error()
+ }
+ resp := message.NewIdentityResultCodeMsg(rc, msg)
+ if err = sess.back.Send(ctx, resp); err != nil {
+ logger.Printf(logger.ERROR, "[identity:%d] Can't send response
(%v): %v\n", cid, resp, err)
+ return
+ }
+ return
+}
diff --git a/src/gnunet/service/zonemaster/service_namestore.go
b/src/gnunet/service/zonemaster/service_namestore.go
new file mode 100644
index 0000000..2c6d7d1
--- /dev/null
+++ b/src/gnunet/service/zonemaster/service_namestore.go
@@ -0,0 +1,90 @@
+// This file is part of gnunet-go, a GNUnet-implementation in Golang.
+// Copyright (C) 2019-2022 Bernd Fix >Y<
+//
+// gnunet-go is free software: you can redistribute it and/or modify it
+// under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// gnunet-go is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// SPDX-License-Identifier: AGPL3.0-or-later
+
+package zonemaster
+
+import (
+ "gnunet/crypto"
+ "gnunet/message"
+ "gnunet/service/store"
+ "gnunet/util"
+)
+
+//----------------------------------------------------------------------
+// "GNUnet Namestore" service implementation:
+//----------------------------------------------------------------------
+
+type ZoneIterator struct {
+ id uint32
+ zk *crypto.ZonePrivate
+ lastUsed util.AbsoluteTime
+ db *store.ZoneDB
+
+ labels []int64
+ pos int
+}
+
+func NewZoneIterator(id uint32, zk *crypto.ZonePrivate, db *store.ZoneDB) (zi
*ZoneIterator, err error) {
+ // get list of labels to handle
+ var labels []int64
+ if labels, err = db.GetLabelIDs(zk); err != nil {
+ return
+ }
+ // assemble zone iterator
+ zi = &ZoneIterator{
+ id: id,
+ zk: zk,
+ lastUsed: util.AbsoluteTimeNow(),
+ db: db,
+ pos: 0,
+ labels: labels,
+ }
+ return
+}
+
+func (zi *ZoneIterator) Next() *message.NamestoreRecordResultMsg {
+ if zi.pos == len(zi.labels)-1 {
+ // end of list reached
+ return nil
+ }
+
+ return nil
+}
+
+// NamestoreService to handle namestore requests
+type NamestoreService struct {
+ zm *ZoneMaster
+ iters *util.Map[uint32, *ZoneIterator]
+}
+
+func NewNamestoreService(zm *ZoneMaster) *NamestoreService {
+ return &NamestoreService{
+ zm: zm,
+ iters: util.NewMap[uint32, *ZoneIterator](),
+ }
+}
+
+func (s *NamestoreService) NewIterator(id uint32, zk *crypto.ZonePrivate)
*ZoneIterator {
+ zi := &ZoneIterator{
+ id: id,
+ zk: zk,
+ lastUsed: util.AbsoluteTimeNow(),
+ }
+ s.iters.Put(id, zi, 0)
+ return zi
+}
diff --git a/src/gnunet/service/zonemaster/zonemaster.go
b/src/gnunet/service/zonemaster/zonemaster.go
index 7c2a13c..4703d2c 100644
--- a/src/gnunet/service/zonemaster/zonemaster.go
+++ b/src/gnunet/service/zonemaster/zonemaster.go
@@ -21,6 +21,7 @@ package zonemaster
import (
"context"
"gnunet/config"
+ "gnunet/core"
"gnunet/enums"
"gnunet/service/dht/blocks"
"gnunet/service/store"
@@ -31,22 +32,36 @@ import (
)
//======================================================================
-// "GNS ZoneMaster" implementation:
-// Manage and publish local zone records
+// "GNS ZoneMaster" implementation (extended):
+// Manage local identities for subsystems. Manage and publish
+// local GNS zone records.
//======================================================================
-// ZoneMaster instance
+// ZoneMaster implements
type ZoneMaster struct {
- cfg *config.Config // Zonemaster configuration
- zdb *store.ZoneDB // ZoneDB connection
- srv *Service // NameStore service
+ Module
+
+ zdb *store.ZoneDB // ZoneDB connection
+ namestore *NamestoreService // namestore subservice
+ identity *IdentityService // identity subservice
}
-// NewZoneMaster initializes a new zone master instance.
-func NewZoneMaster(cfg *config.Config, srv *Service) *ZoneMaster {
- zm := new(ZoneMaster)
- zm.cfg = cfg
- return zm
+// NewService initializes a new zone master service.
+func NewService(ctx context.Context, c *core.Core) *ZoneMaster {
+ mod := NewModule(ctx, c)
+ srv := &ZoneMaster{
+ Module: *mod,
+ }
+
+ // set external function references (external services)
+ srv.StoreLocal = srv.StoreNamecache
+ srv.StoreRemote = srv.StoreDHT
+
+ // instantiate sub-services
+ srv.namestore = NewNamestoreService(srv)
+ srv.identity = NewIdentityService(srv)
+
+ return srv
}
// Run zone master: connect to zone database and start the RPC/HTTP
@@ -55,12 +70,8 @@ func NewZoneMaster(cfg *config.Config, srv *Service)
*ZoneMaster {
func (zm *ZoneMaster) Run(ctx context.Context) {
// connect to database
logger.Println(logger.INFO, "[zonemaster] Connecting to zone
database...")
- dbFile, ok := util.GetParam[string](zm.cfg.ZoneMaster.Storage, "file")
- if !ok {
- logger.Printf(logger.ERROR, "[zonemaster] missing database file
specification")
- return
- }
var err error
+ dbFile, _ := util.GetParam[string](config.Cfg.ZoneMaster.Storage,
"file")
if zm.zdb, err = store.OpenZoneDB(dbFile); err != nil {
logger.Printf(logger.ERROR, "[zonemaster] open database: %v",
err)
return
@@ -69,15 +80,15 @@ func (zm *ZoneMaster) Run(ctx context.Context) {
// start HTTP GUI
zm.startGUI(ctx)
- /*
- // publish on start-up
- if err = zm.Publish(ctx); err != nil {
- logger.Printf(logger.ERROR, "[zonemaster] initial
publish failed: %s", err.Error())
- return
- }
- */
+
+ // publish on start-up
+ if err = zm.Publish(ctx); err != nil {
+ logger.Printf(logger.ERROR, "[zonemaster] initial publish
failed: %s", err.Error())
+ return
+ }
+
// periodically publish GNS blocks to the DHT
- tick := time.NewTicker(time.Duration(zm.cfg.ZoneMaster.Period) *
time.Second)
+ tick := time.NewTicker(time.Duration(config.Cfg.ZoneMaster.Period) *
time.Second)
loop:
for {
select {
@@ -125,34 +136,44 @@ func (zm *ZoneMaster) PublishZoneLabel(ctx
context.Context, zone *store.Zone, la
zk := zone.Key.Public()
logger.Printf(logger.INFO, "[zonemaster] Publishing label '%s' of zone
%s", label.Name, zk.ID())
- // collect public records for zone label
- recs, err := zm.zdb.GetRecords("lid=%d and flags&%d = 0", label.ID,
enums.GNS_FLAG_PRIVATE)
+ // collect all records for label
+ rrSet, expire, err := zm.getRecords(zk, label.ID)
if err != nil {
return err
}
- // assemble record set and find earliest expiration
- expire := util.AbsoluteTimeNever()
- rrSet := blocks.NewRecordSet()
- for _, r := range recs {
- if r.Expire.Compare(expire) < 0 {
- expire = r.Expire
- }
- rrSet.AddRecord(&r.ResourceRecord)
- }
- rrSet.SetPadding()
if rrSet.Count == 0 {
logger.Println(logger.INFO, "[zonemaster] No resource records
-- skipped")
return nil
}
- // assemble GNS query
+ // assemble GNS query (common for DHT and Namecache)
query := blocks.NewGNSQuery(zk, label.Name)
- // assemble, encrypt and sign GNS block
- blk, _ := blocks.NewGNSBlock().(*blocks.GNSBlock)
+ //------------------------------------------------------------------
+ // Publish to DHT
+ //------------------------------------------------------------------
+
+ // filter out private resource records.
+ recsDHT := util.Clone(rrSet.Records)
+ num := uint32(len(recsDHT))
+ for i, rec := range recsDHT {
+ if rec.Flags&enums.GNS_FLAG_PRIVATE != 0 {
+ copy(recsDHT[i:], recsDHT[i+1:])
+ num--
+ recsDHT = recsDHT[:num]
+ }
+ }
+ rrsDHT := &blocks.RecordSet{
+ Count: num,
+ Records: recsDHT,
+ Padding: nil,
+ }
+ rrsDHT.SetPadding()
- blk.Body.Expire = expire
- blk.Body.Data, err = zk.Encrypt(rrSet.Bytes(), label.Name, expire)
+ // build block for DHT
+ blkDHT, _ := blocks.NewGNSBlock().(*blocks.GNSBlock)
+ blkDHT.Body.Expire = expire
+ blkDHT.Body.Data, err = zk.Encrypt(rrSet.Bytes(), label.Name, expire)
if err != nil {
return err
}
@@ -160,19 +181,39 @@ func (zm *ZoneMaster) PublishZoneLabel(ctx
context.Context, zone *store.Zone, la
if err != nil {
return err
}
- if err = blk.Sign(dzk); err != nil {
+ if err = blkDHT.Sign(dzk); err != nil {
+ return err
+ }
+ // publish GNS block to DHT
+ if err = zm.StoreDHT(ctx, query, blkDHT); err != nil {
return err
}
- // DEBUG:
- // logger.Printf(logger.DBG, "[zonemaster] Query key = %s",
hex.EncodeToString(query.Key().Data))
- // logger.Printf(logger.DBG, "[zonemaster] Block data = %s",
hex.EncodeToString(blk.Bytes()))
+ // DEBUG
+ /*
+ logger.Printf(logger.DBG, "[zonemaster] pub = %s",
util.EncodeBinaryToString(zk.Bytes()))
+ logger.Printf(logger.DBG, "[zonemaster] query = %s",
hex.EncodeToString(query.Key().Data))
+ logger.Printf(logger.DBG, "[zonemaster] blk = %s",
hex.EncodeToString(blkDHT.Bytes()))
+ */
+
+ //------------------------------------------------------------------
+ // Publish to Namecache
+ //------------------------------------------------------------------
- // publish GNS block to DHT and Namecache
- if err = zm.srv.StoreDHT(ctx, query, blk); err != nil {
+ // build block for Namecache
+ blkNC, _ := blocks.NewGNSBlock().(*blocks.GNSBlock)
+ blkNC.Body.Expire = expire
+ blkNC.Body.Data = rrSet.Bytes()
+ // sign block
+ if dzk, _, err = zone.Key.Derive(label.Name, "gns"); err != nil {
return err
}
- if err = zm.srv.StoreNamecache(ctx, query, blk); err != nil {
+ if err = blkNC.Sign(dzk); err != nil {
+ return err
+ }
+
+ // publish GNS block to namecache
+ if err = zm.StoreNamecache(ctx, query, blkNC); err != nil {
return err
}
return nil
diff --git a/src/gnunet/transport/reader_writer.go
b/src/gnunet/transport/reader_writer.go
index 2cee0a9..a1a7bbe 100644
--- a/src/gnunet/transport/reader_writer.go
+++ b/src/gnunet/transport/reader_writer.go
@@ -116,7 +116,10 @@ func ReadMessage(ctx context.Context, rdr io.ReadCloser,
buf []byte) (msg messag
err = fmt.Errorf("message{%d} is nil", mh.MsgType)
return
}
- err = data.Unmarshal(msg, buf[:mh.MsgSize])
+ if err = data.Unmarshal(msg, buf[:mh.MsgSize]); err != nil {
+ return
+ }
+ err = msg.Init()
/*
// DEBUG: incoming messages
if mh.MsgType == enums.MSG_DHT_P2P_RESULT {
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnunet-go] branch master updated: Identity service added to zone master.,
gnunet <=