|
39 | 39 | import shutil |
40 | 40 | import io |
41 | 41 | import pathlib |
| 42 | +from typing import NamedTuple |
42 | 43 | from . import BmapCreate, BmapCopy, BmapHelpers, TransRead |
43 | 44 |
|
44 | 45 | VERSION = "3.8.0" |
@@ -129,6 +130,60 @@ def open_block_device(path): |
129 | 130 | return NamedFile(file_obj, path) |
130 | 131 |
|
131 | 132 |
|
| 133 | +class Signature(NamedTuple): |
| 134 | + valid: bool |
| 135 | + fpr: str |
| 136 | + uid: str |
| 137 | + |
| 138 | + |
| 139 | +def verify_bmap_signature_gpgme(bmap_obj, detached_sig): |
| 140 | + try: |
| 141 | + import gpg |
| 142 | + except ImportError: |
| 143 | + error_out( |
| 144 | + 'cannot verify the signature because the python "gpg" ' |
| 145 | + "module is not installed on your system\nPlease, either " |
| 146 | + "install the module or use --no-sig-verify" |
| 147 | + ) |
| 148 | + |
| 149 | + try: |
| 150 | + bmap_data = bmap_obj.read() |
| 151 | + |
| 152 | + if detached_sig: |
| 153 | + det_sig_data = detached_sig.read() |
| 154 | + detached_sig.close() |
| 155 | + else: |
| 156 | + det_sig_data = None |
| 157 | + |
| 158 | + context = gpg.Context() |
| 159 | + plaintext, sigs = context.verify(bmap_data, det_sig_data) |
| 160 | + sigs = sigs.signatures |
| 161 | + except gpg.errors.GPGMEError as err: |
| 162 | + error_out( |
| 163 | + "failure when trying to verify GPG signature: %s\n" |
| 164 | + "make sure the bmap file has proper GPG format", |
| 165 | + err[2].lower(), |
| 166 | + ) |
| 167 | + except gpg.errors.BadSignatures as err: |
| 168 | + error_out( |
| 169 | + "discovered a BAD GPG signature: %s\n", |
| 170 | + detached_sig.name if detached_sig else bmap_obj.name, |
| 171 | + ) |
| 172 | + |
| 173 | + def fpr2uid(fpr): |
| 174 | + key = context.get_key(fpr) |
| 175 | + return "%s <%s>" % (key.uids[0].name, key.uids[0].email) |
| 176 | + |
| 177 | + return plaintext, [ |
| 178 | + Signature( |
| 179 | + (sig.summary & gpg.constants.SIGSUM_VALID) != 0, |
| 180 | + sig.fpr, |
| 181 | + fpr2uid(sig.fpr), |
| 182 | + ) |
| 183 | + for sig in sigs |
| 184 | + ] |
| 185 | + |
| 186 | + |
132 | 187 | def verify_bmap_signature(args, bmap_obj, bmap_path): |
133 | 188 | """ |
134 | 189 | Verify GPG signature of the bmap file if it is present. The signature may |
@@ -182,57 +237,24 @@ def verify_bmap_signature(args, bmap_obj, bmap_path): |
182 | 237 |
|
183 | 238 | log.info("discovered signature file for bmap '%s'" % detached_sig.name) |
184 | 239 |
|
185 | | - try: |
186 | | - import gpg |
187 | | - except ImportError: |
188 | | - error_out( |
189 | | - 'cannot verify the signature because the python "gpg" ' |
190 | | - "module is not installed on your system\nPlease, either " |
191 | | - "install the module or use --no-sig-verify" |
192 | | - ) |
193 | | - |
194 | | - try: |
195 | | - bmap_data = bmap_obj.read() |
196 | | - bmap_obj.seek(0) |
197 | | - |
198 | | - if detached_sig: |
199 | | - det_sig_data = detached_sig.read() |
200 | | - detached_sig.close() |
201 | | - else: |
202 | | - det_sig_data = None |
203 | | - |
204 | | - context = gpg.Context() |
205 | | - plaintext, sigs = context.verify(bmap_data, det_sig_data) |
206 | | - sigs = sigs.signatures |
207 | | - except gpg.errors.GPGMEError as err: |
208 | | - error_out( |
209 | | - "failure when trying to verify GPG signature: %s\n" |
210 | | - "make sure the bmap file has proper GPG format", |
211 | | - err[2].lower(), |
212 | | - ) |
213 | | - except gpg.errors.BadSignatures as err: |
214 | | - error_out( |
215 | | - "discovered a BAD GPG signature: %s\n", |
216 | | - detached_sig.name if detached_sig else bmap_obj.name |
217 | | - ) |
| 240 | + plaintext, sigs = verify_bmap_signature_gpgme(bmap_obj, detached_sig) |
| 241 | + bmap_obj.seek(0) |
218 | 242 |
|
219 | 243 | if not args.no_sig_verify: |
220 | 244 | if len(sigs) == 0: |
221 | 245 | log.warning( |
222 | 246 | 'the "%s" signature file does not actually contain ' |
223 | | - "any valid signatures" % detached_sig.name if detached_sig |
224 | | - else |
225 | | - "the bmap file clearsign signature does not actually " |
| 247 | + "any valid signatures" % detached_sig.name |
| 248 | + if detached_sig |
| 249 | + else "the bmap file clearsign signature does not actually " |
226 | 250 | "contain any valid signatures" |
227 | 251 | ) |
228 | 252 | else: |
229 | 253 | for sig in sigs: |
230 | | - if (sig.summary & gpg.constants.SIGSUM_VALID) != 0: |
231 | | - key = context.get_key(sig.fpr) |
232 | | - author = "%s <%s>" % (key.uids[0].name, key.uids[0].email) |
| 254 | + if sig.valid: |
233 | 255 | log.info( |
234 | 256 | "successfully verified bmap file signature of %s " |
235 | | - "(fingerprint %s)" % (author, sig.fpr) |
| 257 | + "(fingerprint %s)" % (sig.uid, sig.fpr) |
236 | 258 | ) |
237 | 259 | else: |
238 | 260 | error_out( |
|
0 commit comments