README | 15 ++++++++------- README.RU | 8 ++++---- VERSION | 2 +- common.mk | 10 +++++----- doc/about.ru.texi | 5 +++-- doc/about.texi | 17 +++++++++-------- doc/aria2-downloaded.sh | 23 +++++++++++++++++++++++ doc/call.texi | 2 +- doc/cfg.texi | 44 +++++++++++++++++++++++++++++++------------- doc/chunked.texi | 10 ++++++++++ doc/cmds.texi | 70 +++++++++++++++++++++++++++++++++++++++++------------ doc/comparison.ru.texi | 2 +- doc/comparison.texi | 2 +- doc/download.texi | 4 ++++ doc/index.texi | 2 +- doc/install.texi | 2 +- doc/integration.texi | 71 ++++++++++++++++++++++++++++++++++++++--------------- doc/news.ru.texi | 47 ++++++++++++++++++++++++++++++++++++++++++++++- doc/news.texi | 44 ++++++++++++++++++++++++++++++++++++++++++++ doc/niceness.texi | 2 +- doc/pkt.texi | 24 +++++++++++++++++------- doc/usecases.ru.texi | 6 +++--- doc/usecases.texi | 6 +++--- doc/warcer.sh | 24 ++++++++++++++++++++++++ doc/wgeter.sh | 10 ++++++++++ doc/workflow.texi | 6 +++--- makedist.sh | 21 +++++++++++---------- ports/nncp/Makefile | 37 ++++++++----------------------------- ports/nncp/files/nncp.newsyslog.conf.sample.in => ports/nncp/files/nncp.newsyslog.conf.sample | 0 ports/nncp/files/pkg-message.in | 2 +- ports/nncp/pkg-descr | 13 +++++++------ ports/nncp/pkg-plist | 19 +++++++++++++++++++ src/cypherpunks.ru/nncp/call.go | 2 +- src/cypherpunks.ru/nncp/cfg.go | 20 ++++++++++---------- src/cypherpunks.ru/nncp/check.go | 2 +- src/cypherpunks.ru/nncp/chunked.go | 2 +- src/cypherpunks.ru/nncp/cmd/nncp-bundle/main.go | 4 ++-- src/cypherpunks.ru/nncp/cmd/nncp-call/main.go | 4 ++-- src/cypherpunks.ru/nncp/cmd/nncp-caller/main.go | 4 ++-- src/cypherpunks.ru/nncp/cmd/nncp-cfgenc/main.go | 4 ++-- src/cypherpunks.ru/nncp/cmd/nncp-cfgmin/main.go | 4 ++-- src/cypherpunks.ru/nncp/cmd/nncp-cfgnew/main.go | 6 ++++-- src/cypherpunks.ru/nncp/cmd/nncp-check/main.go | 4 ++-- src/cypherpunks.ru/nncp/cmd/nncp-daemon/main.go | 4 ++-- src/cypherpunks.ru/nncp/cmd/nncp-exec/main.go | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/cypherpunks.ru/nncp/cmd/nncp-file/main.go | 62 +++++++++++++++++++++++++++++++++++++++-------------- src/cypherpunks.ru/nncp/cmd/nncp-freq/main.go | 41 ++++++++++++++++++++++++++++++----------- src/cypherpunks.ru/nncp/cmd/nncp-log/main.go | 4 ++-- src/cypherpunks.ru/nncp/cmd/nncp-mail/main.go | 99 ----------------------------------------------------- src/cypherpunks.ru/nncp/cmd/nncp-pkt/main.go | 22 ++++++++++++++++------ src/cypherpunks.ru/nncp/cmd/nncp-reass/main.go | 4 ++-- src/cypherpunks.ru/nncp/cmd/nncp-rm/main.go | 4 ++-- src/cypherpunks.ru/nncp/cmd/nncp-stat/main.go | 4 ++-- src/cypherpunks.ru/nncp/cmd/nncp-toss/main.go | 19 ++++++++++++++++--- src/cypherpunks.ru/nncp/cmd/nncp-xfer/main.go | 4 ++-- src/cypherpunks.ru/nncp/ctx.go | 2 +- src/cypherpunks.ru/nncp/eblob.go | 2 +- src/cypherpunks.ru/nncp/humanizer.go | 14 +++++++------- src/cypherpunks.ru/nncp/jobs.go | 2 +- src/cypherpunks.ru/nncp/lockdir.go | 2 +- src/cypherpunks.ru/nncp/log.go | 2 +- src/cypherpunks.ru/nncp/nncp.go | 2 +- src/cypherpunks.ru/nncp/node.go | 9 ++++++--- src/cypherpunks.ru/nncp/pkt.go | 21 +++++++++++---------- src/cypherpunks.ru/nncp/pkt_test.go | 6 +++--- src/cypherpunks.ru/nncp/sp.go | 27 +++++++++++++++++++++------ src/cypherpunks.ru/nncp/tmp.go | 2 +- src/cypherpunks.ru/nncp/toss.go | 64 +++++++++++++++++++++++++++++++++++------------------ src/cypherpunks.ru/nncp/toss_test.go | 63 +++++++++++++++++++++++++++++++++-------------------- src/cypherpunks.ru/nncp/tx.go | 211 +++++++++++++++++++++++++---------------------------- src/cypherpunks.ru/nncp/tx_test.go | 11 +++++++---- diff --git a/README b/README index 9549f8ef84eb836c6245fdbad9ba0efaa6b6a2e64e0ad8d8370fa540e3b4c11c..946dc2ff08c5cff3582d560152b31dcd85f9122ac21b67c99fea942cd4179311 100644 --- a/README +++ b/README @@ -1,13 +1,14 @@ NNCP (Node to Node copy) is a collection of utilities simplifying -secure store-and-forward files and mail exchanging. +secure store-and-forward files, mail and commands exchanging. This utilities are intended to help build up small size (dozens of -nodes) ad-hoc friend-to-friend (F2F) statically routed darknet networks -for fire-and-forget secure reliable files, file requests and Internet -mail transmission. All packets are integrity checked, end-to-end -encrypted (E2EE), explicitly authenticated by known participants public -keys. Onion encryption is applied to relayed packets. Each node acts -both as a client and server, can use push and poll behaviour model. +nodes) ad-hoc friend-to-friend (F2F) statically routed darknet +delay-tolerant networks for fire-and-forget secure reliable files, file +requests, Internet mail and commands transmission. All packets are +integrity checked, end-to-end encrypted (E2EE), explicitly authenticated +by known participants public keys. Onion encryption is applied to +relayed packets. Each node acts both as a client and server, can use +push and poll behaviour model. Out-of-box offline sneakernet/floppynet, dead drops, sequential and append-only CD-ROM/tape storages, air-gapped computers support. But diff --git a/README.RU b/README.RU index dbac4f4b423dae9ed8258a134e4cddead590348edbb51d1225675659d2d57325..73e844ba5b53dd4b5a4c830b4336a3639a69f9cf656f631975b6eb2d3f0bd4ba 100644 --- a/README.RU +++ b/README.RU @@ -1,10 +1,10 @@ NNCP (Node to Node copy) это набор утилит упрощающий безопасный обмен файлами и почтой в режиме сохранить-и-переслать. -Эти утилиты предназначены помочь с построением одноранговых сетей -небольшого размера (дюжины узлов), в режиме друг-к-другу (F2F) со -статической маршрутизацией для безопасной надёжной передачи файлов, -запросов на передачу файлов и Интернет почты по принципу +Эти утилиты предназначены помочь с построением одноранговых устойчивых к +разрывам сетей небольшого размера (дюжины узлов), в режиме друг-к-другу +(F2F) со статической маршрутизацией для безопасной надёжной передачи +файлов, запросов на передачу файлов, Интернет почты и команд по принципу выстрелил-и-забыл. Все пакеты проверяются на целостность, шифруются по принципу точка-точка (E2EE), аутентифицируются известными публичными ключами участников. Луковичное (onion) шифрование применяется ко всем diff --git a/VERSION b/VERSION index 2c858ab6c54dddd5d5d3f908545751c6fc591a0d5740edad717a56e61e03b2b7..a233cfcdb584133924ee353c0e37f95386fd922c8fe14b78fef107e3d103bae5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0 +3.0 diff --git a/common.mk b/common.mk index 666e78e9dce735d045105e86f9b524a8e49157d896f17f1a95e7142a3d623b98..d78edabb252d4afc25db08db07b4c3cbcddc8e955f1141ad5daaf420e34a1055 100644 --- a/common.mk +++ b/common.mk @@ -25,10 +25,10 @@ nncp-cfgmin \ nncp-cfgnew \ nncp-check \ nncp-daemon \ + nncp-exec \ nncp-file \ nncp-freq \ nncp-log \ - nncp-mail \ nncp-pkt \ nncp-reass \ nncp-rm \ @@ -61,6 +61,9 @@ GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-check nncp-daemon: GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-daemon + +nncp-exec: + GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-exec nncp-file: GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-file @@ -71,9 +74,6 @@ nncp-log: GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-log -nncp-mail: - GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-mail - nncp-pkt: GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-pkt @@ -93,7 +93,7 @@ nncp-xfer: GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-xfer test: - GOPATH=$(GOPATH) go test cypherpunks.ru/nncp/... + GOPATH=$(GOPATH) go test -failfast cypherpunks.ru/nncp/... clean: rm -f $(ALL) diff --git a/doc/about.ru.texi b/doc/about.ru.texi index 018bcedf7f2fcb2fc9c2af6e11bcd8b47156e852f897b06715b3d1dc880689c8..9dad003ce1654232bc09a6544db0edbff26fda7e14c135a6f5bd4f1d78a03591 100644 --- a/doc/about.ru.texi +++ b/doc/about.ru.texi @@ -4,11 +4,12 @@ NNCP (Node to Node copy) это набор утилит упрощающий безопасный обмен файлами и почтой в режиме сохранить-и-переслать. -Эти утилиты предназначены помочь с построением однораговых сетей +Эти утилиты предназначены помочь с построением однораговых +@url{https://ru.wikipedia.org/wiki/DTN, устойчивых к разрывам} сетей небольшого размера (дюжины узлов), в режиме @url{https://ru.wikipedia.org/wiki/Friend-to-friend, друг-к-другу} (F2F) со статической маршрутизацией для безопасной надёжной передачи файлов, -запросов на передачу файлов и Интернет почты по принципу +запросов на передачу файлов, Интернет почты и команд по принципу выстрелил-и-забыл. Все пакеты проверяются на целостность, шифруются по принципу @url{https://en.wikipedia.org/wiki/End-to-end_encryption, точка-точка}, аутентифицируются известными публичными ключами diff --git a/doc/about.texi b/doc/about.texi index 331f4328b117041700811a9958d28e04df96a9381f7d6a032511d90c2631075f..cfb521d21f64d237e671a8ce99cf6fb02564a6efce368247a21c01fd6f6608f6 100644 --- a/doc/about.texi +++ b/doc/about.texi @@ -6,14 +6,15 @@ This utilities are intended to help build up small size (dozens of nodes) ad-hoc @url{https://en.wikipedia.org/wiki/Friend-to-friend, friend-to-friend} (F2F) statically routed -@url{https://en.wikipedia.org/wiki/Darknet, darknet} networks for -fire-and-forget secure reliable files, file requests and Internet mail -transmission. All packets are integrity checked, -@url{https://en.wikipedia.org/wiki/End-to-end_encryption, end-to-end} -encrypted, explicitly authenticated by known participants public keys. -@url{https://en.wikipedia.org/wiki/Onion_routing, Onion encryption} is -applied to relayed packets. Each node acts both as a client and server, -can use push and poll behaviour model. +@url{https://en.wikipedia.org/wiki/Darknet, darknet} +@url{https://en.wikipedia.org/wiki/Delay-tolerant_networking, delay-tolerant} +networks for fire-and-forget secure reliable files, file requests, +Internet mail and commands transmission. All packets are integrity +checked, @url{https://en.wikipedia.org/wiki/End-to-end_encryption, +end-to-end} encrypted, explicitly authenticated by known participants +public keys. @url{https://en.wikipedia.org/wiki/Onion_routing, Onion +encryption} is applied to relayed packets. Each node acts both as a +client and server, can use push and poll behaviour model. Out-of-box offline @url{https://en.wikipedia.org/wiki/Sneakernet, sneakernet/floppynet}, @url{https://en.wikipedia.org/wiki/Dead_drop, diff --git a/doc/aria2-downloaded.sh b/doc/aria2-downloaded.sh new file mode 100755 index 0000000000000000000000000000000000000000..4254042809676df4d31b45d21a53296722920a4d9a9cf55c2bc5b1ced8556094 --- /dev/null +++ b/doc/aria2-downloaded.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +TORRENTS_DIR=/storage/torrents +REMOTE=stargrave.org + +if [ "$2" -eq 0 ]; then + # downloaded .torrent/.metalink + exit 0 +fi + +if [ "$2" -gt 1 ]; then + cd "$3" + while [ "$(pwd)" != $TORRENTS_DIR ]; do + name="$(basename "$(pwd)")" + cd .. + done + tartmp=$(mktemp ./finished.XXXXXX) + tar cf $tartmp "$name" + nncp-file $tartmp $REMOTE:"$name".tar + rm $tartmp +else + nncp-file "$3" $REMOTE: +fi diff --git a/doc/call.texi b/doc/call.texi index de2f665fc73b45bc2c5083b9147a5b688bc594ee62ed9ddacfd8d439084bbae0..0dd2f7f0ff1ee9c6e49efd441e1df664251dcf82de1b3e428e1c1a909c8c090a 100644 --- a/doc/call.texi +++ b/doc/call.texi @@ -151,7 +151,7 @@ and a wildcard year field is appended, that is, @verb{|* * * * Mon|} internally become @verb{|0 * * * * Mon *|}. @item Domain for day-of-week field is [0-7] instead of [0-6], 7 being Sunday -(like 0). This to comply with @url{http://linux.die.net/man/5/crontab}. +(like 0). This to comply with @url{https://linux.die.net/man/5/crontab}. @end itemize @item nice diff --git a/doc/cfg.texi b/doc/cfg.texi index acde3bcb2ea8c781594e678b0816495eee92894898652c8dd60245ffc8a2613a..d9584f226aa352fe19559b6001c09fd305d028d482e4118d84d919ee18b76a03 100644 --- a/doc/cfg.texi +++ b/doc/cfg.texi @@ -27,13 +27,15 @@ id: TIJQL...2NGIA exchpub: CYVGQ...PSEWQ signpub: 2NMVC...CMH5Q noisepub: KIBKK...ESM7Q - sendmail: [/usr/sbin/sendmail] + exec: + sendmail: [/usr/sbin/sendmail] alice: id: XJZBK...65IJQ exchpub: MJACJ...FAI6A signpub: T4AFC...N2FRQ noisepub: UBM5K...VI42A - sendmail: ["/bin/sh", "-c", "false"] + exec: + flag: ["/usr/bin/touch", "-t"] incoming: /home/alice/incoming onlinedeadline: 1800 maxonlinetime: 3600 @@ -47,7 +49,10 @@ bob: id: 2IZNP...UYGYA exchpub: WFLMZ...B7NHA signpub: GTGXG...IE3OA - sendmail: [/usr/sbin/sendmail] + exec: + sendmail: [/usr/sbin/sendmail] + warcer: [/path/to/warcer.sh] + wgeter: [/path/to/wgeter.sh] freq: /home/bob/pub freqchunked: 1024 freqminsize: 2048 @@ -62,9 +67,9 @@ @anchor{CfgNotify} @strong{notify} section contains notification settings for successfully tossed file and freq packets. Corresponding @strong{from} and @strong{to} fields will be substituted in notification email message. -@emph{neigh/self/sendmail} will be used as a local mailer. You can omit -either of those two @emph{from}/@emph{to} sections to omit corresponding -notifications, or the whole section at once. +@emph{neigh/self/exec/sendmail} will be used as a local mailer. You can +omit either of those two @emph{from}/@emph{to} sections to omit +corresponding notifications, or the whole section at once. @strong{self} section contains our node's private keypairs. @strong{exch*} and @strong{sign*} are used during @ref{Encrypted, @@ -85,13 +90,25 @@ @item noisepub If present, then node can be online called using @ref{Sync, synchronization protocol}. Contains authentication public key. -@anchor{CfgSendmail} -@item sendmail -An array containing path to executable and its command line arguments -that is called for mail sending. If it is empty, then no mail processing -will be performed from that node. Sendmail command -@command{["/bin/foo", "bar"]} called the following way: -@command{NNCP_SENDER=NODEID /bin/foo bar RCPT1 RCPT2 ... < MSG}. +@anchor{CfgExec} +@item exec +Dictionary consisting of handles and corresponding command line +arguments. In example above there are @command{sendmail} handles, +@command{warcer}, @command{wgeter} and @command{flag} one. Remote node +can queue some handle execution with providing additional command line +arguments and the body fed to command's stdin. + +@verb{|sendmail: ["/usr/sbin/sendmail", "-t"]|} handle, when called by +@verb{|echo hello world | nncp-exec OURNODE sendmail ARG0 ARG1 ARG2|} +command, will execute: + +@verbatim +echo hello world | + NNCP_SELF=OURNODE \ + NNCP_SENDER=REMOTE \ + NNCP_NICE=64 \ + /usr/sbin/sendmail -t ARG0 ARG1 ARG2 +@end verbatim @anchor{CfgIncoming} @item incoming @@ -111,6 +128,7 @@ @item freqminsize If set, then apply @ref{OptMinSize, -minsize} option during file transmission. +@anchor{CfgVia} @item via An array of node identifiers that will be used as a relay to that node. For example @verb{|[foo,bar]|} means that packet can reach current node diff --git a/doc/chunked.texi b/doc/chunked.texi index e04daeaa3abcb8c55625a66efd552bfef8033f61d0b4a50023de26f87dc91412..ef31db2af873a86967b29d84b18fcdc05c822c0b36cb3d15af49a5f3dc140619 100644 --- a/doc/chunked.texi +++ b/doc/chunked.texi @@ -43,3 +43,13 @@ @item Checksums @tab variable length array of 32 byte fixed length opaque data @tab BLAKE2b-256 checksum of each chunk @end multitable + +@anchor{ChunkedZFS} +It is strongly advisable to reassemble incoming chunked files on +@url{https://en.wikipedia.org/wiki/ZFS, ZFS} dataset with deduplication +feature enabled. It could be more CPU and memory hungry, but will save +your disk's IO and free space from pollution (although temporary). But +pay attention that you chunks must be either equal to, or divisible by +dataset's @option{recordsize} value for deduplication workability. +Default ZFS's @option{recordsize} is 128 KiBs, so it is advisable to +chunk your files on 128, 256, 384, 512, etc KiB blocks. diff --git a/doc/cmds.texi b/doc/cmds.texi index 89a796d3d3c57ef21dd2f14cb6e70d9350538ced5f485aa00306e8eee9cb07ca..2d3b9d17af4d0c179120b8bdb630b3d8bfb3a4eeb9659b05c8dbb88ed64c9f16 100644 --- a/doc/cmds.texi +++ b/doc/cmds.texi @@ -18,8 +18,15 @@ will be 4 KiB (containing file itself and some junk). @item -nice Set desired outgoing packet @ref{Niceness, niceness level}. 1-255 values are allowed. +@item -replynice + Set desired reply packet @ref{Niceness, niceness level}. Only freq + and exec packets look at that niceness level. 1-255 values are + allowed. @item -node Process only single specified node. +@item -via + Override @ref{CfgVia, via} configuration option for destination node. + Specified nodes must be separated with comma: @verb{|NODE1,NODE2|}. @item -spool Override path to spool directory. May be specified by @env{NNCPSPOOL} environment variable. @@ -230,6 +237,39 @@ @option{-maxconn} option specifies how many simultaneous clients daemon can handle. @option{-bind} option specifies @option{addr:port} it must bind to and listen. +@node nncp-exec +@section nncp-exec + +@verbatim +% nncp-exec [options] NODE HANDLE [ARG0 ARG1 ...] +@end verbatim + +Send execution command to @option{NODE} for specified @option{HANDLE}. +Body is read from stdin and compressed. After receiving, remote side +will execute specified @ref{CfgExec, handle} command with @option{ARG*} +appended and decompressed body fed to command's stdin. + +For example, if remote side has following configuration file for your +node: + +@verbatim +exec: + sendmail: [/usr/sbin/sendmail, "-t"] + appender: ["/bin/sh", "-c", "cat >> /append"] +@end verbatim + +then executing @verb{|echo My message | nncp-exec -replynice 123 REMOTE +sendmail root@localhost|} will lead to executing of: + +@verbatim +echo My message | + NNCP_SELF=REMOTE \ + NNCP_SENDER=OurNodeId \ + NNCP_NICE=123 \ + /usr/sbin/sendmail -t root@localhost +@end verbatim + + @node nncp-file @section nncp-file @@ -260,7 +300,8 @@ If @option{-chunked} is specified, then source file will be split @ref{Chunked, on chunks}. @option{INT} is the desired chunk size in KiBs. This mode is more CPU hungry. Pay attention that chunk is saved in spool directory immediately and it is not deleted if any error occurs. -@option{-minsize} option is applied per each chunk. +@option{-minsize} option is applied per each chunk. Do not forget about +@ref{ChunkedZFS, possible} ZFS deduplication issues. If @ref{CfgNotify, notification} is enabled on the remote side for file transmissions, then it will sent simple letter after successful @@ -291,19 +332,6 @@ @end verbatim Parse @ref{Log, log} file and print out its records in human-readable form. -@node nncp-mail -@section nncp-mail - -@verbatim -% nncp-mail [options] NODE USER ... -@end verbatim - -Send mail, that is read from stdin, to @option{NODE} and specified -@option{USER}s. Mail message will be compressed. After receiving, remote -side will execute specified @ref{CfgSendmail, sendmail} command with -@option{USER}s appended as a command line argument and feed decompressed -mail body to that command's stdin. - @node nncp-pkt @section nncp-pkt @@ -399,6 +427,8 @@ 2: f4f883975a663f2252328707a30e71b2678f933b2f3103db8475b03293e4316e 3: 0e9e229501bf0ca42d4aa07393d19406d40b179f3922a3986ef12b41019b45a3 @end verbatim + Do not forget about @ref{ChunkedZFS, possible} ZFS deduplication issues. + @node nncp-rm @section nncp-rm @@ -445,7 +475,14 @@ @node nncp-toss @section nncp-toss @verbatim -% nncp-toss [options] [-dryrun] [-cycle INT] [-seen] +% nncp-toss [options] + [-dryrun] + [-cycle INT] + [-seen] + [-nofile] + [-nofreq] + [-nomail] + [-notrns] @end verbatim Perform "tossing" operation on all inbound packets. This is the tool @@ -464,6 +501,9 @@ @option{-seen} option creates empty @file{XXX.seen} file after successful tossing of @file{XXX} packet. @ref{nncp-xfer} and @ref{nncp-bundle} commands skip inbound packets that has been already seen, processed and tossed. This is helpful to defeat duplicates. + +@option{-nofile}, @option{-nofreq}, @option{-nomail}, @option{-notrns} +options allow to disable any kind of packet types processing. @node nncp-xfer @section nncp-xfer diff --git a/doc/comparison.ru.texi b/doc/comparison.ru.texi index 48a06e7d1be07cf9f1730d962d0d88037207e844c93c1ae6d9177f1fa2456af4..6bf5c7be411776a185d94cf6e88570ff7868fd886e9b66ec303e2d30c0103ecd 100644 --- a/doc/comparison.ru.texi +++ b/doc/comparison.ru.texi @@ -15,7 +15,7 @@ @item Передача почты @tab @strong{Да} @tab @strong{Да} @tab @strong{Да} @tab @strong{Да} @item Передача новостей @tab @strong{Да} @tab @strong{Да} @tab Нет @tab Нет @item Передача файлов @tab @strong{Да} @tab @strong{Да} @tab @strong{Да} @tab Нет @item Разбиение файлов на части @tab Нет @tab @strong{Да} @tab @strong{Да} @tab Нет -@item Удалённое исполнение команд @tab @strong{Да} @tab Нет @tab Нет @tab Нет +@item Удалённое исполнение команд @tab @strong{Да} @tab Нет @tab @strong{Да} @tab Нет @item Возобновляемое скачивание @tab @strong{Да} @tab @strong{Да} @tab @strong{Да} @tab Нет @item Приоритезация пакетов @tab @strong{Да} @tab Нет @tab @strong{Да} @tab Нет @item Сжатие почты @tab Нет @tab @strong{Да} @tab @strong{Да} @tab Нет diff --git a/doc/comparison.texi b/doc/comparison.texi index 6f9a154039ee658af5696af8b5c37a68c312c6233486c7d19df93d73249c802f..d802ee527a6be457d20b2d6b1c91aa8b1558241c79850669a3b19f8326e5861d 100644 --- a/doc/comparison.texi +++ b/doc/comparison.texi @@ -14,7 +14,7 @@ @item Mail transmission @tab @strong{Yes} @tab @strong{Yes} @tab @strong{Yes} @tab @strong{Yes} @item News transmission @tab @strong{Yes} @tab @strong{Yes} @tab No @tab No @item File transmission @tab @strong{Yes} @tab @strong{Yes} @tab @strong{Yes} @tab No @item Chunked files @tab No @tab @strong{Yes} @tab @strong{Yes} @tab No -@item Remote command execution @tab @strong{Yes} @tab No @tab No @tab No +@item Remote command execution @tab @strong{Yes} @tab No @tab @strong{Yes} @tab No @item Resumable downloads @tab @strong{Yes} @tab @strong{Yes} @tab @strong{Yes} @tab No @item Packets prioritizing @tab @strong{Yes} @tab No @tab @strong{Yes} @tab No @item Mail compression @tab No @tab @strong{Yes} @tab @strong{Yes} @tab No diff --git a/doc/download.texi b/doc/download.texi index eefff755b9df5bd979e29f57164ae4ef0f1e6c052f713a3645629aa9e968c5f2..cc2c0c70ccfc3e73e90fcd12011f427209cdc818ccfad0a833739137c5edec88 100644 --- a/doc/download.texi +++ b/doc/download.texi @@ -23,6 +23,10 @@ @multitable {XXXXX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @headitem Version @tab Size @tab Tarball @tab SHA256 checksum +@item @ref{Release 2.0, 2.0} @tab 986 KiB +@tab @url{download/nncp-2.0.tar.xz, link} @url{download/nncp-2.0.tar.xz.sig, sign} +@tab @code{BEF31B13 FB25381E A511FB77 067798AB 27409238 BDF5600F E2EADB29 E5E78996} + @item @ref{Release 1.0, 1.0} @tab 987 KiB @tab @url{download/nncp-1.0.tar.xz, link} @url{download/nncp-1.0.tar.xz.sig, sign} @tab @code{68BF7803 CD25F59A 56D9FD6C 695002B5 BFBAF591 8A6583F4 3139FC28 CA1AB4AF} diff --git a/doc/index.texi b/doc/index.texi index 41eff81f08d5700f513ff92f83736205e4c8e6fa038afad50612040653c2d4d7..2d578a2170b92d35b57ea20e0f306112b4fc765a5bfd2a450ad647a7eebde362 100644 --- a/doc/index.texi +++ b/doc/index.texi @@ -6,7 +6,7 @@ @copying This manual is for NNCP (Node to Node copy) -- collection of utilities simplifying secure store-and-forward files and mail exchanging. -Copyright @copyright{} 2016-2017 @email{stargrave@@stargrave.org, Sergey Matveev} +Copyright @copyright{} 2016-2018 @email{stargrave@@stargrave.org, Sergey Matveev} @quotation Permission is granted to copy, distribute and/or modify this document diff --git a/doc/install.texi b/doc/install.texi index 7aeb0f954d5b8e2c9e716d56c7e7655c313f0727c8b41f194701f035662eaa2c..c9e6e643f73fdc09a8bd9c7ecf8e5b9b3476b447aa4a77c02c5bd45d06af85b8 100644 --- a/doc/install.texi +++ b/doc/install.texi @@ -5,7 +5,7 @@ Possibly NNCP package already exists for your distribution: @itemize @item @url{https://github.com/voidlinux/void-packages/blob/master/srcpkgs/nncp/template, Void Linux} -@item @url{https://git.cypherpunks.ru/cgit.cgi/nncp.git/tree/ports/nncp, FreeBSD currently uncommitted port} +@item @url{https://www.freshports.org/net/nncp/, FreeBSD ports} @end itemize NNCP should run on any POSIX-compatible operating system. diff --git a/doc/integration.texi b/doc/integration.texi index 1223b606610932f02c6d24e80726a1fc6ed8747940aa67c5613b7e64a154b8b6..8b5bcb4affce756d7f35af8ac6291f9b0cd5e8a58bc1c9e3166a54bd18941226 100644 --- a/doc/integration.texi +++ b/doc/integration.texi @@ -9,6 +9,7 @@ * Postfix:: * Web feeds: Feeds. * Web pages: WARCs. * BitTorrent and huge files: BitTorrent. +* Downloading service: DownloadService. * Git:: * Multimedia streaming: Multimedia. @end menu @@ -27,7 +28,7 @@ mail to a LAN that is connected via NNCP. @itemize -@item You need an @ref{nncp-mail} program that extracts the sender +@item You need an @ref{nncp-exec} program that extracts the sender address from mail that arrives via NNCP, and that feeds the mail into the Postfix @command{sendmail} command. @@ -36,13 +37,13 @@ delivery via NNCP: @verbatim /usr/local/etc/postfix/master.cf: nncp unix - n n - - pipe - flags=F user=nncp argv=nncp-mail -quiet $nexthop $recipient + flags=F user=nncp argv=nncp-exec -quiet $nexthop sendmail $recipient @end verbatim -This runs the @command{nncp-mail} command to place outgoing mail into +This runs the @command{nncp-exec} command to place outgoing mail into the NNCP queue after replacing @var{$nexthop} by the the receiving NNCP node and after replacing @var{$recipient} by the recipients. The -@command{pipe(8)} delivery agent executes the @command{nncp-mail} +@command{pipe(8)} delivery agent executes the @command{nncp-exec} command without assistance from the shell, so there are no problems with shell meta characters in command-line parameters. @@ -89,7 +90,7 @@ Here is how to relay mail from a LAN via NNCP to the Internet. @itemize -@item You need an @ref{nncp-mail} program that extracts the sender +@item You need an @ref{nncp-exec} program that extracts the sender address from mail that arrives via NNCP, and that feeds the mail into the Postfix @command{sendmail} command. @@ -115,13 +116,13 @@ @verbatim /usr/local/etc/postfix/master.cf: nncp unix - n n - - pipe - flags=F user=nncp argv=nncp-mail -quiet $nexthop $recipient + flags=F user=nncp argv=nncp-exec -quiet $nexthop sendmail $recipient @end verbatim -This runs the @command{nncp-mail} command to place outgoing mail into +This runs the @command{nncp-exec} command to place outgoing mail into the NNCP queue. It substitutes the hostname (@emph{nncp-gateway}, or whatever you specified) and the recipients before executing the command. -The @command{nncp-mail} command is executed without assistance from the +The @command{nncp-exec} command is executed without assistance from the shell, so there are no problems with shell meta characters. @item Execute the command @command{postfix reload} to make the changes @@ -246,17 +247,9 @@ URIs, Web-seeding, selective downloads, LPD. @command{aria2} can accelerate HTTP*/*FTP downloads by segmented multiple parallel connections. -You can queue you files after they are completely downloaded: -@verbatim -% cat send-downloaded.sh -#!/bin/sh -nncp-file -chunked $(( 1024 * 100 )) "$3" remote.node - -% aria2c \ - --on-download-complete send-downloaded.sh \ - http://example.org/file.iso \ - http://example.org/file.iso.asc -@end verbatim +You can queue you files after they are completely downloaded. +@file{aria2-downloaded.sh} contents: +@verbatiminclude aria2-downloaded.sh Also you can prepare @url{http://aria2.github.io/manual/en/html/aria2c.html#files, input file} @@ -268,11 +261,49 @@ out=nncp.txz http://www.nncpgo.org/download/nncp-0.11.tar.xz.sig out=nncp.txz.sig % aria2c \ - --on-download-complete send-downloaded.sh \ + --on-download-complete aria2-downloaded.sh \ --input-file jobs @end verbatim and all that downloaded (@file{nncp.txz}, @file{nncp.txz.sig}) files will be sent to @file{remote.node} when finished. + +@node DownloadService +@section Downloading service + +Previous sections tell about manual downloading and sending results to +remote node. But one wish to remotely initiate downloading. That can be +easily solved with @ref{CfgExec, exec} handles. + +@verbatim +exec: + warcer: ["/bin/sh", "/path/to/warcer.sh"] + wgeter: ["/bin/sh", "/path/to/wgeter.sh"] + aria2c: [ + "/usr/local/bin/aria2c", + "--on-download-complete", "aria2-downloaded.sh", + "--on-bt-download-complete", "aria2-downloaded.sh" + ] +@end verbatim + +@file{warcer.sh} contents: +@verbatiminclude warcer.sh + +@file{wgeter.sh} contents: +@verbatiminclude wgeter.sh + +Now you can queue that node to send you some website's page, file or +BitTorrents: + +@verbatim +% echo http://www.nncpgo.org/Postfix.html | + nncp-exec remote.node warcer postfix-whole-page +% echo http://www.nncpgo.org/Postfix.html | + nncp-exec remote.node wgeter postfix-html-page +% echo \ + http://www.nncpgo.org/download/nncp-0.11.tar.xz + http://www.nncpgo.org/download/nncp-0.11.tar.xz.sig | + nncp-exec remote.node aria2c +@end verbatim @node Git @section Integration with Git diff --git a/doc/news.ru.texi b/doc/news.ru.texi index 5e4c9f94856602b89715cc7b44d9149ff77b64c5a48482de90247f25f134d5d3..372f15d2e76d3d1cd3da7443247efdb294828ee7cc7d771e2110b281ac6a787b 100644 --- a/doc/news.ru.texi +++ b/doc/news.ru.texi @@ -1,6 +1,51 @@ @node Новости @section Новости +@node Релиз 3.0 +@subsection Релиз 3.0 +@itemize +@item +@strong{Несовместимое} изменение формата простых пакетов. Работа со +старыми версиями не поддерживается. +@item +Добавлена возможность удалённого исполнения команд, путём +конфигурирования @option{exec} опции конфигурационного файла и +использования команды @command{nncp-exec}: + @itemize + @item + Команда @command{nncp-mail} заменена более гибкой и широкой + @command{nncp-exec}. Вместо вызова @verb{|nncp-mail NODE RECIPIENT|} + нужно использовать @verb{|nncp-exec NODE sendmail RECIPIENT|}. + @item + @option{sendmail} опция конфигурационного файла заменена на более гибкую + @option{exec}. @verb{|sendmail: [...]|} нужно заменить на @verb{|exec: + sendmail: [...]|}. + @end itemize +@item +Возможность переопределить @option{via} опцию конфигурации для целевого +узла через @option{-via} опцию командной строки для следующих команд: +@command{nncp-file}, @command{nncp-freq}, @command{nncp-exec}. +@item +Chunked файлы, меньшего размера чем указанный chunk, отправляются просто +в виде одного файла. +@item +Exec команды вызываются с дополнительными переменными окружения +@env{NNCP_NICE} и @env{NNCP_SELF}. +@item +Отправляемые файлы в ответ на запрос имеют приоритет указанный в запросе. +Указать их желаемый приоритет во время вызова @command{nncp-freq} можно +аргументом @option{-replynice}. +@item +Команде @command{nncp-toss} можно сказать не обрабатывать определённые +типы пакетов, за счёт опций @option{-nofile}, @option{-nofreq}, +@option{-noexec}, @option{-notrns}. +@item +По-умолчанию @command{nncp-file} команда для +@option{-minsize}/@option{-chunked} опций использует +@option{FreqMinSize}/@option{FreqChunked} из конфигурационного файла. +Это можно отключить указав нулевое значение. +@end itemize + @node Релиз 2.0 @subsection Релиз 2.0 @itemize @@ -103,7 +148,7 @@ Опция @option{-force} команды @command{nncp-xfer} переименована в @option{-mkdir} для ясности. @item -Опция @option{-minsize} задётся в KiB, а не байтах, для удобства. +Опция @option{-minsize} задаётся в KiB, а не байтах, для удобства. @item Команда @command{nncp-newcfg} переименована в @command{nncp-cfgnew}, diff --git a/doc/news.texi b/doc/news.texi index b17253862b959309278491942488721e1a7ddd9efe1ad9665120cfb6016a4797..140f5b3fece0549f2240fe70daa9cc90f7f16daf60f56ba4270feb7787aefb5c 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -3,6 +3,50 @@ @unnumbered News See also this page @ref{Новости, on russian}. +@node Release 3.0 +@section Release 3.0 +@itemize +@item +@strong{Incompatible} plain packet format changes. Older versions are +not supported. +@item +Ability to queue remote command execution, by configuring @option{exec} +option in configuration file and using @command{nncp-exec} command: + @itemize + @item + @command{nncp-mail} command is replaced with more flexible + @command{nncp-exec}. Instead of @verb{|nncp-mail NODE RECIPIENT|} + you must use @verb{|nncp-exec NODE sendmail RECIPIENT|}. + @item + @option{sendmail} configuration file option is replaced with + @option{exec}. @verb{|sendmail: [...]|} must be replaced with + @verb{|exec: sendmail: [...]|}. + @end itemize +@item +Ability to override @option{via} configuration option for destination +node via @option{-via} command line option for following commands: +@command{nncp-file}, @command{nncp-freq}, @command{nncp-exec}. +@item +Chunked files, having size less than specified chunk size, will be sent +as an ordinary single file. +@item +Exec commands are invoked with additional @env{NNCP_NICE} and +@env{NNCP_SELF} environment variables. +@item +Files, that are sent as a reply to freq, have niceness level taken from +the freq packet. You can set desired niceness during @command{nncp-freq} +invocation using @option{-replynice} option. +@item +@command{nncp-toss} command can ignore specified packet types during +processing: @option{-nofile}, @option{-nofreq}, @option{-noexec}, +@option{-notrns}. +@item +@command{nncp-file} command uses +@option{FreqMinSize}/@option{FreqChunked} conifiguration file options +for @option{-minsize}/@option{-chunked} by default. You can turn this +off by specifying zero value. +@end itemize + @node Release 2.0 @section Release 2.0 @itemize diff --git a/doc/niceness.texi b/doc/niceness.texi index d781e943f6eb72ef31acf15b67da16281b0d15226a28be2855237e804ad5f2ea..ac7b54718e14ddcf91a70f70ab53caa45e0c768f5ee09c4fd13981252efeb7b9 100644 --- a/doc/niceness.texi +++ b/doc/niceness.texi @@ -10,6 +10,6 @@ Send big files with higher nicer level! That will guarantee you that higher priority packets, like mail messages, will pass first, even when lower priority packet was already been partly downloaded. -There are default niceness levels built-in for @ref{nncp-mail}, +There are default niceness levels built-in for @ref{nncp-exec}, @ref{nncp-file} and @ref{nncp-freq} commands. But pay attention that it can give information about underlying payload to the adversary! diff --git a/doc/pkt.texi b/doc/pkt.texi index c46331e31444c6cfde9d7d3e88b6588f147cacfe33f12828bc22855aedf5acc7..f269ab8634205703b90496932652fa652d7a2e5fb5d803465004c3d187977ccf 100644 --- a/doc/pkt.texi +++ b/doc/pkt.texi @@ -13,15 +13,15 @@ @node Plain @section Plain packet Plain packet contains either the whole file, or file request (freq), or -transition packet or email message. It is called "plain", because it +transition packet or exec message. It is called "plain", because it contains plaintext, but plain packets would never be stored on your hard drive. @verbatim HEADER -+-------------------------------+--...---+ -| MAGIC | TYPE | PATHLEN | PATH | PAYLOAD| -+-------------------------------+--...---+ ++--------------------------------------+--...---+ +| MAGIC | TYPE | NICE | PATHLEN | PATH | PAYLOAD| ++--------------------------------------+--...---+ @end verbatim @multitable @columnfractions 0.2 0.3 0.5 @@ -31,7 +31,10 @@ 8-byte, fixed length opaque data @tab @verb{|N N C P P 0x00 0x00 0x01|} @item Payload type @tab unsigned integer @tab - 0 (file), 1 (freq), 2 (mail), 3 (transition) + 0 (file), 1 (freq), 2 (exec), 3 (transition) +@item Niceness @tab + unsigned integer @tab + 1-255, preferred packet @ref{Niceness, niceness} level @item Path length @tab unsigned integer @tab actual length of @emph{path} field's payload @@ -40,7 +43,7 @@ 255 byte, fixed length opaque data @tab @itemize @item UTF-8 encoded destination path for file transfer @item UTF-8 encoded source path for file request - @item UTF-8 encoded, space separated, email recipients list + @item UTF-8 encoded, zero byte separated, exec's arguments @item Node's id the transition packet must be relayed on @end itemize @end multitable @@ -55,8 +58,15 @@ @itemize @item File contents @item Destination path for freq -@item @url{http://zlib.net/, zlib} compressed email +@item @url{http://zlib.net/, zlib} compressed exec body @item Whole encrypted packet we need to relay on +@end itemize + +Also depending on packet's type, niceness level means: + +@itemize +@item Preferable niceness level for files sent by freq +@item @env{NNCP_NICE} variable's value passed during @ref{CfgExec} invocation. @end itemize @node Encrypted diff --git a/doc/usecases.ru.texi b/doc/usecases.ru.texi index eeb1d687b7e4c7cf18ac8cecc73ea4790bcf681185fc192fae117f35c9dd664d..c4797772fad78185aa01545dfe5b64a056f6bf3b382e87903b7e3f69c752c8a3 100644 --- a/doc/usecases.ru.texi +++ b/doc/usecases.ru.texi @@ -35,7 +35,7 @@ @url{https://ru.wikipedia.org/wiki/KISS_(%D0%BF%D1%80%D0%B8%D0%BD%D1%86%D0%B8%D0%BF), KISS}! Просто скажите вашим обоим Postfix-ам (на сервере и ноутбуке) отправлять -сообщения через NNCP (@ref{nncp-mail}) на заданный узел. Это делается +сообщения через NNCP (@ref{nncp-exec}) на заданный узел. Это делается аналогично тому как с UUCP, и описано в @url{http://www.postfix.org/UUCP_README.html, документации Postfix}. @@ -49,7 +49,7 @@ @subsection Легковесная и быстрая замена POP3/IMAP4 @ref{nncp-daemon} может быть соединён с @ref{nncp-caller} длительное время -- он создаёт TCP соединение на многие часы. Когда SMTP сервер -получает письмо, то вызывает @ref{nncp-mail} для создания исходящего +получает письмо, то вызывает @ref{nncp-exec} для создания исходящего зашифрованного пакета. Демон ежесекундно проверяет исходящую директорию и сразу же посылает оповещение о недоставленных пакетах противоположной стороне, которая сразу же их может скачать. @@ -70,7 +70,7 @@ продолжение оборванного приёма и тяжёлые сообщения становится очень проблематично получить. Более того, каждый обрыв может приводить к отсылке данных с самого начала, что не всегда по карману. -Просто отправьте вашу @ref{nncp-mail, почту} и @ref{nncp-file, файлы} +Просто отправьте вашу @ref{nncp-exec, почту} и @ref{nncp-file, файлы} через NNCP. Вы сможете использовать или offline методы доставки -- читайте о них в следующем разделе, либо использовать поставляемый NNCP @ref{nncp-daemon, TCP демон}. diff --git a/doc/usecases.texi b/doc/usecases.texi index ddb2c3a75e61e606f63dc8facf33d0b66e8a1ed5e5623ef09abedde706085c2a..186240bc1de144d674b5670b801cc676294e5c8d7c6b8c7934b06c11e849809f 100644 --- a/doc/usecases.texi +++ b/doc/usecases.texi @@ -34,7 +34,7 @@ overcomplicated and bloated for the simple task. Not an option. @url{https://en.wikipedia.org/wiki/KISS_principle, KISS}! Just tell both of your Postfixes (on the server and notebook) to drop -email as a mail via NNCP (@ref{nncp-mail}) to specified node. This is +email as a mail via NNCP (@ref{nncp-exec}) to specified node. This is done similarly as with UUCP and as written in @url{http://www.postfix.org/UUCP_README.html, Postfix documentation}. @@ -48,7 +48,7 @@ @section Lightweight fast POP3/IMAP4 replacement @ref{nncp-daemon} can be connected with @ref{nncp-caller} for a long time -- it can create TCP connection that lasts for many hours. When -SMTP server receives mail, it will call @ref{nncp-mail} creating an +SMTP server receives mail, it will call @ref{nncp-exec} creating an outbound encrypted packet. Daemon checks outbound directory each second and immediately sends notification about undelivered packets to remote side, that also downloads it at once. @@ -68,7 +68,7 @@ download continuation. SMTP does not support resuming at all and heavy messages is problematic to retrieve. Moreover, each disconnect leads to the same data retransmission again, that can not be afforded sometimes. -Just send your @ref{nncp-mail, mail} and @ref{nncp-file, files} through +Just send your @ref{nncp-exec, mail} and @ref{nncp-file, files} through NNCP. You can use either offline delivery methods -- read about them in the next section, or you can use included NNCP @ref{nncp-daemon, TCP daemon}. diff --git a/doc/warcer.sh b/doc/warcer.sh new file mode 100755 index 0000000000000000000000000000000000000000..7dd64ee43a768411dd837bd1c606d7cd14d87cc63f6f49ff65d12313d53d8cc6 --- /dev/null +++ b/doc/warcer.sh @@ -0,0 +1,24 @@ +#!/bin/sh -ex + +name="$1"-$(date '+%Y%M%d%H%m%S') +read cmdline + +tmp=$(mktemp -d) +cd $tmp +wget \ + --page-requisites \ + --convert-links \ + --adjust-extension \ + --restrict-file-names=ascii \ + --span-hosts \ + --random-wait \ + --execute robots=off \ + --reject '*.woff*,*.ttf,*.eot,*.js' \ + --tries 10 \ + --warc-file "$name" \ + --no-warc-compression \ + --no-warc-keep-log \ + $cmdline || : +xz -9 "$name".warc +nncp-file -nice $NNCP_NICE "$name".warc.xz $NNCP_SENDER: +rm -r $tmp diff --git a/doc/wgeter.sh b/doc/wgeter.sh new file mode 100755 index 0000000000000000000000000000000000000000..f6c0132023d857588d3cfd24ab58815a55630b7e466442bcab5f9d359b3296b0 --- /dev/null +++ b/doc/wgeter.sh @@ -0,0 +1,10 @@ +#!/bin/sh -ex + +name=$1-$(date '+%Y%M%d%H%m%S') +read cmdline + +tmp=$(mktemp) +wget --output-document=$tmp $cmdline +xz -9 $tmp +nncp-file -nice $NNCP_NICE $tmp.xz $NNCP_SENDER:$name.xz +rm $tmp.xz diff --git a/doc/workflow.texi b/doc/workflow.texi index e1a9998f27b5dd063e8171c4efad2d7bedde26da279670879866e619dee82507..4d5d1025c29b33ddc6b21d9aab2bac509d891cc411cb5a3d777ba7b2fb5f3b01 100644 --- a/doc/workflow.texi +++ b/doc/workflow.texi @@ -12,9 +12,9 @@ @item Share your public keys and reachability addressees with your neighbours. Add their keys to your configuration file and do any other required configuration about their reachability, permissions of file or freq transmission. -@item Use @ref{nncp-file}, @ref{nncp-freq}, @ref{nncp-mail} +@item Use @ref{nncp-file}, @ref{nncp-freq}, @ref{nncp-exec} (@ref{Postfix, look how} Postfix SMTP server could be configured) -commands to queue file, freq and mail transmissions. Repeat as +commands to queue file, freq and exec transmissions. Repeat as many times any time as you wish. @item Depending on connection methods, either: @itemize @@ -29,7 +29,7 @@ or broadcasting transmissions for copying packets @end itemize @item After successful packet exchanging (or just simply from time to time), run @ref{nncp-toss} for tossing (decrypting and processing) all -inbound queues to receive mail messages, files, file requests and relay +inbound queues to receive exec messages, files, file requests and relay transition packets to other nodes. @end enumerate diff --git a/makedist.sh b/makedist.sh index 65b854d567b63c456ffe9cfb36911d1cf3595e4ea9957feb4fc68146bd211af5..ee15af83c94f26347162ef41c6d051130df3267ddb615be9056b9f99f9b249d8 100755 --- a/makedist.sh +++ b/makedist.sh @@ -103,12 +103,13 @@ NNCP (Node to Node copy) is a collection of utilities simplifying secure store-and-forward files and mail exchanging. This utilities are intended to help build up small size (dozens of -nodes) ad-hoc friend-to-friend (F2F) statically routed darknet networks -for fire-and-forget secure reliable files, file requests and Internet -mail transmission. All packets are integrity checked, end-to-end -encrypted (E2EE), explicitly authenticated by known participants public -keys. Onion encryption is applied to relayed packets. Each node acts -both as a client and server, can use push and poll behaviour model. +nodes) ad-hoc friend-to-friend (F2F) statically routed darknet +delay-tolerant networks for fire-and-forget secure reliable files, file +requests, Internet mail and commands transmission. All packets are +integrity checked, end-to-end encrypted (E2EE), explicitly authenticated +by known participants public keys. Onion encryption is applied to +relayed packets. Each node acts both as a client and server, can use +push and poll behaviour model. Out-of-box offline sneakernet/floppynet, dead drops, sequential and append-only CD-ROM/tape storages, air-gapped computers support. But @@ -147,10 +148,10 @@ NNCP (Node to Node copy) это набор утилит упрощающий безопасный обмен файлами и почтой в режиме сохранить-и-переслать. -Эти утилиты предназначены помочь с построением одноранговых сетей -небольшого размера (дюжины узлов), в режиме друг-к-другу (F2F) со -статической маршрутизацией для безопасной надёжной передачи файлов, -запросов на передачу файлов и Интернет почты по принципу +Эти утилиты предназначены помочь с построением одноранговых устойчивых к +разрывам сетей небольшого размера (дюжины узлов), в режиме друг-к-другу +(F2F) со статической маршрутизацией для безопасной надёжной передачи +файлов, запросов на передачу файлов, Интернет почты и команд по принципу выстрелил-и-забыл. Все пакеты проверяются на целостность, шифруются по принципу точка-точка (E2EE), аутентифицируются известными публичными ключами участников. Луковичное (onion) шифрование применяется ко всем diff --git a/ports/nncp/Makefile b/ports/nncp/Makefile index 28533f7f6a0209d7028e55d3cc0ca4ea7383daf3f5b926c38054074961723b2d..078575ddd2e4a19789503d7fcbdf6e2a44eab5ee669bf471407a07770330ccd8 100644 --- a/ports/nncp/Makefile +++ b/ports/nncp/Makefile @@ -1,12 +1,12 @@ -# $FreeBSD$ +# $FreeBSD: head/net/nncp/Makefile 460314 2018-01-29 16:17:45Z yuri $ PORTNAME= nncp -PORTVERSION= 2.0 +DISTVERSION= 3.0 CATEGORIES= net MASTER_SITES= http://www.nncpgo.org/download/ MAINTAINER= stargrave@stargrave.org -COMMENT= Utilities for secure store-and-forward files and mail exchanging +COMMENT= Utilities for secure store-and-forward files, mail and command exchanging LICENSE= GPLv3+ LICENSE_FILE= ${WRKSRC}/COPYING @@ -15,38 +15,17 @@ BUILD_DEPENDS= go:lang/go USES= tar:xz MAKEFILE= BSDmakefile - USE_RC_SUBR= nncp-caller nncp-daemon nncp-toss -REQUIRE= DAEMON +INSTALL_TARGET= install-strip + +SUB_FILES= pkg-message pkg-install pkg-deinstall -SUB_FILES= pkg-message pkg-install pkg-deinstall nncp.newsyslog.conf.sample +OPTIONS_DEFINE= DOCS PORTDOCS= AUTHORS NEWS NEWS.RU README README.RU THANKS INFO= nncp -INSTALL_TARGET= install-strip - -PLIST_FILES= bin/nncp-bundle \ - bin/nncp-call \ - bin/nncp-caller \ - bin/nncp-cfgenc \ - bin/nncp-cfgmin \ - bin/nncp-cfgnew \ - bin/nncp-check \ - bin/nncp-daemon \ - bin/nncp-file \ - bin/nncp-freq \ - bin/nncp-log \ - bin/nncp-mail \ - bin/nncp-pkt \ - bin/nncp-reass \ - bin/nncp-rm \ - bin/nncp-stat \ - bin/nncp-toss \ - bin/nncp-xfer \ - "@sample etc/newsyslog.conf.d/nncp.conf.sample" post-install: - ${MKDIR} ${STAGEDIR}${PREFIX}/etc/newsyslog.conf.d - ${INSTALL_DATA} ${WRKDIR}/nncp.newsyslog.conf.sample ${STAGEDIR}${PREFIX}/etc/newsyslog.conf.d/nncp.conf.sample + ${INSTALL_DATA} ${FILESDIR}/nncp.newsyslog.conf.sample ${STAGEDIR}${PREFIX}/etc/nncp.conf.sample .include diff --git a/ports/nncp/files/nncp.newsyslog.conf.sample.in b/ports/nncp/files/nncp.newsyslog.conf.sample rename from ports/nncp/files/nncp.newsyslog.conf.sample.in rename to ports/nncp/files/nncp.newsyslog.conf.sample diff --git a/ports/nncp/files/pkg-message.in b/ports/nncp/files/pkg-message.in index 138a6fb55544a7fd44379ffa0c2e990c66fa065d0f078d0c3979ee37aaffa99e..287bf28950b712fd0f31f45817e087825cd08cf8bc4e067d0aa360283ab2ea79 100644 --- a/ports/nncp/files/pkg-message.in +++ b/ports/nncp/files/pkg-message.in @@ -13,5 +13,5 @@ - Look in nncp.info how to integrate mail exchanging with Postfix. - Generate NNCP configuration file using the command: # umask 077 - # nncp-newcfg > %%PREFIX%%/etc/nncp.yaml + # nncp-cfgnew > %%PREFIX%%/etc/nncp.yaml ====================================================================== diff --git a/ports/nncp/pkg-descr b/ports/nncp/pkg-descr index 8ae73e08aa2227948ffbfcef32e54b2d05ebe3824b82703ffa7c57a55dc4c21a..cf1710bd75ce0e9fddd0f3deb3b92fe7c45677ce250ba6650c0963e887a61b5f 100644 --- a/ports/nncp/pkg-descr +++ b/ports/nncp/pkg-descr @@ -2,12 +2,13 @@ NNCP (Node to Node copy) is a collection of utilities simplifying secure store-and-forward files and mail exchanging. This utilities are intended to help build up small size (dozens of -nodes) ad-hoc friend-to-friend (F2F) statically routed darknet networks -for fire-and-forget secure reliable files, file requests and Internet -mail transmission. All packets are integrity checked, end-to-end -encrypted (E2EE), explicitly authenticated by known participants public -keys. Onion encryption is applied to relayed packets. Each node acts -both as a client and server, can use push and poll behaviour model. +nodes) ad-hoc friend-to-friend (F2F) statically routed darknet +delay-tolerant networks for fire-and-forget secure reliable files, file +requests, Internet mail and commands transmission. All packets are +integrity checked, end-to-end encrypted (E2EE), explicitly authenticated +by known participants public keys. Onion encryption is applied to +relayed packets. Each node acts both as a client and server, can use +push and poll behaviour model. Out-of-box offline sneakernet/floppynet, dead drops, sequential and append-only CD-ROM/tape storages, air-gapped computers support. But diff --git a/ports/nncp/pkg-plist b/ports/nncp/pkg-plist new file mode 100644 index 0000000000000000000000000000000000000000..22fbf9b6e30f0ebd7d0c35dfffb46946da8691ae5cc0db5c1f78b05605a8e787 --- /dev/null +++ b/ports/nncp/pkg-plist @@ -0,0 +1,19 @@ +bin/nncp-bundle +bin/nncp-call +bin/nncp-caller +bin/nncp-cfgenc +bin/nncp-cfgmin +bin/nncp-cfgnew +bin/nncp-check +bin/nncp-daemon +bin/nncp-exec +bin/nncp-file +bin/nncp-freq +bin/nncp-log +bin/nncp-pkt +bin/nncp-reass +bin/nncp-rm +bin/nncp-stat +bin/nncp-toss +bin/nncp-xfer +@sample etc/nncp.conf.sample etc/newsyslog.conf.d/nncp.conf diff --git a/src/cypherpunks.ru/nncp/call.go b/src/cypherpunks.ru/nncp/call.go index 730f2ebf5512baa0b292f01cef0d9cb9b79517048baff499e2d7c95a95edcf34..4098453b334e32249d6eb40f7c18be6167ff7636a6440206c6bae41ae6cfbf28 100644 --- a/src/cypherpunks.ru/nncp/call.go +++ b/src/cypherpunks.ru/nncp/call.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 diff --git a/src/cypherpunks.ru/nncp/cfg.go b/src/cypherpunks.ru/nncp/cfg.go index 1e1dd6e00c2d0ffc4f60205bb0212e7cf41ddf7ae23fc2b69626fb8a046a4f25..e4da5fd53727d256607a65f5c4407c83b2abc4262aba940a429b9b1717c87d5b 100644 --- a/src/cypherpunks.ru/nncp/cfg.go +++ b/src/cypherpunks.ru/nncp/cfg.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -48,14 +48,14 @@ type NodeYAML struct { Id string ExchPub string SignPub string - NoisePub *string `noisepub,omitempty` - Sendmail []string `sendmail,omitempty` - Incoming *string `incoming,omitempty` - Freq *string `freq,omitempty` - FreqChunked *uint64 `freqchunked,omitempty` - FreqMinSize *uint64 `freqminsize,omitempty` - Via []string `via,omitempty` - Calls []CallYAML `calls,omitempty` + NoisePub *string `noisepub,omitempty` + Exec map[string][]string `exec,omitempty` + Incoming *string `incoming,omitempty` + Freq *string `freq,omitempty` + FreqChunked *uint64 `freqchunked,omitempty` + FreqMinSize *uint64 `freqminsize,omitempty` + Via []string `via,omitempty` + Calls []CallYAML `calls,omitempty` Addrs map[string]string `addrs,omitempty` @@ -232,7 +232,7 @@ Name: name, Id: nodeId, ExchPub: new([32]byte), SignPub: ed25519.PublicKey(signPub), - Sendmail: yml.Sendmail, + Exec: yml.Exec, Incoming: incoming, Freq: freq, FreqChunked: freqChunked, diff --git a/src/cypherpunks.ru/nncp/check.go b/src/cypherpunks.ru/nncp/check.go index a0652cb4d1f6d418a8ec08b00555952c30c318d25532cf2e65379f3c754df8cb..a2d1b6e942a5aebac3a84f5948901e74acbb3697af03626bd7b4ada7bb83a9a2 100644 --- a/src/cypherpunks.ru/nncp/check.go +++ b/src/cypherpunks.ru/nncp/check.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 diff --git a/src/cypherpunks.ru/nncp/chunked.go b/src/cypherpunks.ru/nncp/chunked.go index 01aa49b0d93890df4db54fd475f3f44c05698d548083ad5a5cd263b146571ba3..c6f8190b9d99a922469c102c1fcc06795304c06dd16d36a6309f5fdde9033f51 100644 --- a/src/cypherpunks.ru/nncp/chunked.go +++ b/src/cypherpunks.ru/nncp/chunked.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-bundle/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-bundle/main.go index 46eb946c2d202a80d5b9c0d0650e6f391994fc08823093cd24085c799a3de196..9ced7349fe7e88b39195b1f19a665265241bfd3bc587124678aa0c35db25e16d 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-bundle/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-bundle/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -44,7 +44,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-bundle -- Create/digest stream of NNCP encrypted packets\n") + fmt.Fprintf(os.Stderr, "nncp-bundle -- Create/digest stream of NNCP encrypted packets\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options] -tx [-delete] NODE [NODE ...] > ...\n", os.Args[0]) fmt.Fprintf(os.Stderr, " %s [options] -rx -delete [-dryrun] [NODE ...] < ...\n", os.Args[0]) fmt.Fprintf(os.Stderr, " %s [options] -rx [-check] [-dryrun] [NODE ...] < ...\n", os.Args[0]) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-call/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-call/main.go index ae66fe2cddf299582cc5a5284487c1f8df3a02fcee5094bf89fe3f5e4c631ca1..d75162ddc5183b983b068a49e6a11b140286056d3464b7535b737aacd19946ab 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-call/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-call/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -31,7 +31,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-call -- call TCP daemon\n") + fmt.Fprintf(os.Stderr, "nncp-call -- call TCP daemon\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE[:ADDR] [FORCEADDR]\n", os.Args[0]) fmt.Fprintln(os.Stderr, "Options:") flag.PrintDefaults() diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-caller/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-caller/main.go index e06bb88b41e6c3885d4ec4cf665b66a4b6455c35f0c336e0d35d3efba20dde4d..33dc4b60f175dff6482f21b9523939d03128c59f4bced1947fd6aaf3aeda38f8 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-caller/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-caller/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -33,7 +33,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-caller -- croned NNCP TCP daemon caller\n") + fmt.Fprintf(os.Stderr, "nncp-caller -- croned NNCP TCP daemon caller\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options] [NODE ...]\n", os.Args[0]) fmt.Fprintln(os.Stderr, "Options:") flag.PrintDefaults() diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-cfgenc/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-cfgenc/main.go index 06e08f12aea1b0aa9d966a55b6661605170f59528664885cbd47221b1cc73787..fa4dacad8f72688c744c519b3087b062d4320068492b2cedcd91167db38fb347 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-cfgenc/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-cfgenc/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -36,7 +36,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-cfgenc -- encrypt/decrypt configuration file\n") + fmt.Fprintf(os.Stderr, "nncp-cfgenc -- encrypt/decrypt configuration file\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options] cfg.yaml > cfg.yaml.eblob\n", os.Args[0]) fmt.Fprintf(os.Stderr, " %s [options] -d cfg.yaml.eblob > cfg.yaml\n", os.Args[0]) fmt.Fprintf(os.Stderr, " %s [options] -dump cfg.yaml.eblob\n", os.Args[0]) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-cfgmin/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-cfgmin/main.go index 57db531e5164460b346ab62e686ee34356a726c6eb491c078a40edf33b02e327..845f2218f2c401e37110d4ea8822a05c68f794beeafd17713799ccdd7cde4dd3 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-cfgmin/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-cfgmin/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -31,7 +31,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-cfgmin -- print stripped configuration\n") + fmt.Fprintf(os.Stderr, "nncp-cfgmin -- print stripped configuration\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-cfgnew/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-cfgnew/main.go index 423d69e5f654b6a8249af2ee09b6a720e041affb97f02116047ca1109b8af254..7db9060f298d504c5a5382264521c5b6b55e3b3f0d3e837f955fd0988337da36 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-cfgnew/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-cfgnew/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -70,7 +70,9 @@ Id: nodeOur.Id.String(), ExchPub: nncp.ToBase32(nodeOur.ExchPub[:]), SignPub: nncp.ToBase32(nodeOur.SignPub[:]), NoisePub: &noisePub, - Sendmail: []string{nncp.DefaultSendmailPath}, + Exec: map[string][]string{ + "sendmail": []string{nncp.DefaultSendmailPath}, + }, }, }, Spool: nncp.DefaultSpoolPath, diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-check/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-check/main.go index bc2f1fd44f3f25b5a02e25dbc848453f0c73fdbf08abfebe764132fc2c6c5d64..29c1ff4ea74a102236d7a817fd338726bb3554f48818846f93017893e34b2ede 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-check/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-check/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -30,7 +30,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-check -- verify Rx/Tx packets checksum\n") + fmt.Fprintf(os.Stderr, "nncp-check -- verify Rx/Tx packets checksum\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-daemon/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-daemon/main.go index cff2acb785c76b4bbed37dcaa14cbedbaf38f599f8bbc2faf1735f57d5f0a7a5..46d7fa164b3b1253fbb3765b1b36a19b7ac4068b2b6b25213eedeccac8a5b701 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-daemon/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-daemon/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -33,7 +33,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-daemon -- TCP daemon\n") + fmt.Fprintf(os.Stderr, "nncp-daemon -- TCP daemon\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-exec/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-exec/main.go new file mode 100644 index 0000000000000000000000000000000000000000..4bdc2490c28fee082b9fd9f2d5334635d8b4b97512bd6f26545e840eea65d270 --- /dev/null +++ b/src/cypherpunks.ru/nncp/cmd/nncp-exec/main.go @@ -0,0 +1,119 @@ +/* +NNCP -- Node to Node copy, utilities for store-and-forward data exchange +Copyright (C) 2016-2018 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, either version 3 of the License, or +(at your option) any later version. + +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 . +*/ + +// Send execution command via NNCP +package main + +import ( + "bufio" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "strings" + + "cypherpunks.ru/nncp" +) + +func usage() { + fmt.Fprintf(os.Stderr, nncp.UsageHeader()) + fmt.Fprintf(os.Stderr, "nncp-exec -- send execution command\n\n") + fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE HANDLE [ARG0 ARG1 ...]\nOptions:\n", os.Args[0]) + flag.PrintDefaults() +} + +func main() { + var ( + cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file") + niceRaw = flag.Int("nice", nncp.DefaultNiceExec, "Outbound packet niceness") + replyNiceRaw = flag.Int("replynice", nncp.DefaultNiceFile, "Possible reply packet niceness") + minSize = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB") + viaOverride = flag.String("via", "", "Override Via path to destination node") + spoolPath = flag.String("spool", "", "Override path to spool") + logPath = flag.String("log", "", "Override path to logfile") + quiet = flag.Bool("quiet", false, "Print only errors") + debug = flag.Bool("debug", false, "Print debug messages") + version = flag.Bool("version", false, "Print version information") + warranty = flag.Bool("warranty", false, "Print warranty information") + ) + flag.Usage = usage + flag.Parse() + if *warranty { + fmt.Println(nncp.Warranty) + return + } + if *version { + fmt.Println(nncp.VersionGet()) + return + } + if flag.NArg() < 2 { + usage() + os.Exit(1) + } + if *niceRaw < 1 || *niceRaw > 255 { + log.Fatalln("-nice must be between 1 and 255") + } + nice := uint8(*niceRaw) + if *replyNiceRaw < 1 || *replyNiceRaw > 255 { + log.Fatalln("-replynice must be between 1 and 255") + } + replyNice := uint8(*replyNiceRaw) + + ctx, err := nncp.CtxFromCmdline(*cfgPath, *spoolPath, *logPath, *quiet, *debug) + if err != nil { + log.Fatalln("Error during initialization:", err) + } + if ctx.Self == nil { + log.Fatalln("Config lacks private keys") + } + + node, err := ctx.FindNode(flag.Arg(0)) + if err != nil { + log.Fatalln("Invalid NODE specified:", err) + } + + if *viaOverride != "" { + vias := make([]*nncp.NodeId, 0, strings.Count(*viaOverride, ",")+1) + for _, via := range strings.Split(*viaOverride, ",") { + foundNodeId, err := ctx.FindNode(via) + if err != nil { + log.Fatalln("Invalid Via node specified:", err) + } + vias = append(vias, foundNodeId.Id) + } + node.Via = vias + } + + body, err := ioutil.ReadAll(bufio.NewReader(os.Stdin)) + if err != nil { + log.Fatalln("Can not read body from stdin:", err) + } + + if err = ctx.TxExec( + node, + nice, + replyNice, + flag.Args()[1], + flag.Args()[2:], + body, + int64(*minSize)*1024, + ); err != nil { + log.Fatalln(err) + } +} diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-file/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-file/main.go index 0764c11ddc15e6fa67537f440d94eb99b47ad3ba28772fed1184dbdb17dbaaaa..2b7244f7f8a7b8312b15e48e086701e08f866ee95d75df5e49e07672c04d36ee 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-file/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-file/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -31,26 +31,30 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-file -- send file\n") + fmt.Fprintf(os.Stderr, "nncp-file -- send file\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options] SRC NODE:[DST]\nOptions:\n", os.Args[0]) flag.PrintDefaults() fmt.Fprint(os.Stderr, ` If SRC equals to -, then read data from stdin to temporary file. + +-minsize/-chunked take NODE's FreqMinSize/FreqChunked configuration +options by default. You can forcefully turn them off by specifying 0 value. `) } func main() { var ( - cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file") - niceRaw = flag.Int("nice", nncp.DefaultNiceFile, "Outbound packet niceness") - minSize = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB") - chunkSize = flag.Uint64("chunked", 0, "Split file on specified size chunks, in KiB") - spoolPath = flag.String("spool", "", "Override path to spool") - logPath = flag.String("log", "", "Override path to logfile") - quiet = flag.Bool("quiet", false, "Print only errors") - debug = flag.Bool("debug", false, "Print debug messages") - version = flag.Bool("version", false, "Print version information") - warranty = flag.Bool("warranty", false, "Print warranty information") + cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file") + niceRaw = flag.Int("nice", nncp.DefaultNiceFile, "Outbound packet niceness") + argMinSize = flag.Int64("minsize", -1, "Minimal required resulting packet size, in KiB") + argChunkSize = flag.Int64("chunked", -1, "Split file on specified size chunks, in KiB") + viaOverride = flag.String("via", "", "Override Via path to destination node") + spoolPath = flag.String("spool", "", "Override path to spool") + logPath = flag.String("log", "", "Override path to logfile") + quiet = flag.Bool("quiet", false, "Print only errors") + debug = flag.Bool("debug", false, "Print debug messages") + version = flag.Bool("version", false, "Print version information") + warranty = flag.Bool("warranty", false, "Print warranty information") ) flag.Usage = usage flag.Parse() @@ -89,13 +93,39 @@ if err != nil { log.Fatalln("Invalid NODE specified:", err) } - if *chunkSize == 0 { + if *viaOverride != "" { + vias := make([]*nncp.NodeId, 0, strings.Count(*viaOverride, ",")+1) + for _, via := range strings.Split(*viaOverride, ",") { + foundNodeId, err := ctx.FindNode(via) + if err != nil { + log.Fatalln("Invalid Via node specified:", err) + } + vias = append(vias, foundNodeId.Id) + } + node.Via = vias + } + + var minSize int64 + if *argMinSize < 0 { + minSize = node.FreqMinSize + } else if *argMinSize > 0 { + minSize = *argMinSize * 1024 + } + + var chunkSize int64 + if *argChunkSize < 0 { + chunkSize = node.FreqChunked + } else if *argChunkSize > 0 { + chunkSize = *argChunkSize * 1024 + } + + if chunkSize == 0 { err = ctx.TxFile( node, nice, flag.Arg(0), splitted[1], - int64(*minSize)*1024, + minSize, ) } else { err = ctx.TxFileChunked( @@ -103,8 +133,8 @@ node, nice, flag.Arg(0), splitted[1], - int64(*minSize)*1024, - int64(*chunkSize)*1024, + minSize, + chunkSize, ) } if err != nil { diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-freq/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-freq/main.go index 7317c25b1320768f382ab1e25fe84445fce734ab93afb69a469f4aabf7398e2d..606e938d8bf6e566a2335d86e8ab2cb3455310ccbe717adb7c6e38fe4bc2e1e2 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-freq/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-freq/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -32,22 +32,24 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-freq -- send file request\n") + fmt.Fprintf(os.Stderr, "nncp-freq -- send file request\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE:SRC [DST]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } func main() { var ( - cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file") - niceRaw = flag.Int("nice", nncp.DefaultNiceFreq, "Outbound packet niceness") - minSize = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB") - spoolPath = flag.String("spool", "", "Override path to spool") - logPath = flag.String("log", "", "Override path to logfile") - quiet = flag.Bool("quiet", false, "Print only errors") - debug = flag.Bool("debug", false, "Print debug messages") - version = flag.Bool("version", false, "Print version information") - warranty = flag.Bool("warranty", false, "Print warranty information") + cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file") + niceRaw = flag.Int("nice", nncp.DefaultNiceFreq, "Outbound packet niceness") + replyNiceRaw = flag.Int("replynice", nncp.DefaultNiceFile, "Reply file packet niceness") + minSize = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB") + viaOverride = flag.String("via", "", "Override Via path to destination node") + spoolPath = flag.String("spool", "", "Override path to spool") + logPath = flag.String("log", "", "Override path to logfile") + quiet = flag.Bool("quiet", false, "Print only errors") + debug = flag.Bool("debug", false, "Print debug messages") + version = flag.Bool("version", false, "Print version information") + warranty = flag.Bool("warranty", false, "Print warranty information") ) flag.Usage = usage flag.Parse() @@ -67,6 +69,10 @@ if *niceRaw < 1 || *niceRaw > 255 { log.Fatalln("-nice must be between 1 and 255") } nice := uint8(*niceRaw) + if *replyNiceRaw < 1 || *replyNiceRaw > 255 { + log.Fatalln("-replynice must be between 1 and 255") + } + replyNice := uint8(*replyNiceRaw) ctx, err := nncp.CtxFromCmdline(*cfgPath, *spoolPath, *logPath, *quiet, *debug) if err != nil { @@ -86,6 +92,18 @@ if err != nil { log.Fatalln("Invalid NODE specified:", err) } + if *viaOverride != "" { + vias := make([]*nncp.NodeId, 0, strings.Count(*viaOverride, ",")+1) + for _, via := range strings.Split(*viaOverride, ",") { + foundNodeId, err := ctx.FindNode(via) + if err != nil { + log.Fatalln("Invalid Via node specified:", err) + } + vias = append(vias, foundNodeId.Id) + } + node.Via = vias + } + var dst string if flag.NArg() == 2 { dst = flag.Arg(1) @@ -96,6 +114,7 @@ if err = ctx.TxFreq( node, nice, + replyNice, splitted[1], dst, int64(*minSize)*1024, diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-log/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-log/main.go index 1f0a66c5f88a8e32af596f89f2bc51bbb4eade61e13c136066ad8d1ba3c5427c..b099be28957182276d7f7966169fe21731e22537e6eb38cd4f4a637ed11210eb 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-log/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-log/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -31,7 +31,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-log -- read logs\n") + fmt.Fprintf(os.Stderr, "nncp-log -- read logs\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-mail/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-mail/main.go deleted file mode 100644 index 217f947b3034a706bdcbf50d39ba2b91642690fd8d61a55581d98bf06db4566b..0000000000000000000000000000000000000000 --- a/src/cypherpunks.ru/nncp/cmd/nncp-mail/main.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 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, either version 3 of the License, or -(at your option) any later version. - -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 . -*/ - -// Send email via NNCP -package main - -import ( - "bufio" - "flag" - "fmt" - "io/ioutil" - "log" - "os" - "strings" - - "cypherpunks.ru/nncp" -) - -func usage() { - fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-mail -- send email\n") - fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE USER ...\nOptions:\n", os.Args[0]) - flag.PrintDefaults() -} - -func main() { - var ( - cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file") - niceRaw = flag.Int("nice", nncp.DefaultNiceMail, "Outbound packet niceness") - minSize = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB") - spoolPath = flag.String("spool", "", "Override path to spool") - logPath = flag.String("log", "", "Override path to logfile") - quiet = flag.Bool("quiet", false, "Print only errors") - debug = flag.Bool("debug", false, "Print debug messages") - version = flag.Bool("version", false, "Print version information") - warranty = flag.Bool("warranty", false, "Print warranty information") - ) - flag.Usage = usage - flag.Parse() - if *warranty { - fmt.Println(nncp.Warranty) - return - } - if *version { - fmt.Println(nncp.VersionGet()) - return - } - if flag.NArg() < 2 { - usage() - os.Exit(1) - } - if *niceRaw < 1 || *niceRaw > 255 { - log.Fatalln("-nice must be between 1 and 255") - } - nice := uint8(*niceRaw) - - ctx, err := nncp.CtxFromCmdline(*cfgPath, *spoolPath, *logPath, *quiet, *debug) - if err != nil { - log.Fatalln("Error during initialization:", err) - } - if ctx.Self == nil { - log.Fatalln("Config lacks private keys") - } - - node, err := ctx.FindNode(flag.Arg(0)) - if err != nil { - log.Fatalln("Invalid NODE specified:", err) - } - - body, err := ioutil.ReadAll(bufio.NewReader(os.Stdin)) - if err != nil { - log.Fatalln("Can not read mail body from stdin:", err) - } - - if err = ctx.TxMail( - node, - nice, - strings.Join(flag.Args()[1:], " "), - body, - int64(*minSize)*1024, - ); err != nil { - log.Fatalln(err) - } -} diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-pkt/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-pkt/main.go index 1dd7bf1555f7ac9a39c8c5ce55cfa2e48104db3f5c1aae7ad4ee5c8dae1ce6da..09817e13795740be823a0a31089cc47461072be544fd4a47f3be9e5a0e1349f2 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-pkt/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-pkt/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -36,7 +36,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-pkt -- parse raw packet\n") + fmt.Fprintf(os.Stderr, "nncp-pkt -- parse raw packet\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() fmt.Fprintln(os.Stderr, "Packet is read from stdin.") @@ -68,7 +68,7 @@ log.Fatalln("Not enough data to read") } var pkt nncp.Pkt _, err = xdr.Unmarshal(bytes.NewReader(beginning), &pkt) - if err == nil && pkt.Magic == nncp.MagicNNCPPv1 { + if err == nil && pkt.Magic == nncp.MagicNNCPPv2 { if *dump { bufW := bufio.NewWriter(os.Stdout) var r io.Reader @@ -94,19 +94,29 @@ case nncp.PktTypeFile: payloadType = "file" case nncp.PktTypeFreq: payloadType = "file request" - case nncp.PktTypeMail: - payloadType = "mail" + case nncp.PktTypeExec: + payloadType = "exec" case nncp.PktTypeTrns: payloadType = "transitional" } var path string switch pkt.Type { + case nncp.PktTypeExec: + path = string(bytes.Replace( + pkt.Path[:pkt.PathLen], + []byte{0}, + []byte(" "), + -1, + )) case nncp.PktTypeTrns: path = nncp.ToBase32(pkt.Path[:pkt.PathLen]) default: path = string(pkt.Path[:pkt.PathLen]) } - fmt.Printf("Packet type: plain\nPayload type: %s\nPath: %s\n", payloadType, path) + fmt.Printf( + "Packet type: plain\nPayload type: %s\nNiceness: %d\nPath: %s\n", + payloadType, pkt.Nice, path, + ) return } var pktEnc nncp.PktEnc diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-reass/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-reass/main.go index b9b4c912ad63b2b724da5f8e10363232a0dba6c075e1cc2e0c020f9df260e20f..a3bdda7e04865333c9a12e17791f58ecaac6b6d8c23b0aa66f0d81558e6ae027 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-reass/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-reass/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -42,7 +42,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-reass -- reassemble chunked files\n") + fmt.Fprintf(os.Stderr, "nncp-reass -- reassemble chunked files\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options] [FILE.nncp.meta]\nOptions:\n", os.Args[0]) flag.PrintDefaults() fmt.Fprint(os.Stderr, ` diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-rm/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-rm/main.go index db035785742f1296fd02fbc0bfadc22f38a96b57304e576292fdc4e3570272b9..226613f85aadf10244f4e933c4fca2aa3b07f2bc53c261ca3615458d1cff9262 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-rm/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-rm/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -32,7 +32,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-rm -- remove packet\n") + fmt.Fprintf(os.Stderr, "nncp-rm -- remove packet\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options] -tmp\n", os.Args[0]) fmt.Fprintf(os.Stderr, " %s [options] -lock\n", os.Args[0]) fmt.Fprintf(os.Stderr, " %s [options] -node NODE -part\n", os.Args[0]) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-stat/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-stat/main.go index 61e190c3cd9a94a6ffe4badeb0da1895b336d2ff9dc9edc88f3cb5de565cdb8d..c5c248fbd0911f7027a459c31f76cb4cef520f50a0b2f2975777116e9df9d064 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-stat/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-stat/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -32,7 +32,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-stat -- show queued Rx/Tx stats\n") + fmt.Fprintf(os.Stderr, "nncp-stat -- show queued Rx/Tx stats\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-toss/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-toss/main.go index d0e9beee99789fd483b1882bb1baa87505ed2091112cf95aaef56faa3e6887ed..442c561271d76f69ff82f61a28917791fd83d9e1c203c20bf7fe477ee0fdcf02 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-toss/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-toss/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -31,7 +31,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-toss -- process inbound packets\n") + fmt.Fprintf(os.Stderr, "nncp-toss -- process inbound packets\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0]) flag.PrintDefaults() } @@ -44,6 +44,10 @@ niceRaw = flag.Int("nice", 255, "Minimal required niceness") dryRun = flag.Bool("dryrun", false, "Do not actually write any tossed data") doSeen = flag.Bool("seen", false, "Create .seen files") cycle = flag.Uint("cycle", 0, "Repeat tossing after N seconds in infinite loop") + noFile = flag.Bool("nofile", false, "Do not process packets with type: file") + noFreq = flag.Bool("nofreq", false, "Do not process packets with type: freq") + noExec = flag.Bool("noexec", false, "Do not process packets with type: exec") + noTrns = flag.Bool("notrns", false, "Do not process packets with type: transitional") spoolPath = flag.String("spool", "", "Override path to spool") logPath = flag.String("log", "", "Override path to logfile") quiet = flag.Bool("quiet", false, "Print only errors") @@ -88,7 +92,16 @@ for nodeId, node := range ctx.Neigh { if nodeOnly != nil && nodeId != *nodeOnly.Id { continue } - isBad = ctx.Toss(node.Id, nice, *dryRun, *doSeen) + isBad = ctx.Toss( + node.Id, + nice, + *dryRun, + *doSeen, + *noFile, + *noFreq, + *noExec, + *noTrns, + ) } if *cycle > 0 { time.Sleep(time.Duration(*cycle) * time.Second) diff --git a/src/cypherpunks.ru/nncp/cmd/nncp-xfer/main.go b/src/cypherpunks.ru/nncp/cmd/nncp-xfer/main.go index cc0690dec4215d7a0b83ec56bf7f3cf6eb69665a64af1be899e5c66f68b07a79..b89c654cbc62f54c48c4cb181c28a6e2d2bfd4197b5603a479fca6d01218b744 100644 --- a/src/cypherpunks.ru/nncp/cmd/nncp-xfer/main.go +++ b/src/cypherpunks.ru/nncp/cmd/nncp-xfer/main.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -36,7 +36,7 @@ ) func usage() { fmt.Fprintf(os.Stderr, nncp.UsageHeader()) - fmt.Fprintln(os.Stderr, "nncp-xfer -- copy inbound and outbounds packets\n") + fmt.Fprintf(os.Stderr, "nncp-xfer -- copy inbound and outbounds packets\n\n") fmt.Fprintf(os.Stderr, "Usage: %s [options] DIR\nOptions:\n", os.Args[0]) flag.PrintDefaults() } diff --git a/src/cypherpunks.ru/nncp/ctx.go b/src/cypherpunks.ru/nncp/ctx.go index 261d22232f84a1ba5795f857b99345fb83b1b5bfb820d074ed0f6e02700bb963..fae4d3f1ead908398593b6e7db1ab133590d395a8ca0d67deb3a513a1597b9a7 100644 --- a/src/cypherpunks.ru/nncp/ctx.go +++ b/src/cypherpunks.ru/nncp/ctx.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 diff --git a/src/cypherpunks.ru/nncp/eblob.go b/src/cypherpunks.ru/nncp/eblob.go index 7e401f105746eee80aaf9b1c902c6b7beba9785e63868f95b9d29705fb2e1e23..5ba76923636b60d80aa2bcf65506fdcc9ea95bc0c7cfd87f23bdd215b851712c 100644 --- a/src/cypherpunks.ru/nncp/eblob.go +++ b/src/cypherpunks.ru/nncp/eblob.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 diff --git a/src/cypherpunks.ru/nncp/humanizer.go b/src/cypherpunks.ru/nncp/humanizer.go index 18aa7c6eaf541799b44d759b2723995e7b6da45e0d10f42b3dbcba512653e43e..d6f41e3f9a6e6e80ec107f9d52e0723857ffe4685836c8a32e6812bfac87ed86 100644 --- a/src/cypherpunks.ru/nncp/humanizer.go +++ b/src/cypherpunks.ru/nncp/humanizer.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -84,10 +84,10 @@ msg = fmt.Sprintf( "File request from %s:%s to %s: %s", nodeS, sds["src"], sds["dst"], rem, ) - case "mail": + case "exec": msg = fmt.Sprintf( - "Mail to %s@%s (%s): %s", - nodeS, strings.Replace(sds["dst"], " ", ",", -1), size, rem, + "Exec to %s@%s (%s): %s", + nodeS, sds["dst"], size, rem, ) case "trns": msg = fmt.Sprintf( @@ -102,10 +102,10 @@ msg += ": " + err } case "rx": switch sds["type"] { - case "mail": + case "exec": msg = fmt.Sprintf( - "Got mail from %s to %s (%s)", - nodeS, strings.Replace(sds["dst"], " ", ",", -1), size, + "Got exec from %s to %s (%s)", + nodeS, sds["dst"], size, ) case "file": msg = fmt.Sprintf("Got file %s (%s) from %s", sds["dst"], size, nodeS) diff --git a/src/cypherpunks.ru/nncp/jobs.go b/src/cypherpunks.ru/nncp/jobs.go index 574ab15ecff256706ca2c9d344ee56041a2a3a3eb3bf115d00527aa1cf3af3fa..3313bfc7e350fce557d69b7d272ebd6c1891b51f8f729d0db8e0b45f0a4612a1 100644 --- a/src/cypherpunks.ru/nncp/jobs.go +++ b/src/cypherpunks.ru/nncp/jobs.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 diff --git a/src/cypherpunks.ru/nncp/lockdir.go b/src/cypherpunks.ru/nncp/lockdir.go index 02c6cda04041e5db052a86249617eecf3d637932705aaee653ae6c2a2cd0945d..ec21c44ca509a09b52dd1093602da6feb87d1d172e3e190d2853539ad94d056f 100644 --- a/src/cypherpunks.ru/nncp/lockdir.go +++ b/src/cypherpunks.ru/nncp/lockdir.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 diff --git a/src/cypherpunks.ru/nncp/log.go b/src/cypherpunks.ru/nncp/log.go index 428726919d86246e49d3c523eaf120cf8bb8ac1c42bf587f79f83a4725e3c11e..c3b431b216fe0ee1e6ea5790d486cd04ff3c1f7aede29cef8899ada6ec2e93bc 100644 --- a/src/cypherpunks.ru/nncp/log.go +++ b/src/cypherpunks.ru/nncp/log.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 diff --git a/src/cypherpunks.ru/nncp/nncp.go b/src/cypherpunks.ru/nncp/nncp.go index 818cb6475e290061802aec5832f19a3e26b2f969a53af595b17b73f81b46a4f5..25e51e3d5a622616c4af1817bd35867709bf46b16b3aedfff522a7a79e7a01b1 100644 --- a/src/cypherpunks.ru/nncp/nncp.go +++ b/src/cypherpunks.ru/nncp/nncp.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 diff --git a/src/cypherpunks.ru/nncp/node.go b/src/cypherpunks.ru/nncp/node.go index e6ee0b862b969f746125771cff94ebdba24a11d5fe37572074120a54844f4535..7a0d4f85ee97754647aba41a75158d45807bfe96ceb44e552281ef745bb02c96 100644 --- a/src/cypherpunks.ru/nncp/node.go +++ b/src/cypherpunks.ru/nncp/node.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -42,7 +42,7 @@ Id *NodeId ExchPub *[32]byte SignPub ed25519.PublicKey NoisePub *[32]byte - Sendmail []string + Exec map[string][]string Incoming *string Freq *string FreqChunked int64 @@ -85,7 +85,10 @@ signPub, signPrv, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, err } - noiseKey := noise.DH25519.GenerateKeypair(rand.Reader) + noiseKey, err := noise.DH25519.GenerateKeypair(rand.Reader) + if err != nil { + return nil, err + } noisePub := new([32]byte) noisePrv := new([32]byte) copy(noisePrv[:], noiseKey.Private) diff --git a/src/cypherpunks.ru/nncp/pkt.go b/src/cypherpunks.ru/nncp/pkt.go index 43195080b78fb588b81d4381469c4d96c6269177543761104d8ac4e4b8ae79e3..2f430b518c084e5e745379c40641b8684c98d8e8809cf20c695aba641428317a 100644 --- a/src/cypherpunks.ru/nncp/pkt.go +++ b/src/cypherpunks.ru/nncp/pkt.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -42,12 +42,12 @@ KDFXOFSize = 2*(32+64) + 32 PktTypeFile PktType = iota PktTypeFreq PktType = iota - PktTypeMail PktType = iota + PktTypeExec PktType = iota PktTypeTrns PktType = iota MaxPathSize = 1<<8 - 1 - DefaultNiceMail = 64 + DefaultNiceExec = 64 DefaultNiceFreq = 64 DefaultNiceFile = 196 @@ -55,7 +55,7 @@ NNCPBundlePrefix = "NNCP" ) var ( - MagicNNCPPv1 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'P', 0, 0, 1} + MagicNNCPPv2 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'P', 0, 0, 2} MagicNNCPEv3 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'E', 0, 0, 3} BadMagic error = errors.New("Unknown magic number") BadPktType error = errors.New("Unknown packet type") @@ -67,6 +67,7 @@ type Pkt struct { Magic [8]byte Type PktType + Nice uint8 PathLen uint8 Path *[MaxPathSize]byte } @@ -120,18 +121,18 @@ } PktEncOverhead = int64(n) } -func NewPkt(typ PktType, path string) (*Pkt, error) { - pb := []byte(path) - if len(pb) > MaxPathSize { +func NewPkt(typ PktType, nice uint8, path []byte) (*Pkt, error) { + if len(path) > MaxPathSize { return nil, errors.New("Too long path") } pkt := Pkt{ - Magic: MagicNNCPPv1, + Magic: MagicNNCPPv2, Type: typ, - PathLen: uint8(len(pb)), + Nice: nice, + PathLen: uint8(len(path)), Path: new([MaxPathSize]byte), } - copy(pkt.Path[:], pb) + copy(pkt.Path[:], path) return &pkt, nil } diff --git a/src/cypherpunks.ru/nncp/pkt_test.go b/src/cypherpunks.ru/nncp/pkt_test.go index 780229505ead885ab5c25fd8e0b51d3c221ea957fab4d54eb86e37e6e2498696..ca901a44cece39e222430c0dbede26c570a756f2a33114a936b74328d322cd8b 100644 --- a/src/cypherpunks.ru/nncp/pkt_test.go +++ b/src/cypherpunks.ru/nncp/pkt_test.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -41,7 +41,7 @@ var ct bytes.Buffer if len(path) > int(pathSize) { path = path[:int(pathSize)] } - pkt, err := NewPkt(PktTypeFile, path) + pkt, err := NewPkt(PktTypeFile, 123, []byte(path)) if err != nil { panic(err) } @@ -87,7 +87,7 @@ var ct bytes.Buffer if len(path) > int(pathSize) { path = path[:int(pathSize)] } - pkt, err := NewPkt(PktTypeFile, path) + pkt, err := NewPkt(PktTypeFile, 123, []byte(path)) if err != nil { panic(err) } diff --git a/src/cypherpunks.ru/nncp/sp.go b/src/cypherpunks.ru/nncp/sp.go index ef08a174a625dfef6d9a18627fc87595adde7d39076e3fe2abb0d846a6bcc76b..c0e1e8e99c89e2aafd66d6b3fdfe85a00d0e4711f9b09866f8d846b74cfce1d2 100644 --- a/src/cypherpunks.ru/nncp/sp.go +++ b/src/cypherpunks.ru/nncp/sp.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -297,9 +297,13 @@ Public: ctx.Self.NoisePub[:], }, PeerStatic: node.NoisePub[:], } + hs, err := noise.NewHandshakeState(conf) + if err != nil { + return nil, err + } state := SPState{ ctx: ctx, - hs: noise.NewHandshakeState(conf), + hs: hs, Node: node, onlineDeadline: onlineDeadline, maxOnlineTime: maxOnlineTime, @@ -328,7 +332,11 @@ } var buf []byte var payload []byte - buf, _, _ = state.hs.WriteMessage(nil, firstPayload) + buf, _, _, err = state.hs.WriteMessage(nil, firstPayload) + if err != nil { + state.dirUnlock() + return nil, err + } sds := SDS{"node": nodeId, "nice": strconv.Itoa(int(nice))} ctx.LogD("sp-start", sds, "sending first message") conn.SetWriteDeadline(time.Now().Add(DefaultDeadline * time.Second)) @@ -371,9 +379,13 @@ Private: ctx.Self.NoisePrv[:], Public: ctx.Self.NoisePub[:], }, } + hs, err := noise.NewHandshakeState(conf) + if err != nil { + return nil, err + } state := SPState{ ctx: ctx, - hs: noise.NewHandshakeState(conf), + hs: hs, nice: nice, payloads: make(chan []byte), infosOurSeen: make(map[[32]byte]struct{}), @@ -383,7 +395,6 @@ xxOnly: xxOnly, } var buf []byte var payload []byte - var err error ctx.LogD( "sp-start", SDS{"nice": strconv.Itoa(int(nice))}, @@ -449,7 +460,11 @@ firstPayload = append(firstPayload, SPHaltMarshalized...) } ctx.LogD("sp-start", sds, "sending first message") - buf, state.csTheir, state.csOur = state.hs.WriteMessage(nil, firstPayload) + buf, state.csTheir, state.csOur, err = state.hs.WriteMessage(nil, firstPayload) + if err != nil { + state.dirUnlock() + return nil, err + } conn.SetWriteDeadline(time.Now().Add(DefaultDeadline * time.Second)) if err = state.WriteSP(conn, buf); err != nil { ctx.LogE("sp-start", SdsAdd(sds, SDS{"err": err}), "") diff --git a/src/cypherpunks.ru/nncp/tmp.go b/src/cypherpunks.ru/nncp/tmp.go index ea17a205014c134454c2baa5d1c42a346d2b8b32e6ad28aee9d0201d957df55d..4d6f0623603b85cdf955ba1666bc40bf437edc7a22bad46db66f22ee483983e6 100644 --- a/src/cypherpunks.ru/nncp/tmp.go +++ b/src/cypherpunks.ru/nncp/tmp.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 diff --git a/src/cypherpunks.ru/nncp/toss.go b/src/cypherpunks.ru/nncp/toss.go index cf2735763945d1af9124e284b9c262f33e304d3c653e8c452546cdab81bf8787..1942efc0140cfb768a79b03c8153f3c74db07e61f364d25793cdc4837dc2246e 100644 --- a/src/cypherpunks.ru/nncp/toss.go +++ b/src/cypherpunks.ru/nncp/toss.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -20,6 +20,7 @@ package nncp import ( "bufio" + "bytes" "compress/zlib" "fmt" "io" @@ -51,7 +52,7 @@ mime.BEncoding.Encode("UTF-8", subject), )) } -func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun, doSeen bool) bool { +func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun, doSeen, noFile, noFreq, noExec, noTrns bool) bool { isBad := false for job := range ctx.Jobs(nodeId, TRx) { pktName := filepath.Base(job.Fd.Name()) @@ -92,35 +93,45 @@ pktSize = job.Size - PktEncOverhead - PktOverhead sds["size"] = strconv.FormatInt(pktSize, 10) ctx.LogD("rx", sds, "taken") switch pkt.Type { - case PktTypeMail: - recipients := string(pkt.Path[:int(pkt.PathLen)]) + case PktTypeExec: + if noExec { + goto Closing + } + path := bytes.Split(pkt.Path[:int(pkt.PathLen)], []byte{0}) + handle := string(path[0]) + args := make([]string, 0, len(path)-1) + for _, p := range path[1:] { + args = append(args, string(p)) + } sds := SdsAdd(sds, SDS{ - "type": "mail", - "dst": recipients, + "type": "exec", + "dst": strings.Join(append([]string{handle}, args...), " "), }) decompressor, err := zlib.NewReader(pipeR) if err != nil { log.Fatalln(err) } sender := ctx.Neigh[*job.PktEnc.Sender] - sendmail := sender.Sendmail - if len(sendmail) == 0 { - ctx.LogE("rx", SdsAdd(sds, SDS{"err": "No sendmail configured"}), "") + cmdline, exists := sender.Exec[handle] + if !exists || len(cmdline) == 0 { + ctx.LogE("rx", SdsAdd(sds, SDS{"err": "No handle found"}), "") isBad = true goto Closing } if !dryRun { cmd := exec.Command( - sendmail[0], - append( - sendmail[1:len(sendmail)], - strings.Split(recipients, " ")..., - )..., + cmdline[0], + append(cmdline[1:len(cmdline)], args...)..., ) - cmd.Env = append(cmd.Env, "NNCP_SENDER="+sender.Id.String()) + cmd.Env = append( + cmd.Env, + "NNCP_SELF="+ctx.Self.Id.String(), + "NNCP_SENDER="+sender.Id.String(), + "NNCP_NICE="+strconv.Itoa(int(pkt.Nice)), + ) cmd.Stdin = decompressor if err = cmd.Run(); err != nil { - ctx.LogE("rx", SdsAdd(sds, SDS{"err": err}), "sendmail") + ctx.LogE("rx", SdsAdd(sds, SDS{"err": err}), "handle") isBad = true goto Closing } @@ -138,6 +149,9 @@ isBad = true } } case PktTypeFile: + if noFile { + goto Closing + } dst := string(pkt.Path[:int(pkt.PathLen)]) sds := SdsAdd(sds, SDS{"type": "file", "dst": dst}) if filepath.IsAbs(dst) { @@ -207,8 +221,8 @@ if err = os.Remove(job.Fd.Name()); err != nil { ctx.LogE("rx", SdsAdd(sds, SDS{"err": err}), "remove") isBad = true } - sendmail := ctx.Neigh[*ctx.SelfId].Sendmail - if ctx.NotifyFile != nil { + sendmail, exists := ctx.Neigh[*ctx.SelfId].Exec["sendmail"] + if exists && len(sendmail) > 0 && ctx.NotifyFile != nil { cmd := exec.Command( sendmail[0], append(sendmail[1:len(sendmail)], ctx.NotifyFile.To)..., @@ -223,6 +237,9 @@ cmd.Run() } } case PktTypeFreq: + if noFreq { + goto Closing + } src := string(pkt.Path[:int(pkt.PathLen)]) if filepath.IsAbs(src) { ctx.LogE("rx", sds, "non-relative source path") @@ -249,7 +266,7 @@ if !dryRun { if sender.FreqChunked == 0 { err = ctx.TxFile( sender, - job.PktEnc.Nice, + pkt.Nice, filepath.Join(*freq, src), dst, sender.FreqMinSize, @@ -257,7 +274,7 @@ ) } else { err = ctx.TxFileChunked( sender, - job.PktEnc.Nice, + pkt.Nice, filepath.Join(*freq, src), dst, sender.FreqMinSize, @@ -281,8 +298,8 @@ if err = os.Remove(job.Fd.Name()); err != nil { ctx.LogE("rx", SdsAdd(sds, SDS{"err": err}), "remove") isBad = true } - if ctx.NotifyFreq != nil { - sendmail := ctx.Neigh[*ctx.SelfId].Sendmail + sendmail, exists := ctx.Neigh[*ctx.SelfId].Exec["sendmail"] + if exists && len(sendmail) > 0 && ctx.NotifyFreq != nil { cmd := exec.Command( sendmail[0], append(sendmail[1:len(sendmail)], ctx.NotifyFreq.To)..., @@ -296,6 +313,9 @@ cmd.Run() } } case PktTypeTrns: + if noTrns { + goto Closing + } dst := new([blake2b.Size256]byte) copy(dst[:], pkt.Path[:int(pkt.PathLen)]) nodeId := NodeId(*dst) diff --git a/src/cypherpunks.ru/nncp/toss_test.go b/src/cypherpunks.ru/nncp/toss_test.go index 5dd901e5425df26bb48631a67a5484cb8bf914ceb795811786bba29924956a2c..cb763838a67fd4bbc6cde49f2ec73e06fb606fb5299ad204de4020d6a60c53ff 100644 --- a/src/cypherpunks.ru/nncp/toss_test.go +++ b/src/cypherpunks.ru/nncp/toss_test.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -51,8 +51,9 @@ } return names } -func TestTossEmail(t *testing.T) { - f := func(recipients [16]uint8) bool { +func TestTossExec(t *testing.T) { + f := func(replyNice uint8, handleRaw uint32, recipients [16]uint8) bool { + handle := strconv.Itoa(int(handleRaw)) for i, recipient := range recipients { recipients[i] = recipient % 8 } @@ -90,11 +91,13 @@ privates[recipient] = our ctx.Neigh[*our.Id] = our.Their() } for _, recipient := range recipients { - if err := ctx.TxMail( + if err := ctx.TxExec( ctx.Neigh[*privates[recipient].Id], - DefaultNiceMail, - "recipient", - []byte{123}, + DefaultNiceExec, + replyNice, + handle, + []string{"arg0", "arg1"}, + []byte("BODY\n"), 1<<15, ); err != nil { t.Error(err) @@ -108,20 +111,25 @@ os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath) if len(dirFiles(rxPath)) == 0 { continue } - ctx.Toss(ctx.Self.Id, DefaultNiceMail-1, false, false) + ctx.Toss(ctx.Self.Id, DefaultNiceExec-1, false, false, false, false, false, false) if len(dirFiles(rxPath)) == 0 { return false } - ctx.Neigh[*nodeOur.Id].Sendmail = []string{"/bin/sh", "-c", "false"} - ctx.Toss(ctx.Self.Id, DefaultNiceMail, false, false) + ctx.Neigh[*nodeOur.Id].Exec = make(map[string][]string) + ctx.Neigh[*nodeOur.Id].Exec[handle] = []string{"/bin/sh", "-c", "false"} + ctx.Toss(ctx.Self.Id, DefaultNiceExec, false, false, false, false, false, false) if len(dirFiles(rxPath)) == 0 { return false } - ctx.Neigh[*nodeOur.Id].Sendmail = []string{ + ctx.Neigh[*nodeOur.Id].Exec[handle] = []string{ "/bin/sh", "-c", - fmt.Sprintf("cat >> %s", filepath.Join(spool, "mbox")), + fmt.Sprintf( + "echo $NNCP_NICE $0 $1 >> %s ; cat >> %s", + filepath.Join(spool, "mbox"), + filepath.Join(spool, "mbox"), + ), } - ctx.Toss(ctx.Self.Id, DefaultNiceMail, false, false) + ctx.Toss(ctx.Self.Id, DefaultNiceExec, false, false, false, false, false, false) if len(dirFiles(rxPath)) != 0 { return false } @@ -132,7 +140,11 @@ return false } expected := make([]byte, 0, 16) for i := 0; i < 16; i++ { - expected = append(expected, 123) + expected = append( + expected, + []byte(fmt.Sprintf("%d arg0 arg1\n", replyNice))..., + ) + expected = append(expected, []byte("BODY\n")...) } return bytes.Compare(mbox, expected) == 0 } @@ -195,12 +207,12 @@ } } rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx)) os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath) - ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false) + ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false, false, false, false, false) if len(dirFiles(rxPath)) == 0 { return false } ctx.Neigh[*nodeOur.Id].Incoming = &incomingPath - ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false) + ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false, false, false, false, false) if len(dirFiles(rxPath)) != 0 { return false } @@ -270,7 +282,7 @@ } rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx)) os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath) ctx.Neigh[*nodeOur.Id].Incoming = &incomingPath - ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false) + ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false, false, false, false, false) expected := make(map[string]struct{}) expected["samefile"] = struct{}{} for i := 0; i < files-1; i++ { @@ -293,7 +305,7 @@ } } func TestTossFreq(t *testing.T) { - f := func(fileSizes []uint8) bool { + f := func(fileSizes []uint8, replyNice uint8) bool { if len(fileSizes) == 0 { return true } @@ -328,6 +340,7 @@ files[fileName] = fileData if err := ctx.TxFreq( ctx.Neigh[*nodeOur.Id], DefaultNiceFreq, + replyNice, fileName, fileName, 1<<15, @@ -340,12 +353,12 @@ rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx)) txPath := filepath.Join(spool, ctx.Self.Id.String(), string(TTx)) os.Rename(txPath, rxPath) os.MkdirAll(txPath, os.FileMode(0700)) - ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false) + ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false, false, false, false, false) if len(dirFiles(txPath)) != 0 || len(dirFiles(rxPath)) == 0 { return false } ctx.Neigh[*nodeOur.Id].Freq = &spool - ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false) + ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false, false, false, false, false) if len(dirFiles(txPath)) != 0 || len(dirFiles(rxPath)) == 0 { return false } @@ -358,7 +371,7 @@ ); err != nil { panic(err) } } - ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false) + ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false, false, false, false, false) if len(dirFiles(txPath)) == 0 || len(dirFiles(rxPath)) != 0 { return false } @@ -374,6 +387,9 @@ if _, err = xdr.Unmarshal(&buf, &pkt); err != nil { t.Error(err) return false } + if pkt.Nice != replyNice { + return false + } dst := string(pkt.Path[:int(pkt.PathLen)]) if bytes.Compare(buf.Bytes(), files[dst]) != 0 { return false @@ -426,7 +442,7 @@ txPath := filepath.Join(spool, ctx.Self.Id.String(), string(TTx)) os.MkdirAll(txPath, os.FileMode(0700)) for _, data := range datum { pktTrans := Pkt{ - Magic: MagicNNCPPv1, + Magic: MagicNNCPPv2, Type: PktTypeTrns, PathLen: blake2b.Size256, Path: new([MaxPathSize]byte), @@ -455,7 +471,7 @@ ); err != nil { panic(err) } } - ctx.Toss(ctx.Self.Id, 123, false, false) + ctx.Toss(ctx.Self.Id, 123, false, false, false, false, false, false) if len(dirFiles(rxPath)) != 0 { return false } @@ -467,7 +483,6 @@ } for k, data := range datum { if bytes.Compare(dataRead, data) == 0 { delete(datum, k) - break } } } diff --git a/src/cypherpunks.ru/nncp/tx.go b/src/cypherpunks.ru/nncp/tx.go index f63d061fb456035fa19308d02bd3a07f2af67bd8bc9b780ebd2b7200ff402207..e93b7e84085653c08d56a67b0b0c5e95dc1b07d7b247a9c961927e343947856d 100644 --- a/src/cypherpunks.ru/nncp/tx.go +++ b/src/cypherpunks.ru/nncp/tx.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -68,13 +68,7 @@ curSize += padSize var pipeRPrev io.Reader for i := 1; i < len(hops); i++ { - pktTrans := Pkt{ - Magic: MagicNNCPPv1, - Type: PktTypeTrns, - PathLen: blake2b.Size256, - Path: new([MaxPathSize]byte), - } - copy(pktTrans.Path[:], hops[i-1].Id[:]) + pktTrns, _ := NewPkt(PktTypeTrns, 0, hops[i-1].Id[:]) curSize += PktOverhead + PktEncOverhead pipeRPrev = pipeR pipeR, pipeW = io.Pipe() @@ -86,7 +80,7 @@ "size": strconv.FormatInt(size, 10), }, "trns wrote") errs <- PktEncWrite(ctx.Self, node, pkt, nice, size, 0, src, dst) dst.Close() - }(hops[i], &pktTrans, curSize, pipeRPrev, pipeW) + }(hops[i], pktTrns, curSize, pipeRPrev, pipeW) } go func() { _, err := io.Copy(tmp.W, pipeR) @@ -157,7 +151,7 @@ dstPath = filepath.Clean(dstPath) if filepath.IsAbs(dstPath) { return errors.New("Relative destination path required") } - pkt, err := NewPkt(PktTypeFile, dstPath) + pkt, err := NewPkt(PktTypeFile, nice, []byte(dstPath)) if err != nil { return err } @@ -169,25 +163,19 @@ if err != nil { return err } _, err = ctx.Tx(node, pkt, nice, fileSize, minSize, reader) + sds := SDS{ + "type": "file", + "node": node.Id, + "nice": strconv.Itoa(int(nice)), + "src": srcPath, + "dst": dstPath, + "size": strconv.FormatInt(fileSize, 10), + } if err == nil { - ctx.LogI("tx", SDS{ - "type": "file", - "node": node.Id, - "nice": strconv.Itoa(int(nice)), - "src": srcPath, - "dst": dstPath, - "size": strconv.FormatInt(fileSize, 10), - }, "sent") + ctx.LogI("tx", sds, "sent") } else { - ctx.LogE("tx", SDS{ - "type": "file", - "node": node.Id, - "nice": strconv.Itoa(int(nice)), - "src": srcPath, - "dst": dstPath, - "size": strconv.FormatInt(fileSize, 10), - "err": err, - }, "sent") + sds["err"] = err + ctx.LogE("tx", sds, "sent") } return err } @@ -211,6 +199,29 @@ if err != nil { return err } + if fileSize <= chunkSize { + pkt, err := NewPkt(PktTypeFile, nice, []byte(dstPath)) + if err != nil { + return err + } + _, err = ctx.Tx(node, pkt, nice, fileSize, minSize, reader) + sds := SDS{ + "type": "file", + "node": node.Id, + "nice": strconv.Itoa(int(nice)), + "src": srcPath, + "dst": dstPath, + "size": strconv.FormatInt(fileSize, 10), + } + if err == nil { + ctx.LogI("tx", sds, "sent") + } else { + sds["err"] = err + ctx.LogE("tx", sds, "sent") + } + return err + } + leftSize := fileSize metaPkt := ChunkedMeta{ Magic: MagicNNCPMv1, @@ -234,7 +245,7 @@ } else { sizeToSend = chunkSize } path = dstPath + ChunkedSuffixPart + strconv.Itoa(chunkNum) - pkt, err = NewPkt(PktTypeFile, path) + pkt, err = NewPkt(PktTypeFile, nice, []byte(path)) if err != nil { return err } @@ -250,25 +261,19 @@ sizeToSend, minSize, io.TeeReader(reader, hsh), ) + sds := SDS{ + "type": "file", + "node": node.Id, + "nice": strconv.Itoa(int(nice)), + "src": srcPath, + "dst": path, + "size": strconv.FormatInt(sizeToSend, 10), + } if err == nil { - ctx.LogI("tx", SDS{ - "type": "file", - "node": node.Id, - "nice": strconv.Itoa(int(nice)), - "src": srcPath, - "dst": path, - "size": strconv.FormatInt(sizeToSend, 10), - }, "sent") + ctx.LogI("tx", sds, "sent") } else { - ctx.LogE("tx", SDS{ - "type": "file", - "node": node.Id, - "nice": strconv.Itoa(int(nice)), - "src": srcPath, - "dst": path, - "size": strconv.FormatInt(sizeToSend, 10), - "err": err, - }, "sent") + sds["err"] = err + ctx.LogE("tx", sds, "sent") return err } hsh.Sum(metaPkt.Checksums[chunkNum][:0]) @@ -284,36 +289,30 @@ if err != nil { return err } path = dstPath + ChunkedSuffixMeta - pkt, err = NewPkt(PktTypeFile, path) + pkt, err = NewPkt(PktTypeFile, nice, []byte(path)) if err != nil { return err } metaPktSize := int64(metaBuf.Len()) _, err = ctx.Tx(node, pkt, nice, metaPktSize, minSize, &metaBuf) + sds := SDS{ + "type": "file", + "node": node.Id, + "nice": strconv.Itoa(int(nice)), + "src": srcPath, + "dst": path, + "size": strconv.FormatInt(metaPktSize, 10), + } if err == nil { - ctx.LogI("tx", SDS{ - "type": "file", - "node": node.Id, - "nice": strconv.Itoa(int(nice)), - "src": srcPath, - "dst": path, - "size": strconv.FormatInt(metaPktSize, 10), - }, "sent") + ctx.LogI("tx", sds, "sent") } else { - ctx.LogE("tx", SDS{ - "type": "file", - "node": node.Id, - "nice": strconv.Itoa(int(nice)), - "src": srcPath, - "dst": path, - "size": strconv.FormatInt(metaPktSize, 10), - "err": err, - }, "sent") + sds["err"] = err + ctx.LogE("tx", sds, "sent") } return err } -func (ctx *Ctx) TxFreq(node *Node, nice uint8, srcPath, dstPath string, minSize int64) error { +func (ctx *Ctx) TxFreq(node *Node, nice, replyNice uint8, srcPath, dstPath string, minSize int64) error { dstPath = filepath.Clean(dstPath) if filepath.IsAbs(dstPath) { return errors.New("Relative destination path required") @@ -322,36 +321,37 @@ srcPath = filepath.Clean(srcPath) if filepath.IsAbs(srcPath) { return errors.New("Relative source path required") } - pkt, err := NewPkt(PktTypeFreq, srcPath) + pkt, err := NewPkt(PktTypeFreq, replyNice, []byte(srcPath)) if err != nil { return err } src := strings.NewReader(dstPath) size := int64(src.Len()) _, err = ctx.Tx(node, pkt, nice, size, minSize, src) + sds := SDS{ + "type": "freq", + "node": node.Id, + "nice": strconv.Itoa(int(nice)), + "replynice": strconv.Itoa(int(replyNice)), + "src": srcPath, + "dst": dstPath, + } if err == nil { - ctx.LogI("tx", SDS{ - "type": "freq", - "node": node.Id, - "nice": strconv.Itoa(int(nice)), - "src": srcPath, - "dst": dstPath, - }, "sent") + ctx.LogI("tx", sds, "sent") } else { - ctx.LogE("tx", SDS{ - "type": "freq", - "node": node.Id, - "nice": strconv.Itoa(int(nice)), - "src": srcPath, - "dst": dstPath, - "err": err, - }, "sent") + sds["err"] = err + ctx.LogE("tx", sds, "sent") } return err } -func (ctx *Ctx) TxMail(node *Node, nice uint8, recipient string, body []byte, minSize int64) error { - pkt, err := NewPkt(PktTypeMail, recipient) +func (ctx *Ctx) TxExec(node *Node, nice, replyNice uint8, handle string, args []string, body []byte, minSize int64) error { + path := make([][]byte, 0, 1+len(args)) + path = append(path, []byte(handle)) + for _, arg := range args { + path = append(path, []byte(arg)) + } + pkt, err := NewPkt(PktTypeExec, replyNice, bytes.Join(path, []byte{0})) if err != nil { return err } @@ -366,34 +366,31 @@ } compressor.Close() size := int64(compressed.Len()) _, err = ctx.Tx(node, pkt, nice, size, minSize, &compressed) + sds := SDS{ + "type": "exec", + "node": node.Id, + "nice": strconv.Itoa(int(nice)), + "replynice": strconv.Itoa(int(replyNice)), + "dst": strings.Join(append([]string{handle}, args...), " "), + "size": strconv.FormatInt(size, 10), + } if err == nil { - ctx.LogI("tx", SDS{ - "type": "mail", - "node": node.Id, - "nice": strconv.Itoa(int(nice)), - "dst": recipient, - "size": strconv.FormatInt(size, 10), - }, "sent") + ctx.LogI("tx", sds, "sent") } else { - ctx.LogE("tx", SDS{ - "type": "mail", - "node": node.Id, - "nice": strconv.Itoa(int(nice)), - "dst": recipient, - "size": strconv.FormatInt(size, 10), - "err": err, - }, "sent") + sds["err"] = err + ctx.LogE("tx", sds, "sent") } return err } func (ctx *Ctx) TxTrns(node *Node, nice uint8, size int64, src io.Reader) error { - ctx.LogD("tx", SDS{ + sds := SDS{ "type": "trns", "node": node.Id, "nice": strconv.Itoa(int(nice)), "size": strconv.FormatInt(size, 10), - }, "taken") + } + ctx.LogD("tx", sds, "taken") tmp, err := ctx.NewTmpFileWHash() if err != nil { return err @@ -404,20 +401,10 @@ } nodePath := filepath.Join(ctx.Spool, node.Id.String()) err = tmp.Commit(filepath.Join(nodePath, string(TTx))) if err == nil { - ctx.LogI("tx", SDS{ - "type": "trns", - "node": node.Id, - "nice": strconv.Itoa(int(nice)), - "size": strconv.FormatInt(size, 10), - }, "sent") + ctx.LogI("tx", sds, "sent") } else { - ctx.LogI("tx", SDS{ - "type": "trns", - "node": node.Id, - "nice": strconv.Itoa(int(nice)), - "size": strconv.FormatInt(size, 10), - "err": err, - }, "sent") + sds["err"] = err + ctx.LogI("tx", sds, "sent") } os.Symlink(nodePath, filepath.Join(ctx.Spool, node.Name)) return err diff --git a/src/cypherpunks.ru/nncp/tx_test.go b/src/cypherpunks.ru/nncp/tx_test.go index 2cd2e22c81742efa64f52eda45a0cbdb0577eb4d94cb7fb3161b468807ec2f7c..55e7a4eba6cc1498d87924ca6b3b1ee0be601a3cf627953bd83785216d390c97 100644 --- a/src/cypherpunks.ru/nncp/tx_test.go +++ b/src/cypherpunks.ru/nncp/tx_test.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2017 Sergey Matveev +Copyright (C) 2016-2018 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 @@ -33,7 +33,7 @@ "golang.org/x/crypto/blake2b" ) func TestTx(t *testing.T) { - f := func(hops uint8, pathSrc, data string, nice uint8, padSize int16) bool { + f := func(hops uint8, pathSrc, data string, nice, replyNice uint8, padSize int16) bool { if len(pathSrc) > int(MaxPathSize) { pathSrc = pathSrc[:MaxPathSize] } @@ -76,7 +76,7 @@ ctx.Neigh[*node.Id] = node.Their() privates[*node.Id] = node nodeTgt.Via = append(nodeTgt.Via, node.Id) } - pkt, err := NewPkt(PktTypeMail, pathSrc) + pkt, err := NewPkt(PktTypeExec, replyNice, []byte(pathSrc)) src := strings.NewReader(data) dstNode, err := ctx.Tx( nodeTgt, @@ -121,7 +121,10 @@ if _, err = xdr.Unmarshal(&bufR, &pkt); err != nil { return false } if *hopId == *nodeTgt.Id { - if pkt.Type != PktTypeMail { + if pkt.Type != PktTypeExec { + return false + } + if pkt.Nice != replyNice { return false } if !bytes.HasPrefix(pkt.Path[:], []byte(pathSrc)) {