]> git.decadent.org.uk Git - dak.git/commitdiff
SignedFile: allow multiple signatures
authorAnsgar Burchardt <ansgar@debian.org>
Fri, 14 Aug 2015 10:58:48 +0000 (12:58 +0200)
committerAnsgar Burchardt <ansgar@debian.org>
Fri, 14 Aug 2015 11:04:21 +0000 (13:04 +0200)
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

index 654f69a53cf0f0d973eb97aa9a9233dc99f541ae..758b5b6251c6ef810baf9126ececf51f2370f287 100644 (file)
@@ -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):
         #             <expire-timestamp> <sig-version> <reserved> <pubkey-algo>
         #             <hash-algo> <sig-class> <primary-key-fpr>
         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