gnupg: 'gnupg-status-missing-key?' returns a fingerprint when possible.

Until then, 'gnupg-status-missing-key?' would return a key id.  Its
user, 'gnupg-verify*', would then fetch a key with that ID from key
servers, thus possibly the wrong key (due to key ID collisions).  If it
did fetch the wrong key, the effect would be a signature verification
failure down the path--e.g., in "guix refresh -u".

* guix/gnupg.scm (gnupg-verify)[maybe-fingerprint]: New procedure.
[status-line->sexp](errsig-rx): Add parenthetical expression at the end.
Fetch it and add it to the 'signature-error' sexp.
(gnupg-status-missing-key?): Match the whole 'signature-error' sexp and
return preferably the fingerprint rather than KEY-ID.
(gnupg-receive-keys): Rename 'key-id' parameter to 'fingerprint/key-id'.
This commit is contained in:
Ludovic Courtès 2019-12-18 17:37:02 +01:00
parent 9cfa322579
commit 217b4a1587
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5

View file

@ -65,6 +65,11 @@ (define* (gnupg-verify sig file
KEYRING as assumed to be \"trusted\", whether or not they expired or were KEYRING as assumed to be \"trusted\", whether or not they expired or were
revoked. Return a status s-exp if GnuPG failed." revoked. Return a status s-exp if GnuPG failed."
(define (maybe-fingerprint str)
(match (string-trim-both str)
((or "-" "") #f)
(fpr fpr)))
(define (status-line->sexp line) (define (status-line->sexp line)
;; See file `doc/DETAILS' in GnuPG. ;; See file `doc/DETAILS' in GnuPG.
(define sigid-rx (define sigid-rx
@ -78,8 +83,10 @@ (define validsig-rx
(define expkeysig-rx ; good signature, but expired key (define expkeysig-rx ; good signature, but expired key
(make-regexp "^\\[GNUPG:\\] EXPKEYSIG ([[:xdigit:]]+) (.*)$")) (make-regexp "^\\[GNUPG:\\] EXPKEYSIG ([[:xdigit:]]+) (.*)$"))
(define errsig-rx (define errsig-rx
;; Note: The fingeprint part (the last element of the line) appeared in
;; GnuPG 2.2.7 according to 'doc/DETAILS', and it may be missing.
(make-regexp (make-regexp
"^\\[GNUPG:\\] ERRSIG ([[:xdigit:]]+) ([^ ]+) ([^ ]+) ([^ ]+) ([[:digit:]]+) ([[:digit:]]+)")) "^\\[GNUPG:\\] ERRSIG ([[:xdigit:]]+) ([^ ]+) ([^ ]+) ([^ ]+) ([[:digit:]]+) ([[:digit:]]+)(.*)"))
(cond ((regexp-exec sigid-rx line) (cond ((regexp-exec sigid-rx line)
=> =>
@ -108,7 +115,7 @@ (define errsig-rx
((regexp-exec errsig-rx line) ((regexp-exec errsig-rx line)
=> =>
(lambda (match) (lambda (match)
`(signature-error ,(match:substring match 1) ; key id or fingerprint `(signature-error ,(match:substring match 1) ; key id
,(match:substring match 2) ; pubkey algo ,(match:substring match 2) ; pubkey algo
,(match:substring match 3) ; hash algo ,(match:substring match 3) ; hash algo
,(match:substring match 4) ; sig class ,(match:substring match 4) ; sig class
@ -120,7 +127,9 @@ (define errsig-rx
(case rc (case rc
((9) 'missing-key) ((9) 'missing-key)
((4) 'unknown-algorithm) ((4) 'unknown-algorithm)
(else rc)))))) (else rc)))
,(maybe-fingerprint ; fingerprint or #f
(match:substring match 7)))))
(else (else
`(unparsed-line ,line)))) `(unparsed-line ,line))))
@ -153,16 +162,16 @@ (define (gnupg-status-good-signature? status)
#f))) #f)))
(define (gnupg-status-missing-key? status) (define (gnupg-status-missing-key? status)
"If STATUS denotes a missing-key error, then return the key-id of the "If STATUS denotes a missing-key error, then return the fingerprint of the
missing key." missing key or its key id if the fingerprint is unavailable."
(any (lambda (sexp) (any (lambda (sexp)
(match sexp (match sexp
(('signature-error key-id _ ...) (('signature-error key-id _ ... 'missing-key fingerprint)
key-id) (or fingerprint key-id))
(_ #f))) (_ #f)))
status)) status))
(define* (gnupg-receive-keys key-id server (define* (gnupg-receive-keys fingerprint/key-id server
#:optional (keyring (current-keyring))) #:optional (keyring (current-keyring)))
(unless (file-exists? keyring) (unless (file-exists? keyring)
(mkdir-p (dirname keyring)) (mkdir-p (dirname keyring))
@ -170,7 +179,7 @@ (define* (gnupg-receive-keys key-id server
(system* (%gpg-command) "--keyserver" server (system* (%gpg-command) "--keyserver" server
"--no-default-keyring" "--keyring" keyring "--no-default-keyring" "--keyring" keyring
"--recv-keys" key-id)) "--recv-keys" fingerprint/key-id))
(define* (gnupg-verify* sig file (define* (gnupg-verify* sig file
#:key #:key