From 468b0cfbaaed34952d300fa39ae31d06b1e968cb Mon Sep 17 00:00:00 2001 From: Jacob Bachmeyer Date: Thu, 20 Oct 2022 20:48:56 -0500 Subject: [PATCH] Add tests for timestamp ratchet --- testsuite/gatekeeper.all/11_ratchet.exp | 322 ++++++++++++++++++++++++ testsuite/lib/gatekeeper.exp | 6 + 2 files changed, 328 insertions(+) create mode 100644 testsuite/gatekeeper.all/11_ratchet.exp diff --git a/testsuite/gatekeeper.all/11_ratchet.exp b/testsuite/gatekeeper.all/11_ratchet.exp new file mode 100644 index 0000000..acc3b2c --- /dev/null +++ b/testsuite/gatekeeper.all/11_ratchet.exp @@ -0,0 +1,322 @@ +# Tests for timestamp ratchet + +# Copyright (C) 2022 Jacob Bachmeyer +# +# This file is part of a testsuite for the GNU FTP upload system. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +proc check_ratchet_handling { desc args } { + set tenv [new_test_environment] + + array set data { setup {} rounds {} } + array set data $args + + array set setup { + files {} symlinks {} packages {} + } + array set setup $data(setup) + + register_test_packages $tenv $setup(packages) + + foreach {zone filelist} $setup(files) { + foreach {file sig} $filelist { + file mkdir [file dirname [file join $tenv $zone $file]] + put_file [file join $tenv $zone $file] "${file}\n" + age_file [file join $tenv $zone $file] "10 minutes ago" + if { [llength $sig] > 0 } { + put_file [file join $tenv $zone "${file}.sig"] \ + [sign_test_file [file tail $file] \ + [eval [list make_test_signature] $sig]] + age_file [file join $tenv $zone "${file}.sig"] "10 minutes ago" + } + } + } + foreach {zone linklist} $setup(symlinks) { + foreach {target link} $linklist { + # The Tcl [file link] command refuses to create dangling symlinks. + # file link -symbolic [file join $tenv $zone $link] $target + verbose -log [exec ln -sv $target [file join $tenv $zone $link]] + } + } + + foreach {round} $data(rounds) { + array set step { upload {} check {} } + array set step $round + + array set check { + email-to {} log {} file-tree {} + } + array set check $step(check) + + set log_items { + start "ftp-upload start message" + mail,addresses "outgoing mail sent" + } + if { [llength $check(log)] > 0 } { append log_items $check(log) } + + foreach {tag case} $step(upload) { + make_test_case $tenv [list $tag $case] + } + + start_test_services $tenv + run_upload_batch_test + stop_test_services + + analyze_log $tenv "ratchet: $desc" $log_items + analyze_mail $tenv "ratchet: $desc" to $check(email-to) + if { [llength $check(file-tree)] > 0 } { + foreach {zones mode items} $check(file-tree) { + analyze_file_tree $tenv "ratchet: $desc" \ + $zones $mode $items + } + } + } + + close_test_environment $tenv +} + +# ---------------------------------------- + +check_ratchet_handling "simple replay of new upload" setup { + packages { + foo { + email { "foo@example.org" } + keys { { id 1000 name "foo " } } + maintainers { "foo " } + } + } +} rounds { + { upload { + foo.bin { + directive { + version 1.2 + filename foo.bin + directory foo + } dsig { good 00 1000 "Oct 20 18:50:42 CDT 2022" } + file { test } fsig { good 01 1000 "Oct 20 18:50:42 CDT 2022" } + } + } check { + file-tree { + { incoming in-stage stage archive } empty {} + { pub } files { + foo/foo.bin.sig foo/foo.bin + } + } log { + found,foo.bin.directive.asc "found directive in triplet" + found-packet,foo.bin.directive.asc:foo.bin.sig:foo.bin \ + "found triplet" + workdone,1 "1 upload processed" + } email-to { + ftp-upload-script@gnu.org foo@example.gnu.org + ftp-upload-report@gnu.org foo@example.org foo@example.net + } + } } + { upload { + foo.bin { + directive { + version 1.2 + replace true + directory foo + filename foo.bin + } dsig { good 02 1000 "Oct 20 18:50:42 CDT 2022" } + file { test } fsig { good 03 1000 "Oct 20 18:50:42 CDT 2022" } + } + } check { + file-tree { + { incoming stage archive } empty {} + { in-stage } files { + foo.bin.directive.asc foo.bin.sig foo.bin + } + { pub } files { + foo/foo.bin.sig foo/foo.bin + } + } log { + found,foo.bin.directive.asc "found directive in triplet" + found-packet,foo.bin.directive.asc:foo.bin.sig:foo.bin \ + "found triplet" + validate,older-signature-timestamp "simple replay detected" + } email-to { + ftp-upload-script@gnu.org foo@example.gnu.org + ftp-upload-report@gnu.org foo@example.org foo@example.net + } + } } +} + +check_ratchet_handling "replace new upload" setup { + packages { + foo { + email { "foo@example.org" } + keys { { id 1000 name "foo " } } + maintainers { "foo " } + } + } +} rounds { + { upload { + foo.bin { + directive { + version 1.2 + filename foo.bin + directory foo + } dsig { good 00 1000 "Oct 20 18:50:42 CDT 2022" } + file { test } fsig { good 01 1000 "Oct 20 18:50:42 CDT 2022" } + } + } check { + file-tree { + { incoming in-stage stage archive } empty {} + { pub } files { + foo/foo.bin.sig foo/foo.bin + } + } log { + found,foo.bin.directive.asc "found directive in triplet" + found-packet,foo.bin.directive.asc:foo.bin.sig:foo.bin \ + "found triplet" + workdone,1 "1 upload processed" + } email-to { + ftp-upload-script@gnu.org foo@example.gnu.org + ftp-upload-report@gnu.org foo@example.org foo@example.net + } + } } + { upload { + foo.bin { + directive { + version 1.2 + replace true + directory foo + filename foo.bin + } dsig { good 02 1000 "Oct 20 18:52:42 CDT 2022" } + file { test } fsig { good 03 1000 "Oct 20 18:52:42 CDT 2022" } + } + } check { + file-tree { + { incoming in-stage stage } empty {} + { archive } archived-files { + foo/foo.bin + } + { pub } files { + foo/foo.bin.sig foo/foo.bin + } + } log { + found,foo.bin.directive.asc "found directive in triplet" + found-packet,foo.bin.directive.asc:foo.bin.sig:foo.bin \ + "found triplet" + workdone,1 "1 upload processed" + } email-to { + ftp-upload-script@gnu.org foo@example.gnu.org + ftp-upload-report@gnu.org foo@example.org foo@example.net + } + } } +} + +check_ratchet_handling "replay replaced upload" setup { + packages { + foo { + email { "foo@example.org" } + keys { { id 1000 name "foo " } } + maintainers { "foo " } + } + } +} rounds { + { upload { + foo.bin { + directive { + version 1.2 + replace true + directory foo + filename foo.bin + } dsig { good 00 1000 "Oct 20 18:50:42 CDT 2022" } + file { test } fsig { good 01 1000 "Oct 20 18:50:42 CDT 2022" } + } + } check { + file-tree { + { incoming in-stage stage archive } empty {} + { pub } files { + foo/foo.bin.sig foo/foo.bin + } + } log { + found,foo.bin.directive.asc "found directive in triplet" + found-packet,foo.bin.directive.asc:foo.bin.sig:foo.bin \ + "found triplet" + workdone,1 "1 upload processed" + } email-to { + ftp-upload-script@gnu.org foo@example.gnu.org + ftp-upload-report@gnu.org foo@example.org foo@example.net + } + } } + { upload { + foo.bin { + directive { + version 1.2 + replace true + directory foo + filename foo.bin + } dsig { good 02 1000 "Oct 20 18:52:42 CDT 2022" } + file { test } fsig { good 03 1000 "Oct 20 18:52:42 CDT 2022" } + } + } check { + file-tree { + { incoming in-stage stage } empty {} + { archive } archived-files { + foo/foo.bin + } + { pub } files { + foo/foo.bin.sig foo/foo.bin + } + } log { + found,foo.bin.directive.asc "found directive in triplet" + found-packet,foo.bin.directive.asc:foo.bin.sig:foo.bin \ + "found triplet" + workdone,1 "1 upload processed" + } email-to { + ftp-upload-script@gnu.org foo@example.gnu.org + ftp-upload-report@gnu.org foo@example.org foo@example.net + } + } } + { upload { + foo.bin { + directive { + version 1.2 + replace true + directory foo + filename foo.bin + } dsig { good 00 1000 "Oct 20 18:50:42 CDT 2022" } + file { test } fsig { good 01 1000 "Oct 20 18:50:42 CDT 2022" } + } + } check { + file-tree { + { incoming stage } empty {} + { in-stage } files { + foo.bin.directive.asc foo.bin.sig foo.bin + } + { archive } archived-files { + foo/foo.bin + } + { pub } files { + foo/foo.bin.sig foo/foo.bin + } + } log { + found,foo.bin.directive.asc "found directive in triplet" + found-packet,foo.bin.directive.asc:foo.bin.sig:foo.bin \ + "found triplet" + validate,older-signature-timestamp "replay detected" + } email-to { + ftp-upload-script@gnu.org foo@example.gnu.org + ftp-upload-report@gnu.org foo@example.org foo@example.net + } + } } +} + +# ---------------------------------------- + +#EOF diff --git a/testsuite/lib/gatekeeper.exp b/testsuite/lib/gatekeeper.exp index ff6d7c2..4bddcee 100644 --- a/testsuite/lib/gatekeeper.exp +++ b/testsuite/lib/gatekeeper.exp @@ -764,6 +764,12 @@ proc analyze_log { base_dir name assess } { set A(validate,future-signature-timestamp) 1 exp_continue } + -re {^gatekeeper\[[0-9]+\]: \(Test\)\ + GPG signed upload older than/same timestamp[^\r\n]+} { + # from read_directive_file, if signature timestamp bad + set A(validate,older-signature-timestamp) 1 + exp_continue + } -re {^gatekeeper\[[0-9]+\]: \(Test\)\ DEBUG: [^ ]+ size is [[:digit:]]+} { -- 2.25.1