Issue an explicit warning if the Manifest timestamp for Gentoo repository is 24 hours behind the system clock. This is meant to detect attacks based on preventing the user from upgrading. --- cnf/repos.conf | 1 + man/portage.5 | 4 ++++ pym/portage/sync/modules/rsync/__init__.py | 1 + pym/portage/sync/modules/rsync/rsync.py | 21 +++++++++++++++++++++ 4 files changed, 27 insertions(+)
diff --git a/cnf/repos.conf b/cnf/repos.conf index 4a40ff4fc..984ecd220 100644 --- a/cnf/repos.conf +++ b/cnf/repos.conf @@ -7,6 +7,7 @@ sync-type = rsync sync-uri = rsync://rsync.gentoo.org/gentoo-portage auto-sync = yes sync-rsync-verify-metamanifest = yes +sync-rsync-verify-max-age = 24 sync-openpgp-key-path = /var/lib/gentoo/gkeys/keyrings/gentoo/release/pubring.gpg # for daily squashfs snapshots diff --git a/man/portage.5 b/man/portage.5 index d4f755f51..778dedfd5 100644 --- a/man/portage.5 +++ b/man/portage.5 @@ -1086,6 +1086,10 @@ directories if appropriate. Number of parallel jobs to use when verifying nested Manifests. Defaults to the apparent number of processors. .TP +.B sync\-rsync\-verify\-max\-age +Warn if repository is older than the specified number of hours. Disabled +when 0. Defaults to disabled. +.TP .B sync\-rsync\-verify\-metamanifest = yes|no Require the repository to contain a signed MetaManifest and verify it using \fBapp\-portage/gemato\fR. Defaults to no. diff --git a/pym/portage/sync/modules/rsync/__init__.py b/pym/portage/sync/modules/rsync/__init__.py index 27a2548c0..cb80f6d66 100644 --- a/pym/portage/sync/modules/rsync/__init__.py +++ b/pym/portage/sync/modules/rsync/__init__.py @@ -29,6 +29,7 @@ module_spec = { 'sync-rsync-extra-opts', 'sync-rsync-vcs-ignore', 'sync-rsync-verify-jobs', + 'sync-rsync-verify-max-age', 'sync-rsync-verify-metamanifest', ), } diff --git a/pym/portage/sync/modules/rsync/rsync.py b/pym/portage/sync/modules/rsync/rsync.py index dc4674548..732298b3f 100644 --- a/pym/portage/sync/modules/rsync/rsync.py +++ b/pym/portage/sync/modules/rsync/rsync.py @@ -6,6 +6,7 @@ import logging import time import signal import socket +import datetime import io import re import random @@ -109,6 +110,20 @@ class RsyncSync(NewBase): writemsg_level("!!! sync-rsync-verify-jobs not a positive integer: %s\n" % (self.verify_jobs,), level=logging.WARNING, noiselevel=-1) self.verify_jobs = None + # Support overriding max age. + self.max_age = self.repo.module_specific_options.get( + 'sync-rsync-verify-max-age', '') + if self.max_age: + try: + self.max_age = int(self.max_age) + if self.max_age < 0: + raise ValueError(self.max_age) + except ValueError: + writemsg_level("!!! sync-rsync-max-age not a non-negative integer: %s\n" % (self.max_age,), + level=logging.WARNING, noiselevel=-1) + self.max_age = 0 + else: + self.max_age = 0 openpgp_env = None if self.verify_metamanifest and gemato is not None: @@ -339,6 +354,12 @@ class RsyncSync(NewBase): ts = m.find_timestamp() if ts is None: raise RuntimeError('Timestamp not found in Manifest') + if (self.max_age != 0 and + (datetime.datetime.utcnow() - ts.ts).hours > self.max_age): + out.ewarn('Manifest is over 24 hours old, this is suspicious!') + out.ewarn('You may want to try using another mirror and/or reporting this one:') + out.ewarn(' %s' % (dosyncuri,)) + out.ewarn('') out.einfo('Manifest timestamp: %s UTC' % (ts.ts,)) out.einfo('Valid OpenPGP signature found:') -- 2.16.1