From c2fe725a17c75409639b7dd2194a8ca2a1ae6047 Mon Sep 17 00:00:00 2001 From: Papoteur Date: Sat, 27 Mar 2021 18:51:42 +0100 Subject: Check the signature as a first step after selecting an image to write. Nothing happens if the check is OK. Else a message is displayed about missing signature file or checked not passed, and ask to continue or not. The check is now done in main program instead of backend. --- backend/magiback | 7 ---- backend/raw_write.py | 90 +++++++++++----------------------------------------- lib/isodumper.py | 71 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 81 deletions(-) diff --git a/backend/magiback b/backend/magiback index 49162b3..c65b3a3 100755 --- a/backend/magiback +++ b/backend/magiback @@ -38,9 +38,6 @@ class Isodumper(raw_write.Dumper): - - - @@ -121,10 +118,6 @@ class Isodumper(raw_write.Dumper): def progress(self): return self._progress - def get_sum(self, source): - self.key_thread = threading.Thread(target=self._get_sum, args=(source,)) - self.key_thread.start() - def check_write(self, target, source): if hasattr(self, 'key_thread'): self.key_thread.join() diff --git a/backend/raw_write.py b/backend/raw_write.py index 03405bd..7891b43 100755 --- a/backend/raw_write.py +++ b/backend/raw_write.py @@ -27,7 +27,6 @@ import gettext import hashlib import io import logging -import datetime ########### # imports # ########### @@ -37,8 +36,6 @@ import sys import time from subprocess import Popen, PIPE -import gnupg - class Dumper(object): @@ -126,62 +123,6 @@ class Dumper(object): self.finished.set() return - def _get_sum(self, source): - self.return_state = False - self.signature_checked = FalseS - logging.debug("Starting getting sum") - # Check if the sum file has a valid signature - gpg = gnupg.GPG() - gpg.encoding = 'utf-8' - # Use Mageia public key - mageia_keyid = "835E41F4EDCA7A90" - self.sum_type = 'sha3' - sig_file = "{}.{}.gpg".format(source, self.sum_type) - self.source_file = "{}.{}".format(source, self.sum_type) - keys_list = gpg.list_keys() - key_present = False - for entry in keys_list: - if (mageia_keyid == entry['keyid']): - if entry['expires'] and (datetime.datetime.now().timestamp() > float(entry['expires'])): - logging.info("Mageia key expired, reloading") - else: - logging.info("Mageia key already present") - key_present = True - break - try: - if not key_present: - gpg.recv_keys('pool.sks-keyservers.net', mageia_keyid) - self.sum_check_searched = True - with open(sig_file, 'rb') as g: - self.signature_found = True - verified = gpg.verify_file(g, close_file=False) - if verified: - self.signature_checked = True - logging.debug("signature checked") - g.close() - else: - g.seek(0) - verified = gpg.verify_file(g, self.source_file) - if verified: - self.signature_checked = True - logging.debug("Detached signature is OK") - else: - self.signature_checked = False - logging.warning("Signature is false") - except Exception as e: - self.signature_found = False - logging.error(str(e)) - logging.info(_("Signature file {} not found\n" + _("or key expired")).format(sig_file)) - try: - # Look for sum files in the same directory as source - with open(self.source_file,'r') as fs: - # Read the sum in the file - self.sum_check=(fs.readline()).split()[0] - self.sum_file = True - except: - logging.info(_("Sum file {} not found\n").format(self.source_file)) - self.sum_file = False - def _check_write(self, target, source): logging.debug("Start checking") self.return_message = "" @@ -207,25 +148,30 @@ class Dumper(object): sha512func.update(block) sha512sumcalc=sha512func.hexdigest().upper() #f.close() + self.sum_check = "" + sum_type = "sha3" + sum_file = f"{source}.{sum_type}" + try: + # Look for sum files in the same directory as source + with open(sum_file,'r') as fs: + # Read the sum in the file + self.sum_check=(fs.readline()).split()[0] + self.sum_file = True + except: + logging.info(_("Sum file {} not found\n").format(sum_file)) + self.sum_file = False self.return_state = True - if self.signature_found and not self.signature_checked: - #, keep the pourcent, this is the place for source file name - self.return_message = _('Invalid signature for %s')%self.source_file - self.return_state = False + #if self.signature_found and not self.signature_checked: + ##, keep the pourcent, this is the place for source file name + #self.return_message = _('Invalid signature for %s')%self.source_file + #self.return_state = False if (self.sum_check == "") : # Can't get stored sum self.return_message += _('SHA3 sum: {}').format(sha512sumcalc) # compare the sums elif (sha512sumcalc == self.sum_check) : - if self.signature_checked and self.signature_found: + #if self.signature_checked and self.signature_found: #, keep the bracket, this is the place for sum type - self.return_message +="\n" + _("The {} sum check is OK and the sum is signed").format(self.sum_type) - else : - if self.signature_found: - self.return_message +="\n" + _("The validation of the GPG signature failed !") + "\n" + _("The integrity of the ISO image could not be verified.") - self.return_state = False - else: - #, keep the bracket, this is the place for sum type - self.return_message +="\n" + _("The {} sum check is OK but the signature can't be found").format(self.sum_type) + self.return_message +="\n" + _("The {} sum check is OK").format(sum_type) else: self.return_message +="\n" + _("/!\\The computed and stored sums don't match") self.return_state = False diff --git a/lib/isodumper.py b/lib/isodumper.py index d91bc3d..f095410 100755 --- a/lib/isodumper.py +++ b/lib/isodumper.py @@ -45,6 +45,8 @@ import re import gettext from subprocess import Popen, PIPE from pydbus import SystemBus +import gnupg +import datetime import logging import threading @@ -274,6 +276,53 @@ class IsoDumper(basedialog.BaseDialog): else: self.backup_is_selected = False + def get_sum(self, source): + self.return_state = False + self.signature_checked = False + logging.debug("Starting getting sum") + # Check if the sum file has a valid signature + gpg = gnupg.GPG() + gpg.encoding = 'utf-8' + # Use Mageia public key + mageia_keyid = "835E41F4EDCA7A90" + self.sum_type = 'sha3' + sig_file = "{}.{}.gpg".format(source, self.sum_type) + self.source_file = "{}.{}".format(source, self.sum_type) + keys_list = gpg.list_keys() + key_present = False + for entry in keys_list: + if (mageia_keyid == entry['keyid']): + if entry['expires'] and (datetime.datetime.now().timestamp() > float(entry['expires'])): + logging.info("Mageia key expired, reloading") + else: + logging.info("Mageia key already present") + key_present = True + break + try: + if not key_present: + gpg.recv_keys('pool.sks-keyservers.net', mageia_keyid) + self.sum_check_searched = True + with open(sig_file, 'rb') as g: + self.signature_found = True + verified = gpg.verify_file(g, close_file=False) + if verified: + self.signature_checked = True + logging.debug("signature checked") + g.close() + else: + g.seek(0) + verified = gpg.verify_file(g, self.source_file) + if verified: + self.signature_checked = True + logging.debug("Detached signature is OK") + else: + self.signature_checked = False + logging.warning("Signature is false") + except Exception as e: + self.signature_found = False + logging.error(str(e)) + logging.info(_("Signature file {} not found\n" + _("or key expired")).format(sig_file)) + def do_format(self): #code, format_type, name = self.ask_format() if self.partition_cb.value() != "": @@ -305,7 +354,7 @@ class IsoDumper(basedialog.BaseDialog): self.logger(message) self.emergency(message) else: - message = _('An error occurred.') + message = _('An error {} occurred.'.format(rc)) self.emergency(message) self.initial_state() @@ -448,7 +497,6 @@ class IsoDumper(basedialog.BaseDialog): if success: # Writing step self.iface.do_write(source, target, b) - self.iface.get_sum(source) progress = self.iface.progress while not self.iface.done: progress = self.iface.progress @@ -851,6 +899,25 @@ exFAT, NTFS or ext. You can specify a volume name and the format in a new dialog def ask_image(self): self.img_name = yui.YUI.app().askForExistingFile("", "*.iso *.img", self.ChooseImage) if self.img_name != "": + # Check if the image has a signed checksum + self.get_sum(self.img_name) + if self.signature_found: + if not self.signature_checked: + info = Info(_("Warning"), True, + _("The validation of the GPG signature failed !") + "\n" + _("Do you want to continue?")) + if self.ask_YesOrNo(info): + pass + else: + self.img_name = "" + return + else: + info = Info(_("Warning"), True, + _('No GPG signature has been found or the key is expired. Are you sure you want to use this image?')) + if self.ask_YesOrNo(info): + pass + else: + self.img_name = "" + return self.ima.setLabel(os.path.basename(self.img_name)) self.dialog.recalcLayout() self.start_bt.setEnabled() -- cgit v1.2.1