diff options
author | Guilhem Moulin <guilhem@debian.org> | 2022-02-27 16:54:38 +0100 |
---|---|---|
committer | Guilhem Moulin <guilhem@debian.org> | 2022-02-27 16:54:38 +0100 |
commit | 3656ac995b07c5cdeb881b88f371abf38cfb0bc4 (patch) | |
tree | 4365cb82a3fb51decc6a1e2547b0e755df31456c | |
parent | 1c596d75696e8342e9b489ba0bc7b5e7009fa90e (diff) | |
parent | 8ad5e5a218253a76eabf36bfd83f9e1a2a708377 (diff) |
Merge tag 'v0.5.7' into debian/latest
Release version 0.5.7
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | Changelog | 47 | ||||
-rw-r--r-- | Makefile | 135 | ||||
-rw-r--r-- | README | 6 | ||||
-rwxr-xr-x | benchmark/run | 5 | ||||
-rw-r--r-- | doc/benchmark.md | 4 | ||||
-rw-r--r-- | doc/build.md | 65 | ||||
-rw-r--r-- | doc/development.md | 12 | ||||
-rw-r--r-- | doc/getting-started.md | 5 | ||||
-rwxr-xr-x | interimap | 17 | ||||
-rw-r--r-- | interimap.service | 3 | ||||
-rw-r--r-- | interimap@.service | 3 | ||||
-rw-r--r-- | lib/Net/IMAP/InterIMAP.pm | 7 | ||||
-rwxr-xr-x | pullimap | 7 | ||||
-rw-r--r-- | pullimap@.service | 3 | ||||
-rwxr-xr-x | tests/certs/generate | 18 | ||||
-rw-r--r-- | tests/certs/openssl.cnf | 4 | ||||
-rw-r--r-- | tests/config/dovecot/ssl.conf | 3 | ||||
-rw-r--r-- | tests/db-exclusive-lock/t | 4 | ||||
-rw-r--r-- | tests/db-no-create--watch/t | 2 | ||||
-rw-r--r-- | tests/interimap.list (renamed from tests/list) | 3 | ||||
-rw-r--r-- | tests/pullimap.list | 2 | ||||
-rw-r--r-- | tests/pullimap/t | 45 | ||||
-rwxr-xr-x | tests/run | 20 | ||||
-rwxr-xr-x | tests/run-all | 3 | ||||
-rw-r--r-- | tests/tls-protocols/openssl.cnf | 2 | ||||
-rw-r--r--[l---------] | tests/tls-protocols/remote.conf | 5 | ||||
-rw-r--r-- | tests/tls-rsa+ecdsa/t | 2 |
28 files changed, 294 insertions, 142 deletions
@@ -1,6 +1,4 @@ *~ *.bak -/doc/*.1 -/doc/*.html -!/doc/template.html +/build/ /.pc/ @@ -1,3 +1,50 @@ +interimap (0.5.7) upstream; + + * interimap: create database with mode 0600 (but don't change mode of + existing databases). The file was previously created with mode 0644 + minus umask restrictions, which for permissive umask(2)s is too open. + That being said its parent directory is created with restricted mode + 0700 so the impact is limited. pullimap, on the other hand, already + used mode 0600 for state file creation. + * Major Makefile refactoring: improve DESTDIR= handling, add new + targets 'all-nodoc', 'install-nodoc', and 'installcheck'. Also, + rename 'test' target to 'check'. + * `make install` now installs Net/IMAP/InterIMAP.pm to + /usr/local/lib/site_perl by default rather than /usr/local/share/perl5 + (which is not in @INC as of perl 5.34.0-3 from Debian sid). The + installation directory is configurable with sitelib=. + * Refactor test harness so one can check the source with `tests/run + foo`; what's been built with `INTERIMAP_I=./lib INTERIMAP_PATH=./build + ./tests/run foo`, and what's installed with `INTERIMAP_I="" + INTERIMAP_PATH=/usr/bin tests/run foo`. + * Split interimap and pullimap test suites. + + Improve message for missing untagged UIDNEXT responses, which we + require but are omitted from some servers. + + tests/tls-protocols: downgrade OpenSSL security level to 0, which is + required to test TLS version <1.2 on systems with higher security + levels, see SSL_CTX_set_security_level(3ssl). Adapted from a patch + from <xnox> for Unbuntu. + + tests/tls-*: bump Dovecot's ssl_min_protocol to TLSv1.2, which is the + default as of dovecot 1:2.3.18+dfsg1-1 from Debian sid. + + `make clean` now cleans test certificates and key material. + + Add 'use lib "./lib";' to interimap and pullimap, so the programs can + be run directly from the source directory. The directory is + substituted with $(sitelib) at compile time (and the line is commented + out if $(sitelib) is found in @INC). + + doc/build.md: update documentation, and add a new section for how to + install without root privileges. + + Add Documentation=https://guilhem.org/interimap/... URIs to .service + files. + - Don't hardcode path to interimap/pullimap in .service files, and + instead use $(bindir) (expanded at compile time). + - tests/certs/generate: redirect known error output to the standard + output. + - tests/certs/generate: use custom openssl.cnf to avoid depending on + the system default. + - tests/pullimap: allow easy exclusion of --idle'ing tests. + + -- Guilhem Moulin <guilhem@fripost.org> Sun, 27 Feb 2022 16:24:31 +0100 + interimap (0.5.6) upstream; - Bump required Net::SSLeay version to 1.86_06 as it's when get_version() @@ -1,80 +1,117 @@ -DESTDIR ?= /usr/local -BUILD_DOCDIR ?= ./doc +srcdir ?= . +builddir ?= build +prefix ?= /usr/local +exec_prefix ?= $(prefix) +bindir ?= $(exec_prefix)/bin +libdir ?= $(exec_prefix)/lib +sitelib ?= $(libdir)/site_perl +datarootdir ?= $(prefix)/share +mandir ?= $(datarootdir)/man +man1dir ?= $(mandir)/man1 +systemd_userunitdir ?= $(libdir)/systemd/user + CSS ?= /usr/share/javascript/bootstrap4/css/bootstrap.css -HTML_TEMPLATE ?= ./doc/template.html +HTML_TEMPLATE ?= $(srcdir)/doc/template.html -HTML_FILES = $(addprefix $(BUILD_DOCDIR)/,$(patsubst ./doc/%.md,%.html,$(wildcard ./doc/*.md))) -MANUAL_FILES = $(addprefix $(BUILD_DOCDIR)/,$(patsubst ./doc/%.md,%,$(wildcard ./doc/*.[1-9].md))) +PROGRAMS = $(addprefix $(builddir)/,interimap pullimap) +HTML_FILES = $(patsubst $(srcdir)/doc/%.md,$(builddir)/doc/%.html,$(wildcard $(srcdir)/doc/*.md)) +MANUAL_FILES = $(patsubst $(srcdir)/doc/%.md,$(builddir)/doc/%,$(wildcard $(srcdir)/doc/*.[1-9].md)) +SERVICE_FILES = $(patsubst $(srcdir)/%.service,$(builddir)/%.service,$(wildcard $(srcdir)/*.service)) -all: manual +all: all-nodoc manual +all-nodoc: $(PROGRAMS) $(SERVICE_FILES) +doc: manual html manual: $(MANUAL_FILES) html: $(HTML_FILES) +$(PROGRAMS): $(builddir)/%: $(srcdir)/% + @mkdir -vp $(dir $@) + perl -Te "print \"\$$_\\0\" foreach @INC;" | grep -Fxzq -e "$(sitelib)" && prefix="#" || prefix=""; \ + sed -r "0,/^(use\\s+\lib\\s+)([\"'])[^\"']*\\2\\s*;/ s||$$prefix\\1\"$(sitelib)\";|" <"$<" >"$@" + chmod --reference="$<" -- "$@" + # upper case the headers and remove the links -$(MANUAL_FILES): $(BUILD_DOCDIR)/%: ./doc/%.md - pandoc -f markdown -t json -- "$<" | ./pandoc2man.jq | pandoc -s -f json -t man -o "$@" +$(MANUAL_FILES): $(builddir)/doc/%: $(srcdir)/doc/%.md + @mkdir -vp $(dir $@) + pandoc -f markdown -t json -- "$<" | $(srcdir)/pandoc2man.jq | pandoc -s -f json -t man -o "$@" + +$(SERVICE_FILES): $(builddir)/%.service: $(srcdir)/%.service + @mkdir -vp $(dir $@) + sed "s|@bindir@|$(bindir)|" <"$<" >"$@" -test: - ./tests/certs/generate - ./tests/run-all +testcerts: + $(srcdir)/tests/certs/generate + +check: check-interimap check-pullimap +check-interimap: $(builddir)/interimap testcerts + INTERIMAP_I=$(srcdir)/lib INTERIMAP_PATH=$(builddir) $(srcdir)/tests/run-all interimap.list +check-pullimap: $(builddir)/pullimap testcerts + INTERIMAP_I=$(srcdir)/lib INTERIMAP_PATH=$(builddir) $(srcdir)/tests/run-all pullimap.list + +installcheck: installcheck-interimap installcheck-pullimap +installcheck-interimap: testcerts + INTERIMAP_I="" INTERIMAP_PATH=$(bindir) $(srcdir)/tests/run-all interimap.list +installcheck-pullimap: testcerts + INTERIMAP_I="" INTERIMAP_PATH=$(bindir) $(srcdir)/tests/run-all pullimap.list release: - @if ! git diff HEAD --quiet -- ./Changelog ./interimap ./pullimap ./lib/Net/IMAP/InterIMAP.pm; then \ + @if ! git -C $(srcdir) diff --quiet HEAD -- Changelog interimap pullimap lib/Net/IMAP/InterIMAP.pm; then \ echo "Dirty state, refusing to release!" >&2; \ exit 1; \ fi - VERS=$$(dpkg-parsechangelog -l Changelog -SVersion 2>/dev/null) && \ - if git rev-parse -q --verify "refs/tags/v$$VERS" >/dev/null; then echo "tag exists" 2>/dev/null; exit 1; fi && \ - sed -ri "0,/^( -- .*) .*/ s//\\1 $(shell date -R)/" ./Changelog && \ + VERS=$$(dpkg-parsechangelog -l $(srcdir)/Changelog -SVersion 2>/dev/null) && \ + if git -C $(srcdir) rev-parse -q --verify "refs/tags/v$$VERS" >/dev/null; then echo "tag exists" 2>/dev/null; exit 1; fi && \ + sed -ri "0,/^( -- .*) .*/ s//\\1 $(shell date -R)/" $(srcdir)/Changelog && \ sed -ri "0,/^(our\\s+\\\$$VERSION\\s*=\\s*)'[0-9.]+'\\s*;/ s//\\1'$$VERS';/" \ - -- ./interimap ./pullimap && \ + -- $(srcdir)/interimap $(srcdir)/pullimap && \ sed -ri "0,/^(package\\s+Net::IMAP::InterIMAP\\s+)v[0-9.]+\\s*;/ s//\\1v$$VERS;/" \ - -- ./lib/Net/IMAP/InterIMAP.pm && \ + -- $(srcdir)/lib/Net/IMAP/InterIMAP.pm && \ sed -ri "0,/^(use\\s+Net::IMAP::InterIMAP\\s+)[0-9.]+(\\s|\\$$)/ s//\\1$$VERS\\2/" \ - -- ./interimap ./pullimap && \ - git commit -m "Prepare new release v$$VERS." \ - -- ./Changelog ./interimap ./pullimap ./lib/Net/IMAP/InterIMAP.pm && \ - git tag -sm "Release version $$VERS" "v$$VERS" - -## make html CSS="https://guilhem.org/static/css/bootstrap.min.css" BUILD_DOCDIR="$XDG_RUNTIME_DIR/Downloads" -$(HTML_FILES): $(BUILD_DOCDIR)/%.html: ./doc/%.md $(HTML_TEMPLATE) - mtime="$$(git --no-pager log -1 --pretty="format:%ct" -- "$<" 2>/dev/null)"; \ + -- $(srcdir)/interimap $(srcdir)/pullimap && \ + git -C $(srcdir) commit -m "Prepare new release v$$VERS." \ + -- Changelog interimap pullimap lib/Net/IMAP/InterIMAP.pm && \ + git -C $(srcdir) tag -sm "Release version $$VERS" "v$$VERS" + +$(HTML_FILES): $(builddir)/doc/%.html: $(srcdir)/doc/%.md $(HTML_TEMPLATE) + @mkdir -vp $(dir $@) + mtime="$$(git -C $(srcdir) --no-pager log -1 --pretty="format:%ct" -- "$<" 2>/dev/null)"; \ [ -n "$$mtime" ] || mtime="$$(date +%s -r "$<")"; \ - [ "$<" = "doc/index.md" ] && parent="" || parent="./index.html"; \ pandoc -sp -f markdown -t html+smart --css=$(CSS) --template=$(HTML_TEMPLATE) \ --variable=date:"$$(LC_TIME=C date +"Last modified on %a, %d %b %Y at %T %z" -d @"$$mtime")" \ --variable=keywords:"interimap" \ --variable=lang:"en" \ - --variable=parent:"$$parent" \ + --variable=parent:"$(if $(filter $@,$(builddir)/doc/index.html),,./index.html)" \ --output="$@" -- "$<" -doc: manual html +INSTALL ?= install +INSTALL_PROGRAM ?= $(INSTALL) +INSTALL_DATA ?= $(INSTALL) -m0644 -prefix ?= $(DESTDIR) -exec_prefix ?= $(prefix) -bindir ?= $(exec_prefix)/bin -libdir ?= $(exec_prefix)/lib -datarootdir ?= $(prefix)/share -mandir ?= $(datarootdir)/man -man1dir ?= $(mandir)/man1 +install: install-nodoc + -$(INSTALL_DATA) -vDt $(DESTDIR)$(man1dir) $(builddir)/doc/interimap.1 $(builddir)/doc/pullimap.1 + $(INSTALL_DATA) -vDt $(DESTDIR)$(datarootdir)/doc/pullimap $(srcdir)/pullimap.sample + $(INSTALL_DATA) -vDt $(DESTDIR)$(datarootdir)/doc/interimap $(srcdir)/interimap.sample \ + $(srcdir)/doc/getting-started.md $(srcdir)/doc/multi-account.md $(srcdir)/README -install: all - install -m0755 -vDt $(bindir) ./interimap ./pullimap - install -m0644 -vDT ./lib/Net/IMAP/InterIMAP.pm $(datarootdir)/perl5/Net/IMAP/InterIMAP.pm - install -m0644 -vDt $(man1dir) $(BUILD_DOCDIR)/interimap.1 $(BUILD_DOCDIR)/pullimap.1 - install -m0644 -vDt $(datarootdir)/doc/pullimap ./pullimap.sample - install -m0644 -vDt $(datarootdir)/doc/interimap ./interimap.sample ./doc/getting-started.md ./doc/multi-account.md README - install -m0644 -vDt $(libdir)/systemd/user ./*.service +install-nodoc: all-nodoc + $(INSTALL_PROGRAM) -vDt $(DESTDIR)$(bindir) $(builddir)/interimap $(builddir)/pullimap + $(INSTALL_DATA) -vDT $(srcdir)/lib/Net/IMAP/InterIMAP.pm $(DESTDIR)$(sitelib)/Net/IMAP/InterIMAP.pm + $(INSTALL_DATA) -vDt $(DESTDIR)$(systemd_userunitdir) $(SERVICE_FILES) uninstall: - rm -vf -- $(bindir)/interimap $(man1dir)/interimap.1 $(libdir)/systemd/user/interimap*.service - rm -vf -- $(bindir)/pullimap $(man1dir)/pullimap.1 $(libdir)/systemd/user/pullimap*.service - rm -vf -- $(datarootdir)/perl5/Net/IMAP/InterIMAP.pm - rm -rvf -- $(datarootdir)/doc/interimap $(datarootdir)/doc/pullimap - rm -vf -- $(BUILD_DOCDIR)/interimap.1 $(BUILD_DOCDIR)/pullimap.1 + rm -vf -- $(DESTDIR)$(bindir)/interimap $(DESTDIR)$(man1dir)/interimap.1 $(DESTDIR)$(systemd_userunitdir)/interimap*.service + rm -vf -- $(DESTDIR)$(bindir)/pullimap $(DESTDIR)$(man1dir)/pullimap.1 $(DESTDIR)$(systemd_userunitdir)/pullimap*.service + rm -vf -- $(DESTDIR)$(sitelib)/Net/IMAP/InterIMAP.pm + rm -rvf -- $(DESTDIR)$(datarootdir)/doc/interimap $(DESTDIR)$(datarootdir)/doc/pullimap clean: - rm -vf -- $(MANUAL_FILES) $(HTML_FILES) + rm -vf -- $(PROGRAMS) $(MANUAL_FILES) $(HTML_FILES) $(SERVICE_FILES) + rm -vf -- $(srcdir)/tests/certs/*.key $(srcdir)/tests/certs/*.crt $(srcdir)/tests/certs/*.pem + -rmdir -vp --ignore-fail-on-non-empty -- $(builddir)/doc -.PHONY: all manual html doc test release install uninstall clean +.PHONY: all all-nodoc manual html doc release testcerts \ + check check-interimap check-pullimap \ + install install-nodoc \ + installcheck installcheck-interimap installcheck-pullimap \ + uninstall clean @@ -77,6 +77,6 @@ sockets (type=imaps or type=imap). ______________________________________________________________________________ -InterIMAP is Copyright© 2015-2020 Guilhem Moulin ⟨guilhem@fripost.org⟩, and -licensed for use under the GNU General Public License version 3 or later. See -‘COPYING’ for specific terms and distribution information. +InterIMAP is Copyright © 2015-2022 Guilhem Moulin ⟨guilhem@fripost.org⟩, and +is licensed for use under the GNU General Public License version 3 or later. +See ‘COPYING’ for specific terms and distribution information. diff --git a/benchmark/run b/benchmark/run index 4a83c68..650270a 100755 --- a/benchmark/run +++ b/benchmark/run @@ -198,9 +198,10 @@ cat >"$ROOTDIR/dev/shm/nobody/.offlineimaprc" <<-EOF EOF # install interimap's development version -install -oroot -groot -m0755 -Dt "/$ROOTDIR/usr/bin" \ +install -oroot -groot -m0755 -Dt "$ROOTDIR/usr/bin" \ ./interimap ./benchmark/random_maildir.pl -install -oroot -groot -Dm0644 \ +sed -ri "0,/^(use\\s+\lib\\s+)([\"'])[^\"']*\\2\\s*;/ s||#&|" -- "$ROOTDIR/usr/bin/interimap" +install -oroot -groot -m0644 -DT \ ./lib/Net/IMAP/InterIMAP.pm "$ROOTDIR/usr/share/perl5/Net/IMAP/InterIMAP.pm" # create a random mail store at mdbox:~/mail.back diff --git a/doc/benchmark.md b/doc/benchmark.md index 72f51a4..f2f6cda 100644 --- a/doc/benchmark.md +++ b/doc/benchmark.md @@ -48,8 +48,8 @@ by placing packet counters on the interface. [OfflineIMAP]: https://www.offlineimap.org/ [benchmark-script]: https://git.guilhem.org/interimap/plain/benchmark/run [Dovecot]: https://dovecot.org -[dbox]: https://wiki.dovecot.org/MailboxFormat/dbox -[maildir]: https://wiki.dovecot.org/MailboxFormat/Maildir +[dbox]: https://doc.dovecot.org/admin_manual/mailbox_formats/dbox/ +[maildir]: https://doc.dovecot.org/admin_manual/mailbox_formats/maildir/ ----------------------------------------------------------------------- diff --git a/doc/build.md b/doc/build.md index 2e4e511..b40760e 100644 --- a/doc/build.md +++ b/doc/build.md @@ -38,10 +38,10 @@ Additional packages are required in order to run the test suite: $ sudo apt install dovecot-imapd dovecot-lmtpd openssl procps sqlite3 xxd <!-- --> - $ make test + $ make check -(The test suite also needs to bind to TCP ports 10024, 10143 and 10993 -on the loopback interface.) +(Note also that the test suite needs to bind to TCP ports 10024, 10143 +and 10993 on the loopback interface.) Generate documentation ====================== @@ -51,32 +51,53 @@ Yet another set of packages is needed to generate the documentation: $ sudo apt install jq pandoc Run `` `make manual` `` (or just `` `make` ``) in order to generate the -manpages. You'll find them at `doc/*.[1-9]`. Use for instance `` `man --l doc/interimap.1` `` in order to read your copy of the [`interimap`(1)] -manpage. +manuals. You'll find them at `build/doc/*.[1-9]`. Then use for +instance `` `man -l build/doc/interimap.1` `` to read your local copy of +the [`interimap`(1)] manual. -The HTML documentation can be built with `` `make html` ``. HTML files -are generated alongside their Markdown source by default, but you can -choose another target directory using the `HTML_ROOTDIR` environment -variable (the value of which defaults to `./doc`). Moreover the -[`libjs-bootstrap`](https://tracker.debian.org/libjs-bootstrap) is -needed by default for the local CSS file; this can be controlled with -the `CSS` environment variable (the value of which defaults to -`/usr/share/javascript/bootstrap/css/bootstrap.min.css`). +The HTML documentation can be built with `` `make html` ``. By default +HTML files are generated at `build/doc/*.html`, and a local CSS file is +used — namely `/usr/share/javascript/bootstrap4/css/bootstrap.css`, +shipped the by [`libjs-bootstrap`](https://tracker.debian.org/libjs-bootstrap) +package. But this is configurable: use for instance -For instance, use + $ make html builddir="$XDG_RUNTIME_DIR/interimap" \ + CSS="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" - $ env CSS="https://guilhem.org/static/css/bootstrap.min.css" \ - HTML_ROOTDIR="$XDG_RUNTIME_DIR/interimap" \ - make html +to generate the HTML documentation under `$XDG_RUNTIME_DIR/interimap/doc` +using a remote CSS file. -to generate the HTML documentation under directory `$XDG_RUNTIME_DIR/interimap` -(which needs to exist) using a remote CSS file. - -The `doc` target generates all documentation, manpages as well as HTML +The `doc` target generates all documentation, manuals as well as HTML pages. +Installation without root privileges +==================================== + +By default `` `make install` `` installs [`interimap`(1)] under +`/usr/local`, hence requires root privileges. However another prefix +can be used in order to perform the (un)installation as an unprivileged +user. For instance + + $ install -m0700 -vd ${XDG_DATA_HOME:-~/.local/share}/interimap + $ make install-nodoc \ + prefix=$HOME/.local \ + sitelib=${XDG_DATA_HOME:-~/.local/share}/interimap/lib \ + systemd_userunitdir=${XDG_DATA_HOME:-~/.local/share}/systemd/user + +skips documentation and installs + + * executables into `~/.local/bin` (instead of `/usr/local/bin`); + * libraries into `$XDG_DATA_HOME/interimap/lib` or `~/.local/share/interimap/lib` + (instead of `/usr/local/lib/site_perl`); and + * [systemd user unit files][`systemd.unit`(5)] into `$XDG_DATA_HOME/systemd/user` + or `~/.local/share/systemd/user` (instead of `/usr/local/lib/systemd/user`). + +Note that for uninstallation one must call `` `make uninstall prefix=…` `` +with the very same assignment(s) used for installation. + +[`systemd.unit`(5)]: https://www.freedesktop.org/software/systemd/man/systemd.unit.html + Build custom Debian packages ============================ diff --git a/doc/development.md b/doc/development.md index f4578b9..0fe54f4 100644 --- a/doc/development.md +++ b/doc/development.md @@ -136,7 +136,7 @@ and `remote` accounts. Run [`interimap`(1)] without `--watch` in order to create the database. - $ env -i PATH="$PATH" perl -I./lib -T ./interimap --config="$BASEDIR/interimap.conf" + $ env -i PATH="$PATH" perl -T ./interimap --config="$BASEDIR/interimap.conf" Creating new schema in database file …/interimap.db database: Created mailbox INBOX […] @@ -144,7 +144,7 @@ Run [`interimap`(1)] without `--watch` in order to create the database. You can now run [`interimap`(1)] with `--watch` set, here to one second to observe synchronization steps early. - $ env -i PATH="$PATH" perl -I./lib -T ./interimap --config="$BASEDIR/interimap.conf" \ + $ env -i PATH="$PATH" perl -T ./interimap --config="$BASEDIR/interimap.conf" \ --watch=1 --debug Use instructions from the [previous section][Mail storage access] @@ -168,12 +168,12 @@ Create a [`pullimap`(1)] configuration file with as section `[foo]`. Run [`pullimap`(1)] without `--idle` in order to create the state file. - $ env -i PATH="$PATH" perl -I./lib -T ./pullimap --config="$BASEDIR/pullimap.conf" \ + $ env -i PATH="$PATH" perl -T ./pullimap --config="$BASEDIR/pullimap.conf" \ --no-delivery foo You can now run [`pullimap`(1)] with `--idle` set. - $ env -i PATH="$PATH" perl -I./lib -T ./pullimap --config="$BASEDIR/pullimap.conf" \ + $ env -i PATH="$PATH" perl -T ./pullimap --config="$BASEDIR/pullimap.conf" \ --no-delivery --idle --debug foo Use instructions from the [previous section][Mail storage access] @@ -194,10 +194,10 @@ recursively remove the directory `$BASEDIR`. [IMAP4rev1]: https://tools.ietf.org/html/rfc3501 [Dovecot]: https://dovecot.org [Dovecot Logging]: https://doc.dovecot.org/admin_manual/logging/ -[Dovecot LDA]: https://wiki.dovecot.org/LDA +[Dovecot LDA]: https://doc.dovecot.org/configuration_manual/protocols/lda/ [`getlogin`(3)]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getlogin.html [User Databases]: https://doc.dovecot.org/configuration_manual/authentication/user_databases_userdb/ -[Maildir]: https://wiki.dovecot.org/MailLocation/Maildir +[Maildir]: https://doc.dovecot.org/configuration_manual/mail_location/Maildir/ [RFC 2342]: https://tools.ietf.org/html/rfc2342 [Dovecot Namespaces]: https://doc.dovecot.org/configuration_manual/namespace/ [`interimap`(1)]: interimap.1.html diff --git a/doc/getting-started.md b/doc/getting-started.md index 74fc8da..7a77a6b 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -84,7 +84,7 @@ mailbox delivery) then don't disable them, and modify Dovecot's system wide configuration instead. Same thing if your mail client isn't able to spawn a command for IMAP communication, and instead insists on connecting to a network socket (in that case you'll even need to -configure [user authentication](https://wiki.dovecot.org/Authentication) +configure [user authentication](https://doc.dovecot.org/configuration_manual/authentication/) for the IMAP service, which is out of scope for the present document). Run the following command to terminate and disable the system-wide @@ -113,7 +113,8 @@ Some remarks on the above: running `` `doveconf -nc ${XDG_CONFIG_HOME:-~/.config}/dovecot/dovecot.conf` ``. * Messages will be stored in Maildir format under `~/Mail`. Ensure the directory is either *empty* or *doesn't exist* before - continuing! You may want to choose a different [format](https://wiki.dovecot.org/MailboxFormat) + continuing! You may want to choose a different + [format](https://doc.dovecot.org/admin_manual/mailbox_formats/) here, or simply append `:LAYOUT=fs` to the `mail_location` value in order to use a nicer (File System like) Maildir layout. * The `separator` setting defines the IMAP hierarchy delimiter. This @@ -2,7 +2,7 @@ #---------------------------------------------------------------------- # Fast bidirectional synchronization for QRESYNC-capable IMAP servers -# Copyright © 2015-2020 Guilhem Moulin <guilhem@fripost.org> +# Copyright © 2015-2022 Guilhem Moulin <guilhem@fripost.org> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -22,17 +22,18 @@ use v5.14.2; use strict; use warnings; -our $VERSION = '0.5.6'; +our $VERSION = '0.5.7'; my $NAME = 'interimap'; my $DATABASE_VERSION = 1; use Getopt::Long qw/:config posix_default no_ignore_case gnu_compat bundling auto_version/; use DBI ':sql_types'; use DBD::SQLite::Constants ':file_open'; -use Fcntl qw/F_GETFD F_SETFD FD_CLOEXEC/; +use Fcntl qw/O_WRONLY O_CREAT O_EXCL F_GETFD F_SETFD FD_CLOEXEC/; use List::Util 'first'; -use Net::IMAP::InterIMAP 0.5.6 qw/xdg_basedir read_config compact_set/; +use lib "./lib"; +use Net::IMAP::InterIMAP 0.5.7 qw/xdg_basedir read_config compact_set/; # Clean up PATH $ENV{PATH} = join ':', qw{/usr/bin /bin}; @@ -159,6 +160,12 @@ $SIG{TERM} = sub { cleanup(); exit 0; }; # Open (and maybe create) the database { + # don't auto-create in long-lived mode + unless ($CONFIG{watch} or -e $DBFILE) { + sysopen(my $fh, $DBFILE, O_WRONLY | O_CREAT | O_EXCL, 0600) or die "Can't create $DBFILE: $!"; + close $fh or warn "close: $!"; + } + my $dbi_data_source = "dbi:SQLite:dbname=".$DBFILE; my %dbi_attrs = ( AutoCommit => 0, @@ -166,8 +173,6 @@ $SIG{TERM} = sub { cleanup(); exit 0; }; sqlite_use_immediate_transaction => 1, sqlite_open_flags => SQLITE_OPEN_READWRITE ); - # don't auto-create in long-lived mode - $dbi_attrs{sqlite_open_flags} |= SQLITE_OPEN_CREATE unless defined $CONFIG{watch}; $DBH = DBI::->connect($dbi_data_source, undef, undef, \%dbi_attrs); $DBH->sqlite_busy_timeout(250); diff --git a/interimap.service b/interimap.service index 6d7fa45..6abc874 100644 --- a/interimap.service +++ b/interimap.service @@ -1,11 +1,12 @@ [Unit] Description=Fast bidirectional synchronization for QRESYNC-capable IMAP servers Documentation=man:interimap(1) +Documentation=https://guilhem.org/interimap/interimap.1.html Wants=network-online.target After=network-online.target [Service] -ExecStart=/usr/bin/interimap --watch=60 +ExecStart=@bindir@/interimap --watch=60 RestartSec=10min Restart=on-failure diff --git a/interimap@.service b/interimap@.service index 6957b79..f870065 100644 --- a/interimap@.service +++ b/interimap@.service @@ -1,12 +1,13 @@ [Unit] Description=Fast bidirectional synchronization for QRESYNC-capable IMAP servers (instance %i) Documentation=man:interimap(1) +Documentation=https://guilhem.org/interimap/interimap.1.html PartOf=interimap.service Wants=network-online.target After=network-online.target [Service] -ExecStart=/usr/bin/interimap --config=%i --watch=60 +ExecStart=@bindir@/interimap --config=%i --watch=60 RestartSec=10min Restart=on-failure diff --git a/lib/Net/IMAP/InterIMAP.pm b/lib/Net/IMAP/InterIMAP.pm index a171554..55a18a0 100644 --- a/lib/Net/IMAP/InterIMAP.pm +++ b/lib/Net/IMAP/InterIMAP.pm @@ -1,6 +1,6 @@ #---------------------------------------------------------------------- # A minimal IMAP4 client for QRESYNC-capable servers -# Copyright © 2015-2020 Guilhem Moulin <guilhem@fripost.org> +# Copyright © 2015-2022 Guilhem Moulin <guilhem@fripost.org> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ # along with this program. If not, see <https://www.gnu.org/licenses/>. #---------------------------------------------------------------------- -package Net::IMAP::InterIMAP v0.5.6; +package Net::IMAP::InterIMAP v0.5.7; use v5.20.0; use warnings; use strict; @@ -1312,7 +1312,8 @@ sub pull_new_messages($$&@) { # 2^32-1: don't use '*' since the highest UID can be known already $range .= "$since:4294967295"; - $UIDNEXT = $cache->{UIDNEXT} // $self->panic(); # sanity check + $UIDNEXT = $cache->{UIDNEXT} // + $self->panic("Unknown UIDNEXT value - non-compliant server?"); $self->fetch($range, "($attrs)", sub($) { my $mail = shift; $UIDNEXT = $mail->{UID} + 1 if $UIDNEXT <= $mail->{UID}; @@ -2,7 +2,7 @@ #---------------------------------------------------------------------- # Pull mails from an IMAP mailbox and deliver them to an SMTP session -# Copyright © 2016-2020 Guilhem Moulin <guilhem@fripost.org> +# Copyright © 2016-2022 Guilhem Moulin <guilhem@fripost.org> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -22,7 +22,7 @@ use v5.20.2; use strict; use warnings; -our $VERSION = '0.5.6'; +our $VERSION = '0.5.7'; my $NAME = 'pullimap'; use Errno 'EINTR'; @@ -31,7 +31,8 @@ use Getopt::Long qw/:config posix_default no_ignore_case gnu_getopt auto_version use List::Util 'first'; use Socket qw/PF_INET PF_INET6 SOCK_STREAM IPPROTO_TCP/; -use Net::IMAP::InterIMAP 0.5.6 qw/xdg_basedir read_config compact_set/; +use lib "./lib"; +use Net::IMAP::InterIMAP 0.5.7 qw/xdg_basedir read_config compact_set/; # Clean up PATH $ENV{PATH} = join ':', qw{/usr/bin /bin}; diff --git a/pullimap@.service b/pullimap@.service index a9ce09a..4f9518b 100644 --- a/pullimap@.service +++ b/pullimap@.service @@ -1,11 +1,12 @@ [Unit] Description=Pull mails from an IMAP mailbox and deliver them to an SMTP session (instance %i) Documentation=man:pullimap(1) +Documentation=https://guilhem.org/interimap/pullimap.1.html Wants=network-online.target After=network-online.target [Service] -ExecStart=/usr/bin/pullimap --idle %i +ExecStart=@bindir@/pullimap --idle %i RestartSec=2min Restart=always diff --git a/tests/certs/generate b/tests/certs/generate index de379a0..8e9c451 100755 --- a/tests/certs/generate +++ b/tests/certs/generate @@ -8,12 +8,20 @@ BASEDIR="$(dirname -- "$0")" OU="InterIMAP test suite" cd "$BASEDIR" +OPENSSL_CONF="./openssl.cnf" +export OPENSSL_CONF + cadir="$(mktemp --tmpdir --directory)" trap 'rm -rf -- "$cadir"' EXIT INT TERM +genpkey() { + local key="$1" + shift + openssl genpkey -out "$key" "$@" 2>&1 +} # generate CA (we intentionally throw away the private key and serial # file to avoid reuse) -openssl genpkey -algorithm RSA -out "$cadir/ca.key" +genpkey "$cadir/ca.key" -algorithm RSA openssl req -new -x509 -rand /dev/urandom -subj "/OU=$OU/CN=Fake Root CA" -key "$cadir/ca.key" -out ./ca.crt SERIAL=1 @@ -31,14 +39,14 @@ new() { printf "subjectAltName = %s\\n" "$3" >>"$cadir/new-ext.cnf" fi openssl x509 -req -in "$cadir/new.csr" -CA ./ca.crt -CAkey "$cadir/ca.key" \ - -CAserial "$cadir/ca.srl" -CAcreateserial -extfile "$cadir/new-ext.cnf" + -CAserial "$cadir/ca.srl" -CAcreateserial -extfile "$cadir/new-ext.cnf" 2>&1 } -openssl genpkey -algorithm RSA -out ./dovecot.rsa.key +genpkey ./dovecot.rsa.key -algorithm RSA new ./dovecot.rsa.key "localhost" "DNS:localhost,DNS:ip6-localhost,IP:127.0.0.1,IP:::1" >./dovecot.rsa.crt -openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve -out ./dovecot.ecdsa.key +genpkey ./dovecot.ecdsa.key -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve new ./dovecot.ecdsa.key "localhost" >./dovecot.ecdsa.crt -openssl genpkey -algorithm RSA -out ./dovecot.rsa2.key +genpkey ./dovecot.rsa2.key -algorithm RSA new ./dovecot.rsa2.key "imap.example.net" "DNS:imap.example.net,DNS:localhost" >./dovecot.rsa2.crt diff --git a/tests/certs/openssl.cnf b/tests/certs/openssl.cnf new file mode 100644 index 0000000..b1af7b8 --- /dev/null +++ b/tests/certs/openssl.cnf @@ -0,0 +1,4 @@ +[ req ] +distinguished_name = req_distinguished_name + +[ req_distinguished_name ] diff --git a/tests/config/dovecot/ssl.conf b/tests/config/dovecot/ssl.conf index 3fd99d5..1f3a698 100644 --- a/tests/config/dovecot/ssl.conf +++ b/tests/config/dovecot/ssl.conf @@ -2,4 +2,5 @@ ssl = required ssl_cert = <dovecot.rsa.crt ssl_key = <dovecot.rsa.key ssl_dh = <dhparams.pem -ssl_min_protocol = TLSv1 +ssl_min_protocol = TLSv1.2 +ssl_cipher_list = DEFAULT@SECLEVEL=2 diff --git a/tests/db-exclusive-lock/t b/tests/db-exclusive-lock/t index c2df4b5..837d21b 100644 --- a/tests/db-exclusive-lock/t +++ b/tests/db-exclusive-lock/t @@ -10,7 +10,7 @@ sleep .5 # subsequent runs fail as we can't acquire the exclusive lock ! interimap || error -grep -Fx "DBD::SQLite::db do failed: database is locked at ./interimap line 176." <"$STDERR" \ - || error "Is \$DBH->do(\"PRAGMA locking_mode = EXCLUSIVE\"); at line 176?" +grep -Ex "DBD::SQLite::db do failed: database is locked at (\S+/)?interimap line 181\." <"$STDERR" \ + || error "Is \$DBH->do(\"PRAGMA locking_mode = EXCLUSIVE\"); at line 181?" # vim: set filetype=sh : diff --git a/tests/db-no-create--watch/t b/tests/db-no-create--watch/t index a8ea07e..37fc6cb 100644 --- a/tests/db-no-create--watch/t +++ b/tests/db-no-create--watch/t @@ -1,6 +1,6 @@ ! interimap --watch=60 || error -grep -Ex "DBI connect\(.*\) failed: unable to open database file at \./interimap line 172\." <"$STDERR" || error +grep -Ex "DBI connect\(.*\) failed: unable to open database file at (\S+/)?interimap line 177\." <"$STDERR" || error test \! -e "$XDG_DATA_HOME/interimap/remote.db" || error # vim: set filetype=sh : diff --git a/tests/list b/tests/interimap.list index d1058ba..559daed 100644 --- a/tests/list +++ b/tests/interimap.list @@ -61,6 +61,3 @@ split-set Split large sets to avoid extra-long command lines sync-live-crippled local/remote simulation (crippled remote) sync-live-tls local/remote simulation (TLS remote) sync-live-multi local/remote1+remote2+remote3 simulation (3 local namespaces) - -. pullimap - ... pullimap diff --git a/tests/pullimap.list b/tests/pullimap.list new file mode 100644 index 0000000..f4304b9 --- /dev/null +++ b/tests/pullimap.list @@ -0,0 +1,2 @@ +. pullimap + ... pullimap diff --git a/tests/pullimap/t b/tests/pullimap/t index 0dfe634..58a19ca 100644 --- a/tests/pullimap/t +++ b/tests/pullimap/t @@ -6,6 +6,13 @@ step_start "\`pullimap --idle\` refuses to create the state file" ! pullimap --idle "remote" || error step_done +step_start "\`pullimap\` creates statefile with mode 0600" +pullimap "remote" || error +if ! st="$(stat -c"%#a" -- "$XDG_DATA_HOME/pullimap/remote")" || [ "$st" != "0600" ]; then + error "$XDG_DATA_HOME/pullimap/remote has mode $st != 0600" +fi +step_done + # compare mailboxes (can't compare the RFC 3501 TEXT as the LMTPd inconditionally # adds a Return-Path: header -- and also Delivered-To: and Received: to by default) list_mails_sha256() { @@ -104,29 +111,31 @@ doveadm -u "remote" search mailbox "$MAILBOX" unseen >"$TMPDIR/unseen" step_done -step_start "--idle (${TIMEOUT}s)" +if [ $TIMEOUT -gt 0 ]; then + step_start "--idle (${TIMEOUT}s)" -pullimap --idle "remote" & PID=$! -trap "ptree_abort $PID" EXIT INT TERM + pullimap --idle "remote" & PID=$! + trap "ptree_abort $PID" EXIT INT TERM -timer=$(( $(date +%s) + TIMEOUT )) -while [ $(date +%s) -le $timer ]; do - n="$(shuf -n1 -i1-5)" - for (( i=0; i < n; i++)); do - sample_message | deliver -u "remote" -- -m "$MAILBOX" - done + timer=$(( $(date +%s) + TIMEOUT )) + while [ $(date +%s) -le $timer ]; do + n="$(shuf -n1 -i1-5)" + for (( i=0; i < n; i++)); do + sample_message | deliver -u "remote" -- -m "$MAILBOX" + done - s=$(shuf -n1 -i1-1500) - [ $s -ge 1000 ] && s="$(printf "1.%03d" $((s-1000)))" || s="$(printf "0.%03d" $s)" - sleep "$s" -done + s=$(shuf -n1 -i1-1500) + [ $s -ge 1000 ] && s="$(printf "1.%03d" $((s-1000)))" || s="$(printf "0.%03d" $s)" + sleep "$s" + done -sleep 5 -ptree_abort $PID -trap - EXIT INT TERM + sleep 5 + ptree_abort $PID + trap - EXIT INT TERM -check -step_done + check + step_done +fi step_start "Purging" @@ -38,6 +38,12 @@ fi # cleanup environment unset OPENSSL_CONF SSL_CERT_FILE SSL_CERT_DIR +if [ -z "${INTERIMAP_PATH+x}" ]; then + INTERIMAP_PATH="./" +elif [ -n "$INTERIMAP_PATH" ]; then + INTERIMAP_PATH="${INTERIMAP_PATH%/}/" +fi + ROOTDIR="$(mktemp --tmpdir="${TMPDIR:-/dev/shm}" --directory "$1.XXXXXXXXXX")" declare -a DOVECOT_SERVER=() trap cleanup EXIT INT TERM @@ -206,26 +212,32 @@ prepare interimap() { _interimap_cmd "interimap" "$@"; } pullimap() { _interimap_cmd "pullimap" "$@"; } _interimap_cmd() { - declare -a ENVIRON=() + declare -a ENVIRON=() args=() local script="$1" rv=0 shift environ_set "local" [ -z "${OPENSSL_CONF+x}" ] || ENVIRON+=( OPENSSL_CONF="$OPENSSL_CONF" ) [ -z "${SSL_CERT_FILE+x}" ] || ENVIRON+=( SSL_CERT_FILE="$SSL_CERT_FILE" ) [ -z "${SSL_CERT_DIR+x}" ] || ENVIRON+=( SSL_CERT_DIR="$SSL_CERT_DIR" ) - env -i "${ENVIRON[@]}" perl -I./lib -T "./$script" "$@" 2>"$STDERR" || rv=$? + [ -z "${INTERIMAP_I:+x}" ] || args+=( perl -I"$INTERIMAP_I" -T ) + args+=( "$INTERIMAP_PATH$script" "$@" ) + #printf "I: Running \`%s\`\\n" "${args[*]}" >&3 + env -i "${ENVIRON[@]}" "${args[@]}" 2>"$STDERR" || rv=$? cat <"$STDERR" >&2 return $rv } interimap_init() { local u="${1-remote}" - local db="$XDG_DATA_HOME/interimap/$u.db" + local db="$XDG_DATA_HOME/interimap/$u.db" st local cfg="config${u#remote}" test \! -e "$db" || error "Database already exists" 1 interimap --config "$cfg" || error "Couldn't initialize interimap" 1 test -f "$db" || error "Database is still missing" 1 grep -Fx "Creating new schema in database file $db" <"$STDERR" || error "DB wasn't created" 1 + if ! st="$(stat -c"%#a" -- "$db")" || [ "$st" != "0600" ]; then + error "$db has mode $st != 0600" 1 + fi } doveadm() { if [ $# -le 2 ] || [ "$1" != "-u" ]; then @@ -449,7 +461,7 @@ passed() { # Run test in a sub-shell declare -a ENVIRON=() environ_set "local" -export TMPDIR TESTDIR STDERR "${ENVIRON[@]}" +export TMPDIR TESTDIR INTERIMAP_PATH INTERIMAP_I STDERR "${ENVIRON[@]}" export -f environ_set doveadm interimap interimap_init pullimap _interimap_cmd export -f sqlite3 sample_message deliver ptree_abort step_start step_done passed export -f check_mailbox_status check_mailbox_status_values check_mailbox_status2 diff --git a/tests/run-all b/tests/run-all index d13f689..79e62d1 100755 --- a/tests/run-all +++ b/tests/run-all @@ -24,6 +24,7 @@ export PATH BASEDIR="$(dirname -- "$0")" RUN="$BASEDIR/run" +list="$1" failed=0 @@ -54,7 +55,7 @@ while IFS="" read -r x; do fi INDENT="$indent" "$RUN" "$t" ${desc+"$desc"} || failed=$(( failed+1 )) -done <"$BASEDIR/list" +done <"$BASEDIR/$list" if [ $failed -eq 0 ]; then printf "All tests passed.\\n" diff --git a/tests/tls-protocols/openssl.cnf b/tests/tls-protocols/openssl.cnf index 980097d..3d9769d 100644 --- a/tests/tls-protocols/openssl.cnf +++ b/tests/tls-protocols/openssl.cnf @@ -11,4 +11,4 @@ system_default = system_default_sect [system_default_sect] MinProtocol = None -CipherString = DEFAULT +CipherString = DEFAULT@SECLEVEL=0 diff --git a/tests/tls-protocols/remote.conf b/tests/tls-protocols/remote.conf index 6029749..96b3713 120000..100644 --- a/tests/tls-protocols/remote.conf +++ b/tests/tls-protocols/remote.conf @@ -1 +1,4 @@ -../tls/remote.conf
\ No newline at end of file +!include conf.d/imapd.conf +!include conf.d/ssl.conf +ssl_min_protocol = TLSv1 +ssl_cipher_list = DEFAULT@SECLEVEL=0 diff --git a/tests/tls-rsa+ecdsa/t b/tests/tls-rsa+ecdsa/t index c9f5b96..fd2b1be 100644 --- a/tests/tls-rsa+ecdsa/t +++ b/tests/tls-rsa+ecdsa/t @@ -28,7 +28,7 @@ interimap_init check_mailbox_status "INBOX" interimap --debug || error -# which peer certificate is used is up to libssl +# which peer certificate is used is up to libssl grep -Fx -e "remote: Peer certificate fingerprint: sha256\$$X509_SHA256" \ -e "remote: Peer certificate fingerprint: sha256\$$X509_ALT_SHA256" \ <"$STDERR" || error |