1 |
Issue an explicit warning if the Manifest timestamp for Gentoo |
2 |
repository is 24 hours behind the system clock. This is meant to detect |
3 |
attacks based on preventing the user from upgrading. |
4 |
--- |
5 |
cnf/repos.conf | 1 + |
6 |
man/portage.5 | 4 ++++ |
7 |
pym/portage/sync/modules/rsync/__init__.py | 1 + |
8 |
pym/portage/sync/modules/rsync/rsync.py | 21 +++++++++++++++++++++ |
9 |
4 files changed, 27 insertions(+) |
10 |
|
11 |
diff --git a/cnf/repos.conf b/cnf/repos.conf |
12 |
index 4a40ff4fc..984ecd220 100644 |
13 |
--- a/cnf/repos.conf |
14 |
+++ b/cnf/repos.conf |
15 |
@@ -7,6 +7,7 @@ sync-type = rsync |
16 |
sync-uri = rsync://rsync.gentoo.org/gentoo-portage |
17 |
auto-sync = yes |
18 |
sync-rsync-verify-metamanifest = yes |
19 |
+sync-rsync-verify-max-age = 24 |
20 |
sync-openpgp-key-path = /var/lib/gentoo/gkeys/keyrings/gentoo/release/pubring.gpg |
21 |
|
22 |
# for daily squashfs snapshots |
23 |
diff --git a/man/portage.5 b/man/portage.5 |
24 |
index d4f755f51..778dedfd5 100644 |
25 |
--- a/man/portage.5 |
26 |
+++ b/man/portage.5 |
27 |
@@ -1086,6 +1086,10 @@ directories if appropriate. |
28 |
Number of parallel jobs to use when verifying nested Manifests. Defaults |
29 |
to the apparent number of processors. |
30 |
.TP |
31 |
+.B sync\-rsync\-verify\-max\-age |
32 |
+Warn if repository is older than the specified number of hours. Disabled |
33 |
+when 0. Defaults to disabled. |
34 |
+.TP |
35 |
.B sync\-rsync\-verify\-metamanifest = yes|no |
36 |
Require the repository to contain a signed MetaManifest and verify |
37 |
it using \fBapp\-portage/gemato\fR. Defaults to no. |
38 |
diff --git a/pym/portage/sync/modules/rsync/__init__.py b/pym/portage/sync/modules/rsync/__init__.py |
39 |
index 27a2548c0..cb80f6d66 100644 |
40 |
--- a/pym/portage/sync/modules/rsync/__init__.py |
41 |
+++ b/pym/portage/sync/modules/rsync/__init__.py |
42 |
@@ -29,6 +29,7 @@ module_spec = { |
43 |
'sync-rsync-extra-opts', |
44 |
'sync-rsync-vcs-ignore', |
45 |
'sync-rsync-verify-jobs', |
46 |
+ 'sync-rsync-verify-max-age', |
47 |
'sync-rsync-verify-metamanifest', |
48 |
), |
49 |
} |
50 |
diff --git a/pym/portage/sync/modules/rsync/rsync.py b/pym/portage/sync/modules/rsync/rsync.py |
51 |
index dc4674548..732298b3f 100644 |
52 |
--- a/pym/portage/sync/modules/rsync/rsync.py |
53 |
+++ b/pym/portage/sync/modules/rsync/rsync.py |
54 |
@@ -6,6 +6,7 @@ import logging |
55 |
import time |
56 |
import signal |
57 |
import socket |
58 |
+import datetime |
59 |
import io |
60 |
import re |
61 |
import random |
62 |
@@ -109,6 +110,20 @@ class RsyncSync(NewBase): |
63 |
writemsg_level("!!! sync-rsync-verify-jobs not a positive integer: %s\n" % (self.verify_jobs,), |
64 |
level=logging.WARNING, noiselevel=-1) |
65 |
self.verify_jobs = None |
66 |
+ # Support overriding max age. |
67 |
+ self.max_age = self.repo.module_specific_options.get( |
68 |
+ 'sync-rsync-verify-max-age', '') |
69 |
+ if self.max_age: |
70 |
+ try: |
71 |
+ self.max_age = int(self.max_age) |
72 |
+ if self.max_age < 0: |
73 |
+ raise ValueError(self.max_age) |
74 |
+ except ValueError: |
75 |
+ writemsg_level("!!! sync-rsync-max-age not a non-negative integer: %s\n" % (self.max_age,), |
76 |
+ level=logging.WARNING, noiselevel=-1) |
77 |
+ self.max_age = 0 |
78 |
+ else: |
79 |
+ self.max_age = 0 |
80 |
|
81 |
openpgp_env = None |
82 |
if self.verify_metamanifest and gemato is not None: |
83 |
@@ -339,6 +354,12 @@ class RsyncSync(NewBase): |
84 |
ts = m.find_timestamp() |
85 |
if ts is None: |
86 |
raise RuntimeError('Timestamp not found in Manifest') |
87 |
+ if (self.max_age != 0 and |
88 |
+ (datetime.datetime.utcnow() - ts.ts).hours > self.max_age): |
89 |
+ out.ewarn('Manifest is over 24 hours old, this is suspicious!') |
90 |
+ out.ewarn('You may want to try using another mirror and/or reporting this one:') |
91 |
+ out.ewarn(' %s' % (dosyncuri,)) |
92 |
+ out.ewarn('') |
93 |
|
94 |
out.einfo('Manifest timestamp: %s UTC' % (ts.ts,)) |
95 |
out.einfo('Valid OpenPGP signature found:') |
96 |
-- |
97 |
2.16.1 |