kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit 56755e162db1b89015e3320757a37fcfb8ddbfeb
parent 2b750a220d91fbbd5b41fbed5be909b1445eb1c7
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Thu, 28 May 2026 18:32:29 -0700

pkg: canonicalize artifact order

Diffstat:
Mdoc/DISTRIBUTE.md | 10++++++++--
Mdriver/pkg.c | 41+++++++++++++++++++++++++++++++++++------
Mtest/pkg/run.sh | 468++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 472 insertions(+), 47 deletions(-)

diff --git a/doc/DISTRIBUTE.md b/doc/DISTRIBUTE.md @@ -252,14 +252,20 @@ cfree pkg create --name N --version V [--desc D] -s SECKEY \ [--format cfpkg|tar.gz] [--compression none|lz4-block-v1] \ -o OUT FILE... cfree pkg verify [-p PUBKEY | --tofu] [--format cfpkg|tar.gz] FILE -cfree pkg unpack FILE -C DIR +cfree pkg unpack [--verify] [-p PUBKEY | --tofu] [--format cfpkg|tar.gz] \ + FILE -C DIR cfree pkg inspect FILE -cfree pkg trust {list | add PUBKEY [label] | remove KEYID} +cfree pkg trust {path | list | add PUBKEY [label] | remove KEYID} ``` `create` infers the physical representation from `-o`: `.cfpkg` is native, `.tar.gz` is portable. `--format` overrides inference. +`pkg trust path` prints the trusted-keys file path after applying +`$CFREE_TRUSTED_KEYS` / `$HOME` resolution. `pkg unpack` verifies before writing +artifacts; `--verify` makes that verification explicit in the command and emits +the normal verification success line. + ## Implementation status Implemented: diff --git a/driver/pkg.c b/driver/pkg.c @@ -2,6 +2,7 @@ #include <stddef.h> #include <stdint.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include "dist/blake2b.h" @@ -145,12 +146,19 @@ static void pkg_region_root(uint8_t out[DIST_BLAKE2B_LEN], const char* kind, dist_cfpkg2_root_hash(out, kind, 0, h); } +static int pkg_input_cmp(const void* ap, const void* bp) { + const PkgInputFile* a = (const PkgInputFile*)ap; + const PkgInputFile* b = (const PkgInputFile*)bp; + int c = strcmp(a->path, b->path); + if (c != 0) return c; + return strcmp(a->src, b->src); +} + static int pkg_load_inputs(const CfreeContext* ctx, const char** files, size_t n_files, PkgInputFile* in, DistManifest* m) { size_t i; memset(m, 0, sizeof *m); for (i = 0; i < n_files; ++i) { - DistArtifact* a; in[i].src = files[i]; in[i].path = driver_basename(files[i]); if (pkg_read_file(ctx, files[i], &in[i].fd) != DIST_OK) { @@ -162,6 +170,16 @@ static int pkg_load_inputs(const CfreeContext* ctx, const char** files, driver_errf(PKG_TOOL, "create: too many artifacts"); return DIST_ERR; } + } + + qsort(in, n_files, sizeof in[0], pkg_input_cmp); + + for (i = 0; i < n_files; ++i) { + DistArtifact* a; + if (i > 0 && driver_streq(in[i - 1].path, in[i].path)) { + driver_errf(PKG_TOOL, "create: duplicate artifact path: %s", in[i].path); + return DIST_ERR; + } a = &m->artifacts[m->n_artifacts++]; a->id = (uint64_t)i; snprintf(a->path, sizeof a->path, "%s", in[i].path); @@ -207,9 +225,9 @@ void driver_help_pkg(void) { " [--format cfpkg|tar.gz] [--compression none|lz4-block-v1]\n" " -o OUT FILE...\n" " cfree pkg verify [-p PUBKEY | --tofu] [--format cfpkg|tar.gz] FILE\n" - " cfree pkg unpack FILE -C DIR\n" + " cfree pkg unpack [--verify] [-p PUBKEY | --tofu] [--format cfpkg|tar.gz] FILE -C DIR\n" " cfree pkg inspect FILE\n" - " cfree pkg trust {list | add PUBKEY [label] | remove KEYID}\n"); + " cfree pkg trust {path | list | add PUBKEY [label] | remove KEYID}\n"); } static int pkg_keygen(DriverEnv* env, const CfreeContext* ctx, int argc, @@ -989,13 +1007,15 @@ done: static int pkg_verify_or_unpack(DriverEnv* env, const CfreeContext* ctx, int argc, char** argv, int unpack) { const char *file = NULL, *pubkey = NULL, *dir = "."; - int tofu = 0, i; + int tofu = 0, explicit_verify = 0, i; PkgFormat fmt = PKG_FMT_AUTO; for (i = 0; i < argc; ++i) { if (driver_streq(argv[i], "-p") && i + 1 < argc) pubkey = argv[++i]; else if (driver_streq(argv[i], "--tofu")) tofu = 1; + else if (unpack && driver_streq(argv[i], "--verify")) + explicit_verify = 1; else if (driver_streq(argv[i], "--format") && i + 1 < argc) { fmt = pkg_parse_format(argv[++i]); if (fmt == PKG_FMT_AUTO) { @@ -1020,11 +1040,12 @@ static int pkg_verify_or_unpack(DriverEnv* env, const CfreeContext* ctx, if (fmt == PKG_FMT_AUTO) fmt = pkg_infer_format(file); if (fmt == PKG_FMT_TARGZ) return pkg_verify_portable(env, ctx, file, pubkey, tofu, - unpack ? dir : NULL, unpack) == DIST_OK + unpack ? dir : NULL, + unpack && !explicit_verify) == DIST_OK ? 0 : 1; return pkg_verify_native(env, ctx, file, pubkey, tofu, unpack ? dir : NULL, - unpack) == DIST_OK + unpack && !explicit_verify) == DIST_OK ? 0 : 1; } @@ -1093,6 +1114,14 @@ static int pkg_trust(DriverEnv* env, const CfreeContext* ctx, int argc, "no trusted-keys path (set CFREE_TRUSTED_KEYS or HOME)"); return 1; } + if (driver_streq(sub, "path")) { + if (argc > 1) { + driver_errf(PKG_TOOL, "trust path: unexpected argument: %s", argv[1]); + return 2; + } + driver_printf("%s\n", tpath); + return 0; + } if (driver_streq(sub, "list")) { CfreeFileData fd = {0}; if (pkg_read_file(ctx, tpath, &fd) != DIST_OK) { diff --git a/test/pkg/run.sh b/test/pkg/run.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Driver-level checks for portable package gzip/DEFLATE handling. +# Driver-level checks for cfree pkg distribution formats. set -u @@ -16,8 +16,19 @@ fi work=$(mktemp -d "${TMPDIR:-/tmp}/cfree-pkg-test.XXXXXX") trap 'rm -rf "$work"' EXIT +HOME="$work/home" +CFREE_TRUSTED_KEYS="$work/trusted_keys" +export HOME CFREE_TRUSTED_KEYS +mkdir -p "$HOME" "$work/in" "$work/pkg" "$work/unpack" + pass=0 fail=0 +skip=0 +failures= + +artifacts="empty.dat one.bin payload.txt chunk64.bin chunk64p1.bin chunk3.bin" +artifact_paths= +reversed_artifact_paths= ok() { printf 'PASS %s\n' "$1" @@ -30,63 +41,442 @@ not_ok() { sed 's/^/ | /' "$2" fi fail=$((fail + 1)) + failures="$failures $1" +} + +skip_test() { + printf 'SKIP %s\n' "$1" + skip=$((skip + 1)) +} + +run_ok() { + name=$1 + shift + if "$@" > "$work/$name.out" 2> "$work/$name.err"; then + ok "$name" + else + not_ok "$name" "$work/$name.err" + fi +} + +run_fail() { + name=$1 + shift + if "$@" > "$work/$name.out" 2> "$work/$name.err"; then + { + echo "command unexpectedly succeeded" + sed 's/^/stdout: /' "$work/$name.out" + } > "$work/$name.diag" + not_ok "$name" "$work/$name.diag" + else + ok "$name" + fi +} + +contains() { + name=$1 + file=$2 + needle=$3 + if grep -F "$needle" "$file" >/dev/null 2>&1; then + ok "$name" + else + { + printf 'missing text: %s\n' "$needle" + sed 's/^/file: /' "$file" + } > "$work/$name.diag" + not_ok "$name" "$work/$name.diag" + fi +} + +not_contains() { + name=$1 + file=$2 + needle=$3 + if grep -F "$needle" "$file" >/dev/null 2>&1; then + { + printf 'unexpected text: %s\n' "$needle" + sed 's/^/file: /' "$file" + } > "$work/$name.diag" + not_ok "$name" "$work/$name.diag" + else + ok "$name" + fi +} + +same_file() { + name=$1 + want=$2 + got=$3 + if cmp -s "$want" "$got"; then + ok "$name" + else + { + printf 'files differ:\n' + printf ' want: %s\n' "$want" + printf ' got: %s\n' "$got" + } > "$work/$name.diag" + not_ok "$name" "$work/$name.diag" + fi } -mkdir -p "$work/in" -{ - i=0 - while [ "$i" -lt 4096 ]; do - printf 'portable package deflate regression line %04d\n' "$i" - i=$((i + 1)) +same_artifacts() { + name=$1 + dir=$2 + diag="$work/$name.diag" + : > "$diag" + good=1 + for f in $artifacts; do + if ! cmp -s "$work/in/$f" "$dir/$f"; then + printf 'artifact differs or is missing: %s\n' "$f" >> "$diag" + good=0 + fi done -} > "$work/in/payload.txt" + if [ "$good" -eq 1 ]; then + ok "$name" + else + not_ok "$name" "$diag" + fi +} -if "$CFREE" pkg keygen -o "$work/key" > "$work/keygen.out" 2> "$work/keygen.err"; then - ok "pkg-keygen" -else - not_ok "pkg-keygen" "$work/keygen.err" -fi +have_cmd() { + command -v "$1" >/dev/null 2>&1 +} -if "$CFREE" pkg create --name deflate-smoke --version 1.0.0 \ - --format tar.gz -s "$work/key.key" -o "$work/pkg.tar.gz" \ - "$work/in/payload.txt" > "$work/create.out" 2> "$work/create.err"; then - ok "pkg-create-targz-deflate" -else - not_ok "pkg-create-targz-deflate" "$work/create.err" -fi +make_fixtures() { + : > "$work/in/empty.dat" + printf x > "$work/in/one.bin" + { + i=0 + while [ "$i" -lt 4096 ]; do + printf 'portable package deflate regression line %04d\n' "$i" + i=$((i + 1)) + done + } > "$work/in/payload.txt" + dd if=/dev/zero of="$work/in/chunk64.bin" bs=65536 count=1 >/dev/null 2>&1 + dd if=/dev/zero of="$work/in/chunk64p1.bin" bs=65536 count=1 >/dev/null 2>&1 + printf y >> "$work/in/chunk64p1.bin" + dd if=/dev/zero of="$work/in/chunk3.bin" bs=65536 count=3 >/dev/null 2>&1 + printf tail >> "$work/in/chunk3.bin" -if gzip -t "$work/pkg.tar.gz" > "$work/gzip-test.out" 2> "$work/gzip-test.err"; then - ok "host-gzip-accepts-cfree-output" + artifact_paths= + for f in $artifacts; do + artifact_paths="$artifact_paths $work/in/$f" + done + + reversed_artifact_paths= + for f in chunk3.bin chunk64p1.bin chunk64.bin payload.txt one.bin empty.dat; do + reversed_artifact_paths="$reversed_artifact_paths $work/in/$f" + done +} + +keyid_from_keygen() { + sed -n 's/.*key id \([0-9a-fA-F][0-9a-fA-F]*\)).*/\1/p' "$1" +} + +inspect_checks() { + label=$1 + out=$2 + contains "$label-inspect-magic" "$out" "cfree-package 2" + contains "$label-inspect-name" "$out" "name = matrix-test" + contains "$label-inspect-version" "$out" "version = 1.0.0" + contains "$label-inspect-desc" "$out" "description = package test matrix" + contains "$label-inspect-hash" "$out" "hash = blake2b-merkle-v1" + contains "$label-inspect-empty" "$out" "path = empty.dat" + contains "$label-inspect-boundary" "$out" "path = chunk64p1.bin" + contains "$label-inspect-blake2b" "$out" "blake2b = " + not_contains "$label-inspect-no-sha256" "$out" "sha256" +} + +repack_targz() { + src=$1 + out=$2 + files=$(cd "$src" && find . -type f -print | sed 's#^\./##' | sort) + (cd "$src" && tar -czf "$out" $files) +} + +extract_targz() { + pkg=$1 + dst=$2 + mkdir -p "$dst" + gzip -dc "$pkg" | tar -xf - -C "$dst" +} + +flip_byte() { + file=$1 + off=$2 + printf '\377' | dd of="$file" bs=1 seek="$off" count=1 conv=notrunc >/dev/null 2>&1 +} + +cfpkg_field_offset() { + file=$1 + idx=$2 + perl -e ' + use strict; + use warnings; + my ($file, $idx) = @ARGV; + open my $fh, "<:raw", $file or die "$file: $!"; + seek $fh, 16 + 8 * $idx, 0 or die "seek: $!"; + read $fh, my $b, 8; + die "short read" unless length($b) == 8; + print unpack("Q<", $b); + ' "$file" "$idx" +} + +run_matrix_for_package() { + label=$1 + pkg=$2 + format=$3 + + run_ok "$label-inspect" "$CFREE" pkg inspect "$pkg" + inspect_checks "$label" "$work/$label-inspect.out" + + run_ok "$label-verify-pubkey" "$CFREE" pkg verify -p "$work/key.pub" "$pkg" + contains "$label-verify-output-name" "$work/$label-verify-pubkey.out" "ok: matrix-test 1.0.0" + + outdir="$work/unpack/$label" + mkdir -p "$outdir" + run_ok "$label-unpack-pubkey" "$CFREE" pkg unpack --verify -p "$work/key.pub" "$pkg" -C "$outdir" + contains "$label-unpack-verify-output-name" "$work/$label-unpack-pubkey.out" "ok: matrix-test 1.0.0" + same_artifacts "$label-unpack-content" "$outdir" + + run_ok "$label-verify-format-override" "$CFREE" pkg verify -p "$work/key.pub" --format "$format" "$pkg" +} + +make_fixtures + +run_ok "pkg-keygen" "$CFREE" pkg keygen -o "$work/key" +keyid=$(keyid_from_keygen "$work/pkg-keygen.out") +if [ -n "$keyid" ]; then + ok "pkg-keygen-keyid" else - not_ok "host-gzip-accepts-cfree-output" "$work/gzip-test.err" + echo "could not parse key id from keygen output" > "$work/pkg-keygen-keyid.diag" + not_ok "pkg-keygen-keyid" "$work/pkg-keygen-keyid.diag" fi -if "$CFREE" pkg verify -p "$work/key.pub" "$work/pkg.tar.gz" \ - > "$work/verify.out" 2> "$work/verify.err"; then - ok "pkg-verify-cfree-gzip" +run_ok "pkg-create-targz-deflate" "$CFREE" pkg create \ + --name matrix-test --version 1.0.0 --desc "package test matrix" \ + --format tar.gz -s "$work/key.key" -o "$work/pkg/matrix.tar.gz" \ + $artifact_paths + +run_ok "pkg-create-cfpkg-none" "$CFREE" pkg create \ + --name matrix-test --version 1.0.0 --desc "package test matrix" \ + --format cfpkg --compression none -s "$work/key.key" \ + -o "$work/pkg/matrix-none.cfpkg" $artifact_paths + +run_ok "pkg-create-cfpkg-lz4" "$CFREE" pkg create \ + --name matrix-test --version 1.0.0 --desc "package test matrix" \ + --format cfpkg --compression lz4-block-v1 -s "$work/key.key" \ + -o "$work/pkg/matrix-lz4.cfpkg" $artifact_paths + +run_ok "pkg-create-order-targz-forward" "$CFREE" pkg create \ + --name order-test --version 1.0.0 --desc "order independence" \ + --format tar.gz -s "$work/key.key" -o "$work/pkg/order-forward.tar.gz" \ + $artifact_paths +run_ok "pkg-create-order-targz-reversed" "$CFREE" pkg create \ + --name order-test --version 1.0.0 --desc "order independence" \ + --format tar.gz -s "$work/key.key" -o "$work/pkg/order-reversed.tar.gz" \ + $reversed_artifact_paths +run_ok "pkg-inspect-order-targz-forward" "$CFREE" pkg inspect "$work/pkg/order-forward.tar.gz" +run_ok "pkg-inspect-order-targz-reversed" "$CFREE" pkg inspect "$work/pkg/order-reversed.tar.gz" +same_file "pkg-order-targz-manifest-independent" \ + "$work/pkg-inspect-order-targz-forward.out" \ + "$work/pkg-inspect-order-targz-reversed.out" +same_file "pkg-order-targz-bytes-independent" \ + "$work/pkg/order-forward.tar.gz" "$work/pkg/order-reversed.tar.gz" + +run_ok "pkg-create-order-cfpkg-forward" "$CFREE" pkg create \ + --name order-test --version 1.0.0 --desc "order independence" \ + --format cfpkg --compression lz4-block-v1 -s "$work/key.key" \ + -o "$work/pkg/order-forward.cfpkg" $artifact_paths +run_ok "pkg-create-order-cfpkg-reversed" "$CFREE" pkg create \ + --name order-test --version 1.0.0 --desc "order independence" \ + --format cfpkg --compression lz4-block-v1 -s "$work/key.key" \ + -o "$work/pkg/order-reversed.cfpkg" $reversed_artifact_paths +run_ok "pkg-inspect-order-cfpkg-forward" "$CFREE" pkg inspect "$work/pkg/order-forward.cfpkg" +run_ok "pkg-inspect-order-cfpkg-reversed" "$CFREE" pkg inspect "$work/pkg/order-reversed.cfpkg" +same_file "pkg-order-cfpkg-manifest-independent" \ + "$work/pkg-inspect-order-cfpkg-forward.out" \ + "$work/pkg-inspect-order-cfpkg-reversed.out" +same_file "pkg-order-cfpkg-bytes-independent" \ + "$work/pkg/order-forward.cfpkg" "$work/pkg/order-reversed.cfpkg" + +run_matrix_for_package "targz" "$work/pkg/matrix.tar.gz" "tar.gz" +run_matrix_for_package "cfpkg-none" "$work/pkg/matrix-none.cfpkg" "cfpkg" +run_matrix_for_package "cfpkg-lz4" "$work/pkg/matrix-lz4.cfpkg" "cfpkg" + +run_ok "host-gzip-accepts-cfree-output" gzip -t "$work/pkg/matrix.tar.gz" +if gunzip -c "$work/pkg/matrix.tar.gz" > "$work/pkg/matrix.tar" 2> "$work/gunzip.err" && + gzip -c "$work/pkg/matrix.tar" > "$work/pkg/host.tar.gz" 2> "$work/regzip.err"; then + run_ok "pkg-inspect-host-gzip" "$CFREE" pkg inspect "$work/pkg/host.tar.gz" + run_ok "pkg-verify-host-gzip" "$CFREE" pkg verify -p "$work/key.pub" "$work/pkg/host.tar.gz" else - not_ok "pkg-verify-cfree-gzip" "$work/verify.err" + not_ok "pkg-inspect-host-gzip" "$work/gunzip.err" + not_ok "pkg-verify-host-gzip" "$work/regzip.err" fi -if gunzip -c "$work/pkg.tar.gz" > "$work/pkg.tar" 2> "$work/gunzip.err" && - gzip -c "$work/pkg.tar" > "$work/host.tar.gz" 2> "$work/regzip.err" && - "$CFREE" pkg inspect "$work/host.tar.gz" \ - > "$work/inspect-host.out" 2> "$work/inspect-host.err"; then - ok "pkg-inspect-host-gzip" +run_ok "pkg-create-infer-targz" "$CFREE" pkg create \ + --name matrix-test --version 1.0.0 -s "$work/key.key" \ + -o "$work/pkg/infer.tar.gz" "$work/in/payload.txt" +run_ok "pkg-create-infer-cfpkg" "$CFREE" pkg create \ + --name matrix-test --version 1.0.0 -s "$work/key.key" \ + -o "$work/pkg/infer.cfpkg" "$work/in/payload.txt" +run_fail "pkg-create-unknown-extension-needs-format" "$CFREE" pkg create \ + --name matrix-test --version 1.0.0 -s "$work/key.key" \ + -o "$work/pkg/unknown.pkg" "$work/in/payload.txt" +run_ok "pkg-create-override-targz-extension" "$CFREE" pkg create \ + --name matrix-test --version 1.0.0 --format tar.gz -s "$work/key.key" \ + -o "$work/pkg/override.pkg" "$work/in/payload.txt" +run_ok "pkg-verify-override-targz-extension" "$CFREE" pkg verify -p "$work/key.pub" \ + --format tar.gz "$work/pkg/override.pkg" +run_fail "pkg-verify-wrong-format-native" "$CFREE" pkg verify -p "$work/key.pub" \ + --format cfpkg "$work/pkg/matrix.tar.gz" +run_fail "pkg-verify-wrong-format-portable" "$CFREE" pkg verify -p "$work/key.pub" \ + --format tar.gz "$work/pkg/matrix-none.cfpkg" + +run_fail "pkg-verify-untrusted-no-key" "$CFREE" pkg verify "$work/pkg/matrix.tar.gz" +run_ok "pkg-trust-path" "$CFREE" pkg trust path +contains "pkg-trust-path-output" "$work/pkg-trust-path.out" "$CFREE_TRUSTED_KEYS" +run_ok "pkg-trust-list-empty" "$CFREE" pkg trust list +contains "pkg-trust-list-empty-message" "$work/pkg-trust-list-empty.out" "(no trusted keys" +run_ok "pkg-trust-add" "$CFREE" pkg trust add "$work/key.pub" matrix-label +run_ok "pkg-trust-list-added" "$CFREE" pkg trust list +contains "pkg-trust-list-added-key" "$work/pkg-trust-list-added.out" "$keyid" +contains "pkg-trust-list-added-label" "$work/pkg-trust-list-added.out" "matrix-label" +run_ok "pkg-verify-trusted-store" "$CFREE" pkg verify "$work/pkg/matrix.tar.gz" +run_ok "pkg-trust-remove" "$CFREE" pkg trust remove "$keyid" +run_ok "pkg-trust-list-removed" "$CFREE" pkg trust list +not_contains "pkg-trust-list-removed-key" "$work/pkg-trust-list-removed.out" "$keyid" +run_fail "pkg-verify-after-trust-remove" "$CFREE" pkg verify "$work/pkg/matrix.tar.gz" + +mkdir -p "$work/tofu-home" +run_ok "pkg-verify-tofu-pins" env HOME="$work/tofu-home" CFREE_TRUSTED_KEYS="$work/tofu.keys" \ + "$CFREE" pkg verify --tofu "$work/pkg/matrix.tar.gz" +contains "pkg-tofu-file-key" "$work/tofu.keys" "$keyid" +run_ok "pkg-verify-tofu-store" env HOME="$work/tofu-home" CFREE_TRUSTED_KEYS="$work/tofu.keys" \ + "$CFREE" pkg verify "$work/pkg/matrix.tar.gz" + +run_ok "pkg-keygen-wrong" "$CFREE" pkg keygen -o "$work/wrong" +run_fail "pkg-verify-wrong-pubkey" "$CFREE" pkg verify -p "$work/wrong.pub" "$work/pkg/matrix.tar.gz" + +if have_cmd tar; then + extract_targz "$work/pkg/matrix.tar.gz" "$work/tar-ok" + for f in cfree/package.manifest cfree/package.manifest.minisig cfree/package.pub $artifacts; do + safe_f=$(printf '%s\n' "$f" | sed 's#[^A-Za-z0-9_.-]#-#g') + if [ -f "$work/tar-ok/$f" ]; then + ok "portable-member-$f" + else + echo "missing tar member: $f" > "$work/portable-member-$safe_f.diag" + not_ok "portable-member-$f" "$work/portable-member-$safe_f.diag" + fi + done + + cp -R "$work/tar-ok" "$work/tar-missing-manifest" + rm -f "$work/tar-missing-manifest/cfree/package.manifest" + repack_targz "$work/tar-missing-manifest" "$work/pkg/bad-missing-manifest.tar.gz" + run_fail "portable-missing-manifest-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-missing-manifest.tar.gz" + + cp -R "$work/tar-ok" "$work/tar-missing-signature" + rm -f "$work/tar-missing-signature/cfree/package.manifest.minisig" + repack_targz "$work/tar-missing-signature" "$work/pkg/bad-missing-signature.tar.gz" + run_fail "portable-missing-signature-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-missing-signature.tar.gz" + + cp -R "$work/tar-ok" "$work/tar-missing-artifact" + rm -f "$work/tar-missing-artifact/payload.txt" + repack_targz "$work/tar-missing-artifact" "$work/pkg/bad-missing-artifact.tar.gz" + run_fail "portable-missing-artifact-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-missing-artifact.tar.gz" + + cp -R "$work/tar-ok" "$work/tar-extra-member" + printf extra > "$work/tar-extra-member/extra.dat" + repack_targz "$work/tar-extra-member" "$work/pkg/bad-extra-member.tar.gz" + run_fail "portable-extra-member-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-extra-member.tar.gz" + + cp -R "$work/tar-ok" "$work/tar-mutated-artifact" + printf tamper >> "$work/tar-mutated-artifact/payload.txt" + repack_targz "$work/tar-mutated-artifact" "$work/pkg/bad-mutated-artifact.tar.gz" + run_fail "portable-mutated-artifact-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-mutated-artifact.tar.gz" + + cp -R "$work/tar-ok" "$work/tar-mutated-manifest" + printf '\n# tamper\n' >> "$work/tar-mutated-manifest/cfree/package.manifest" + repack_targz "$work/tar-mutated-manifest" "$work/pkg/bad-mutated-manifest.tar.gz" + run_fail "portable-mutated-manifest-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-mutated-manifest.tar.gz" else - not_ok "pkg-inspect-host-gzip" "$work/inspect-host.err" + skip_test "portable-tar-member-and-repack-tests" fi -if "$CFREE" pkg verify -p "$work/key.pub" "$work/host.tar.gz" \ - > "$work/verify-host.out" 2> "$work/verify-host.err"; then - ok "pkg-verify-host-gzip" +cp "$work/pkg/matrix.tar.gz" "$work/pkg/bad-gzip-byte.tar.gz" +flip_byte "$work/pkg/bad-gzip-byte.tar.gz" 0 +run_fail "portable-corrupt-gzip-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-gzip-byte.tar.gz" + +cp "$work/pkg/matrix-none.cfpkg" "$work/pkg/bad-native-magic.cfpkg" +flip_byte "$work/pkg/bad-native-magic.cfpkg" 0 +run_fail "native-bad-magic-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-native-magic.cfpkg" + +dd if="$work/pkg/matrix-none.cfpkg" of="$work/pkg/bad-native-truncated.cfpkg" \ + bs=1 count=100 >/dev/null 2>&1 +run_fail "native-truncated-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-native-truncated.cfpkg" + +cp "$work/pkg/matrix-none.cfpkg" "$work/pkg/bad-native-manifest.cfpkg" +flip_byte "$work/pkg/bad-native-manifest.cfpkg" 160 +run_fail "native-mutated-manifest-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-native-manifest.cfpkg" + +if have_cmd perl; then + descriptor_off=$(cfpkg_field_offset "$work/pkg/matrix-none.cfpkg" 4) + index_off=$(cfpkg_field_offset "$work/pkg/matrix-none.cfpkg" 10) + content_off=$(cfpkg_field_offset "$work/pkg/matrix-none.cfpkg" 12) + + cp "$work/pkg/matrix-none.cfpkg" "$work/pkg/bad-native-descriptor.cfpkg" + flip_byte "$work/pkg/bad-native-descriptor.cfpkg" "$descriptor_off" + run_fail "native-mutated-descriptor-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-native-descriptor.cfpkg" + + cp "$work/pkg/matrix-none.cfpkg" "$work/pkg/bad-native-index.cfpkg" + flip_byte "$work/pkg/bad-native-index.cfpkg" "$index_off" + run_fail "native-mutated-index-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-native-index.cfpkg" + + cp "$work/pkg/matrix-none.cfpkg" "$work/pkg/bad-native-content.cfpkg" + flip_byte "$work/pkg/bad-native-content.cfpkg" "$content_off" + run_fail "native-mutated-content-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/bad-native-content.cfpkg" else - not_ok "pkg-verify-host-gzip" "$work/verify-host.err" + skip_test "native-region-offset-corruption-tests" fi +run_fail "pkg-create-missing-required-fails" "$CFREE" pkg create \ + --name missing-version -s "$work/key.key" -o "$work/pkg/missing.tar.gz" "$work/in/payload.txt" +run_fail "pkg-create-unknown-format-fails" "$CFREE" pkg create \ + --name matrix-test --version 1.0.0 --format nope -s "$work/key.key" \ + -o "$work/pkg/badformat.tar.gz" "$work/in/payload.txt" +run_fail "pkg-create-unknown-compression-fails" "$CFREE" pkg create \ + --name matrix-test --version 1.0.0 --format cfpkg --compression nope \ + -s "$work/key.key" -o "$work/pkg/badcomp.cfpkg" "$work/in/payload.txt" +mkdir -p "$work/dup/a" "$work/dup/b" +printf one > "$work/dup/a/same.dat" +printf two > "$work/dup/b/same.dat" +run_fail "pkg-create-duplicate-artifact-path-fails" "$CFREE" pkg create \ + --name matrix-test --version 1.0.0 --format tar.gz -s "$work/key.key" \ + -o "$work/pkg/duplicate.tar.gz" "$work/dup/a/same.dat" "$work/dup/b/same.dat" +run_fail "pkg-verify-missing-file-fails" "$CFREE" pkg verify -p "$work/key.pub" \ + "$work/pkg/does-not-exist.tar.gz" +printf not-a-package > "$work/not-a-package.cfpkg" +run_fail "pkg-inspect-malformed-fails" "$CFREE" pkg inspect "$work/not-a-package.cfpkg" +run_fail "pkg-trust-add-missing-pubkey-fails" "$CFREE" pkg trust add +run_fail "pkg-trust-remove-bad-keyid-fails" "$CFREE" pkg trust remove xyz + if [ "$fail" -ne 0 ]; then - printf 'pkg: %d passed, %d failed\n' "$pass" "$fail" + printf 'pkg: failures:%s\n' "$failures" + printf 'pkg: %d passed, %d failed, %d skipped\n' "$pass" "$fail" "$skip" exit 1 fi -printf 'pkg: %d passed\n' "$pass" +printf 'pkg: %d passed, %d skipped\n' "$pass" "$skip"