~ruther/guix-local

0ac2a0fd1813fb5c04b22f6443d8f8a96d3c9645 — Ludovic Courtès 2 months ago 5d6dfd8
authenticate: Report failure to load keys to the daemon.

Previously, when failing to load a signing key, ‘guix authenticate’ would
print a backtrace and exit with a non-zero code.  That, in turn, would lead
the guix-daemon child process to crash with:

  nix/libutil/serialise.cc:15: virtual nix::BufferedSink::~BufferedSink(): Assertion `!bufPos' failed.

This patch fixes it by reporting the error to the daemon as was intended.

* guix/scripts/authenticate.scm (guix-authenticate): Arrange to call
‘load-key-pair’ from within ‘with-reply’.
* tests/guix-authenticate.sh: Test it.

Fixes: guix/guix#4928
Reported-by: Rutherther <rutherther@ditigal.xyz>
Change-Id: I8654ad6fdfbe18c55e1e85647d0c49f408d0574a
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Merges: #4961
2 files changed, 24 insertions(+), 16 deletions(-)

M guix/scripts/authenticate.scm
M tests/guix-authenticate.sh
M guix/scripts/authenticate.scm => guix/scripts/authenticate.scm +18 -15
@@ 1,5 1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2020 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2013-2017, 2020, 2025 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;


@@ 196,20 196,23 @@ Sign data or verify signatures.  This tool is meant to be used internally by
           ;; Read a request on standard input and reply.
           (match (read-command (current-input-port))
             (("sign" signing-key (= base16-string->bytevector hash))
              (let* ((key-pairs keys
                                (match (vhash-assoc signing-key key-pairs)
                                  ((_ . keys)
                                   (values key-pairs keys))
                                  (#f
                                   (let ((keys (load-key-pair signing-key)))
                                     (values (vhash-cons signing-key keys
                                                         key-pairs)
                                             keys))))))
                (with-reply (canonical-sexp->string
                             (match keys
                               ((public . secret)
                                (sign-with-key public secret hash)))))
                (loop key-pairs)))
              (let ((cached-keys (match (vhash-assoc signing-key key-pairs)
                                   ((_ . keys) keys)
                                   (#f #f)))
                    (new-keys #f))
                (with-reply (begin
                              (unless cached-keys
                                ;; Delay 'load-key-pair' call so that failure
                                ;; to load keys is reported via 'with-reply'.
                                (set! new-keys (load-key-pair signing-key)))
                              (canonical-sexp->string
                               (match (or cached-keys new-keys)
                                 ((public . secret)
                                  (sign-with-key public secret hash))))))
                (loop (if new-keys
                          (vhash-cons signing-key new-keys
                                      key-pairs)
                          key-pairs))))
             (("verify" signature)
              (with-reply (bytevector->base16-string
                           (validate-signature

M tests/guix-authenticate.sh => tests/guix-authenticate.sh +6 -1
@@ 1,5 1,5 @@
# GNU Guix --- Functional package management for GNU
# Copyright © 2013, 2014, 2020 Ludovic Courtès <ludo@gnu.org>
# Copyright © 2013, 2014, 2020, 2025 Ludovic Courtès <ludo@gnu.org>
#
# This file is part of GNU Guix.
#


@@ 85,3 85,8 @@ sed -i "$sig" -e's/^0 //g'
echo "verify $(cat $sig)" | guix authenticate
hash2="$(echo "verify $(cat $sig)" | guix authenticate | cut -f2 -d ' ')"
test "$(echo $hash2 | cut -d : -f 2)" = "$hash"

# Make sure an error is properly reported for unreadable key pairs, with exit
# code zero (the process would keep running commands on standard input).
echo "sign 9:/dev/null $hash_len:$hash" | guix authenticate
test $(echo "sign 9:/dev/null $hash_len:$hash" | guix authenticate | cut -f1 -d ' ') = 500