summary refs log tree commit diff
path: root/build-aux/git-authenticate.scm
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2020-05-01 16:30:41 +0200
committerLudovic Courtès <ludo@gnu.org>2020-05-04 09:56:13 +0200
commit92db1036b7d3ad12548c81450a31e401b4c4f2b5 (patch)
treee5315508caca34916e8397f84643039600bfb34f /build-aux/git-authenticate.scm
parentbee5b7a0f8547a40f05d0891a71fff1fed4b2b3e (diff)
downloadguix-92db1036b7d3ad12548c81450a31e401b4c4f2b5.tar.gz
git-authenticate: Load the list of authorized keys from the tree.
* build-aux/git-authenticate.scm (read-authorizations)
(commit-authorized-keys): New procedures.
(authenticate-commit): Use it instead of %AUTHORIZED-SIGNING-KEYS.
Diffstat (limited to 'build-aux/git-authenticate.scm')
-rw-r--r--build-aux/git-authenticate.scm37
1 files changed, 36 insertions, 1 deletions
diff --git a/build-aux/git-authenticate.scm b/build-aux/git-authenticate.scm
index 0d5eb4caa9..fc02f9ef66 100644
--- a/build-aux/git-authenticate.scm
+++ b/build-aux/git-authenticate.scm
@@ -34,6 +34,7 @@
              (srfi srfi-26)
              (srfi srfi-34)
              (srfi srfi-35)
+             (rnrs bytevectors)
              (rnrs io ports)
              (ice-9 match)
              (ice-9 format)
@@ -266,6 +267,39 @@ commit ~a: key ~a is missing")
                                        data))))))
             ('good-signature data)))))))
 
+(define (read-authorizations port)
+  "Read authorizations in the '.guix-authorizations' format from PORT, and
+return a list of authorized fingerprints."
+  (match (read port)
+    (('authorizations ('version 0)
+                      (((? string? fingerprints) _ ...) ...)
+                      _ ...)
+     (map (lambda (fingerprint)
+            (base16-string->bytevector
+             (string-downcase (string-filter char-set:graphic fingerprint))))
+          fingerprints))))
+
+(define* (commit-authorized-keys repository commit
+                                 #:optional (default-authorizations '()))
+  "Return the list of OpenPGP fingerprints authorized to sign COMMIT, based on
+authorizations listed in its parent commits.  If one of the parent commits
+does not specify anything, fall back to DEFAULT-AUTHORIZATIONS."
+  (define (commit-authorizations commit)
+    (catch 'git-error
+      (lambda ()
+        (let* ((tree  (commit-tree commit))
+               (entry (tree-entry-bypath tree ".guix-authorizations"))
+               (blob  (blob-lookup repository (tree-entry-id entry))))
+          (read-authorizations
+           (open-bytevector-input-port (blob-content blob)))))
+      (lambda (key error)
+        (if (= (git-error-code error) GIT_ENOTFOUND)
+            default-authorizations
+            (throw key error)))))
+
+  (apply lset-intersection bytevector=?
+         (map commit-authorizations (commit-parents commit))))
+
 (define (authenticate-commit repository commit keyring)
   "Authenticate COMMIT from REPOSITORY and return the signing key fingerprint.
 Raise an error when authentication fails."
@@ -276,7 +310,8 @@ Raise an error when authentication fails."
     (commit-signing-key repository id keyring))
 
   (unless (member (openpgp-public-key-fingerprint signing-key)
-                  %authorized-signing-keys)
+                  (commit-authorized-keys repository commit
+                                          %authorized-signing-keys))
     (raise (condition
             (&message
              (message (format #f (G_ "commit ~a not signed by an authorized \