From: Sergey Matveev Date: Sun, 30 Nov 2025 08:33:32 +0000 (+0300) Subject: Ev7 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=refs%2Fheads%2Fkekscm;p=nncp.git Ev7 --- diff --git a/src/cfg.go b/src/cfg.go index 365231d..a806e8f 100644 --- a/src/cfg.go +++ b/src/cfg.go @@ -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 index 3a9f03e..0000000 --- a/src/cfgdir.go +++ /dev/null @@ -1,989 +0,0 @@ -// NNCP -- Node to Node copy, utilities for store-and-forward data exchange -// Copyright (C) 2016-2025 Sergey Matveev -// -// 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 . - -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 = ¬ify - } - - 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 -} diff --git a/src/cmd/nncp/ack.go b/src/cmd/nncp/ack.go index f97fbaa..af5a58e 100644 --- a/src/cmd/nncp/ack.go +++ b/src/cmd/nncp/ack.go @@ -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) diff --git a/src/cmd/nncp/bundle.go b/src/cmd/nncp/bundle.go index 841a831..2005cac 100644 --- a/src/cmd/nncp/bundle.go +++ b/src/cmd/nncp/bundle.go @@ -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 index 8e40d2f..0000000 --- a/src/cmd/nncp/cfgdir.go +++ /dev/null @@ -1,94 +0,0 @@ -// NNCP -- Node to Node copy, utilities for store-and-forward data exchange -// Copyright (C) 2016-2025 Sergey Matveev -// -// 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 . - -// 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") - } -} diff --git a/src/cmd/nncp/cfgmin.go b/src/cmd/nncp/cfgmin.go index 00bfa33..d4904b9 100644 --- a/src/cmd/nncp/cfgmin.go +++ b/src/cmd/nncp/cfgmin.go @@ -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, } } diff --git a/src/cmd/nncp/cfgnew.go b/src/cmd/nncp/cfgnew.go index 13cb63f..d2e9992 100644 --- a/src/cmd/nncp/cfgnew.go +++ b/src/cmd/nncp/cfgnew.go @@ -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, diff --git a/src/cmd/nncp/main.go b/src/cmd/nncp/main.go index 3970de1..6773863 100644 --- a/src/cmd/nncp/main.go +++ b/src/cmd/nncp/main.go @@ -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: diff --git a/src/cmd/nncp/pkt.go b/src/cmd/nncp/pkt.go index 70ace98..399bcab 100644 --- a/src/cmd/nncp/pkt.go +++ b/src/cmd/nncp/pkt.go @@ -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 } diff --git a/src/cmd/nncp/xfer.go b/src/cmd/nncp/xfer.go index 46bb397..355dd02 100644 --- a/src/cmd/nncp/xfer.go +++ b/src/cmd/nncp/xfer.go @@ -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") } diff --git a/src/ctx.go b/src/ctx.go index 8de89a0..b64ddb0 100644 --- a/src/ctx.go +++ b/src/ctx.go @@ -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 { diff --git a/src/jobs.go b/src/jobs.go index f789ba3..b23bddd 100644 --- a/src/jobs.go +++ b/src/jobs.go @@ -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 } diff --git a/src/magic.go b/src/magic.go index 5075dc7..18f3d11 100644 --- a/src/magic.go +++ b/src/magic.go @@ -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}, diff --git a/src/nncp.go b/src/nncp.go index 653f2e1..7bc5e99 100644 --- a/src/nncp.go +++ b/src/nncp.go @@ -39,7 +39,7 @@ along with this program. If not, see .` ) var ( - Version string = "8.13.0" + Version string = "dev" Base32Codec *base32.Encoding = base32.StdEncoding.WithPadding(base32.NoPadding) ) diff --git a/src/node.go b/src/node.go index fc67390..93b2ac3 100644 --- a/src/node.go +++ b/src/node.go @@ -16,16 +16,21 @@ 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, } diff --git a/src/pkt.go b/src/pkt.go index ee0d334..2dddd21 100644 --- a/src/pkt.go +++ b/src/pkt.go @@ -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 } diff --git a/src/toss.go b/src/toss.go index bebad97..d7190aa 100644 --- a/src/toss.go +++ b/src/toss.go @@ -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) diff --git a/src/tx.go b/src/tx.go index 2504135..c587527 100644 --- 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[:])