]> Cypherpunks repositories - nncp.git/commitdiff
Ev7 kekscm
authorSergey Matveev <stargrave@stargrave.org>
Sun, 30 Nov 2025 08:33:32 +0000 (11:33 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sun, 30 Nov 2025 08:33:32 +0000 (11:33 +0300)
18 files changed:
src/cfg.go
src/cfgdir.go [deleted file]
src/cmd/nncp/ack.go
src/cmd/nncp/bundle.go
src/cmd/nncp/cfgdir.go [deleted file]
src/cmd/nncp/cfgmin.go
src/cmd/nncp/cfgnew.go
src/cmd/nncp/main.go
src/cmd/nncp/pkt.go
src/cmd/nncp/xfer.go
src/ctx.go
src/jobs.go
src/magic.go
src/nncp.go
src/node.go
src/pkt.go
src/toss.go
src/tx.go

index 365231deafbb2aadb565a14751da9e8f031458bf..a806e8ffa0ded3b28271b38af8a66459a7601f6d 100644 (file)
@@ -17,6 +17,7 @@ package nncp
 
 import (
        "bytes"
+       "encoding/hex"
        "encoding/json"
        "errors"
        "fmt"
@@ -28,7 +29,7 @@ import (
 
        "github.com/gorhill/cronexpr"
        "github.com/hjson/hjson-go/v4"
-       "golang.org/x/crypto/ed25519"
+       "golang.org/x/crypto/blake2b"
        "golang.org/x/term"
 )
 
@@ -37,6 +38,7 @@ const (
        CfgSpoolEnv = "NNCPSPOOL"
        CfgLogEnv   = "NNCPLOG"
        CfgNoSync   = "NNCPNOSYNC"
+       CfgKeysEnv  = "NNCPKEYS"
 )
 
 var (
@@ -44,12 +46,12 @@ var (
        DefaultSendmailPath string = "/usr/sbin/sendmail"
        DefaultSpoolPath    string = "/var/spool/nncp"
        DefaultLogPath      string = "/var/spool/nncp/log"
+       DefaultKeysPath     string = "/usr/local/etc/nncp.keys"
 )
 
 type NodeJSON struct {
        Id       string              `json:"id"`
-       ExchPub  string              `json:"exchpub"`
-       SignPub  string              `json:"signpub"`
+       KeyId    string              `json:"keyid"`
        NoisePub *string             `json:"noisepub,omitempty"`
        Incoming *string             `json:"incoming,omitempty"`
        Exec     map[string][]string `json:"exec,omitempty"`
@@ -104,10 +106,7 @@ type CallJSON struct {
 
 type NodeOurJSON struct {
        Id       string `json:"id"`
-       ExchPub  string `json:"exchpub"`
-       ExchPrv  string `json:"exchprv"`
-       SignPub  string `json:"signpub"`
-       SignPrv  string `json:"signprv"`
+       KeyId    string `json:"keyid"`
        NoisePub string `json:"noisepub"`
        NoisePrv string `json:"noiseprv"`
 }
@@ -163,20 +162,12 @@ func NewNode(name string, cfg NodeJSON) (*Node, error) {
                return nil, err
        }
 
-       exchPub, err := Base32Codec.DecodeString(cfg.ExchPub)
+       keyId, err := hex.DecodeString(cfg.KeyId)
        if err != nil {
                return nil, err
        }
-       if len(exchPub) != 32 {
-               return nil, errors.New("Invalid exchPub size")
-       }
-
-       signPub, err := Base32Codec.DecodeString(cfg.SignPub)
-       if err != nil {
-               return nil, err
-       }
-       if len(signPub) != ed25519.PublicKeySize {
-               return nil, errors.New("Invalid signPub size")
+       if len(keyId) != 32 {
+               return nil, errors.New("Invalid keyid size")
        }
 
        var noisePub []byte
@@ -346,8 +337,6 @@ func NewNode(name string, cfg NodeJSON) (*Node, error) {
        node := Node{
                Name:           name,
                Id:             nodeId,
-               ExchPub:        new([32]byte),
-               SignPub:        ed25519.PublicKey(signPub),
                Exec:           cfg.Exec,
                Incoming:       incoming,
                FreqPath:       freqPath,
@@ -363,7 +352,7 @@ func NewNode(name string, cfg NodeJSON) (*Node, error) {
                OnlineDeadline: defOnlineDeadline,
                MaxOnlineTime:  defMaxOnlineTime,
        }
-       copy(node.ExchPub[:], exchPub)
+       copy(node.KeyId[:], keyId)
        if len(noisePub) > 0 {
                node.NoisePub = new([32]byte)
                copy(node.NoisePub[:], noisePub)
@@ -377,36 +366,12 @@ func NewNodeOur(cfg *NodeOurJSON) (*NodeOur, error) {
                return nil, err
        }
 
-       exchPub, err := Base32Codec.DecodeString(cfg.ExchPub)
-       if err != nil {
-               return nil, err
-       }
-       if len(exchPub) != 32 {
-               return nil, errors.New("Invalid exchPub size")
-       }
-
-       exchPrv, err := Base32Codec.DecodeString(cfg.ExchPrv)
-       if err != nil {
-               return nil, err
-       }
-       if len(exchPrv) != 32 {
-               return nil, errors.New("Invalid exchPrv size")
-       }
-
-       signPub, err := Base32Codec.DecodeString(cfg.SignPub)
-       if err != nil {
-               return nil, err
-       }
-       if len(signPub) != ed25519.PublicKeySize {
-               return nil, errors.New("Invalid signPub size")
-       }
-
-       signPrv, err := Base32Codec.DecodeString(cfg.SignPrv)
+       keyId, err := hex.DecodeString(cfg.KeyId)
        if err != nil {
                return nil, err
        }
-       if len(signPrv) != ed25519.PrivateKeySize {
-               return nil, errors.New("Invalid signPrv size")
+       if len(keyId) != 32 {
+               return nil, errors.New("Invalid keyid size")
        }
 
        noisePub, err := Base32Codec.DecodeString(cfg.NoisePub)
@@ -427,15 +392,11 @@ func NewNodeOur(cfg *NodeOurJSON) (*NodeOur, error) {
 
        node := NodeOur{
                Id:       id,
-               ExchPub:  new([32]byte),
-               ExchPrv:  new([32]byte),
-               SignPub:  ed25519.PublicKey(signPub),
-               SignPrv:  ed25519.PrivateKey(signPrv),
+               KeyId:    new([blake2b.Size256]byte),
                NoisePub: new([32]byte),
                NoisePrv: new([32]byte),
        }
-       copy(node.ExchPub[:], exchPub)
-       copy(node.ExchPrv[:], exchPrv)
+       copy(node.KeyId[:], keyId)
        copy(node.NoisePub[:], noisePub)
        copy(node.NoisePrv[:], noisePrv)
        return &node, nil
diff --git a/src/cfgdir.go b/src/cfgdir.go
deleted file mode 100644 (file)
index 3a9f03e..0000000
+++ /dev/null
@@ -1,989 +0,0 @@
-// NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-// Copyright (C) 2016-2025 Sergey Matveev <stargrave@stargrave.org>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 3 of the License.
-//
-// This program 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 General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-package nncp
-
-import (
-       "errors"
-       "fmt"
-       "io/fs"
-       "os"
-       "path/filepath"
-       "sort"
-       "strconv"
-       "strings"
-)
-
-func cfgDirMkdir(dst ...string) error {
-       return os.MkdirAll(filepath.Join(dst...), os.FileMode(0777))
-}
-
-func cfgDirSave(v interface{}, dst ...string) error {
-       var r string
-       switch v := v.(type) {
-       case *string:
-               if v == nil {
-                       return nil
-               }
-               r = *v
-       case string:
-               r = v
-       case *int:
-               if v == nil {
-                       return nil
-               }
-               r = strconv.Itoa(*v)
-       case *uint:
-               if v == nil {
-                       return nil
-               }
-               r = strconv.Itoa(int(*v))
-       case *uint64:
-               if v == nil {
-                       return nil
-               }
-               r = strconv.FormatUint(*v, 10)
-       case int:
-               r = strconv.Itoa(v)
-       default:
-               panic("unsupported value type")
-       }
-       mode := os.FileMode(0666)
-       if strings.HasSuffix(dst[len(dst)-1], "prv") {
-               mode = os.FileMode(0600)
-       }
-       return os.WriteFile(filepath.Join(dst...), []byte(r+"\n"), mode)
-}
-
-func cfgDirTouch(dst ...string) error {
-       if fd, err := os.Create(filepath.Join(dst...)); err == nil {
-               fd.Close()
-       } else {
-               return err
-       }
-       return nil
-}
-
-func CfgToDir(dst string, cfg *CfgJSON) (err error) {
-       if err = cfgDirMkdir(dst); err != nil {
-               return
-       }
-       if err = cfgDirSave(cfg.Spool, dst, "spool"); err != nil {
-               return
-       }
-       if err = cfgDirSave(cfg.Log, dst, "log"); err != nil {
-               return
-       }
-       if err = cfgDirSave(cfg.Umask, dst, "umask"); err != nil {
-               return
-       }
-       if cfg.OmitPrgrs {
-               if err = cfgDirTouch(dst, "noprogress"); err != nil {
-                       return
-               }
-       }
-       if cfg.NoHdr {
-               if err = cfgDirTouch(dst, "nohdr"); err != nil {
-                       return
-               }
-       }
-
-       if len(cfg.MCDRxIfis) > 0 {
-               if err = cfgDirSave(
-                       strings.Join(cfg.MCDRxIfis, "\n"),
-                       dst, "mcd-listen",
-               ); err != nil {
-                       return
-               }
-       }
-       if len(cfg.MCDTxIfis) > 0 {
-               if err = cfgDirMkdir(dst, "mcd-send"); err != nil {
-                       return
-               }
-               for ifi, t := range cfg.MCDTxIfis {
-                       if err = cfgDirSave(t, dst, "mcd-send", ifi); err != nil {
-                               return
-                       }
-               }
-       }
-
-       if cfg.Notify != nil {
-               if cfg.Notify.File != nil {
-                       if err = cfgDirMkdir(dst, "notify", "file"); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(
-                               cfg.Notify.File.From,
-                               dst, "notify", "file", "from",
-                       ); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(
-                               cfg.Notify.File.To,
-                               dst, "notify", "file", "to",
-                       ); err != nil {
-                               return
-                       }
-               }
-               if cfg.Notify.Freq != nil {
-                       if err = cfgDirMkdir(dst, "notify", "freq"); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(
-                               cfg.Notify.Freq.From,
-                               dst, "notify", "freq", "from",
-                       ); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(
-                               cfg.Notify.Freq.To,
-                               dst, "notify", "freq", "to",
-                       ); err != nil {
-                               return
-                       }
-               }
-               for k, v := range cfg.Notify.Exec {
-                       if err = cfgDirMkdir(dst, "notify", "exec", k); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(v.From, dst, "notify", "exec", k, "from"); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(v.To, dst, "notify", "exec", k, "to"); err != nil {
-                               return
-                       }
-               }
-       }
-
-       if cfg.Self != nil {
-               if err = cfgDirMkdir(dst, "self"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(cfg.Self.Id, dst, "self", "id"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(cfg.Self.ExchPub, dst, "self", "exchpub"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(cfg.Self.ExchPrv, dst, "self", "exchprv"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(cfg.Self.SignPub, dst, "self", "signpub"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(cfg.Self.SignPrv, dst, "self", "signprv"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(cfg.Self.NoisePub, dst, "self", "noisepub"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(cfg.Self.NoisePrv, dst, "self", "noiseprv"); err != nil {
-                       return
-               }
-       }
-
-       for name, n := range cfg.Neigh {
-               if err = cfgDirMkdir(dst, "neigh", name); err != nil {
-                       return
-               }
-               if err = cfgDirSave(n.Id, dst, "neigh", name, "id"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(n.ExchPub, dst, "neigh", name, "exchpub"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(n.SignPub, dst, "neigh", name, "signpub"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(n.NoisePub, dst, "neigh", name, "noisepub"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(n.Incoming, dst, "neigh", name, "incoming"); err != nil {
-                       return
-               }
-
-               if len(n.Exec) > 0 {
-                       if err = cfgDirMkdir(dst, "neigh", name, "exec"); err != nil {
-                               return
-                       }
-                       for k, v := range n.Exec {
-                               if err = cfgDirSave(
-                                       strings.Join(v, "\n"),
-                                       dst, "neigh", name, "exec", k,
-                               ); err != nil {
-                                       return
-                               }
-                       }
-               }
-
-               if n.Freq != nil {
-                       if err = cfgDirMkdir(dst, "neigh", name, "freq"); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(
-                               n.Freq.Path,
-                               dst, "neigh", name, "freq", "path",
-                       ); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(
-                               n.Freq.Chunked,
-                               dst, "neigh", name, "freq", "chunked",
-                       ); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(
-                               n.Freq.MinSize,
-                               dst, "neigh", name, "freq", "minsize",
-                       ); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(
-                               n.Freq.MaxSize,
-                               dst, "neigh", name, "freq", "maxsize",
-                       ); err != nil {
-                               return
-                       }
-               }
-
-               if n.ACK != nil {
-                       if err = cfgDirMkdir(dst, "neigh", name, "ack"); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(
-                               n.ACK.MinSize,
-                               dst, "neigh", name, "ack", "minsize",
-                       ); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(
-                               n.ACK.Nice,
-                               dst, "neigh", name, "ack", "nice",
-                       ); err != nil {
-                               return
-                       }
-               }
-
-               if len(n.Via) > 0 {
-                       if err = cfgDirSave(
-                               strings.Join(n.Via, "\n"),
-                               dst, "neigh", name, "via",
-                       ); err != nil {
-                               return
-                       }
-               }
-
-               if len(n.Addrs) > 0 {
-                       if err = cfgDirMkdir(dst, "neigh", name, "addrs"); err != nil {
-                               return
-                       }
-                       for k, v := range n.Addrs {
-                               if err = cfgDirSave(v, dst, "neigh", name, "addrs", k); err != nil {
-                                       return
-                               }
-                       }
-               }
-
-               if err = cfgDirSave(n.RxRate, dst, "neigh", name, "rxrate"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(n.TxRate, dst, "neigh", name, "txrate"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(n.OnlineDeadline, dst, "neigh", name, "onlinedeadline"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(n.MaxOnlineTime, dst, "neigh", name, "maxonlinetime"); err != nil {
-                       return
-               }
-
-               for i, call := range n.Calls {
-                       is := strconv.Itoa(i)
-                       if err = cfgDirMkdir(dst, "neigh", name, "calls", is); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(call.Cron, dst, "neigh", name, "calls", is, "cron"); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(call.Nice, dst, "neigh", name, "calls", is, "nice"); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(call.Xx, dst, "neigh", name, "calls", is, "xx"); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(call.RxRate, dst, "neigh", name, "calls", is, "rxrate"); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(call.TxRate, dst, "neigh", name, "calls", is, "txrate"); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(call.Addr, dst, "neigh", name, "calls", is, "addr"); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(call.OnlineDeadline, dst, "neigh", name, "calls", is, "onlinedeadline"); err != nil {
-                               return
-                       }
-                       if err = cfgDirSave(call.MaxOnlineTime, dst, "neigh", name, "calls", is, "maxonlinetime"); err != nil {
-                               return
-                       }
-                       if call.WhenTxExists {
-                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "when-tx-exists"); err != nil {
-                                       return
-                               }
-                       }
-                       if call.NoCK {
-                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "nock"); err != nil {
-                                       return
-                               }
-                       }
-                       if call.MCDIgnore {
-                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "mcd-ignore"); err != nil {
-                                       return
-                               }
-                       }
-                       if call.AutoToss {
-                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "autotoss"); err != nil {
-                                       return
-                               }
-                       }
-                       if call.AutoTossDoSeen {
-                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "autotoss-doseen"); err != nil {
-                                       return
-                               }
-                       }
-                       if call.AutoTossNoFile {
-                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "autotoss-nofile"); err != nil {
-                                       return
-                               }
-                       }
-                       if call.AutoTossNoFreq {
-                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "autotoss-nofreq"); err != nil {
-                                       return
-                               }
-                       }
-                       if call.AutoTossNoExec {
-                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "autotoss-noexec"); err != nil {
-                                       return
-                               }
-                       }
-                       if call.AutoTossNoTrns {
-                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "autotoss-notrns"); err != nil {
-                                       return
-                               }
-                       }
-                       if call.AutoTossNoArea {
-                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "autotoss-noarea"); err != nil {
-                                       return
-                               }
-                       }
-                       if call.AutoTossNoACK {
-                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "autotoss-noack"); err != nil {
-                                       return
-                               }
-                       }
-                       if call.AutoTossGenACK {
-                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "autotoss-gen-ack"); err != nil {
-                                       return
-                               }
-                       }
-               }
-       }
-
-       for name, a := range cfg.Areas {
-               if err = cfgDirMkdir(dst, "areas", name); err != nil {
-                       return
-               }
-               if err = cfgDirSave(a.Id, dst, "areas", name, "id"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(a.Pub, dst, "areas", name, "pub"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(a.Prv, dst, "areas", name, "prv"); err != nil {
-                       return
-               }
-               if err = cfgDirSave(a.Incoming, dst, "areas", name, "incoming"); err != nil {
-                       return
-               }
-               if a.AllowUnknown {
-                       if err = cfgDirTouch(dst, "areas", name, "allow-unknown"); err != nil {
-                               return
-                       }
-               }
-               if len(a.Exec) > 0 {
-                       if err = cfgDirMkdir(dst, "areas", name, "exec"); err != nil {
-                               return
-                       }
-                       for k, v := range a.Exec {
-                               if err = cfgDirSave(
-                                       strings.Join(v, "\n"),
-                                       dst, "areas", name, "exec", k,
-                               ); err != nil {
-                                       return
-                               }
-                       }
-               }
-               if len(a.Subs) > 0 {
-                       if err = cfgDirSave(
-                               strings.Join(a.Subs, "\n"),
-                               dst, "areas", name, "subs",
-                       ); err != nil {
-                               return
-                       }
-               }
-       }
-
-       if len(cfg.YggdrasilAliases) > 0 {
-               if err = cfgDirMkdir(dst, "yggdrasil-aliases"); err != nil {
-                       return
-               }
-               for alias, v := range cfg.YggdrasilAliases {
-                       if err = cfgDirSave(v, dst, "yggdrasil-aliases", alias); err != nil {
-                               return
-                       }
-               }
-       }
-
-       return
-}
-
-func cfgDirLoad(src ...string) (v string, exists bool, err error) {
-       b, err := os.ReadFile(filepath.Join(src...))
-       if err != nil {
-               if errors.Is(err, fs.ErrNotExist) {
-                       return "", false, nil
-               }
-               return "", false, err
-       }
-       return strings.TrimSuffix(string(b), "\n"), true, nil
-}
-
-func cfgDirLoadMust(src ...string) (v string, err error) {
-       s, exists, err := cfgDirLoad(src...)
-       if err != nil {
-               return "", err
-       }
-       if !exists {
-               return "", fmt.Errorf("required \"%s\" does not exist", src[len(src)-1])
-       }
-       return s, nil
-}
-
-func cfgDirLoadOpt(src ...string) (v *string, err error) {
-       s, exists, err := cfgDirLoad(src...)
-       if err != nil {
-               return nil, err
-       }
-       if !exists {
-               return nil, nil
-       }
-       return &s, nil
-}
-
-func cfgDirLoadIntOpt(src ...string) (i64 *int64, err error) {
-       s, err := cfgDirLoadOpt(src...)
-       if err != nil {
-               return nil, err
-       }
-       if s == nil {
-               return nil, nil
-       }
-       i, err := strconv.ParseInt(*s, 10, 64)
-       if err != nil {
-               return nil, err
-       }
-       return &i, nil
-}
-
-func cfgDirExists(src ...string) bool {
-       if _, err := os.Stat(filepath.Join(src...)); err == nil {
-               return true
-       }
-       return false
-}
-
-func cfgDirReadFromTo(src ...string) (*FromToJSON, error) {
-       fromTo := FromToJSON{}
-
-       var err error
-       fromTo.From, err = cfgDirLoadMust(append(src, "from")...)
-       if err != nil {
-               return nil, err
-       }
-
-       fromTo.To, err = cfgDirLoadMust(append(src, "to")...)
-       if err != nil {
-               return nil, err
-       }
-
-       return &fromTo, nil
-}
-
-func DirToCfg(src string) (*CfgJSON, error) {
-       cfg := CfgJSON{}
-       var err error
-
-       cfg.Spool, err = cfgDirLoadMust(src, "spool")
-       if err != nil {
-               return nil, err
-       }
-       cfg.Log, err = cfgDirLoadMust(src, "log")
-       if err != nil {
-               return nil, err
-       }
-
-       if cfg.Umask, err = cfgDirLoadOpt(src, "umask"); err != nil {
-               return nil, err
-       }
-       cfg.OmitPrgrs = cfgDirExists(src, "noprogress")
-       cfg.NoHdr = cfgDirExists(src, "nohdr")
-
-       sp, err := cfgDirLoadOpt(src, "mcd-listen")
-       if err != nil {
-               return nil, err
-       }
-       if sp != nil {
-               cfg.MCDRxIfis = strings.Split(*sp, "\n")
-       }
-
-       fis, err := os.ReadDir(filepath.Join(src, "mcd-send"))
-       if err != nil && !errors.Is(err, fs.ErrNotExist) {
-               return nil, err
-       }
-       if len(fis) > 0 {
-               cfg.MCDTxIfis = make(map[string]int, len(fis))
-       }
-       for _, fi := range fis {
-               n := fi.Name()
-               if n[0] == '.' {
-                       continue
-               }
-               b, err := os.ReadFile(filepath.Join(src, "mcd-send", fi.Name()))
-               if err != nil {
-                       return nil, err
-               }
-               i, err := strconv.Atoi(strings.TrimSuffix(string(b), "\n"))
-               if err != nil {
-                       return nil, err
-               }
-               cfg.MCDTxIfis[n] = i
-       }
-
-       notify := NotifyJSON{Exec: make(map[string]*FromToJSON)}
-       if cfgDirExists(src, "notify", "file") {
-               if notify.File, err = cfgDirReadFromTo(src, "notify", "file"); err != nil {
-                       return nil, err
-               }
-       }
-       if cfgDirExists(src, "notify", "freq") {
-               if notify.Freq, err = cfgDirReadFromTo(src, "notify", "freq"); err != nil {
-                       return nil, err
-               }
-       }
-       fis, err = os.ReadDir(filepath.Join(src, "notify", "exec"))
-       if err != nil && !errors.Is(err, fs.ErrNotExist) {
-               return nil, err
-       }
-       for _, fi := range fis {
-               n := fi.Name()
-               if n[0] == '.' || !fi.IsDir() {
-                       continue
-               }
-               if notify.Exec[fi.Name()], err = cfgDirReadFromTo(src, "notify", "exec", n); err != nil {
-                       return nil, err
-               }
-       }
-       if notify.File != nil || notify.Freq != nil || len(notify.Exec) > 0 {
-               cfg.Notify = &notify
-       }
-
-       if _, err = os.ReadDir(filepath.Join(src, "self")); err == nil {
-               self := NodeOurJSON{}
-               if self.Id, err = cfgDirLoadMust(src, "self", "id"); err != nil {
-                       return nil, err
-               }
-               if self.ExchPub, err = cfgDirLoadMust(src, "self", "exchpub"); err != nil {
-                       return nil, err
-               }
-               if self.ExchPrv, err = cfgDirLoadMust(src, "self", "exchprv"); err != nil {
-                       return nil, err
-               }
-               if self.SignPub, err = cfgDirLoadMust(src, "self", "signpub"); err != nil {
-                       return nil, err
-               }
-               if self.SignPrv, err = cfgDirLoadMust(src, "self", "signprv"); err != nil {
-                       return nil, err
-               }
-               if self.NoisePub, err = cfgDirLoadMust(src, "self", "noisepub"); err != nil {
-                       return nil, err
-               }
-               if self.NoisePrv, err = cfgDirLoadMust(src, "self", "noiseprv"); err != nil {
-                       return nil, err
-               }
-               cfg.Self = &self
-       } else if !errors.Is(err, fs.ErrNotExist) {
-               return nil, err
-       }
-
-       cfg.Neigh = make(map[string]NodeJSON)
-       fis, err = os.ReadDir(filepath.Join(src, "neigh"))
-       if err != nil && !errors.Is(err, fs.ErrNotExist) {
-               return nil, err
-       }
-       for _, fi := range fis {
-               n := fi.Name()
-               if n[0] == '.' {
-                       continue
-               }
-               node := NodeJSON{}
-               if node.Id, err = cfgDirLoadMust(src, "neigh", n, "id"); err != nil {
-                       return nil, err
-               }
-               if node.ExchPub, err = cfgDirLoadMust(src, "neigh", n, "exchpub"); err != nil {
-                       return nil, err
-               }
-               if node.SignPub, err = cfgDirLoadMust(src, "neigh", n, "signpub"); err != nil {
-                       return nil, err
-               }
-               if node.NoisePub, err = cfgDirLoadOpt(src, "neigh", n, "noisepub"); err != nil {
-                       return nil, err
-               }
-               if node.Incoming, err = cfgDirLoadOpt(src, "neigh", n, "incoming"); err != nil {
-                       return nil, err
-               }
-
-               node.Exec = make(map[string][]string)
-               fis2, err := os.ReadDir(filepath.Join(src, "neigh", n, "exec"))
-               if err != nil && !errors.Is(err, fs.ErrNotExist) {
-                       return nil, err
-               }
-               for _, fi2 := range fis2 {
-                       n2 := fi2.Name()
-                       if n2[0] == '.' {
-                               continue
-                       }
-                       s, err := cfgDirLoadMust(src, "neigh", n, "exec", n2)
-                       if err != nil {
-                               return nil, err
-                       }
-                       node.Exec[n2] = strings.Split(s, "\n")
-               }
-
-               if cfgDirExists(src, "neigh", n, "freq") {
-                       node.Freq = &NodeFreqJSON{}
-                       if node.Freq.Path, err = cfgDirLoadOpt(src, "neigh", n, "freq", "path"); err != nil {
-                               return nil, err
-                       }
-
-                       i64, err := cfgDirLoadIntOpt(src, "neigh", n, "freq", "chunked")
-                       if err != nil {
-                               return nil, err
-                       }
-                       if i64 != nil {
-                               i := uint64(*i64)
-                               node.Freq.Chunked = &i
-                       }
-
-                       i64, err = cfgDirLoadIntOpt(src, "neigh", n, "freq", "minsize")
-                       if err != nil {
-                               return nil, err
-                       }
-                       if i64 != nil {
-                               i := uint64(*i64)
-                               node.Freq.MinSize = &i
-                       }
-
-                       i64, err = cfgDirLoadIntOpt(src, "neigh", n, "freq", "maxsize")
-                       if err != nil {
-                               return nil, err
-                       }
-                       if i64 != nil {
-                               i := uint64(*i64)
-                               node.Freq.MaxSize = &i
-                       }
-               }
-
-               if cfgDirExists(src, "neigh", n, "ack") {
-                       node.ACK = &NodeACKJSON{}
-                       i64, err := cfgDirLoadIntOpt(src, "neigh", n, "ack", "minsize")
-                       if err != nil {
-                               return nil, err
-                       }
-                       if i64 != nil {
-                               i := uint64(*i64)
-                               node.ACK.MinSize = &i
-                       }
-                       if node.ACK.Nice, err = cfgDirLoadOpt(
-                               src, "neigh", n, "ack", "nice",
-                       ); err != nil {
-                               return nil, err
-                       }
-               }
-
-               via, err := cfgDirLoadOpt(src, "neigh", n, "via")
-               if err != nil {
-                       return nil, err
-               }
-               if via != nil {
-                       node.Via = strings.Split(*via, "\n")
-               }
-
-               node.Addrs = make(map[string]string)
-               fis2, err = os.ReadDir(filepath.Join(src, "neigh", n, "addrs"))
-               if err != nil && !errors.Is(err, fs.ErrNotExist) {
-                       return nil, err
-               }
-               for _, fi2 := range fis2 {
-                       n2 := fi2.Name()
-                       if n2[0] == '.' {
-                               continue
-                       }
-                       if node.Addrs[n2], err = cfgDirLoadMust(src, "neigh", n, "addrs", n2); err != nil {
-                               return nil, err
-                       }
-               }
-
-               i64, err := cfgDirLoadIntOpt(src, "neigh", n, "rxrate")
-               if err != nil {
-                       return nil, err
-               }
-               if i64 != nil {
-                       i := int(*i64)
-                       node.RxRate = &i
-               }
-
-               i64, err = cfgDirLoadIntOpt(src, "neigh", n, "txrate")
-               if err != nil {
-                       return nil, err
-               }
-               if i64 != nil {
-                       i := int(*i64)
-                       node.TxRate = &i
-               }
-
-               i64, err = cfgDirLoadIntOpt(src, "neigh", n, "onlinedeadline")
-               if err != nil {
-                       return nil, err
-               }
-               if i64 != nil {
-                       i := uint(*i64)
-                       node.OnlineDeadline = &i
-               }
-
-               i64, err = cfgDirLoadIntOpt(src, "neigh", n, "maxonlinetime")
-               if err != nil {
-                       return nil, err
-               }
-               if i64 != nil {
-                       i := uint(*i64)
-                       node.MaxOnlineTime = &i
-               }
-
-               fis2, err = os.ReadDir(filepath.Join(src, "neigh", n, "calls"))
-               if err != nil && !errors.Is(err, fs.ErrNotExist) {
-                       return nil, err
-               }
-               callsIdx := make([]int, 0, len(fis2))
-               for _, fi2 := range fis2 {
-                       n2 := fi2.Name()
-                       if !fi2.IsDir() {
-                               continue
-                       }
-                       i, err := strconv.Atoi(n2)
-                       if err != nil {
-                               continue
-                       }
-                       callsIdx = append(callsIdx, i)
-               }
-               sort.Ints(callsIdx)
-               for _, i := range callsIdx {
-                       call := CallJSON{}
-                       is := strconv.Itoa(i)
-                       if call.Cron, err = cfgDirLoadMust(
-                               src, "neigh", n, "calls", is, "cron",
-                       ); err != nil {
-                               return nil, err
-                       }
-                       if call.Nice, err = cfgDirLoadOpt(
-                               src, "neigh", n, "calls", is, "nice",
-                       ); err != nil {
-                               return nil, err
-                       }
-                       if call.Xx, err = cfgDirLoadOpt(
-                               src, "neigh", n, "calls", is, "xx",
-                       ); err != nil {
-                               return nil, err
-                       }
-
-                       i64, err = cfgDirLoadIntOpt(src, "neigh", n, "calls", is, "rxrate")
-                       if err != nil {
-                               return nil, err
-                       }
-                       if i64 != nil {
-                               i := int(*i64)
-                               call.RxRate = &i
-                       }
-
-                       i64, err = cfgDirLoadIntOpt(src, "neigh", n, "calls", is, "txrate")
-                       if err != nil {
-                               return nil, err
-                       }
-                       if i64 != nil {
-                               i := int(*i64)
-                               call.TxRate = &i
-                       }
-
-                       if call.Addr, err = cfgDirLoadOpt(
-                               src, "neigh", n, "calls", is, "addr",
-                       ); err != nil {
-                               return nil, err
-                       }
-
-                       i64, err = cfgDirLoadIntOpt(src, "neigh", n, "calls", is, "onlinedeadline")
-                       if err != nil {
-                               return nil, err
-                       }
-                       if i64 != nil {
-                               i := uint(*i64)
-                               call.OnlineDeadline = &i
-                       }
-
-                       i64, err = cfgDirLoadIntOpt(src, "neigh", n, "calls", is, "maxonlinetime")
-                       if err != nil {
-                               return nil, err
-                       }
-                       if i64 != nil {
-                               i := uint(*i64)
-                               call.MaxOnlineTime = &i
-                       }
-
-                       if cfgDirExists(src, "neigh", n, "calls", is, "when-tx-exists") {
-                               call.WhenTxExists = true
-                       }
-                       if cfgDirExists(src, "neigh", n, "calls", is, "nock") {
-                               call.NoCK = true
-                       }
-                       if cfgDirExists(src, "neigh", n, "calls", is, "mcd-ignore") {
-                               call.MCDIgnore = true
-                       }
-                       if cfgDirExists(src, "neigh", n, "calls", is, "autotoss") {
-                               call.AutoToss = true
-                       }
-                       if cfgDirExists(src, "neigh", n, "calls", is, "autotoss-doseen") {
-                               call.AutoTossDoSeen = true
-                       }
-                       if cfgDirExists(src, "neigh", n, "calls", is, "autotoss-nofile") {
-                               call.AutoTossNoFile = true
-                       }
-                       if cfgDirExists(src, "neigh", n, "calls", is, "autotoss-nofreq") {
-                               call.AutoTossNoFreq = true
-                       }
-                       if cfgDirExists(src, "neigh", n, "calls", is, "autotoss-noexec") {
-                               call.AutoTossNoExec = true
-                       }
-                       if cfgDirExists(src, "neigh", n, "calls", is, "autotoss-notrns") {
-                               call.AutoTossNoTrns = true
-                       }
-                       if cfgDirExists(src, "neigh", n, "calls", is, "autotoss-noarea") {
-                               call.AutoTossNoArea = true
-                       }
-                       if cfgDirExists(src, "neigh", n, "calls", is, "autotoss-noack") {
-                               call.AutoTossNoACK = true
-                       }
-                       if cfgDirExists(src, "neigh", n, "calls", is, "autotoss-gen-ack") {
-                               call.AutoTossGenACK = true
-                       }
-                       node.Calls = append(node.Calls, call)
-               }
-               cfg.Neigh[n] = node
-       }
-
-       cfg.Areas = make(map[string]AreaJSON)
-       fis, err = os.ReadDir(filepath.Join(src, "areas"))
-       if err != nil && !errors.Is(err, fs.ErrNotExist) {
-               return nil, err
-       }
-       for _, fi := range fis {
-               n := fi.Name()
-               if n[0] == '.' {
-                       continue
-               }
-               area := AreaJSON{}
-               if area.Id, err = cfgDirLoadMust(src, "areas", n, "id"); err != nil {
-                       return nil, err
-               }
-               if area.Pub, err = cfgDirLoadOpt(src, "areas", n, "pub"); err != nil {
-                       return nil, err
-               }
-               if area.Prv, err = cfgDirLoadOpt(src, "areas", n, "prv"); err != nil {
-                       return nil, err
-               }
-
-               subs, err := cfgDirLoadOpt(src, "areas", n, "subs")
-               if err != nil {
-                       return nil, err
-               }
-               if subs != nil {
-                       area.Subs = strings.Split(*subs, "\n")
-               }
-
-               area.Exec = make(map[string][]string)
-               fis2, err := os.ReadDir(filepath.Join(src, "areas", n, "exec"))
-               if err != nil && !errors.Is(err, fs.ErrNotExist) {
-                       return nil, err
-               }
-               for _, fi2 := range fis2 {
-                       n2 := fi2.Name()
-                       if n2[0] == '.' {
-                               continue
-                       }
-                       s, err := cfgDirLoadMust(src, "areas", n, "exec", n2)
-                       if err != nil {
-                               return nil, err
-                       }
-                       area.Exec[n2] = strings.Split(s, "\n")
-               }
-
-               if area.Incoming, err = cfgDirLoadOpt(src, "areas", n, "incoming"); err != nil {
-                       return nil, err
-               }
-
-               if cfgDirExists(src, "areas", n, "allow-unknown") {
-                       area.AllowUnknown = true
-               }
-               cfg.Areas[n] = area
-       }
-
-       fis, err = os.ReadDir(filepath.Join(src, "yggdrasil-aliases"))
-       if err != nil && !errors.Is(err, fs.ErrNotExist) {
-               return nil, err
-       }
-       if len(fis) > 0 {
-               cfg.YggdrasilAliases = make(map[string]string, len(fis))
-       }
-       for _, fi := range fis {
-               n := fi.Name()
-               if n[0] == '.' {
-                       continue
-               }
-               b, err := os.ReadFile(filepath.Join(src, "yggdrasil-aliases", fi.Name()))
-               if err != nil {
-                       return nil, err
-               }
-               cfg.YggdrasilAliases[n] = strings.TrimSuffix(string(b), "\n")
-       }
-
-       return &cfg, nil
-}
index f97fbaad178e9cf009de52c794921c93bd29723a..af5a58edc2489e16bc7d8e9bebc6b6ae455184f5 100644 (file)
@@ -221,7 +221,7 @@ func mainACK() {
                                ctx.Self,
                                ctx.Neigh,
                                bufio.NewReaderSize(fd, nncp.MTHBlockSize),
-                               pipeW, true, nil,
+                               pipeW,
                        )
                        var pkt nncp.Pkt
                        _, err = xdr.Unmarshal(pipeR, &pkt)
index 841a8311eed917e22746d91bf035a311844ce682..2005cac29e8b6714181dc2af43ad99a3b954158f 100644 (file)
@@ -311,6 +311,8 @@ func mainBundle() {
                        case nncp.MagicNNCPEv5.B:
                                err = nncp.MagicNNCPEv5.TooOld()
                        case nncp.MagicNNCPEv6.B:
+                               err = nncp.MagicNNCPEv6.TooOld()
+                       case nncp.MagicNNCPEv7.B:
                        default:
                                err = errors.New("Bad packet magic number")
                        }
diff --git a/src/cmd/nncp/cfgdir.go b/src/cmd/nncp/cfgdir.go
deleted file mode 100644 (file)
index 8e40d2f..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-// NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-// Copyright (C) 2016-2025 Sergey Matveev <stargrave@stargrave.org>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 3 of the License.
-//
-// This program 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 General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-// Convert NNCP Hjson configuration file to the directory layout.
-package main
-
-import (
-       "flag"
-       "fmt"
-       "log"
-       "os"
-
-       "github.com/hjson/hjson-go/v4"
-       "go.cypherpunks.su/nncp/v8"
-)
-
-func usageCfgDir() {
-       fmt.Fprint(os.Stderr, "nncp-cfgdir -- Convert configuration file to the directory layout.\n\n")
-       fmt.Fprintf(os.Stderr, "Usage: %s [options] [-cfg ...] -dump /path/to/dir\n", os.Args[0])
-       fmt.Fprintf(os.Stderr, "       %s [options] -load /path/to/dir >cfg.hjson\nOptions:\n", os.Args[0])
-       flag.PrintDefaults()
-}
-
-func mainCfgDir() {
-       var (
-               doDump   = flag.Bool("dump", false, "Dump configuration file to the directory")
-               doLoad   = flag.Bool("load", false, "Load directory to create configuration file")
-               cfgPath  = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
-               version  = flag.Bool("version", false, "Print version information")
-               warranty = flag.Bool("warranty", false, "Print warranty information")
-       )
-       log.SetFlags(log.Lshortfile)
-       flag.Usage = usageCfgDir
-       flag.Parse()
-       if *warranty {
-               fmt.Println(nncp.Warranty)
-               return
-       }
-       if *version {
-               fmt.Println(nncp.VersionGet())
-               return
-       }
-
-       if (!*doDump && !*doLoad) || flag.NArg() != 1 {
-               usageCfgDir()
-               os.Exit(1)
-       }
-
-       if *doDump {
-               cfgRaw, err := os.ReadFile(*cfgPath)
-               if err != nil {
-                       log.Fatalln(err)
-               }
-               cfg, err := nncp.CfgParse(cfgRaw)
-               if err != nil {
-                       log.Fatalln(err)
-               }
-               if err = nncp.CfgToDir(flag.Arg(0), cfg); err != nil {
-                       log.Fatalln(err)
-               }
-       }
-       if *doLoad {
-               cfg, err := nncp.DirToCfg(flag.Arg(0))
-               if err != nil {
-                       log.Fatalln(err)
-               }
-               if _, err = nncp.Cfg2Ctx(cfg); err != nil {
-                       log.Fatalln(err)
-               }
-               marshaled, err := hjson.MarshalWithOptions(cfg, hjson.EncoderOptions{
-                       Eol:            "\n",
-                       BracesSameLine: true,
-                       QuoteAlways:    false,
-                       IndentBy:       "  ",
-               })
-               if err != nil {
-                       log.Fatalln(err)
-               }
-               os.Stdout.Write(marshaled)
-               os.Stdout.WriteString("\n")
-       }
-}
index 00bfa3354038ffc9a67ea53fd3ea658f234577ce..d4904b9f6103be3d4679d71631cde6aa04d5eab0 100644 (file)
@@ -68,8 +68,7 @@ func mainCfgMin() {
                }
                cfg.Neigh[node.Name] = nncp.NodeJSON{
                        Id:       node.Id.String(),
-                       ExchPub:  nncp.Base32Codec.EncodeToString(node.ExchPub[:]),
-                       SignPub:  nncp.Base32Codec.EncodeToString(node.SignPub[:]),
+                       KeyId:    nncp.HexEncode(node.KeyId[:]),
                        NoisePub: noisePub,
                }
        }
index 13cb63f01b022187b511ab59cd3fc6e679413e9e..d2e9992a7f25d3b73b4611e11e99641f60cdce21 100644 (file)
@@ -43,6 +43,7 @@ func mainCfgNew() {
                areaName   = flag.String("area", "", "Generate area's keypairs")
                yggdrasil  = flag.Bool("yggdrasil", false, "Generate Yggdrasil keypair")
                noComments = flag.Bool("nocomments", false, "Do not include descriptive comments")
+               name       = flag.String("name", "anon", "Name in public key")
                version    = flag.Bool("version", false, "Print version information")
                warranty   = flag.Bool("warranty", false, "Print warranty information")
        )
@@ -135,7 +136,7 @@ func mainCfgNew() {
                return
        }
 
-       nodeOur, err := nncp.NewNodeGenerate()
+       nodeOur, err := nncp.NewNodeGenerate(*name)
        if err != nil {
                log.Fatalln(err)
        }
@@ -148,10 +149,7 @@ func mainCfgNew() {
   self: {
     # DO NOT show anyone your private keys!!!
     id: %s
-    exchpub: %s
-    exchprv: %s
-    signpub: %s
-    signprv: %s
+    keyid: %s
     noiseprv: %s
     noisepub: %s
   }
@@ -159,8 +157,7 @@ func mainCfgNew() {
   neigh: {
     self: {
       id: %s
-      exchpub: %s
-      signpub: %s
+      keyid: %s
       noisepub: %s
       exec: {sendmail: ["%s"]}
     }
@@ -169,15 +166,11 @@ func mainCfgNew() {
                        nncp.DefaultSpoolPath,
                        nncp.DefaultLogPath,
                        nodeOur.Id.String(),
-                       nncp.Base32Codec.EncodeToString(nodeOur.ExchPub[:]),
-                       nncp.Base32Codec.EncodeToString(nodeOur.ExchPrv[:]),
-                       nncp.Base32Codec.EncodeToString(nodeOur.SignPub[:]),
-                       nncp.Base32Codec.EncodeToString(nodeOur.SignPrv[:]),
+                       nncp.HexEncode(nodeOur.KeyId[:]),
                        nncp.Base32Codec.EncodeToString(nodeOur.NoisePrv[:]),
                        nncp.Base32Codec.EncodeToString(nodeOur.NoisePub[:]),
                        nodeOur.Id.String(),
-                       nncp.Base32Codec.EncodeToString(nodeOur.ExchPub[:]),
-                       nncp.Base32Codec.EncodeToString(nodeOur.SignPub[:]),
+                       nncp.HexEncode(nodeOur.KeyId[:]),
                        nncp.Base32Codec.EncodeToString(nodeOur.NoisePub[:]),
                        nncp.DefaultSendmailPath,
                )
@@ -237,10 +230,7 @@ func mainCfgNew() {
   self: {
     # DO NOT show anyone your private keys!!!
     id: %s
-    exchpub: %s
-    exchprv: %s
-    signpub: %s
-    signprv: %s
+    keyid: %s
     noiseprv: %s
     noisepub: %s
   }
@@ -249,8 +239,7 @@ func mainCfgNew() {
     self: {
       # You should give public keys below to your neighbours
       id: %s
-      exchpub: %s
-      signpub: %s
+      keyid: %s
       noisepub: %s
 
       exec: {
@@ -332,15 +321,11 @@ func mainCfgNew() {
                        nncp.DefaultSpoolPath,
                        nncp.DefaultLogPath,
                        nodeOur.Id.String(),
-                       nncp.Base32Codec.EncodeToString(nodeOur.ExchPub[:]),
-                       nncp.Base32Codec.EncodeToString(nodeOur.ExchPrv[:]),
-                       nncp.Base32Codec.EncodeToString(nodeOur.SignPub[:]),
-                       nncp.Base32Codec.EncodeToString(nodeOur.SignPrv[:]),
+                       nncp.HexEncode(nodeOur.KeyId[:]),
                        nncp.Base32Codec.EncodeToString(nodeOur.NoisePrv[:]),
                        nncp.Base32Codec.EncodeToString(nodeOur.NoisePub[:]),
                        nodeOur.Id.String(),
-                       nncp.Base32Codec.EncodeToString(nodeOur.ExchPub[:]),
-                       nncp.Base32Codec.EncodeToString(nodeOur.SignPub[:]),
+                       nncp.HexEncode(nodeOur.KeyId[:]),
                        nncp.Base32Codec.EncodeToString(nodeOur.NoisePub[:]),
                        nncp.DefaultSendmailPath,
                        nncp.DefaultSendmailPath,
index 3970de1698e76a7b0599fe60e1e92595aaa65cc1..6773863b86ba5f7fb0b43a5206f2a48c5ce1eb9c 100644 (file)
@@ -14,7 +14,6 @@ const (
        CmdNameBundle   = "nncp-bundle"
        CmdNameCall     = "nncp-call"
        CmdNameCaller   = "nncp-caller"
-       CmdNameCfgDir   = "nncp-cfgdir"
        CmdNameCfgEnc   = "nncp-cfgenc"
        CmdNameCfgMin   = "nncp-cfgmin"
        CmdNameCfgNew   = "nncp-cfgnew"
@@ -47,8 +46,6 @@ func main() {
                mainCall()
        case CmdNameCaller:
                mainCaller()
-       case CmdNameCfgDir:
-               mainCfgDir()
        case CmdNameCfgEnc:
                mainCfgEnc()
        case CmdNameCfgMin:
index 70ace986aee9284fe771ee5cd017540ffca95d88..399bcab5e4334356fd8439b0bf8096ece28c313e 100644 (file)
@@ -144,20 +144,13 @@ Recipient: %s (%s)
        bufW := bufio.NewWriter(os.Stdout)
        var err error
        if area == nil {
-               _, _, _, err = nncp.PktEncRead(
+               _, _, err = nncp.PktEncRead(
                        ctx.Self, ctx.Neigh,
                        io.MultiReader(bytes.NewReader(beginning), bufio.NewReader(os.Stdin)),
-                       bufW, senderNode != nil, nil,
+                       bufW,
                )
        } else {
-               areaNode := nncp.NodeOur{Id: new(nncp.NodeId), ExchPrv: new([32]byte)}
-               copy(areaNode.Id[:], area.Id[:])
-               copy(areaNode.ExchPrv[:], area.Prv[:])
-               _, _, _, err = nncp.PktEncRead(
-                       &areaNode, ctx.Neigh,
-                       io.MultiReader(bytes.NewReader(beginning), bufio.NewReader(os.Stdin)),
-                       bufW, senderNode != nil, nil,
-               )
+               panic("no area yet")
        }
        if err != nil {
                log.Fatalln(err)
@@ -195,10 +188,9 @@ func mainPkt() {
 
        if *overheads {
                fmt.Printf(
-                       "Plain: %d\nEncrypted: %d\nSize: %d\n",
+                       "Plain: %d\nEncrypted: %d\n",
                        nncp.PktOverhead,
                        nncp.PktEncOverhead,
-                       nncp.PktSizeOverhead,
                )
                return
        }
@@ -221,6 +213,8 @@ func mainPkt() {
                case nncp.MagicNNCPEv5.B:
                        log.Fatalln(nncp.MagicNNCPEv5.TooOld())
                case nncp.MagicNNCPEv6.B:
+                       log.Fatalln(nncp.MagicNNCPEv6.TooOld())
+               case nncp.MagicNNCPEv7.B:
                        doEncrypted(ctx, pktEnc, *dump, beginning[:nncp.PktEncOverhead])
                        return
                }
index 46bb39798bd9ba3ccd09559864dee2ca48e52aee..355dd020dc3c1c14edcf34cfb3702221173e84a1 100644 (file)
@@ -247,6 +247,8 @@ func mainXfer() {
                                case nncp.MagicNNCPEv5.B:
                                        err = nncp.MagicNNCPEv5.TooOld()
                                case nncp.MagicNNCPEv6.B:
+                                       err = nncp.MagicNNCPEv6.TooOld()
+                               case nncp.MagicNNCPEv7.B:
                                default:
                                        err = errors.New("is not an encrypted packet")
                                }
index 8de89a05087803d91eb8d302d30d7f7122e8b00d..b64ddb062809cb2d51127260339e247161dc038f 100644 (file)
@@ -121,6 +121,10 @@ func CtxFromCmdline(
        if env != "" {
                cfgPath = env
        }
+       env = os.Getenv(CfgKeysEnv)
+       if env != "" {
+               DefaultKeysPath = env
+       }
        if showPrgrs && omitPrgrs {
                return nil, errors.New("simultaneous -progress and -noprogress")
        }
@@ -132,10 +136,7 @@ func CtxFromCmdline(
                                return nil, err
                        }
                        if fi.IsDir() {
-                               cfg, err = DirToCfg(cfgPath)
-                               if err != nil {
-                                       return nil, err
-                               }
+                               panic("cfg is dir")
                        } else {
                                cfgRaw, err := os.ReadFile(cfgPath)
                                if err != nil {
index f789ba34c3d7c25ab5a071660bfc2dd61939f3c3..b23bddd07c37a75b93360d4821b9ec2fb2027506 100644 (file)
@@ -183,6 +183,8 @@ func (ctx *Ctx) jobsFind(nodeId *NodeId, xx TRxTx, nock, part bool) chan Job {
                        case MagicNNCPEv5.B:
                                err = MagicNNCPEv5.TooOld()
                        case MagicNNCPEv6.B:
+                               err = MagicNNCPEv6.TooOld()
+                       case MagicNNCPEv7.B:
                        default:
                                err = BadMagic
                        }
index 5075dc775a4f5ecb6bd52ea52cd2415fb5442439..18f3d112ff33c26eed8cdc97987b01bbf3901596 100644 (file)
@@ -69,7 +69,11 @@ var (
        }
        MagicNNCPEv6 = Magic{
                B:    [8]byte{'N', 'N', 'C', 'P', 'E', 0, 0, 6},
-               Name: "NNCPEv6 (encrypted packet v6)", Till: "now",
+               Name: "NNCPEv6 (encrypted packet v6)", Till: "8.13.0",
+       }
+       MagicNNCPEv7 = Magic{
+               B:    [8]byte{'N', 'N', 'C', 'P', 'E', 0, 0, 7},
+               Name: "NNCPEv7 (encrypted packet v7)", Till: "now",
        }
        MagicNNCPSv1 = Magic{
                B:    [8]byte{'N', 'N', 'C', 'P', 'S', 0, 0, 1},
index 653f2e11beb2a8fa7ce60447e74a02e00800c99c..7bc5e99783b1e845620abdbb085b0d251a0b7b37 100644 (file)
@@ -39,7 +39,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.`
 )
 
 var (
-       Version string = "8.13.0"
+       Version string = "dev"
 
        Base32Codec *base32.Encoding = base32.StdEncoding.WithPadding(base32.NoPadding)
 )
index fc67390ba1e31ac694187d89bbd97e7e058c7da1..93b2ac3623a46387a3b9146f6100972966d13d2f 100644 (file)
 package nncp
 
 import (
+       "bytes"
        "crypto/rand"
+       "encoding/hex"
        "errors"
        "fmt"
+       "io"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "strings"
        "sync"
        "time"
 
        "github.com/flynn/noise"
        "golang.org/x/crypto/blake2b"
-       "golang.org/x/crypto/ed25519"
-       "golang.org/x/crypto/nacl/box"
 )
 
 const DummyB32Id = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
@@ -36,11 +41,14 @@ func (id NodeId) String() string {
        return Base32Codec.EncodeToString(id[:])
 }
 
+func HexEncode(b []byte) string {
+       return strings.ToUpper(hex.EncodeToString(b))
+}
+
 type Node struct {
        Name           string
        Id             *NodeId
-       ExchPub        *[32]byte
-       SignPub        ed25519.PublicKey
+       KeyId          [32]byte
        NoisePub       *[32]byte
        Exec           map[string][]string
        Incoming       *string
@@ -65,20 +73,68 @@ type Node struct {
 
 type NodeOur struct {
        Id       *NodeId
-       ExchPub  *[32]byte
-       ExchPrv  *[32]byte
-       SignPub  ed25519.PublicKey
-       SignPrv  ed25519.PrivateKey
+       KeyId    *[32]byte
        NoisePub *[32]byte
        NoisePrv *[32]byte
 }
 
-func NewNodeGenerate() (*NodeOur, error) {
-       exchPub, exchPrv, err := box.GenerateKey(rand.Reader)
+func NewNodeGenerate(name string) (*NodeOur, error) {
+       prv, err := os.CreateTemp(DefaultKeysPath, "prv*")
+       if err != nil {
+               return nil, err
+       }
+       defer os.Remove(prv.Name())
+       pub, err := os.CreateTemp(DefaultKeysPath, "pub*")
+       if err != nil {
+               return nil, err
+       }
+       defer os.Remove(pub.Name())
+       cmd := exec.Command("cmkeytool",
+               "-sub", "N="+name,
+               "-algo", "mceliece6960119-x25519",
+               "-ku", "kem", "-ku", "nncp")
+       cmd.ExtraFiles = []*os.File{nil, nil, pub, nil, nil, nil, prv}
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               return nil, fmt.Errorf("%s: %s", err, string(out))
+       }
+       _, err = prv.Seek(0, io.SeekStart)
        if err != nil {
                return nil, err
        }
-       signPub, signPrv, err := ed25519.GenerateKey(rand.Reader)
+       cmd = exec.Command("kekspp", "-v", "-p", "/pub-id")
+       cmd.Stdin = prv
+       out, err = cmd.Output()
+       if err != nil {
+               return nil, err
+       }
+       out = bytes.TrimRight(out, "\n")
+       keyId, err := hex.DecodeString(string(out))
+       if err != nil {
+               return nil, err
+       }
+       if len(keyId) != blake2b.Size256 {
+               panic("unexpected pub-id len")
+       }
+       err = os.Rename(prv.Name(), filepath.Join(DefaultKeysPath, string(out)+".prv"))
+       if err != nil {
+               return nil, err
+       }
+       err = os.Rename(pub.Name(), filepath.Join(DefaultKeysPath, string(out)+".pub"))
+       if err != nil {
+               return nil, err
+       }
+       err = os.Symlink(
+               "../"+string(out)+".prv",
+               filepath.Join(DefaultKeysPath, "prvs", string(out)),
+       )
+       if err != nil {
+               return nil, err
+       }
+       err = os.Symlink(
+               "../"+string(out)+".pub",
+               filepath.Join(DefaultKeysPath, "pubs", string(out)),
+       )
        if err != nil {
                return nil, err
        }
@@ -86,21 +142,16 @@ func NewNodeGenerate() (*NodeOur, error) {
        if err != nil {
                return nil, err
        }
-       noisePub := new([32]byte)
-       noisePrv := new([32]byte)
-       copy(noisePrv[:], noiseKey.Private)
-       copy(noisePub[:], noiseKey.Public)
-
-       id := NodeId(blake2b.Sum256([]byte(signPub)))
+       id := NodeId(keyId)
        node := NodeOur{
                Id:       &id,
-               ExchPub:  exchPub,
-               ExchPrv:  exchPrv,
-               SignPub:  signPub,
-               SignPrv:  signPrv,
-               NoisePub: noisePub,
-               NoisePrv: noisePrv,
+               KeyId:    new([blake2b.Size256]byte),
+               NoisePub: new([32]byte),
+               NoisePrv: new([32]byte),
        }
+       copy(node.KeyId[:], keyId)
+       copy(node.NoisePub[:], noiseKey.Public)
+       copy(node.NoisePrv[:], noiseKey.Private)
        return &node, nil
 }
 
@@ -108,8 +159,7 @@ func (nodeOur *NodeOur) Their() *Node {
        return &Node{
                Name:        "self",
                Id:          nodeOur.Id,
-               ExchPub:     nodeOur.ExchPub,
-               SignPub:     nodeOur.SignPub,
+               KeyId:       *nodeOur.KeyId,
                FreqChunked: MaxFileSize,
                FreqMaxSize: MaxFileSize,
        }
index ee0d334d58a8caa8afba8f0e08f80af23f5c1478..2dddd21a5709685012a974bdbda935c04c547c4a 100644 (file)
@@ -17,18 +17,13 @@ package nncp
 
 import (
        "bytes"
-       "crypto/cipher"
-       "crypto/rand"
        "errors"
        "io"
+       "os"
+       "os/exec"
+       "path/filepath"
 
        xdr "github.com/davecgh/go-xdr/xdr2"
-       "golang.org/x/crypto/chacha20poly1305"
-       "golang.org/x/crypto/curve25519"
-       "golang.org/x/crypto/ed25519"
-       "golang.org/x/crypto/nacl/box"
-       "golang.org/x/crypto/poly1305"
-       "lukechampine.com/blake3"
 )
 
 type PktType uint8
@@ -52,13 +47,8 @@ const (
 var (
        BadPktType error = errors.New("Unknown packet type")
 
-       DeriveKeyFullCtx = string(MagicNNCPEv6.B[:]) + " FULL"
-       DeriveKeySizeCtx = string(MagicNNCPEv6.B[:]) + " SIZE"
-       DeriveKeyPadCtx  = string(MagicNNCPEv6.B[:]) + " PAD"
-
-       PktOverhead     int64
-       PktEncOverhead  int64
-       PktSizeOverhead int64
+       PktOverhead    int64
+       PktEncOverhead int64
 
        TooBig = errors.New("Too big than allowed")
 )
@@ -84,13 +74,6 @@ type PktEnc struct {
        Nice      uint8
        Sender    *NodeId
        Recipient *NodeId
-       ExchPub   [32]byte
-       Sign      [ed25519.SignatureSize]byte
-}
-
-type PktSize struct {
-       Payload uint64
-       Pad     uint64
 }
 
 func NewPkt(typ PktType, nice uint8, path []byte) (*Pkt, error) {
@@ -132,64 +115,6 @@ func init() {
        }
        PktEncOverhead = int64(n)
        buf.Reset()
-
-       size := PktSize{}
-       n, err = xdr.Marshal(&buf, size)
-       if err != nil {
-               panic(err)
-       }
-       PktSizeOverhead = int64(n)
-}
-
-func ctrIncr(b []byte) {
-       for i := len(b) - 1; i >= 0; i-- {
-               b[i]++
-               if b[i] != 0 {
-                       return
-               }
-       }
-       panic("counter overflow")
-}
-
-func TbsPrepare(our *NodeOur, their *Node, pktEnc *PktEnc) []byte {
-       tbs := PktTbs{
-               Magic:     MagicNNCPEv6.B,
-               Nice:      pktEnc.Nice,
-               Sender:    their.Id,
-               Recipient: our.Id,
-               ExchPub:   pktEnc.ExchPub,
-       }
-       var tbsBuf bytes.Buffer
-       if _, err := xdr.Marshal(&tbsBuf, &tbs); err != nil {
-               panic(err)
-       }
-       return tbsBuf.Bytes()
-}
-
-func TbsVerify(our *NodeOur, their *Node, pktEnc *PktEnc) ([]byte, bool, error) {
-       tbs := TbsPrepare(our, their, pktEnc)
-       return tbs, ed25519.Verify(their.SignPub, tbs, pktEnc.Sign[:]), nil
-}
-
-func sizeWithTags(size int64) (fullSize int64) {
-       size += PktSizeOverhead
-       fullSize = size + (size/EncBlkSize)*poly1305.TagSize
-       if size%EncBlkSize != 0 {
-               fullSize += poly1305.TagSize
-       }
-       return
-}
-
-func sizePadCalc(sizePayload, minSize int64, wrappers int) (sizePad int64) {
-       expectedSize := sizePayload - PktOverhead
-       for i := 0; i < wrappers; i++ {
-               expectedSize = PktEncOverhead + sizeWithTags(PktOverhead+expectedSize)
-       }
-       sizePad = minSize - expectedSize
-       if sizePad < 0 {
-               sizePad = 0
-       }
-       return
 }
 
 func PktEncWrite(
@@ -198,152 +123,50 @@ func PktEncWrite(
        minSize, maxSize int64, wrappers int,
        r io.Reader, w io.Writer,
 ) (pktEncRaw []byte, size int64, err error) {
-       pub, prv, err := box.GenerateKey(rand.Reader)
-       if err != nil {
-               return nil, 0, err
-       }
-
-       var buf bytes.Buffer
-       _, err = xdr.Marshal(&buf, pkt)
-       if err != nil {
-               return
-       }
-       pktRaw := make([]byte, buf.Len())
-       copy(pktRaw, buf.Bytes())
-       buf.Reset()
-
-       tbs := PktTbs{
-               Magic:     MagicNNCPEv6.B,
-               Nice:      nice,
-               Sender:    our.Id,
-               Recipient: their.Id,
-               ExchPub:   *pub,
-       }
-       _, err = xdr.Marshal(&buf, &tbs)
-       if err != nil {
-               return
-       }
-       signature := new([ed25519.SignatureSize]byte)
-       copy(signature[:], ed25519.Sign(our.SignPrv, buf.Bytes()))
-       ad := blake3.Sum256(buf.Bytes())
-       buf.Reset()
-
-       pktEnc := PktEnc{
-               Magic:     MagicNNCPEv6.B,
-               Nice:      nice,
-               Sender:    our.Id,
-               Recipient: their.Id,
-               ExchPub:   *pub,
-               Sign:      *signature,
-       }
-       _, err = xdr.Marshal(&buf, &pktEnc)
-       if err != nil {
-               return
-       }
-       pktEncRaw = make([]byte, buf.Len())
-       copy(pktEncRaw, buf.Bytes())
-       buf.Reset()
-       _, err = w.Write(pktEncRaw)
-       if err != nil {
-               return
-       }
-
-       sharedKey, err := curve25519.X25519(prv[:], their.ExchPub[:])
-       if err != nil {
-               return
-       }
-       keyFull := make([]byte, chacha20poly1305.KeySize)
-       keySize := make([]byte, chacha20poly1305.KeySize)
-       blake3.DeriveKey(keyFull, DeriveKeyFullCtx, sharedKey)
-       blake3.DeriveKey(keySize, DeriveKeySizeCtx, sharedKey)
-       aeadFull, err := chacha20poly1305.New(keyFull)
-       if err != nil {
-               return
-       }
-       aeadSize, err := chacha20poly1305.New(keySize)
-       if err != nil {
-               return
-       }
-       nonce := make([]byte, aeadFull.NonceSize())
-
-       data := make([]byte, EncBlkSize, EncBlkSize+aeadFull.Overhead())
-       mr := io.MultiReader(bytes.NewReader(pktRaw), r)
-       var sizePayload int64
-       var n int
-       var ct []byte
-       for {
-               n, err = io.ReadFull(mr, data)
-               sizePayload += int64(n)
-               if sizePayload > maxSize {
-                       err = TooBig
+       {
+               var buf bytes.Buffer
+               pktEnc := PktEnc{
+                       Magic:     MagicNNCPEv7.B,
+                       Nice:      nice,
+                       Sender:    our.Id,
+                       Recipient: their.Id,
+               }
+               _, err = xdr.Marshal(&buf, &pktEnc)
+               if err != nil {
                        return
                }
-               if err == nil {
-                       ct = aeadFull.Seal(data[:0], nonce, data[:n], ad[:])
-                       _, err = w.Write(ct)
-                       if err != nil {
-                               return
-                       }
-                       ctrIncr(nonce)
-                       continue
-               }
-               if !(err == io.EOF || err == io.ErrUnexpectedEOF) {
+               pktEncRaw = buf.Bytes()
+       }
+       cmd := exec.Command("cmenctool", "-no-to", "-no-from", "-no-id", "-from",
+               filepath.Join(DefaultKeysPath, "pubs", HexEncode(our.KeyId[:])),
+               filepath.Join(DefaultKeysPath, "pubs", HexEncode(their.KeyId[:])),
+       )
+       cmd.Env = append(cmd.Env, "CM_PRVS="+filepath.Join(DefaultKeysPath, "prvs"))
+       cmd.Env = append(cmd.Env, "CM_PUBS="+filepath.Join(DefaultKeysPath, "pubs"))
+       {
+               var buf bytes.Buffer
+               _, err = xdr.Marshal(&buf, &pkt)
+               if err != nil {
                        return
                }
-               break
+               cmd.Stdin = io.MultiReader(&buf, r)
        }
-
-       sizePad := sizePadCalc(sizePayload, minSize, wrappers)
-       _, err = xdr.Marshal(&buf, &PktSize{uint64(sizePayload), uint64(sizePad)})
+       cmd.Stderr = os.Stderr
+       encrypted, err := cmd.StdoutPipe()
        if err != nil {
                return
        }
-
-       var aeadLast cipher.AEAD
-       if n+int(PktSizeOverhead) > EncBlkSize {
-               left := make([]byte, (n+int(PktSizeOverhead))-EncBlkSize)
-               copy(left, data[n-len(left):])
-               copy(data[PktSizeOverhead:], data[:n-len(left)])
-               copy(data[:PktSizeOverhead], buf.Bytes())
-               ct = aeadSize.Seal(data[:0], nonce, data[:EncBlkSize], ad[:])
-               _, err = w.Write(ct)
-               if err != nil {
-                       return
-               }
-               ctrIncr(nonce)
-               copy(data, left)
-               n = len(left)
-               aeadLast = aeadFull
-       } else {
-               copy(data[PktSizeOverhead:], data[:n])
-               copy(data[:PktSizeOverhead], buf.Bytes())
-               n += int(PktSizeOverhead)
-               aeadLast = aeadSize
-       }
-
-       var sizeBlockPadded int
-       var sizePadLeft int64
-       if sizePad > EncBlkSize-int64(n) {
-               sizeBlockPadded = EncBlkSize
-               sizePadLeft = sizePad - (EncBlkSize - int64(n))
-       } else {
-               sizeBlockPadded = n + int(sizePad)
-               sizePadLeft = 0
-       }
-       for i := n; i < sizeBlockPadded; i++ {
-               data[i] = 0
+       err = cmd.Start()
+       if err != nil {
+               return
        }
-       ct = aeadLast.Seal(data[:0], nonce, data[:sizeBlockPadded], ad[:])
-       _, err = w.Write(ct)
+       size, err = io.Copy(w, io.MultiReader(bytes.NewReader(pktEncRaw), encrypted))
        if err != nil {
                return
        }
-
-       size = sizePayload
-       if sizePadLeft > 0 {
-               keyPad := make([]byte, chacha20poly1305.KeySize)
-               blake3.DeriveKey(keyPad, DeriveKeyPadCtx, sharedKey[:])
-               _, err = io.CopyN(w, blake3.New(32, keyPad).XOF(), sizePadLeft)
+       err = cmd.Wait()
+       if err != nil {
+               return
        }
        return
 }
@@ -351,9 +174,7 @@ func PktEncWrite(
 func PktEncRead(
        our *NodeOur, nodes map[NodeId]*Node,
        r io.Reader, w io.Writer,
-       signatureVerify bool,
-       sharedKeyCached []byte,
-) (sharedKey []byte, their *Node, size int64, err error) {
+) (their *Node, size int64, err error) {
        var pktEnc PktEnc
        _, err = xdr.Unmarshal(r, &pktEnc)
        if err != nil {
@@ -371,6 +192,8 @@ func PktEncRead(
        case MagicNNCPEv5.B:
                err = MagicNNCPEv5.TooOld()
        case MagicNNCPEv6.B:
+               err = MagicNNCPEv6.TooOld()
+       case MagicNNCPEv7.B:
        default:
                err = BadMagic
        }
@@ -381,150 +204,27 @@ func PktEncRead(
                err = errors.New("Invalid recipient")
                return
        }
-
-       var tbsRaw []byte
-       if signatureVerify {
-               their = nodes[*pktEnc.Sender]
-               if their == nil {
-                       err = errors.New("Unknown sender")
-                       return
-               }
-               var verified bool
-               tbsRaw, verified, err = TbsVerify(our, their, &pktEnc)
-               if err != nil {
-                       return
-               }
-               if !verified {
-                       err = errors.New("Invalid signature")
-                       return
-               }
-       } else {
-               tbsRaw = TbsPrepare(our, &Node{Id: pktEnc.Sender}, &pktEnc)
-       }
-       ad := blake3.Sum256(tbsRaw)
-       if sharedKeyCached == nil {
-               var key []byte
-               key, err = curve25519.X25519(our.ExchPrv[:], pktEnc.ExchPub[:])
-               if err != nil {
-                       return
-               }
-               sharedKey = key[:]
-       } else {
-               sharedKey = sharedKeyCached
-       }
-
-       keyFull := make([]byte, chacha20poly1305.KeySize)
-       keySize := make([]byte, chacha20poly1305.KeySize)
-       blake3.DeriveKey(keyFull, DeriveKeyFullCtx, sharedKey[:])
-       blake3.DeriveKey(keySize, DeriveKeySizeCtx, sharedKey[:])
-       aeadFull, err := chacha20poly1305.New(keyFull)
-       if err != nil {
-               return
-       }
-       aeadSize, err := chacha20poly1305.New(keySize)
+       cmd := exec.Command("cmenctool", "-d",
+               "-assume-to", HexEncode(pktEnc.Recipient[:]),
+               "-assume-from", HexEncode(pktEnc.Sender[:]))
+       cmd.Env = append(cmd.Env, "CM_PRVS="+filepath.Join(DefaultKeysPath, "prvs"))
+       cmd.Env = append(cmd.Env, "CM_PUBS="+filepath.Join(DefaultKeysPath, "pubs"))
+       cmd.Stdin = r
+       decrypted, err := cmd.StdoutPipe()
        if err != nil {
                return
        }
-       nonce := make([]byte, aeadFull.NonceSize())
-
-       ct := make([]byte, EncBlkSize+aeadFull.Overhead())
-       pt := make([]byte, EncBlkSize)
-       var n int
-FullRead:
-       for {
-               n, err = io.ReadFull(r, ct)
-               switch err {
-               case nil:
-                       pt, err = aeadFull.Open(pt[:0], nonce, ct, ad[:])
-                       if err != nil {
-                               break FullRead
-                       }
-                       size += EncBlkSize
-                       _, err = w.Write(pt)
-                       if err != nil {
-                               return
-                       }
-                       ctrIncr(nonce)
-                       continue
-               case io.ErrUnexpectedEOF:
-                       break FullRead
-               default:
-                       return
-               }
-       }
-
-       pt, err = aeadSize.Open(pt[:0], nonce, ct[:n], ad[:])
+       err = cmd.Start()
        if err != nil {
                return
        }
-       var pktSize PktSize
-       _, err = xdr.Unmarshal(bytes.NewReader(pt), &pktSize)
+       size, err = io.Copy(w, decrypted)
        if err != nil {
                return
        }
-       pt = pt[PktSizeOverhead:]
-
-       left := int64(pktSize.Payload) - size
-       for left > int64(len(pt)) {
-               size += int64(len(pt))
-               left -= int64(len(pt))
-               _, err = w.Write(pt)
-               if err != nil {
-                       return
-               }
-               n, err = io.ReadFull(r, ct)
-               if err != nil && err != io.ErrUnexpectedEOF {
-                       return
-               }
-               ctrIncr(nonce)
-               pt, err = aeadFull.Open(pt[:0], nonce, ct[:n], ad[:])
-               if err != nil {
-                       return
-               }
-       }
-       size += left
-       _, err = w.Write(pt[:left])
+       err = cmd.Wait()
        if err != nil {
                return
        }
-       pt = pt[left:]
-
-       if pktSize.Pad < uint64(len(pt)) {
-               err = errors.New("unexpected pad")
-               return
-       }
-       for i := 0; i < len(pt); i++ {
-               if pt[i] != 0 {
-                       err = errors.New("non-zero pad byte")
-                       return
-               }
-       }
-       sizePad := int64(pktSize.Pad) - int64(len(pt))
-       if sizePad == 0 {
-               return
-       }
-
-       keyPad := make([]byte, chacha20poly1305.KeySize)
-       blake3.DeriveKey(keyPad, DeriveKeyPadCtx, sharedKey[:])
-       xof := blake3.New(32, keyPad).XOF()
-       pt = make([]byte, len(ct))
-       for sizePad > 0 {
-               n, err = io.ReadFull(r, ct)
-               if err != nil && err != io.ErrUnexpectedEOF {
-                       return
-               }
-               _, err = io.ReadFull(xof, pt[:n])
-               if err != nil {
-                       panic(err)
-               }
-               if !bytes.Equal(ct[:n], pt[:n]) {
-                       err = errors.New("wrong pad value")
-                       return
-               }
-               sizePad -= int64(n)
-       }
-       if sizePad < 0 {
-               err = errors.New("excess pad")
-       }
        return
 }
index bebad978e7c388a44398771d0c48f07457ae7c98..d7190aa969c6406f88c83500281b385e96411717 100644 (file)
@@ -36,8 +36,6 @@ import (
        xdr "github.com/davecgh/go-xdr/xdr2"
        "github.com/dustin/go-humanize"
        "github.com/klauspost/compress/zstd"
-       "golang.org/x/crypto/blake2b"
-       "golang.org/x/crypto/poly1305"
 )
 
 const (
@@ -81,16 +79,6 @@ func newNotification(fromTo *FromToJSON, subject string, body []byte) io.Reader
        return strings.NewReader(strings.Join(lines, "\n"))
 }
 
-func pktSizeWithoutEnc(pktSize int64) int64 {
-       pktSize = pktSize - PktEncOverhead - PktOverhead - PktSizeOverhead
-       pktSizeBlocks := pktSize / (EncBlkSize + poly1305.TagSize)
-       if pktSize%(EncBlkSize+poly1305.TagSize) != 0 {
-               pktSize -= poly1305.TagSize
-       }
-       pktSize -= pktSizeBlocks * poly1305.TagSize
-       return pktSize
-}
-
 var JobRepeatProcess = errors.New("needs processing repeat")
 
 func jobProcess(
@@ -689,7 +677,7 @@ func jobProcess(
                        } else {
                                via := node.Via[:len(node.Via)-1]
                                node = ctx.Neigh[*node.Via[len(node.Via)-1]]
-                               node = &Node{Id: node.Id, Via: via, ExchPub: node.ExchPub}
+                               node = &Node{Id: node.Id, Via: via, KeyId: node.KeyId}
                                pktTrns, err := NewPkt(PktTypeTrns, 0, nodeId[:])
                                if err != nil {
                                        panic(err)
@@ -753,235 +741,6 @@ func jobProcess(
                        }
                }
 
-       case PktTypeArea:
-               if opts.NoArea {
-                       return nil
-               }
-               areaId := new(AreaId)
-               copy(areaId[:], pkt.Path[:int(pkt.PathLen)])
-               les := append(les, LE{"Type", "area"}, LE{"Area", areaId})
-               logMsg := func(les LEs) string {
-                       return fmt.Sprintf(
-                               "Tossing %s/%s (%s): area %s",
-                               sender.Name, pktName,
-                               humanize.IBytes(pktSize),
-                               ctx.AreaName(areaId),
-                       )
-               }
-               area := ctx.AreaId2Area[*areaId]
-               if area == nil {
-                       err = errors.New("unknown area")
-                       ctx.LogE("rx-area-unknown", les, err, logMsg)
-                       return err
-               }
-               pktEnc, pktEncRaw, err := ctx.HdrRead(pipeR)
-               fullPipeR := io.MultiReader(bytes.NewReader(pktEncRaw), pipeR)
-               if err != nil {
-                       ctx.LogE("rx-area-pkt-enc-read", les, err, logMsg)
-                       return err
-               }
-               msgHashRaw := blake2b.Sum256(pktEncRaw)
-               msgHash := Base32Codec.EncodeToString(msgHashRaw[:])
-               les = append(les, LE{"AreaMsg", msgHash})
-               ctx.LogD("rx-area", les, logMsg)
-
-               if opts.DryRun {
-                       for _, nodeId := range area.Subs {
-                               node := ctx.Neigh[*nodeId]
-                               lesEcho := append(les, LE{"Echo", nodeId})
-                               seenDir := filepath.Join(
-                                       ctx.Spool, nodeId.String(), AreaDir, area.Id.String(),
-                               )
-                               seenPath := filepath.Join(seenDir, msgHash)
-                               logMsgNode := func(les LEs) string {
-                                       return fmt.Sprintf(
-                                               "%s: echoing to: %s", logMsg(les), node.Name,
-                                       )
-                               }
-                               if _, err := os.Stat(seenPath); err == nil {
-                                       ctx.LogD("rx-area-echo-seen", lesEcho, func(les LEs) string {
-                                               return logMsgNode(les) + ": already sent"
-                                       })
-                                       continue
-                               }
-                               ctx.LogI("rx-area-echo", lesEcho, logMsgNode)
-                       }
-               } else {
-                       for _, nodeId := range area.Subs {
-                               node := ctx.Neigh[*nodeId]
-                               lesEcho := append(les, LE{"Echo", nodeId})
-                               seenDir := filepath.Join(
-                                       ctx.Spool, nodeId.String(), AreaDir, area.Id.String(),
-                               )
-                               seenPath := filepath.Join(seenDir, msgHash)
-                               logMsgNode := func(les LEs) string {
-                                       return fmt.Sprintf("%s: echo to: %s", logMsg(les), node.Name)
-                               }
-                               if _, err := os.Stat(seenPath); err == nil {
-                                       ctx.LogD("rx-area-echo-seen", lesEcho, func(les LEs) string {
-                                               return logMsgNode(les) + ": already sent"
-                                       })
-                                       continue
-                               }
-                               if nodeId != sender.Id && nodeId != pktEnc.Sender {
-                                       ctx.LogI("rx-area-echo", lesEcho, logMsgNode)
-                                       if _, _, _, err = ctx.Tx(
-                                               node,
-                                               &pkt,
-                                               nice,
-                                               int64(pktSize), 0, MaxFileSize,
-                                               fullPipeR,
-                                               pktName,
-                                               nil,
-                                       ); err != nil {
-                                               ctx.LogE("rx-area", lesEcho, err, logMsgNode)
-                                               return err
-                                       }
-                               }
-                               if err = os.MkdirAll(seenDir, os.FileMode(0777)); err != nil {
-                                       ctx.LogE("rx-area-mkdir", lesEcho, err, logMsgNode)
-                                       return err
-                               }
-                               if fd, err := os.Create(seenPath); err == nil {
-                                       fd.Close()
-                                       if err = DirSync(seenDir); err != nil {
-                                               ctx.LogE("rx-area-dirsync", les, err, logMsgNode)
-                                               return err
-                                       }
-                               } else {
-                                       ctx.LogE("rx-area-touch", lesEcho, err, logMsgNode)
-                                       return err
-                               }
-                               return JobRepeatProcess
-                       }
-               }
-
-               seenDir := filepath.Join(
-                       ctx.Spool, ctx.SelfId.String(), AreaDir, area.Id.String(),
-               )
-               seenPath := filepath.Join(seenDir, msgHash)
-               if _, err := os.Stat(seenPath); err == nil {
-                       ctx.LogD("rx-area-seen", les, func(les LEs) string {
-                               return logMsg(les) + ": already seen"
-                       })
-                       if !opts.DryRun && jobPath != "" {
-                               if err = os.Remove(jobPath); err != nil {
-                                       ctx.LogE("rx-area-remove", les, err, func(les LEs) string {
-                                               return fmt.Sprintf(
-                                                       "Tossing area %s/%s (%s): %s: removing",
-                                                       sender.Name, pktName,
-                                                       humanize.IBytes(pktSize),
-                                                       msgHash,
-                                               )
-                                       })
-                                       return err
-                               } else if ctx.HdrUsage {
-                                       os.Remove(JobPath2Hdr(jobPath))
-                               }
-                       }
-                       return nil
-               }
-
-               if area.Prv == nil {
-                       ctx.LogD("rx-area-no-prv", les, func(les LEs) string {
-                               return logMsg(les) + ": no private key for decoding"
-                       })
-               } else {
-                       signatureVerify := true
-                       if _, senderKnown := ctx.Neigh[*pktEnc.Sender]; !senderKnown {
-                               if !area.AllowUnknown {
-                                       err = errors.New("unknown sender")
-                                       ctx.LogE(
-                                               "rx-area-unknown",
-                                               append(les, LE{"Sender", pktEnc.Sender}),
-                                               err,
-                                               func(les LEs) string {
-                                                       return logMsg(les) + ": sender: " + pktEnc.Sender.String()
-                                               },
-                                       )
-                                       return err
-                               }
-                               signatureVerify = false
-                       }
-                       areaNodeOur := NodeOur{Id: new(NodeId), ExchPrv: new([32]byte)}
-                       copy(areaNodeOur.Id[:], area.Id[:])
-                       copy(areaNodeOur.ExchPrv[:], area.Prv[:])
-                       areaNode := Node{
-                               Id:       new(NodeId),
-                               Name:     area.Name,
-                               Incoming: area.Incoming,
-                               Exec:     area.Exec,
-                               Origin:   pktEnc.Sender,
-                       }
-                       copy(areaNode.Id[:], area.Id[:])
-                       pktName := fmt.Sprintf(
-                               "area/%s/%s",
-                               Base32Codec.EncodeToString(areaId[:]), msgHash,
-                       )
-
-                       pipeR, pipeW := io.Pipe()
-                       errs := make(chan error, 1)
-                       go func() {
-                               errs <- jobProcess(
-                                       ctx,
-                                       pipeR,
-                                       pktName,
-                                       les,
-                                       &areaNode,
-                                       nice,
-                                       uint64(pktSizeWithoutEnc(int64(pktSize))),
-                                       "",
-                                       decompressor,
-                                       opts,
-                               )
-                       }()
-                       _, _, _, err = PktEncRead(
-                               &areaNodeOur,
-                               ctx.Neigh,
-                               fullPipeR,
-                               pipeW,
-                               signatureVerify,
-                               nil,
-                       )
-                       if err != nil {
-                               ctx.LogE("rx-area-pkt-enc-read2", les, err, logMsg)
-                               pipeW.CloseWithError(err)
-                               <-errs
-                               return err
-                       }
-                       pipeW.Close()
-                       if err = <-errs; err != nil {
-                               return err
-                       }
-               }
-
-               if !opts.DryRun && jobPath != "" {
-                       if err = os.MkdirAll(seenDir, os.FileMode(0777)); err != nil {
-                               ctx.LogE("rx-area-mkdir", les, err, logMsg)
-                               return err
-                       }
-                       if fd, err := os.Create(seenPath); err == nil {
-                               fd.Close()
-                               if err = DirSync(seenDir); err != nil {
-                                       ctx.LogE("rx-area-dirsync", les, err, logMsg)
-                                       return err
-                               }
-                       }
-                       if err = os.Remove(jobPath); err != nil {
-                               ctx.LogE("rx", les, err, func(les LEs) string {
-                                       return fmt.Sprintf(
-                                               "Tossing area %s/%s (%s): %s: removing",
-                                               sender.Name, pktName,
-                                               humanize.IBytes(pktSize),
-                                               msgHash,
-                                       )
-                               })
-                               return err
-                       } else if ctx.HdrUsage {
-                               os.Remove(JobPath2Hdr(jobPath))
-                       }
-               }
-
        case PktTypeACK:
                if opts.NoACK {
                        return nil
@@ -1111,7 +870,6 @@ func (ctx *Ctx) Toss(nodeId *NodeId, xx TRxTx, opts *TossOpts) bool {
                        continue
                }
                errs := make(chan error, 1)
-               var sharedKey []byte
        Retry:
                pipeR, pipeW := io.Pipe()
                go func() {
@@ -1122,20 +880,18 @@ func (ctx *Ctx) Toss(nodeId *NodeId, xx TRxTx, opts *TossOpts) bool {
                                les,
                                sender,
                                job.PktEnc.Nice,
-                               uint64(pktSizeWithoutEnc(job.Size)),
+                               uint64(job.Size),
                                job.Path,
                                decompressor,
                                opts,
                        )
                }()
                pipeWB := bufio.NewWriter(pipeW)
-               sharedKey, _, _, err = PktEncRead(
+               _, _, err = PktEncRead(
                        ctx.Self,
                        ctx.Neigh,
                        bufio.NewReaderSize(fd, MTHBlockSize),
                        pipeWB,
-                       sharedKey == nil,
-                       sharedKey,
                )
                if err != nil {
                        pipeW.CloseWithError(err)
index 2504135a5883cb57bb724e172d45a2a91210b6a5..c587527901d665aeff5c52e6b581a1ed332ab77d 100644 (file)
--- a/src/tx.go
+++ b/src/tx.go
@@ -71,18 +71,7 @@ func (ctx *Ctx) Tx(
        if area != nil {
                wrappers++
        }
-       var expectedSize int64
-       if srcSize > 0 {
-               expectedSize = srcSize + PktOverhead
-               expectedSize += sizePadCalc(expectedSize, minSize, wrappers)
-               expectedSize = PktEncOverhead + sizeWithTags(expectedSize)
-               if maxSize != 0 && expectedSize > maxSize {
-                       return nil, 0, "", TooBig
-               }
-               if !ctx.IsEnoughSpace(expectedSize) {
-                       return nil, 0, "", errors.New("is not enough space")
-               }
-       }
+       expectedSize := srcSize + PktOverhead + PktEncOverhead
        tmp, err := ctx.NewTmpFileWHash()
        if err != nil {
                return nil, 0, "", err
@@ -112,53 +101,7 @@ func (ctx *Ctx) Tx(
                        dst.Close()
                }(src, pipeW)
        } else {
-               go func(src io.Reader, dst io.WriteCloser) {
-                       ctx.LogD("tx", LEs{
-                               {"Area", area.Id},
-                               {"Nice", int(nice)},
-                               {"Size", expectedSize},
-                       }, func(les LEs) string {
-                               return fmt.Sprintf(
-                                       "Tx area packet to %s (source %s) nice: %s",
-                                       ctx.AreaName(areaId),
-                                       humanize.IBytes(uint64(expectedSize)),
-                                       NicenessFmt(nice),
-                               )
-                       })
-                       areaNode := Node{Id: new(NodeId), ExchPub: new([32]byte)}
-                       copy(areaNode.Id[:], area.Id[:])
-                       copy(areaNode.ExchPub[:], area.Pub[:])
-                       pktEncRaw, size, err := PktEncWrite(
-                               ctx.Self, &areaNode, pkt, nice, 0, maxSize, 0, src, dst,
-                       )
-                       results <- PktEncWriteResult{pktEncRaw, size, err}
-                       dst.Close()
-               }(src, pipeW)
-               pipeRPrev = pipeR
-               pipeR, pipeW = io.Pipe()
-               go func(src io.Reader, dst io.WriteCloser) {
-                       pktArea, err := NewPkt(PktTypeArea, 0, area.Id[:])
-                       if err != nil {
-                               panic(err)
-                       }
-                       ctx.LogD("tx", LEs{
-                               {"Node", hops[0].Id},
-                               {"Nice", int(nice)},
-                               {"Size", expectedSize},
-                       }, func(les LEs) string {
-                               return fmt.Sprintf(
-                                       "Tx packet to %s (source %s) nice: %s",
-                                       ctx.NodeName(hops[0].Id),
-                                       humanize.IBytes(uint64(expectedSize)),
-                                       NicenessFmt(nice),
-                               )
-                       })
-                       pktEncRaw, size, err := PktEncWrite(
-                               ctx.Self, hops[0], pktArea, nice, minSize, maxSize, wrappers, src, dst,
-                       )
-                       results <- PktEncWriteResult{pktEncRaw, size, err}
-                       dst.Close()
-               }(pipeRPrev, pipeW)
+               panic("no area yet")
        }
        for i := 1; i < len(hops); i++ {
                pktTrns, err := NewPkt(PktTypeTrns, 0, hops[i-1].Id[:])