From 4c4d817b9eee1195b84bb1ec642449485fa4c0ee Mon Sep 17 00:00:00 2001 From: Ansgar Burchardt Date: Fri, 14 Aug 2015 12:58:48 +0200 Subject: [PATCH] SignedFile: allow multiple signatures The InRelease file is currently signed using multiple keys and we want to be able to verify its signature. So allow multiple signatures as long as all of them are valid. For uploads (.changes files) we still require that only a single signature is present. This is currently enforced by the 'fingerprint', 'primary_fingerprint' and 'signature_id' accessors. --- daklib/gpg.py | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/daklib/gpg.py b/daklib/gpg.py index 654f69a5..758b5b62 100644 --- a/daklib/gpg.py +++ b/daklib/gpg.py @@ -80,12 +80,27 @@ class SignedFile(object): self.valid = False self.expired = False self.invalid = False - self.fingerprint = None - self.primary_fingerprint = None - self.signature_id = None + self.fingerprints = [] + self.primary_finterprints = [] + self.signature_ids = [] self._verify(data, require_signature) + @property + def fingerprint(self): + assert len(self.fingerprints) == 1 + return self.fingerprints[0] + + @property + def primary_fingerprint(self): + assert len(self.primary_fingerprints) == 1 + return self.primary_fingerprints[0] + + @property + def signature_id(self): + assert len(self.signature_ids) == 1 + return self.signature_ids[0] + def _verify(self, data, require_signature): with _Pipe() as stdin: with _Pipe() as contents: @@ -121,6 +136,9 @@ class SignedFile(object): if require_signature and not self.valid: raise GpgException("No valid signature found. (GPG exited with status code %s)\n%s" % (exit_code, self.stderr)) + assert len(self.fingerprints) == len(self.primary_fingerprints) + assert len(self.fingerprints) == len(self.signature_ids) + def _do_io(self, read, write): for fd in write.keys(): old = fcntl.fcntl(fd, fcntl.F_GETFL) @@ -178,11 +196,9 @@ class SignedFile(object): # # if fields[1] == "VALIDSIG": - if self.fingerprint is not None: - raise GpgException("More than one signature is not (yet) supported.") self.valid = True - self.fingerprint = fields[2] - self.primary_fingerprint = fields[11] + self.fingerprints.append(fields[2]) + self.primary_fingerprints.append(fields[11]) self.signature_timestamp = self._parse_timestamp(fields[4], fields[3]) elif fields[1] == "BADARMOR": @@ -198,9 +214,7 @@ class SignedFile(object): raise GpgException("Other error: %s %s" % (fields[2], fields[3])) elif fields[1] == "SIG_ID": - if self.signature_id is not None: - raise GpgException("More than one signature id.") - self.signature_id = fields[2] + self.signature_ids.append(fields[2]) elif fields[1] in ('PLAINTEXT', 'GOODSIG', 'NOTATION_NAME', 'NOTATION_DATA', 'SIGEXPIRED', 'KEYEXPIRED', 'POLICY_URL'): pass -- 2.39.2