1 |
No changes beside EAPI guards, full eclass included for review |
2 |
convenience. |
3 |
|
4 |
Signed-off-by: Michał Górny <mgorny@g.o> |
5 |
--- |
6 |
eclass/verify-sig.eclass | 16 +++++----------- |
7 |
1 file changed, 5 insertions(+), 11 deletions(-) |
8 |
|
9 |
diff --git a/eclass/verify-sig.eclass b/eclass/verify-sig.eclass |
10 |
index e3ef7f240283..7f89e5388ba3 100644 |
11 |
--- a/eclass/verify-sig.eclass |
12 |
+++ b/eclass/verify-sig.eclass |
13 |
@@ -1,271 +1,265 @@ |
14 |
-# Copyright 2020 Gentoo Authors |
15 |
+# Copyright 2020-2021 Gentoo Authors |
16 |
# Distributed under the terms of the GNU General Public License v2 |
17 |
|
18 |
# @ECLASS: verify-sig.eclass |
19 |
# @MAINTAINER: |
20 |
# Michał Górny <mgorny@g.o> |
21 |
-# @SUPPORTED_EAPIS: 7 |
22 |
+# @SUPPORTED_EAPIS: 7 8 |
23 |
# @BLURB: Eclass to verify upstream signatures on distfiles |
24 |
# @DESCRIPTION: |
25 |
# verify-sig eclass provides a streamlined approach to verifying |
26 |
# upstream signatures on distfiles. Its primary purpose is to permit |
27 |
# developers to easily verify signatures while bumping packages. |
28 |
# The eclass removes the risk of developer forgetting to perform |
29 |
# the verification, or performing it incorrectly, e.g. due to additional |
30 |
# keys in the local keyring. It also permits users to verify |
31 |
# the developer's work. |
32 |
# |
33 |
# To use the eclass, start by packaging the upstream's key |
34 |
# as app-crypt/openpgp-keys-*. Then inherit the eclass, add detached |
35 |
# signatures to SRC_URI and set VERIFY_SIG_OPENPGP_KEY_PATH. The eclass |
36 |
# provides verify-sig USE flag to toggle the verification. |
37 |
# |
38 |
# Example use: |
39 |
# @CODE |
40 |
# inherit verify-sig |
41 |
# |
42 |
# SRC_URI="https://example.org/${P}.tar.gz |
43 |
# verify-sig? ( https://example.org/${P}.tar.gz.sig )" |
44 |
# BDEPEND=" |
45 |
# verify-sig? ( app-crypt/openpgp-keys-example )" |
46 |
# |
47 |
# VERIFY_SIG_OPENPGP_KEY_PATH=/usr/share/openpgp-keys/example.asc |
48 |
# @CODE |
49 |
|
50 |
-case "${EAPI:-0}" in |
51 |
- 0|1|2|3|4|5|6) |
52 |
- die "Unsupported EAPI=${EAPI} (obsolete) for ${ECLASS}" |
53 |
- ;; |
54 |
- 7) |
55 |
- ;; |
56 |
- *) |
57 |
- die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" |
58 |
- ;; |
59 |
+case ${EAPI} in |
60 |
+ 7|8) ;; |
61 |
+ *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; |
62 |
esac |
63 |
|
64 |
EXPORT_FUNCTIONS src_unpack |
65 |
|
66 |
if [[ ! ${_VERIFY_SIG_ECLASS} ]]; then |
67 |
|
68 |
IUSE="verify-sig" |
69 |
|
70 |
BDEPEND=" |
71 |
verify-sig? ( |
72 |
app-crypt/gnupg |
73 |
>=app-portage/gemato-16 |
74 |
)" |
75 |
|
76 |
# @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEY_PATH |
77 |
# @DEFAULT_UNSET |
78 |
# @DESCRIPTION: |
79 |
# Path to key bundle used to perform the verification. This is required |
80 |
# when using default src_unpack. Alternatively, the key path can be |
81 |
# passed directly to the verification functions. |
82 |
|
83 |
# @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEYSERVER |
84 |
# @DEFAULT_UNSET |
85 |
# @DESCRIPTION: |
86 |
# Keyserver used to refresh keys. If not specified, the keyserver |
87 |
# preference from the key will be respected. If no preference |
88 |
# is specified by the key, the GnuPG default will be used. |
89 |
|
90 |
# @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEY_REFRESH |
91 |
# @USER_VARIABLE |
92 |
# @DESCRIPTION: |
93 |
# Attempt to refresh keys via WKD/keyserver. Set it to "yes" |
94 |
# in make.conf to enable. Note that this requires working Internet |
95 |
# connection. |
96 |
: ${VERIFY_SIG_OPENPGP_KEY_REFRESH:=no} |
97 |
|
98 |
# @FUNCTION: verify-sig_verify_detached |
99 |
# @USAGE: <file> <sig-file> [<key-file>] |
100 |
# @DESCRIPTION: |
101 |
# Read the detached signature from <sig-file> and verify <file> against |
102 |
# it. <key-file> can either be passed directly, or it defaults |
103 |
# to VERIFY_SIG_OPENPGP_KEY_PATH. The function dies if verification |
104 |
# fails. |
105 |
verify-sig_verify_detached() { |
106 |
local file=${1} |
107 |
local sig=${2} |
108 |
local key=${3:-${VERIFY_SIG_OPENPGP_KEY_PATH}} |
109 |
|
110 |
[[ -n ${key} ]] || |
111 |
die "${FUNCNAME}: no key passed and VERIFY_SIG_OPENPGP_KEY_PATH unset" |
112 |
|
113 |
local extra_args=() |
114 |
[[ ${VERIFY_SIG_OPENPGP_KEY_REFRESH} == yes ]] || extra_args+=( -R ) |
115 |
[[ -n ${VERIFY_SIG_OPENPGP_KEYSERVER+1} ]] && extra_args+=( |
116 |
--keyserver "${VERIFY_SIG_OPENPGP_KEYSERVER}" |
117 |
) |
118 |
|
119 |
# GPG upstream knows better than to follow the spec, so we can't |
120 |
# override this directory. However, there is a clean fallback |
121 |
# to GNUPGHOME. |
122 |
addpredict /run/user |
123 |
|
124 |
local filename=${file##*/} |
125 |
[[ ${file} == - ]] && filename='(stdin)' |
126 |
einfo "Verifying ${filename} ..." |
127 |
gemato gpg-wrap -K "${key}" "${extra_args[@]}" -- \ |
128 |
gpg --verify "${sig}" "${file}" || |
129 |
die "PGP signature verification failed" |
130 |
} |
131 |
|
132 |
# @FUNCTION: verify-sig_verify_message |
133 |
# @USAGE: <file> <output-file> [<key-file>] |
134 |
# @DESCRIPTION: |
135 |
# Verify that the file ('-' for stdin) contains a valid, signed PGP |
136 |
# message and write the message into <output-file> ('-' for stdout). |
137 |
# <key-file> can either be passed directly, or it defaults |
138 |
# to VERIFY_SIG_OPENPGP_KEY_PATH. The function dies if verification |
139 |
# fails. Note that using output from <output-file> is important as it |
140 |
# prevents the injection of unsigned data. |
141 |
verify-sig_verify_message() { |
142 |
local file=${1} |
143 |
local output_file=${2} |
144 |
local key=${3:-${VERIFY_SIG_OPENPGP_KEY_PATH}} |
145 |
|
146 |
[[ -n ${key} ]] || |
147 |
die "${FUNCNAME}: no key passed and VERIFY_SIG_OPENPGP_KEY_PATH unset" |
148 |
|
149 |
local extra_args=() |
150 |
[[ ${VERIFY_SIG_OPENPGP_KEY_REFRESH} == yes ]] || extra_args+=( -R ) |
151 |
[[ -n ${VERIFY_SIG_OPENPGP_KEYSERVER+1} ]] && extra_args+=( |
152 |
--keyserver "${VERIFY_SIG_OPENPGP_KEYSERVER}" |
153 |
) |
154 |
|
155 |
# GPG upstream knows better than to follow the spec, so we can't |
156 |
# override this directory. However, there is a clean fallback |
157 |
# to GNUPGHOME. |
158 |
addpredict /run/user |
159 |
|
160 |
local filename=${file##*/} |
161 |
[[ ${file} == - ]] && filename='(stdin)' |
162 |
einfo "Verifying ${filename} ..." |
163 |
gemato gpg-wrap -K "${key}" "${extra_args[@]}" -- \ |
164 |
gpg --verify --output="${output_file}" "${file}" || |
165 |
die "PGP signature verification failed" |
166 |
} |
167 |
|
168 |
# @FUNCTION: verify-sig_verify_signed_checksums |
169 |
# @USAGE: <checksum-file> <algo> <files> [<key-file>] |
170 |
# @DESCRIPTION: |
171 |
# Verify the checksums for all files listed in the space-separated list |
172 |
# <files> (akin to ${A}) using a PGP-signed <checksum-file>. <algo> |
173 |
# specified the checksum algorithm (e.g. sha256). <key-file> can either |
174 |
# be passed directly, or it defaults to VERIFY_SIG_OPENPGP_KEY_PATH. |
175 |
# |
176 |
# The function dies if PGP verification fails, the checksum file |
177 |
# contains unsigned data, one of the files do not match checksums |
178 |
# or are missing from the checksum file. |
179 |
verify-sig_verify_signed_checksums() { |
180 |
local checksum_file=${1} |
181 |
local algo=${2} |
182 |
local files=() |
183 |
read -r -d '' -a files <<<"${3}" |
184 |
local key=${4:-${VERIFY_SIG_OPENPGP_KEY_PATH}} |
185 |
|
186 |
local chksum_prog chksum_len |
187 |
case ${algo} in |
188 |
sha256) |
189 |
chksum_prog=sha256sum |
190 |
chksum_len=64 |
191 |
;; |
192 |
*) |
193 |
die "${FUNCNAME}: unknown checksum algo ${algo}" |
194 |
;; |
195 |
esac |
196 |
|
197 |
[[ -n ${key} ]] || |
198 |
die "${FUNCNAME}: no key passed and VERIFY_SIG_OPENPGP_KEY_PATH unset" |
199 |
|
200 |
local checksum filename junk ret=0 count=0 |
201 |
while read -r checksum filename junk; do |
202 |
[[ ${#checksum} -eq ${chksum_len} ]] || continue |
203 |
[[ -z ${checksum//[0-9a-f]} ]] || continue |
204 |
has "${filename}" "${files[@]}" || continue |
205 |
[[ -z ${junk} ]] || continue |
206 |
|
207 |
"${chksum_prog}" -c --strict - <<<"${checksum} ${filename}" |
208 |
if [[ ${?} -eq 0 ]]; then |
209 |
(( count++ )) |
210 |
else |
211 |
ret=1 |
212 |
fi |
213 |
done < <(verify-sig_verify_message "${checksum_file}" - "${key}") |
214 |
|
215 |
[[ ${ret} -eq 0 ]] || |
216 |
die "${FUNCNAME}: at least one file did not verify successfully" |
217 |
[[ ${count} -eq ${#files[@]} ]] || |
218 |
die "${FUNCNAME}: checksums for some of the specified files were missing" |
219 |
} |
220 |
|
221 |
# @FUNCTION: verify-sig_src_unpack |
222 |
# @DESCRIPTION: |
223 |
# Default src_unpack override that verifies signatures for all |
224 |
# distfiles if 'verify-sig' flag is enabled. The function dies if any |
225 |
# of the signatures fails to verify or if any distfiles are not signed. |
226 |
# Please write src_unpack() yourself if you need to perform partial |
227 |
# verification. |
228 |
verify-sig_src_unpack() { |
229 |
if use verify-sig; then |
230 |
local f suffix found |
231 |
local distfiles=() signatures=() nosigfound=() straysigs=() |
232 |
|
233 |
# find all distfiles and signatures, and combine them |
234 |
for f in ${A}; do |
235 |
found= |
236 |
for suffix in .asc .sig; do |
237 |
if [[ ${f} == *${suffix} ]]; then |
238 |
signatures+=( "${f}" ) |
239 |
found=sig |
240 |
break |
241 |
else |
242 |
if has "${f}${suffix}" ${A}; then |
243 |
distfiles+=( "${f}" ) |
244 |
found=dist+sig |
245 |
break |
246 |
fi |
247 |
fi |
248 |
done |
249 |
if [[ ! ${found} ]]; then |
250 |
nosigfound+=( "${f}" ) |
251 |
fi |
252 |
done |
253 |
|
254 |
# check if all distfiles are signed |
255 |
if [[ ${#nosigfound[@]} -gt 0 ]]; then |
256 |
eerror "The following distfiles lack detached signatures:" |
257 |
for f in "${nosigfound[@]}"; do |
258 |
eerror " ${f}" |
259 |
done |
260 |
die "Unsigned distfiles found" |
261 |
fi |
262 |
|
263 |
# check if there are no stray signatures |
264 |
for f in "${signatures[@]}"; do |
265 |
if ! has "${f%.*}" "${distfiles[@]}"; then |
266 |
straysigs+=( "${f}" ) |
267 |
fi |
268 |
done |
269 |
if [[ ${#straysigs[@]} -gt 0 ]]; then |
270 |
eerror "The following signatures do not match any distfiles:" |
271 |
for f in "${straysigs[@]}"; do |
272 |
eerror " ${f}" |
273 |
done |
274 |
die "Unused signatures found" |
275 |
fi |
276 |
|
277 |
# now perform the verification |
278 |
for f in "${signatures[@]}"; do |
279 |
verify-sig_verify_detached \ |
280 |
"${DISTDIR}/${f%.*}" "${DISTDIR}/${f}" |
281 |
done |
282 |
fi |
283 |
|
284 |
# finally, unpack the distfiles |
285 |
default_src_unpack |
286 |
} |
287 |
|
288 |
_VERIFY_SIG_ECLASS=1 |
289 |
fi |
290 |
-- |
291 |
2.32.0 |