VERSION | 2 +- doc/building.texi | 12 ++++++------ doc/download.texi | 4 ++++ doc/integrity.texi | 4 ++-- doc/news.ru.texi | 20 ++++++++++++++++++++ doc/news.texi | 18 ++++++++++++++++++ makedist.sh | 2 +- ports/nncp/Makefile | 2 +- src/cmd/nncp-bundle/main.go | 3 +++ src/cmd/nncp-cfgnew/main.go | 4 ++-- src/cmd/nncp-reass/main.go | 3 +++ src/cmd/nncp-xfer/main.go | 5 +++++ src/humanizer.go | 25 ++++++++++++++++++++++++- src/sp.go | 22 +++++++++++++++++----- src/tmp.go | 18 +++++++++++++++++- src/toss.go | 4 ++++ diff --git a/VERSION b/VERSION index 05e2d1d765d5f1e08f762bed62ec68e741252932278b059d74dd571e480ce227..9871b3c67fa0b9d06b62dc407cd355e0a52c7e10ff11d9c8b206bc1cddb05392 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.1.1 +5.1.2 diff --git a/doc/building.texi b/doc/building.texi index ab4c0aa94c52dcbe151d5ddb1873d9e293981776f4d88464611570058a056b34..091105605015347b3e9752aad2cd609a681fb3ab61b406ca6f691a5d4f1f00cf 100644 --- a/doc/building.texi +++ b/doc/building.texi @@ -11,16 +11,16 @@ @verb{|apt install golang|} @end table @verbatim -$ [fetch|wget] http://www.nncpgo.org/download/nncp-5.1.1.tar.xz -$ [fetch|wget] http://www.nncpgo.org/download/nncp-5.1.1.tar.xz.sig -$ gpg --verify nncp-5.1.1.tar.xz.sig nncp-5.1.1.tar.xz -$ xz --decompress --stdout nncp-5.1.1.tar.xz | tar xf - -$ make -C nncp-5.1.1 all +$ [fetch|wget] http://www.nncpgo.org/download/nncp-5.1.2.tar.xz +$ [fetch|wget] http://www.nncpgo.org/download/nncp-5.1.2.tar.xz.sig +$ gpg --verify nncp-5.1.2.tar.xz.sig nncp-5.1.2.tar.xz +$ xz --decompress --stdout nncp-5.1.2.tar.xz | tar xf - +$ make -C nncp-5.1.2 all @end verbatim There is @command{install} make-target respecting @env{DESTDIR}. It will install binaries and info-documentation: @verbatim -# make -C nncp-5.1.1 install PREFIX=/usr/local +# make -C nncp-5.1.2 install PREFIX=/usr/local @end verbatim diff --git a/doc/download.texi b/doc/download.texi index 8ecb0b7b831a5adabc917b8acbd1c0b8af76444aef092880d5e1e71798041356..ea4e122f703d4ad9ab0639a5827aece8cbc143bdb3f2de5bf36ab5e826dc1691 100644 --- a/doc/download.texi +++ b/doc/download.texi @@ -23,6 +23,10 @@ @multitable {XXXXX} {XXXX-XX-XX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @headitem Version @tab Date @tab Size @tab Tarball @tab SHA256 checksum +@item @ref{Release 5.1.1, 5.1.1} @tab 2019-12-01 @tab 1103 KiB +@tab @url{download/nncp-5.1.1.tar.xz, link} @url{download/nncp-5.1.1.tar.xz.sig, sign} +@tab @code{B9537678 E5B549BA 6FA0D20D 41B2D4A9 4ED31F2C AB9FAF63 A388D95E 7662A93F} + @item @ref{Release 5.1.0, 5.1.0} @tab 2019-11-24 @tab 1103 KiB @tab @url{download/nncp-5.1.0.tar.xz, link} @url{download/nncp-5.1.0.tar.xz.sig, sign} @tab @code{6F5B74EC 952EAFEC 2A787463 CE1E808E CC990F03 D46F28E9 A89BAB55 5A2C2214} diff --git a/doc/integrity.texi b/doc/integrity.texi index ccba0ac33bcc7bed198fcc1574e91629b4f60a77f75376efb523c51692d358e4..5458e3f57837f74e64c07d1c7c739ef7287a702e58abfb57b9423a5c029c88cd 100644 --- a/doc/integrity.texi +++ b/doc/integrity.texi @@ -4,7 +4,7 @@ You @strong{have to} check downloaded archives integrity and verify their signature to be sure that you have got trusted, untampered software. For integrity and authentication of downloaded binaries -@url{https://www.gnupg.org/, The GNU Privacy Guard} is used. You must +@url{https://www.gnupg.org/, GNU Privacy Guard} is used. You must download signature (@file{.sig}) provided with the tarball. For the very first time you need to import signing public key. It is @@ -31,5 +31,5 @@ @end itemize Then you could verify tarballs signature: @verbatim -$ gpg --verify nncp-5.1.1.tar.xz.sig nncp-5.1.1.tar.xz +$ gpg --verify nncp-5.1.2.tar.xz.sig nncp-5.1.2.tar.xz @end verbatim diff --git a/doc/news.ru.texi b/doc/news.ru.texi index 70f067b3c9b849fbf4f88aee66f579cbbaf811f538604aa228314798321a0dbe..e0b0dadb5a52c123c908b39c713528a5bb33f3bd14fe849f8a396aea5762f76d 100644 --- a/doc/news.ru.texi +++ b/doc/news.ru.texi @@ -1,6 +1,26 @@ @node Новости @section Новости +@node Релиз 5.1.2 +@subsection Релиз 5.1.2 +@itemize + +@item +Исправлена @strong{критичная} уязвимость: аутентификация online нод +могла приводить к некорректной идентификации удалённой стороны, позволяя +скачивать чужие зашифрованные пакеты. + +@item +Исправлена ошибка: в новосозданных конфигурационных файлах, приватный +публичный ключ Noise были поменяны местами, что приводило к +невозможности online аутентификации нод. + +@item +Явная синхронизация (fsync) директорий для гарантированного +переименования файлов. + +@end itemize + @node Релиз 5.1.1 @subsection Релиз 5.1.1 @itemize diff --git a/doc/news.texi b/doc/news.texi index 8baca54eecb26b06988f7e6c15d83db2faaa4afe5190df85cb434fbe071bb662..052be070bc6b436b9dc76bbfed42c85b47a35d8e3376452f163df7096dfd6c3b 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -3,6 +3,24 @@ @unnumbered News See also this page @ref{Новости, on russian}. +@node Release 5.1.2 +@section Release 5.1.2 +@itemize + +@item +@strong{Critical} vulnerability: remote peers authentication could lead +to incorrect identification of remote side, allowing foreign encrypted +packets downloading. + +@item +Bugfix: private and public Noise keys were swapped in newly created +configuration files, that lead to inability to authenticate online peers. + +@item +Explicit directories fsync-ing for guaranteed files renaming. + +@end itemize + @node Release 5.1.1 @section Release 5.1.1 @itemize diff --git a/makedist.sh b/makedist.sh index 6ea75c23101225ca596a5a1edb2914003646e86c2554d502a007b132492e786c..52004652c0156038657ed22783778843c065da29e87cf5d30b32ed521c495ee7 100755 --- a/makedist.sh +++ b/makedist.sh @@ -10,7 +10,7 @@ cd $tmp/nncp-$release git checkout v$release rm -fr .git -mod_name=go.cypherpunks.ru/nncp/v5 +mod_name=$(sed -n 's/^module //p' src/go.mod) mv src src.orig mkdir -p src/$mod_name mv src.orig/* src/$mod_name diff --git a/ports/nncp/Makefile b/ports/nncp/Makefile index c6948ca6cb8030e477d88772ddef9a29a4eb7a95034b4ba3abbf0186acc31e35..b248e505dc5ca7a4211d9a9e5e83ee008a6114752d6d94bdea8010b9369ea054 100644 --- a/ports/nncp/Makefile +++ b/ports/nncp/Makefile @@ -1,7 +1,7 @@ # $FreeBSD: head/net/nncp/Makefile 517819 2019-11-17 11:51:56Z dmgk $ PORTNAME= nncp -DISTVERSION= 5.1.1 +DISTVERSION= 5.1.2 CATEGORIES= net MASTER_SITES= http://www.nncpgo.org/download/ diff --git a/src/cmd/nncp-bundle/main.go b/src/cmd/nncp-bundle/main.go index 342b949983604c15998168153691add6b56a78437938b10e1ac7d9b2f0d8bf5c..832c8b328e8233736a43c9ce3957de4ccc337cbd448c51ab17f95d2ee802ad35 100644 --- a/src/cmd/nncp-bundle/main.go +++ b/src/cmd/nncp-bundle/main.go @@ -378,6 +378,9 @@ } if err = os.Rename(tmp.Name(), dstPath); err != nil { log.Fatalln("Error during renaming:", err) } + if err = nncp.DirSync(selfPath); err != nil { + log.Fatalln("Error during syncing:", err) + } } } ctx.LogI("nncp-bundle", nncp.SdsAdd(sds, nncp.SDS{ diff --git a/src/cmd/nncp-cfgnew/main.go b/src/cmd/nncp-cfgnew/main.go index 7a5f3c627c2b958a44e46b8a880420e1f92084f891c187bfc7a713236dfc7656..6c4cf7a0df4d74e311658caba6843874a47ef947ac790543774ead66b288301a 100644 --- a/src/cmd/nncp-cfgnew/main.go +++ b/src/cmd/nncp-cfgnew/main.go @@ -86,8 +86,8 @@ nncp.ToBase32(nodeOur.ExchPub[:]), nncp.ToBase32(nodeOur.ExchPrv[:]), nncp.ToBase32(nodeOur.SignPub[:]), nncp.ToBase32(nodeOur.SignPrv[:]), - nncp.ToBase32(nodeOur.NoisePub[:]), nncp.ToBase32(nodeOur.NoisePrv[:]), + nncp.ToBase32(nodeOur.NoisePub[:]), nodeOur.Id.String(), nncp.ToBase32(nodeOur.ExchPub[:]), nncp.ToBase32(nodeOur.SignPub[:]), @@ -220,8 +220,8 @@ nncp.ToBase32(nodeOur.ExchPub[:]), nncp.ToBase32(nodeOur.ExchPrv[:]), nncp.ToBase32(nodeOur.SignPub[:]), nncp.ToBase32(nodeOur.SignPrv[:]), - nncp.ToBase32(nodeOur.NoisePub[:]), nncp.ToBase32(nodeOur.NoisePrv[:]), + nncp.ToBase32(nodeOur.NoisePub[:]), nodeOur.Id.String(), nncp.ToBase32(nodeOur.ExchPub[:]), nncp.ToBase32(nodeOur.SignPub[:]), diff --git a/src/cmd/nncp-reass/main.go b/src/cmd/nncp-reass/main.go index 14a98b9f0398c6d0bac513c3017dbb32f1b5cefaf9b10a020273440d43c01b99..515424fa6ab7e5f3609dd26e88323a62b65db43dca65ed5104cf1fa4ff879f05 100644 --- a/src/cmd/nncp-reass/main.go +++ b/src/cmd/nncp-reass/main.go @@ -238,6 +238,9 @@ } if err = os.Rename(tmp.Name(), dstPath); err != nil { log.Fatalln(err) } + if err = nncp.DirSync(mainDir); err != nil { + log.Fatalln(err) + } ctx.LogI("nncp-reass", nncp.SDS{"path": path}, "done") return !hasErrors } diff --git a/src/cmd/nncp-xfer/main.go b/src/cmd/nncp-xfer/main.go index 6de52b8dcc6e7a5fdd9fb526fb16b6e1d3e09e18e6486d5f1312d151aa725885..1858ebff9e587d4d8708fead86df93b319df8267fa3497737ae6953f9cf8459c 100644 --- a/src/cmd/nncp-xfer/main.go +++ b/src/cmd/nncp-xfer/main.go @@ -330,6 +330,11 @@ ctx.LogE("nncp-xfer", nncp.SdsAdd(sds, nncp.SDS{"err": err}), "rename") isBad = true continue } + if err = nncp.DirSync(dstPath); err != nil { + ctx.LogE("nncp-xfer", nncp.SdsAdd(sds, nncp.SDS{"err": err}), "sync") + isBad = true + continue + } os.Remove(filepath.Join(dstPath, pktName+".part")) delete(sds, "tmp") ctx.LogI("nncp-xfer", nncp.SdsAdd(sds, nncp.SDS{ diff --git a/src/humanizer.go b/src/humanizer.go index ac94e70c683043b0c7d53fc96460e0d49a3dfb854674494581948fde7e1cdb51..7dc2778a8ec53c33d5970dc64c13a77a6984368250aabf51d878752902df5c1f 100644 --- a/src/humanizer.go +++ b/src/humanizer.go @@ -173,7 +173,10 @@ } case "nncp-rm": msg += "removing " + sds["file"] case "call-start": - msg = fmt.Sprintf("Connected to %s", nodeS) + msg = fmt.Sprintf("Connection to %s", nodeS) + if err, exists := sds["err"]; exists { + msg += ": " + err + } case "call-finish": rx, err := strconv.ParseUint(sds["rxbytes"], 10, 64) if err != nil { @@ -197,6 +200,26 @@ nodeS, humanize.IBytes(uint64(rx)), humanize.IBytes(uint64(rxs)), humanize.IBytes(uint64(tx)), humanize.IBytes(uint64(txs)), ) + case "sp-start": + if nodeS == "" { + msg += "SP" + if peer, exists := sds["peer"]; exists { + msg += fmt.Sprintf(": %s", peer) + } + } else { + nice, err := NicenessParse(sds["nice"]) + if err != nil { + return s + } + msg += fmt.Sprintf("SP with %s (nice %s)", nodeS, NicenessFmt(nice)) + } + if len(rem) > 0 { + msg += ": " + rem + } + if err, exists := sds["err"]; exists { + msg += ": " + err + } + case "sp-info": nice, err := NicenessParse(sds["nice"]) if err != nil { diff --git a/src/sp.go b/src/sp.go index b901a24a679105c9c36fcba976457c3034deb6ec126d5a9cf6e8151775a29ce6..51a1fafbc37b7f9ba25b77681d92f0ecc99ccc3b305c240bf4f72f265a253558 100644 --- a/src/sp.go +++ b/src/sp.go @@ -231,6 +231,10 @@ func (state *SPState) ReadSP(src io.Reader) ([]byte, error) { var sp SPRaw n, err := xdr.UnmarshalLimited(src, &sp, 1<<17) if err != nil { + ue := err.(*xdr.UnmarshalError) + if ue.Err == io.EOF { + return nil, ue.Err + } return nil, err } state.RxLastSeen = time.Now() @@ -415,8 +419,9 @@ return err } var node *Node - for _, node = range state.Ctx.Neigh { - if subtle.ConstantTimeCompare(state.hs.PeerStatic(), node.NoisePub[:]) == 1 { + for _, n := range state.Ctx.Neigh { + if subtle.ConstantTimeCompare(state.hs.PeerStatic(), n.NoisePub[:]) == 1 { + node = n break } } @@ -838,12 +843,12 @@ } sdsp["xx"] = string(TRx) sdsp["hash"] = ToBase32(file.Hash[:]) sdsp["size"] = strconv.Itoa(len(file.Payload)) - filePath := filepath.Join( + dirToSync := filepath.Join( state.Ctx.Spool, state.Node.Id.String(), string(TRx), - ToBase32(file.Hash[:]), ) + filePath := filepath.Join(dirToSync, ToBase32(file.Hash[:])) state.Ctx.LogD("sp-file", sdsp, "opening part") fd, err := os.OpenFile( filePath+PartSuffix, @@ -901,7 +906,14 @@ state.Ctx.LogE("sp-file", sdsp, "checksum mismatch") return } state.Ctx.LogI("sp-done", SdsAdd(sdsp, SDS{"xx": string(TRx)}), "") - os.Rename(filePath+PartSuffix, filePath) + if err = os.Rename(filePath+PartSuffix, filePath); err != nil { + state.Ctx.LogE("sp-file", SdsAdd(sdsp, SDS{"err": err}), "rename") + return + } + if err = DirSync(dirToSync); err != nil { + state.Ctx.LogE("sp-file", SdsAdd(sdsp, SDS{"err": err}), "sync") + return + } state.Lock() delete(state.infosTheir, *file.Hash) state.Unlock() diff --git a/src/tmp.go b/src/tmp.go index 0b1672a56890508dbdc28b9c69a68e0ef026fde497b5538fc2745fffd76a5413..a2a19cbcf91e9896525cac703e8f6a60279912a21ca95a2847068893adc2fb25 100644 --- a/src/tmp.go +++ b/src/tmp.go @@ -79,6 +79,19 @@ tmp.Fd.Close() os.Remove(tmp.Fd.Name()) } +func DirSync(dirPath string) error { + fd, err := os.Open(dirPath) + if err != nil { + return err + } + err = fd.Sync() + if err != nil { + fd.Close() + return err + } + return fd.Close() +} + func (tmp *TmpFileWHash) Commit(dir string) error { var err error if err = os.MkdirAll(dir, os.FileMode(0777)); err != nil { @@ -95,5 +108,8 @@ } tmp.Fd.Close() checksum := ToBase32(tmp.Hsh.Sum(nil)) tmp.ctx.LogD("tmp", SDS{"src": tmp.Fd.Name(), "dst": checksum}, "commit") - return os.Rename(tmp.Fd.Name(), filepath.Join(dir, checksum)) + if err = os.Rename(tmp.Fd.Name(), filepath.Join(dir, checksum)); err != nil { + return err + } + return DirSync(dir) } diff --git a/src/toss.go b/src/toss.go index e91dd5b5403978f9a2a55c03b0967b82ca8a7a16c831ba1fb53576d8a391614c..bf8e4edd44bf0f9d3062b181d428f6d4f936019692a5cd7efc433262bafdf397 100644 --- a/src/toss.go +++ b/src/toss.go @@ -261,6 +261,10 @@ if err = os.Rename(tmp.Name(), dstPath); err != nil { ctx.LogE("rx", SdsAdd(sds, SDS{"err": err}), "rename") isBad = true } + if err = DirSync(*incoming); err != nil { + ctx.LogE("rx", SdsAdd(sds, SDS{"err": err}), "sync") + isBad = true + } delete(sds, "tmp") } ctx.LogI("rx", sds, "")