diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/base32.scm | 31 | ||||
-rw-r--r-- | tests/guix-authenticate.sh | 77 | ||||
-rw-r--r-- | tests/store.scm | 117 |
3 files changed, 126 insertions, 99 deletions
diff --git a/tests/base32.scm b/tests/base32.scm index 134e578633..a999edcacc 100644 --- a/tests/base32.scm +++ b/tests/base32.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013, 2015 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2012, 2013, 2015, 2020 Ludovic Courtès <ludo@gnu.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -23,26 +23,12 @@ #:use-module (srfi srfi-1) #:use-module (srfi srfi-34) #:use-module (srfi srfi-64) - #:use-module (ice-9 rdelim) - #:use-module (ice-9 popen) #:use-module (ice-9 match) #:use-module (rnrs bytevectors) #:use-module (rnrs io ports)) ;; Test the (guix base32) module. -(define %nix-hash - (or (and=> (getenv "NIX_HASH") - (match-lambda - ("" #f) - (val val))) - "nix-hash")) - -(define %have-nix-hash? - ;; Note: Use `system', not `system*', because of <http://bugs.gnu.org/13166>. - (false-if-exception - (zero? (system (string-append %nix-hash " --version"))))) - (test-begin "base32") (test-assert "bytevector->base32-string" @@ -85,19 +71,4 @@ (nix-base32-string->bytevector (string-append (make-string 51 #\a) "e")))) -;; The following test requires `nix-hash' in $PATH. -(unless %have-nix-hash? - (test-skip 1)) - -(test-assert "sha256 & bytevector->nix-base32-string" - (let ((file (search-path %load-path "tests/test.drv"))) - (equal? (bytevector->nix-base32-string - (sha256 (call-with-input-file file get-bytevector-all))) - (let* ((c (format #f "~a --type sha256 --base32 --flat \"~a\"" - %nix-hash file)) - (p (open-input-pipe c)) - (l (read-line p))) - (close-pipe p) - l)))) - (test-end) diff --git a/tests/guix-authenticate.sh b/tests/guix-authenticate.sh index 72c3d161d7..f3b36ee41d 100644 --- a/tests/guix-authenticate.sh +++ b/tests/guix-authenticate.sh @@ -1,5 +1,5 @@ # GNU Guix --- Functional package management for GNU -# Copyright © 2013, 2014 Ludovic Courtès <ludo@gnu.org> +# Copyright © 2013, 2014, 2020 Ludovic Courtès <ludo@gnu.org> # # This file is part of GNU Guix. # @@ -28,68 +28,51 @@ rm -f "$sig" "$hash" trap 'rm -f "$sig" "$hash"' EXIT +key="$abs_top_srcdir/tests/signing-key.sec" +key_len="`echo -n $key | wc -c`" + # A hexadecimal string as long as a sha256 hash. -echo "2749f0ea9f26c6c7be746a9cff8fa4c2f2a02b000070dba78429e9a11f87c6eb" \ - > "$hash" +hash="2749f0ea9f26c6c7be746a9cff8fa4c2f2a02b000070dba78429e9a11f87c6eb" +hash_len="`echo -n $hash | wc -c`" -guix authenticate rsautl -sign \ - -inkey "$abs_top_srcdir/tests/signing-key.sec" \ - -in "$hash" > "$sig" +echo "sign $key_len:$key $hash_len:$hash" | guix authenticate > "$sig" test -f "$sig" +case "$(cat $sig)" in + "0 "*) ;; + *) echo "broken signature: $(cat $sig)" + exit 42;; +esac + +# Remove the leading "0". +sed -i "$sig" -e's/^0 //g' -hash2="`guix authenticate rsautl -verify \ - -inkey $abs_top_srcdir/tests/signing-key.pub \ - -pubin -in $sig`" -test "$hash2" = `cat "$hash"` - -# Same thing in a pipeline, using the command line syntax that Nix/Crypto.pm -# uses. -hash2="` \ - cat "$hash" \ - | guix authenticate rsautl -sign \ - -inkey "$abs_top_srcdir/tests/signing-key.sec" \ - | guix authenticate rsautl -verify \ - -inkey $abs_top_srcdir/tests/signing-key.pub \ - -pubin`" -test "$hash2" = `cat "$hash"` +hash2="$(echo verify $(cat "$sig") | guix authenticate)" +test "$(echo $hash2 | cut -d : -f 2)" = "$hash" # Detect corrupt signatures. -if guix authenticate rsautl -verify \ - -inkey "$abs_top_srcdir/tests/signing-key.pub" \ - -pubin -in /dev/null -then false -else true -fi +code="$(echo "verify 5:wrong" | guix authenticate | cut -f1 -d ' ')" +test "$code" -ne 0 # Detect invalid signatures. # The signature has (payload (data ... (hash sha256 #...#))). We proceed by # modifying this hash. sed -i "$sig" \ -e's|#[A-Z0-9]\{64\}#|#0000000000000000000000000000000000000000000000000000000000000000#|g' -if guix authenticate rsautl -verify \ - -inkey "$abs_top_srcdir/tests/signing-key.pub" \ - -pubin -in "$sig" -then false -else true -fi - +code="$(echo "verify $(cat $sig)" | guix authenticate | cut -f1 -d ' ')" +test "$code" -ne 0 # Test for <http://bugs.gnu.org/17312>: make sure 'guix authenticate' produces # valid signatures when run in the C locale. -echo "5eff0b55c9c5f5e87b4e34cd60a2d5654ca1eb78c7b3c67c3179fed1cff07b4c" \ - > "$hash" +hash="5eff0b55c9c5f5e87b4e34cd60a2d5654ca1eb78c7b3c67c3179fed1cff07b4c" LC_ALL=C export LC_ALL -guix authenticate rsautl -sign \ - -inkey "$abs_top_srcdir/tests/signing-key.sec" \ - -in "$hash" > "$sig" - -guix authenticate rsautl -verify \ - -inkey "$abs_top_srcdir/tests/signing-key.pub" \ - -pubin -in "$sig" -hash2="`guix authenticate rsautl -verify \ - -inkey $abs_top_srcdir/tests/signing-key.pub \ - -pubin -in $sig`" -test "$hash2" = `cat "$hash"` +echo "sign $key_len:$key $hash_len:$hash" | guix authenticate > "$sig" + +# Remove the leading "0". +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" diff --git a/tests/store.scm b/tests/store.scm index ee3e01f33b..38051bf5e5 100644 --- a/tests/store.scm +++ b/tests/store.scm @@ -23,6 +23,8 @@ #:use-module (guix utils) #:use-module (guix monads) #:use-module ((gcrypt hash) #:prefix gcrypt:) + #:use-module ((gcrypt pk-crypto) #:prefix gcrypt:) + #:use-module (guix pki) #:use-module (guix base32) #:use-module (guix packages) #:use-module (guix derivations) @@ -141,6 +143,15 @@ (string-append (%store-prefix) "/" (make-string 32 #\e) "-foobar")))) +(test-equal "with-store, multiple values" ;<https://bugs.gnu.org/42912> + '(1 2 3) + (call-with-values + (lambda () + (with-store s + (add-text-to-store s "foo" "bar") + (values 1 2 3))) + list)) + (test-assert "valid-path? error" (with-store s (guard (c ((store-protocol-error? c) #t)) @@ -212,30 +223,22 @@ ;;(> freed 0) (not (file-exists? p)))))) -(test-assert "add-text-to-store vs. delete-paths" - ;; Before, 'add-text-to-store' would return PATH2 without noticing that it - ;; is no longer valid. +(test-assert "add-text-to-store/add-to-store vs. delete-paths" + ;; Before, 'add-text-to-store' and 'add-to-store' would return the same + ;; store item without noticing that it is no longer valid. (with-store store (let* ((text (random-text)) - (path (add-text-to-store store "delete-me" text)) - (deleted (delete-paths store (list path))) - (path2 (add-text-to-store store "delete-me" text))) - (and (string=? path path2) - (equal? deleted (list path)) - (valid-path? store path) - (file-exists? path))))) - -(test-assert "add-to-store vs. delete-paths" - ;; Same as above. - (with-store store - (let* ((file (search-path %load-path "guix.scm")) - (path (add-to-store store "delete-me" #t "sha256" file)) - (deleted (delete-paths store (list path))) - (path2 (add-to-store store "delete-me" #t "sha256" file))) - (and (string=? path path2) - (equal? deleted (list path)) - (valid-path? store path) - (file-exists? path))))) + (file (search-path %load-path "guix.scm")) + (path1 (add-text-to-store store "delete-me" text)) + (path2 (add-to-store store "delete-me" #t "sha256" file)) + (deleted (delete-paths store (list path1 path2)))) + (and (string=? path1 (add-text-to-store store "delete-me" text)) + (string=? path2 (add-to-store store "delete-me" #t "sha256" file)) + (lset= string=? deleted (list path1 path2)) + (valid-path? store path1) + (valid-path? store path2) + (file-exists? path1) + (file-exists? path2))))) (test-equal "add-file-tree-to-store" `(42 @@ -957,6 +960,76 @@ (list out1 out2)))) #:guile-for-build (%guile-for-build))) + +(test-assert "import not signed" + (let* ((text (random-text)) + (file (add-file-tree-to-store %store + `("tree" directory + ("text" regular (data ,text)) + ("link" symlink "text")))) + (dump (call-with-bytevector-output-port + (lambda (port) + (write-int 1 port) ;start + + (write-file file port) ;contents + (write-int #x4558494e port) ;%export-magic + (write-string file port) ;store item + (write-string-list '() port) ;references + (write-string "" port) ;deriver + (write-int 0 port) ;not signed + + (write-int 0 port))))) ;done + + ;; Ensure 'import-paths' raises an exception. + (guard (c ((store-protocol-error? c) + (and (not (zero? (store-protocol-error-status c))) + (string-contains (store-protocol-error-message c) + "lacks a signature")))) + (let* ((source (open-bytevector-input-port dump)) + (imported (import-paths %store source))) + (pk 'unsigned-imported imported) + #f)))) + +(test-assert "import signed by unauthorized key" + (let* ((text (random-text)) + (file (add-file-tree-to-store %store + `("tree" directory + ("text" regular (data ,text)) + ("link" symlink "text")))) + (key (gcrypt:generate-key + (gcrypt:string->canonical-sexp + "(genkey (ecdsa (curve Ed25519) (flags rfc6979)))"))) + (dump (call-with-bytevector-output-port + (lambda (port) + (write-int 1 port) ;start + + (write-file file port) ;contents + (write-int #x4558494e port) ;%export-magic + (write-string file port) ;store item + (write-string-list '() port) ;references + (write-string "" port) ;deriver + (write-int 1 port) ;signed + (write-string (gcrypt:canonical-sexp->string + (signature-sexp + (gcrypt:bytevector->hash-data + (gcrypt:sha256 #vu8(0 1 2)) + #:key-type 'ecc) + (gcrypt:find-sexp-token key 'private-key) + (gcrypt:find-sexp-token key 'public-key))) + port) + + (write-int 0 port))))) ;done + + ;; Ensure 'import-paths' raises an exception. + (guard (c ((store-protocol-error? c) + (and (not (zero? (store-protocol-error-status c))) + (string-contains (store-protocol-error-message c) + "unauthorized public key")))) + (let* ((source (open-bytevector-input-port dump)) + (imported (import-paths %store source))) + (pk 'unauthorized-imported imported) + #f)))) + (test-assert "import corrupt path" (let* ((text (random-text)) (file (add-text-to-store %store "text" text)) |