#!/bin/sh
# -*- mode: sh; coding: utf-8 -*-
# Test archive signing scripts
# Copyright © 2005 Canonical Limited
#	Authors: Robert Collins <robert.collins@canonical.com>
#
# See the file "COPYING" for further information about
# the copyright and warranty status of this work.

set -e

arg0="$0"
srcdir=`dirname "$arg0"`

. ${srcdir}/test-framework

setup_with_setup_archives

test_class "signing rules"

begin_test "import a signed revision with trivial rule"
touch $(tla whereis-archive jane@example.com--2003|sed s/cached://)/\=meta-info/signed-archive
mkdir -p $HOME/.arch-params/signing
echo "true" > $HOME/.arch-params/signing/\=default.check
echo "gpg --clearsign" > $HOME/.arch-params/signing/\=default
  make_hello_world tmp-tree
  cd tmp-tree
  tla init-tree --nested jane@example.com--2003/hello-world--mainline--1.0
  tla add hello-world.c README
  tla import -L 'initial import' 1>/dev/null
  cd ..
  rm -rf tmp-tree
end_test

begin_test "commit to a signed archive with trivial rule"
tla get jane@example.com--2003/hello-world--mainline--1.0 foo
cd foo
touch new-file
tla add new-file
tla commit -s 'succeed' || test_fail "failed to commit with trivial signing rule"
cd ..
end_test 

begin_test "commit to a signed archive with trivial new rule"
tla get jane@example.com--2003/hello-world--mainline--1.0 foo
cd foo
touch new-file-2
tla add new-file-2
touch ~/.arch-params/archives/jane@example.com--2003
echo "false" > $HOME/.arch-params/signing/\=default
tla commit -s 'succed2' || test_fail "failed to commit with new trivial signing rule"
cd ..
end_test

begin_test "make-archive -m sets signing if the original is"
cp ~/.arch-params/archives/jane@example.com--2003{,.old}
tla make-archive --mirror jane@example.com--2003 ${ARCHIVEDIR}/jane-archive-mirror
[ -e ${ARCHIVEDIR}/jane-archive-mirror/=meta-info/signed-archive ] || test_fail "make-archive -m did not create signing flag automatically"
rm -rf $CACHEDIR/archives/jane@example.com--2003
rm -rf ${ARCHIVEDIR}/jane-archive-mirror
mv ~/.arch-params/archives/jane@example.com--2003{.old,}
rm -f ~/.arch-params/=locations/jane@example.com--2003-MIRROR
end_test

begin_test "make-archive -m set not set signing if the original isn't"
cp ~/.arch-params/archives/jane@example.com--2003{,.old}
mv $(tla whereis-archive jane@example.com--2003|sed s/cached://)/\=meta-info/signed-archive{,.old}
tla make-archive --mirror jane@example.com--2003 ${ARCHIVEDIR}/jane-archive-mirror
[ -e ${ARCHIVEDIR}/jane-archive-mirror/=meta-info/signed-archive ] && test_fail "make-archive -m set the signing flag incorrectly"
rm -rf $CACHEDIR/archives/jane@example.com--2003
rm -rf ${ARCHIVEDIR}/jane-archive-mirror
rm -f ~/.arch-params/=locations/jane@example.com--2003-MIRROR
mv ~/.arch-params/archives/jane@example.com--2003{.old,}
mv $(tla whereis-archive jane@example.com--2003|sed s/cached://)/\=meta-info/signed-archive{.old,}
end_test

begin_test "make-archive -M sets signing if the original is"
cp ~/.arch-params/archives/jane@example.com--2003{,.old}
[ -e ~/.arch-params/archives/jane@example.com--2003-SOURCE ] && test_fail "-SOURCE false archive registration exists"
tla make-archive --mirror-from jane@example.com--2003 ${ARCHIVEDIR}/jane-archive-mirror
[ -e ~/.arch-params/archives/jane@example.com--2003-SOURCE ] && test_fail "-SOURCE false archive registration exists"
[ -e ${ARCHIVEDIR}/jane-archive-mirror/=meta-info/signed-archive ] || test_fail "make-archive -M did not create signing flag automatically"
rm -rf $CACHEDIR/archives/jane@example.com--2003
rm -rf ${ARCHIVEDIR}/jane-archive-mirror
mv ~/.arch-params/archives/jane@example.com--2003{.old,}
end_test

begin_test "make-archive -M does not set signing if the original isn't"
cp ~/.arch-params/archives/jane@example.com--2003{,.old}
mv $(tla whereis-archive jane@example.com--2003|sed s/cached://)/\=meta-info/signed-archive{,.old}
tla make-archive --mirror jane@example.com--2003 ${ARCHIVEDIR}/jane-archive-mirror
[ -e ${ARCHIVEDIR}/jane-archive-mirror/=meta-info/signed-archive ] && test_fail "make-archive -M set the signing flag incorrectly"
rm -rf $CACHEDIR/archives/jane@example.com--2003
rm -rf ${ARCHIVEDIR}/jane-archive-mirror
mv ~/.arch-params/archives/jane@example.com--2003{.old,}
mv $(tla whereis-archive jane@example.com--2003|sed s/cached://)/\=meta-info/signed-archive{.old,}
end_test


begin_test "Make a mirror with old style registration"
tla make-archive -s --mirror jane@example.com--2003 ${CACHEDARCHIVEDIR}/jane-archive-mirror
rm ~/.arch-params/archives/jane@example.com--2003
touch ~/.arch-params/archives/jane@example.com--2003
mkdir -p ~/.arch-params/\=locations
echo ${CACHEDARCHIVEDIR}/jane-archive > $HOME/.arch-params/\=locations/jane@example.com--2003
echo ${CACHEDARCHIVEDIR}/jane-archive-mirror > $HOME/.arch-params/\=locations/jane@example.com--2003-MIRROR
end_test

begin_test "mirror to a mirror with old style registration new signing rule"
# set a bad signing rule to trigger a failure if it doesn't copy
echo "gpg_command=false" > ~/.arch-params/archives/jane@example.com--2003
tla archive-mirror jane@example.com--2003
diff ${ARCHIVEDIR}/jane-archive/hello-world--mainline--1.0/patch-1/checksum.cacherev  ${ARCHIVEDIR}/jane-archive-mirror/hello-world--mainline--1.0/patch-1/checksum.cacherev
end_test

begin_test "bad gpg_options break commits"
tla get jane@example.com--2003/hello-world--mainline--1.0 foo
cd foo
touch new-file-3
tla add new-file-3
echo "gpg_options=--breakme-harder" > ~/.arch-params/archives/jane@example.com--2003
tla commit -s 'should not work' && test_fail "gpg_options were ignored"
cd ..
end_test

begin_test "mirror to a mirror with old style registration old style signing rule"
# nuke mirror branch
rm -rf ${ARCHIVEDIR}/jane-archive-mirror/hello-world--mainline--1.0
# nuke new rule
rm -f ~/.arch-params/archives/jane@example.com--2003
#reset signing rule to fail in case it tries it
echo "false" > $HOME/.arch-params/signing/jane@example.com--2003
#reset signing on mirror to copy
echo "jane@example.com--2003" > $HOME/.arch-params/signing/jane@example.com--2003-MIRROR
tla archive-mirror jane@example.com--2003
diff ${ARCHIVEDIR}/jane-archive/hello-world--mainline--1.0/patch-1/checksum.cacherev  ${ARCHIVEDIR}/jane-archive-mirror/hello-world--mainline--1.0/patch-1/checksum.cacherev
end_test

test_default_rule_import ()
{
  begin_test $1
  # remove defaults
  rm -f ~/.arch-params/archives/defaults
  # create \=default
  echo $2 > ~/.arch-params/signing/\=default
  # cause defaults to be imported
  tla abrowse jane@example.com--2003
  # check for helpful comment
  file_matches "^# Imported default signing rules$" ~/.arch-params/archives/defaults || test_fail 'gpg import comment not present'
  # check for gpg command
  file_matches "^gpg_command=$3$" ~/.arch-params/archives/defaults || test_fail 'gpg command not imported'
  # check for gpg options
  if [ -n "$4" ]; then
    file_matches "^gpg_options=$4$" ~/.arch-params/archives/defaults  || test_fail 'gpg options not imported'
  fi
  end_test
}

test_default_rule_import "defaults creation imports gnome-gpg --default-key foo --clearsign --other-option" "gnome-gpg --default-key foo --clearsign --otheroption" gnome-gpg "--default-key foo --otheroption"
test_default_rule_import "defaults creation imports gpg --clearsign --use-agent" "gpg --clearsign --use-agent" gpg --use-agent
test_default_rule_import "defaults creation imports agpg --no-tty --quiet --no-verbose --batch --clearsign" "agpg --no-tty --quiet --no-verbose --batch --clearsign" agpg "--no-tty --quiet --no-verbose --batch"
test_default_rule_import "defaults creation imports gnome-gpg --clearsign" "gnome-gpg --clearsign" gnome-gpg ""

begin_test "defaults creation doesn't import actual shell scripts"
# remove defaults
rm -f ~/.arch-params/archives/defaults
# create \=default
echo "if [ -n "$DISPLAY" ]; then
gnome-gpg --clearsign
else
  gpg --clearsign
fi" > ~/.arch-params/signing/\=default
# cause defaults to be imported
tla abrowse jane@example.com--2003
# check for helpful comment
file_matches "^# Imported default signing rules$" ~/.arch-params/archives/defaults && test_fail 'gpg import comment present'
# check for gpg command
file_matches "^gpg_command=" ~/.arch-params/archives/defaults && test_fail 'gpg command imported'
# check for gpg options
file_matches "^gpg_options=" ~/.arch-params/archives/defaults &&  test_fail 'gpg options imported'
end_test

test_default_check_rule_import ()
{
  begin_test $1
  # remove defaults
  rm -f ~/.arch-params/archives/defaults
  # create \=default
  echo $2 > ~/.arch-params/signing/\=default.check
  # cause defaults to be imported
  tla abrowse jane@example.com--2003 2>,,error-out
  # check for gpg options
  if [ -n "$3" ]; then
    file_matches "# Unconvertable check script" ~/.arch-params/archives/defaults  || test_fail 'check script conversion not warned in ini file'
    file_matches "WARNING: Unconvertable check script .*\\.check" ,,error-out  || test_fail 'check script conversion not warned'
  else
    file_matches "# Unconvertable check script" ~/.arch-params/archives/defaults && test_fail 'check script conversion warned in ini file'
    file_matches "WARNING: Unconvertable check script .*\\.check" ,,error-out && test_fail 'check script conversion warned'
  fi
  rm ,,error-out
  end_test
}

test_default_check_rule_import 'defaults creation imports check bazaar-gpg-check gpg_command="gpg --verify-files -"' 'bazaar-gpg-check gpg_command="gpg --verify-files -"' 
test_default_check_rule_import 'defaults upgrade =gpg-check.awk gpg_command="gpg  --keyserver subkeys.pgp.net --keyserver-options auto-key-retrieve --verify-files -"' '=gpg-check.awk gpg_command="gpg  --keyserver subkeys.pgp.net --keyserver-options auto-key-retrieve --verify-files -"' should-fail
test_default_check_rule_import 'defaults upgrade gpg-check.awk gpg_command="gpg --verify-files - 2>/dev/null"' 'gpg-check.awk gpg_command="gpg --verify-files - 2>/dev/null"'
test_default_check_rule_import 'defaults upgrade /usr/bin/tla-gpg-check gpg_command="/usr/bin/gpg --verify-files -"' '/usr/bin/tla-gpg-check gpg_command="/usr/bin/gpg --verify-files -"'

begin_test "check a signed commit via an old style checking rule"
echo "true" > $HOME/.arch-params/signing/\=default.check
tla get jane@example.com--2003/hello-world--mainline--1.0 foo
cd foo
touch new-file-4
tla add new-file-4
touch ~/.arch-params/archives/jane@example.com--2003
tla commit -s 'succeed-to-check' || test_fail "failed to commit with trivial signing rule"
rm ~/.arch-params/archives/jane@example.com--2003
echo "gpg --verify-files - " > $HOME/.arch-params/signing/\=default.check
cd ..
rm -rf $CACHEDIR/archives/jane@example.com--2003
tla cat-archive-log jane@example.com--2003/hello-world--mainline--1.0--patch-3 | grep succeed-to-check
end_test 

begin_test "deny access via an old style checking rule"
echo "false" > $HOME/.arch-params/signing/\=default.check
rm -rf $CACHEDIR/archives/jane@example.com--2003
tla cat-archive-log jane@example.com--2003/hello-world--mainline--1.0--patch-3 && test_fail "acessed banned archive"
end_test

begin_test "check a signed commit via a new style checking rule"
echo "validate_creator=ignore
validate_archivename=ignore
#allowed_ids=70C34B0E" > ~/.arch-params/archives/jane@example.com--2003
echo "false" > $HOME/.arch-params/signing/jane@example.com--2003
rm -rf $CACHEDIR/archives/jane@example.com--2003
tla cat-archive-log jane@example.com--2003/hello-world--mainline--1.0--patch-3 | grep succeed-to-check
end_test

begin_test "check a signed commit via a new style checking rule with limited fingerprint"
echo "validate_creator=ignore
validate_archivename=ignore
#allowed_ids=70C34B0E
allowed_fingerprints=8493E437C428276B4FB1D3370E7FC6A670C34B0E GARBAGETOFILTER" > ~/.arch-params/archives/jane@example.com--2003
echo "false" > $HOME/.arch-params/signing/jane@example.com--2003
rm -rf $CACHEDIR/archives/jane@example.com--2003
tla cat-archive-log jane@example.com--2003/hello-world--mainline--1.0--patch-3 | grep succeed-to-check
end_test

begin_test "check a signed commit via a new style checking rule with limited incorrect fingerprint"
echo "validate_creator=ignore
validate_archivename=ignore
#allowed_ids=70C34B0E
allowed_fingerprints=8493E437C428276B4FB1D3370E7FC6A670C34B0F GARBAGETOFILTER" > ~/.arch-params/archives/jane@example.com--2003
echo "false" > $HOME/.arch-params/signing/jane@example.com--2003
rm -rf $CACHEDIR/archives/jane@example.com--2003
tla cat-archive-log jane@example.com--2003/hello-world--mainline--1.0--patch-3 && test_fail "accessed archive with incorrect fingerprint"
end_test

begin_test "check a signed commit via a new style checking rule with limited id"
echo "validate_creator=ignore
validate_archivename=ignore
allowed_ids=0E7FC6A670C34B0E john@example.com" > ~/.arch-params/archives/jane@example.com--2003
echo "false" > $HOME/.arch-params/signing/jane@example.com--2003
rm -rf $CACHEDIR/archives/jane@example.com--2003
tla cat-archive-log jane@example.com--2003/hello-world--mainline--1.0--patch-3 | grep succeed-to-check
end_test

begin_test "check a signed commit via a new style checking rule with limited uid"
echo "validate_creator=ignore
validate_archivename=ignore
allowed_ids=0E7FC6A670C34XXX jane@example.com" > ~/.arch-params/archives/jane@example.com--2003
echo "false" > $HOME/.arch-params/signing/jane@example.com--2003
rm -rf $CACHEDIR/archives/jane@example.com--2003
tla cat-archive-log jane@example.com--2003/hello-world--mainline--1.0--patch-3 | grep succeed-to-check
end_test


begin_test "check a signed commit via a new style checking rule with limited incorrect id"
echo "validate_creator=ignore
validate_archivename=ignore
allowed_ids=0E7FC6B670C34B0E john@example.com" > ~/.arch-params/archives/jane@example.com--2003
echo "false" > $HOME/.arch-params/signing/jane@example.com--2003
rm -rf $CACHEDIR/archives/jane@example.com--2003
tla cat-archive-log jane@example.com--2003/hello-world--mainline--1.0--patch-3 && test_fail "accessed archive with incorrect ids"
end_test

begin_test "check a signed commit via a new style checking rule with limited uid and bad fingerprint"
echo "validate_creator=ignore
validate_archivename=ignore
allowed_ids=0E7FC6A670C34XXX jane@example.com
allowed_fingerprints=8493E437C428276B4FB1D3370E7FC6A670C34B0F GARBAGE" > ~/.arch-params/archives/jane@example.com--2003
echo "false" > $HOME/.arch-params/signing/jane@example.com--2003
rm -rf $CACHEDIR/archives/jane@example.com--2003
tla cat-archive-log jane@example.com--2003/hello-world--mainline--1.0--patch-3 | grep succeed-to-check
end_test

begin_test "check a signed commit via a new style checking rule with limited bad uid and good fingerprint"
echo "validate_creator=ignore
validate_archivename=ignore
allowed_ids=0E7FC6A670C34XXX john@example.com
allowed_fingerprints=8493E437C428276B4FB1D3370E7FC6A670C34B0E GARBAGE" > ~/.arch-params/archives/jane@example.com--2003
echo "false" > $HOME/.arch-params/signing/jane@example.com--2003
rm -rf $CACHEDIR/archives/jane@example.com--2003
tla cat-archive-log jane@example.com--2003/hello-world--mainline--1.0--patch-3 | grep succeed-to-check
end_test

begin_test "check a signed commit via a new style checking rule with limited bad uid and bad fingerprint"
echo "validate_creator=ignore
validate_archivename=ignore
allowed_ids=0E7FC6A670C34XXX john@example.com
allowed_fingerprints=8493E437C428276B4FB1D3370E7FC6A670C34BFF GARBAGE" > ~/.arch-params/archives/jane@example.com--2003
echo "false" > $HOME/.arch-params/signing/jane@example.com--2003
rm -rf $CACHEDIR/archives/jane@example.com--2003
tla cat-archive-log jane@example.com--2003/hello-world--mainline--1.0--patch-3 && test_fail "accessed archive with neither fingerprint or id permitted"
end_test

begin_test "unsigned archives with new registry can be read from"
mkdir temp
tla import --automatic -d temp foo@example.org--2003/demo--0
touch ~/.arch-params/archives/foo@example.org--2003
rm -rf $CACHEDIR/archives/foo@example.org--2003
tla get foo@example.org--2003/demo--0
end_test

begin_test "unsigned archives with new registry can be committed to"
tla get foo@example.org--2003/demo--0 demo
cd demo
touch new-file
tla add new-file
tla commit -s 'committed'
end_test

begin_test "unsigned archives with when_unsigned=warn warn on read"
cp ~/.arch-params/archives/foo@example.org--2003{,.old}
echo "when_unsigned=warn" >> ~/.arch-params/archives/foo@example.org--2003 || test_fail "couldn't set when_unsigned"
rm -rf $CACHEDIR/archives/foo@example.org--2003 || test_fail "couldn't remove the foo@example.org archive cached data"
tla get foo@example.org--2003/demo--0 2>,,error-out || test_fail "couldn't get foo's tree"
file_matches 'WARNING: archive .* is configured as a signed archive' ,,error-out || test_fail "no warning emiitted"
mv ~/.arch-params/archives/foo@example.org--2003{.old,}
end_test

begin_test "unsigned archives with when_unsigned=error error on read"
cp ~/.arch-params/archives/foo@example.org--2003{,.old}
echo "when_unsigned=error" >> ~/.arch-params/archives/foo@example.org--2003
rm -rf $CACHEDIR/archives/foo@example.org--2003
tla get foo@example.org--2003/demo--0 && test_fail "accessed unsigned archive when when_unsigned=error"
mv ~/.arch-params/archives/foo@example.org--2003{.old,}
end_test

begin_test "cannot commit to unsigned archives with when_unsigned=error"
cp ~/.arch-params/archives/foo@example.org--2003{,.old}
echo "when_unsigned=ignore" >> ~/.arch-params/archives/foo@example.org--2003
rm -rf $CACHEDIR/archives/foo@example.org--2003
tla get foo@example.org--2003/demo--0 demo
touch demo/new-file-2
tla add demo/new-file-2
echo "when_unsigned=error" > ~/.arch-params/archives/foo@example.org--2003
tla commit -d demo -s 'commit 2' && test_fail "commited to unsigned archive when when_unsigned=error"
mv ~/.arch-params/archives/foo@example.org--2003{.old,}
end_test

begin_test "change-archive --remove-signatures"
# backup the archive so we can check
cp -pR $ARCHIVEDIR/jane-archive backup
# new format registration
echo "url=${ARCHIVEDIR}/jane-archive master
when_unsigned=error" > ~/.arch-params/archives/jane@example.com--2003
rm ~/.arch-params/signing/jane@example.com--2003
tla change-archive --remove-signatures jane@example.com--2003 || test_fail "failed to remove signatures"
file_matches "^when_unsigned=ignore$" ~/.arch-params/archives/jane@example.com--2003 || test_fail "when_unsigned not set to ignore in archive registration"
diff ${ARCHIVEDIR}/jane-archive/hello-world--mainline--1.0/patch-1/checksum.cacherev  backup/hello-world--mainline--1.0/patch-1/checksum.cacherev && test_fail "checksum not regenerated"
# uncomment me when the registry URL list is active. diff ${ARCHIVEDIR}/jane-archive/hello-world--mainline--1.0/patch-1/checksum.cacherev  ${ARCHIVEDIR}/jane-archive-mirror/hello-world--mainline--1.0/patch-1/checksum.cacherev
end_test

begin_test "change-archive --add-signatures"
# backup the archive so we can check
cp -pR $ARCHIVEDIR/jane-archive backup
# new format registration
echo "url=${ARCHIVEDIR}/jane-archive master" > ~/.arch-params/archives/jane@example.com--2003
tla change-archive --add-signatures jane@example.com--2003
file_matches "^when_unsigned=error$" ~/.arch-params/archives/jane@example.com--2003 || test_fail "when_unsigned not set to error in archive registration"
diff ${ARCHIVEDIR}/jane-archive/hello-world--mainline--1.0/patch-1/checksum.cacherev  backup/hello-world--mainline--1.0/patch-1/checksum.cacherev && test_fail "checksum not regenerated"
# uncomment me when the registry URL list is active. diff ${ARCHIVEDIR}/jane-archive/hello-world--mainline--1.0/patch-1/checksum.cacherev  ${ARCHIVEDIR}/jane-archive-mirror/hello-world--mainline--1.0/patch-1/checksum.cacherev
end_test

# check a signature from a second key, where we have signed one uid, but not the other uid
#  - the uid matching should /not/ match the other uid.

clean_workdir
