2011-10-20 08:15:05 +08:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='signed commit tests'
|
|
|
|
. ./test-lib.sh
|
gpg-interface: use more status letters
According to gpg2's doc/DETAILS:
For each signature only one of the codes GOODSIG, BADSIG,
EXPSIG, EXPKEYSIG, REVKEYSIG or ERRSIG will be emitted.
gpg1 ("classic") behaves the same (although doc/DETAILS differs).
Currently, we parse gpg's status output for GOODSIG, BADSIG and
trust information and translate that into status codes G, B, U, N
for the %G? format specifier.
git-verify-* returns success in the GOODSIG case only. This is
somewhat in disagreement with gpg, which considers the first 5 of
the 6 above as VALIDSIG, but we err on the very safe side.
Introduce additional status codes E, X, Y, R for ERRSIG, EXPSIG,
EXPKEYSIG, and REVKEYSIG so that a user of %G? gets more information
about the absence of a 'G' on first glance.
Requested-by: Alex <agrambot@gmail.com>
Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-10-12 21:04:15 +08:00
|
|
|
GNUPGHOME_NOT_USED=$GNUPGHOME
|
2011-10-20 08:15:05 +08:00
|
|
|
. "$TEST_DIRECTORY/lib-gpg.sh"
|
|
|
|
|
|
|
|
test_expect_success GPG 'create signed commits' '
|
2013-12-16 21:55:04 +08:00
|
|
|
test_when_finished "test_unconfig commit.gpgsign" &&
|
|
|
|
|
2011-10-20 08:15:05 +08:00
|
|
|
echo 1 >file && git add file &&
|
|
|
|
test_tick && git commit -S -m initial &&
|
|
|
|
git tag initial &&
|
|
|
|
git branch side &&
|
|
|
|
|
|
|
|
echo 2 >file && test_tick && git commit -a -S -m second &&
|
|
|
|
git tag second &&
|
|
|
|
|
|
|
|
git checkout side &&
|
|
|
|
echo 3 >elif && git add elif &&
|
|
|
|
test_tick && git commit -m "third on side" &&
|
|
|
|
|
|
|
|
git checkout master &&
|
|
|
|
test_tick && git merge -S side &&
|
|
|
|
git tag merge &&
|
|
|
|
|
|
|
|
echo 4 >file && test_tick && git commit -a -m "fourth unsigned" &&
|
|
|
|
git tag fourth-unsigned &&
|
|
|
|
|
2012-01-06 02:54:14 +08:00
|
|
|
test_tick && git commit --amend -S -m "fourth signed" &&
|
2013-12-16 21:55:04 +08:00
|
|
|
git tag fourth-signed &&
|
|
|
|
|
|
|
|
git config commit.gpgsign true &&
|
|
|
|
echo 5 >file && test_tick && git commit -a -m "fifth signed" &&
|
|
|
|
git tag fifth-signed &&
|
|
|
|
|
|
|
|
git config commit.gpgsign false &&
|
|
|
|
echo 6 >file && test_tick && git commit -a -m "sixth" &&
|
|
|
|
git tag sixth-unsigned &&
|
|
|
|
|
|
|
|
git config commit.gpgsign true &&
|
|
|
|
echo 7 >file && test_tick && git commit -a -m "seventh" --no-gpg-sign &&
|
|
|
|
git tag seventh-unsigned &&
|
|
|
|
|
|
|
|
test_tick && git rebase -f HEAD^^ && git tag sixth-signed HEAD^ &&
|
2015-03-20 18:07:15 +08:00
|
|
|
git tag seventh-signed &&
|
2014-06-17 08:05:54 +08:00
|
|
|
|
|
|
|
echo 8 >file && test_tick && git commit -a -m eighth -SB7227189 &&
|
2016-05-03 05:58:45 +08:00
|
|
|
git tag eighth-signed-alt &&
|
|
|
|
|
|
|
|
# commit.gpgsign is still on but this must not be signed
|
|
|
|
git tag ninth-unsigned $(echo 9 | git commit-tree HEAD^{tree}) &&
|
|
|
|
# explicit -S of course must sign.
|
|
|
|
git tag tenth-signed $(echo 9 | git commit-tree -S HEAD^{tree})
|
2011-10-20 08:15:05 +08:00
|
|
|
'
|
|
|
|
|
2014-06-23 15:05:51 +08:00
|
|
|
test_expect_success GPG 'verify and show signatures' '
|
2011-10-20 08:15:05 +08:00
|
|
|
(
|
2016-05-03 05:58:45 +08:00
|
|
|
for commit in initial second merge fourth-signed \
|
|
|
|
fifth-signed sixth-signed seventh-signed tenth-signed
|
2011-10-20 08:15:05 +08:00
|
|
|
do
|
2014-06-23 15:05:51 +08:00
|
|
|
git verify-commit $commit &&
|
2011-10-20 08:15:05 +08:00
|
|
|
git show --pretty=short --show-signature $commit >actual &&
|
t7510: use consistent &&-chains in loop
We check multiple commits in a loop. Because we want to
break out of the loop if any single iteration fails, we use
a subshell/exit like:
(
for i in $stuff
do
do-something $i || exit 1
done
)
However, we are inconsistent in our loop body. Some commands
get their own "|| exit 1", and others try to chain to the
next command with "&&", like:
X &&
Y || exit 1
Z || exit 1
This is a little hard to read and follow, because X and Y
are treated differently for no good reason. But much worse,
the second loop follows a similar pattern and gets it wrong.
"Y" is expected to fail, so we use "&& exit 1", giving us:
X &&
Y && exit 1
Z || exit 1
That gets the test for X wrong (we do not exit unless both X
fails and Y unexpectedly succeeds, but we would want to exit
if _either_ is wrong). We can write this clearly and
correctly by consistently using "&&", followed by a single
"|| exit 1", and negating Y with "!" (as we would in a
normal &&-chain). Like:
X &&
! Y &&
Z || exit 1
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-17 08:03:43 +08:00
|
|
|
grep "Good signature from" actual &&
|
|
|
|
! grep "BAD signature from" actual &&
|
|
|
|
echo $commit OK || exit 1
|
2011-10-20 08:15:05 +08:00
|
|
|
done
|
|
|
|
) &&
|
|
|
|
(
|
2016-05-03 05:58:45 +08:00
|
|
|
for commit in merge^2 fourth-unsigned sixth-unsigned \
|
|
|
|
seventh-unsigned ninth-unsigned
|
2011-10-20 08:15:05 +08:00
|
|
|
do
|
2014-06-23 15:05:51 +08:00
|
|
|
test_must_fail git verify-commit $commit &&
|
2011-10-20 08:15:05 +08:00
|
|
|
git show --pretty=short --show-signature $commit >actual &&
|
t7510: use consistent &&-chains in loop
We check multiple commits in a loop. Because we want to
break out of the loop if any single iteration fails, we use
a subshell/exit like:
(
for i in $stuff
do
do-something $i || exit 1
done
)
However, we are inconsistent in our loop body. Some commands
get their own "|| exit 1", and others try to chain to the
next command with "&&", like:
X &&
Y || exit 1
Z || exit 1
This is a little hard to read and follow, because X and Y
are treated differently for no good reason. But much worse,
the second loop follows a similar pattern and gets it wrong.
"Y" is expected to fail, so we use "&& exit 1", giving us:
X &&
Y && exit 1
Z || exit 1
That gets the test for X wrong (we do not exit unless both X
fails and Y unexpectedly succeeds, but we would want to exit
if _either_ is wrong). We can write this clearly and
correctly by consistently using "&&", followed by a single
"|| exit 1", and negating Y with "!" (as we would in a
normal &&-chain). Like:
X &&
! Y &&
Z || exit 1
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-17 08:03:43 +08:00
|
|
|
! grep "Good signature from" actual &&
|
|
|
|
! grep "BAD signature from" actual &&
|
|
|
|
echo $commit OK || exit 1
|
2014-06-17 08:05:54 +08:00
|
|
|
done
|
|
|
|
) &&
|
|
|
|
(
|
|
|
|
for commit in eighth-signed-alt
|
|
|
|
do
|
|
|
|
git show --pretty=short --show-signature $commit >actual &&
|
|
|
|
grep "Good signature from" actual &&
|
|
|
|
! grep "BAD signature from" actual &&
|
|
|
|
grep "not certified" actual &&
|
|
|
|
echo $commit OK || exit 1
|
2011-10-20 08:15:05 +08:00
|
|
|
done
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
2015-06-22 07:14:40 +08:00
|
|
|
test_expect_success GPG 'verify-commit exits success on untrusted signature' '
|
2015-06-22 07:14:39 +08:00
|
|
|
git verify-commit eighth-signed-alt 2>actual &&
|
|
|
|
grep "Good signature from" actual &&
|
|
|
|
! grep "BAD signature from" actual &&
|
|
|
|
grep "not certified" actual
|
|
|
|
'
|
|
|
|
|
2015-06-22 07:14:42 +08:00
|
|
|
test_expect_success GPG 'verify signatures with --raw' '
|
|
|
|
(
|
|
|
|
for commit in initial second merge fourth-signed fifth-signed sixth-signed seventh-signed
|
|
|
|
do
|
|
|
|
git verify-commit --raw $commit 2>actual &&
|
|
|
|
grep "GOODSIG" actual &&
|
|
|
|
! grep "BADSIG" actual &&
|
|
|
|
echo $commit OK || exit 1
|
|
|
|
done
|
|
|
|
) &&
|
|
|
|
(
|
|
|
|
for commit in merge^2 fourth-unsigned sixth-unsigned seventh-unsigned
|
|
|
|
do
|
|
|
|
test_must_fail git verify-commit --raw $commit 2>actual &&
|
|
|
|
! grep "GOODSIG" actual &&
|
|
|
|
! grep "BADSIG" actual &&
|
|
|
|
echo $commit OK || exit 1
|
|
|
|
done
|
|
|
|
) &&
|
|
|
|
(
|
|
|
|
for commit in eighth-signed-alt
|
|
|
|
do
|
|
|
|
git verify-commit --raw $commit 2>actual &&
|
|
|
|
grep "GOODSIG" actual &&
|
|
|
|
! grep "BADSIG" actual &&
|
|
|
|
grep "TRUST_UNDEFINED" actual &&
|
|
|
|
echo $commit OK || exit 1
|
|
|
|
done
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
2014-06-23 15:05:51 +08:00
|
|
|
test_expect_success GPG 'show signed commit with signature' '
|
|
|
|
git show -s initial >commit &&
|
|
|
|
git show -s --show-signature initial >show &&
|
|
|
|
git verify-commit -v initial >verify.1 2>verify.2 &&
|
|
|
|
git cat-file commit initial >cat &&
|
2015-03-10 04:03:01 +08:00
|
|
|
grep -v -e "gpg: " -e "Warning: " show >show.commit &&
|
|
|
|
grep -e "gpg: " -e "Warning: " show >show.gpg &&
|
2014-06-23 15:05:51 +08:00
|
|
|
grep -v "^ " cat | grep -v "^gpgsig " >cat.commit &&
|
|
|
|
test_cmp show.commit commit &&
|
|
|
|
test_cmp show.gpg verify.2 &&
|
|
|
|
test_cmp cat.commit verify.1
|
|
|
|
'
|
|
|
|
|
2011-10-20 08:15:05 +08:00
|
|
|
test_expect_success GPG 'detect fudged signature' '
|
2014-06-17 07:59:59 +08:00
|
|
|
git cat-file commit seventh-signed >raw &&
|
tests: make forging GPG signed commits and tags more robust
A couple of test scripts create forged GPG signed commits or tags to
check that such forgery can't fool various git commands' signature
verification. All but one of those test scripts are prone to
occasional failures because the forgery creates a bogus GPG signature,
and git commands error out with an unexpected error message, e.g.
"Commit deadbeef does not have a GPG signature" instead of "... has a
bad GPG signature".
't5573-pull-verify-signatures.sh', 't7510-signed-commit.sh' and
't7612-merge-verify-signatures.sh' create forged signed commits like
this:
git commit -S -m "bad on side" &&
git cat-file commit side-bad >raw &&
sed -e "s/bad/forged bad/" raw >forged &&
git hash-object -w -t commit forged >forged.commit
On rare occasions the given pattern occurs not only in the commit
message but in the GPG signature as well, and after it's replaced in
the signature the resulting signature becomes invalid, GPG will report
CRC error and that it couldn't find any signature, which will then
ultimately cause the test failure.
Since in all three cases the pattern to be replaced during the forgery
is the first word of the commit message's subject line, and since the
GPG signature in the commit object is indented by a space, let's just
anchor those patterns to the beginning of the line to prevent this
issue.
The test script 't7030-verify-tag.sh' creates a forged signed tag
object in a similar way by replacing the pattern "seventh", but the
GPG signature in tag objects is not indented by a space, so the above
solution is not applicable in this case. However, in the tag object
in question the pattern "seventh" occurs not only in the tag message
but in the 'tag' header as well. To create a forged tag object it's
sufficient to replace only one of the two occurences, so modify the
sed script to limit the pattern to the 'tag' header (i.e. a line
beginning with "tag ", which, because of the space character, can
never occur in the base64-encoded GPG signature).
Note that the forgery in 't7004-tag.sh' is not affected by this issue:
while 't7004' does create a forged signed tag kind of the same way,
it replaces "signed-tag" in the tag object, which, because of the '-'
character, can never occur in the base64-encoded GPG signarute.
Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-06-04 21:39:26 +08:00
|
|
|
sed -e "s/^seventh/7th forged/" raw >forged1 &&
|
2011-10-20 08:15:05 +08:00
|
|
|
git hash-object -w -t commit forged1 >forged1.commit &&
|
2018-06-04 21:39:25 +08:00
|
|
|
test_must_fail git verify-commit $(cat forged1.commit) &&
|
2011-10-20 08:15:05 +08:00
|
|
|
git show --pretty=short --show-signature $(cat forged1.commit) >actual1 &&
|
|
|
|
grep "BAD signature from" actual1 &&
|
|
|
|
! grep "Good signature from" actual1
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success GPG 'detect fudged signature with NUL' '
|
2014-06-17 07:59:59 +08:00
|
|
|
git cat-file commit seventh-signed >raw &&
|
2011-10-20 08:15:05 +08:00
|
|
|
cat raw >forged2 &&
|
|
|
|
echo Qwik | tr "Q" "\000" >>forged2 &&
|
|
|
|
git hash-object -w -t commit forged2 >forged2.commit &&
|
2018-06-04 21:39:25 +08:00
|
|
|
test_must_fail git verify-commit $(cat forged2.commit) &&
|
2011-10-20 08:15:05 +08:00
|
|
|
git show --pretty=short --show-signature $(cat forged2.commit) >actual2 &&
|
|
|
|
grep "BAD signature from" actual2 &&
|
|
|
|
! grep "Good signature from" actual2
|
|
|
|
'
|
|
|
|
|
2012-01-06 02:54:14 +08:00
|
|
|
test_expect_success GPG 'amending already signed commit' '
|
|
|
|
git checkout fourth-signed^0 &&
|
|
|
|
git commit --amend -S --no-edit &&
|
2014-06-23 15:05:51 +08:00
|
|
|
git verify-commit HEAD &&
|
2012-01-06 02:54:14 +08:00
|
|
|
git show -s --show-signature HEAD >actual &&
|
|
|
|
grep "Good signature from" actual &&
|
|
|
|
! grep "BAD signature from" actual
|
|
|
|
'
|
|
|
|
|
2014-06-17 08:06:24 +08:00
|
|
|
test_expect_success GPG 'show good signature with custom format' '
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
G
|
|
|
|
13B6F51ECDDE430D
|
|
|
|
C O Mitter <committer@example.com>
|
|
|
|
EOF
|
|
|
|
git log -1 --format="%G?%n%GK%n%GS" sixth-signed >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success GPG 'show bad signature with custom format' '
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
B
|
|
|
|
13B6F51ECDDE430D
|
|
|
|
C O Mitter <committer@example.com>
|
|
|
|
EOF
|
|
|
|
git log -1 --format="%G?%n%GK%n%GS" $(cat forged1.commit) >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
gpg-interface: use more status letters
According to gpg2's doc/DETAILS:
For each signature only one of the codes GOODSIG, BADSIG,
EXPSIG, EXPKEYSIG, REVKEYSIG or ERRSIG will be emitted.
gpg1 ("classic") behaves the same (although doc/DETAILS differs).
Currently, we parse gpg's status output for GOODSIG, BADSIG and
trust information and translate that into status codes G, B, U, N
for the %G? format specifier.
git-verify-* returns success in the GOODSIG case only. This is
somewhat in disagreement with gpg, which considers the first 5 of
the 6 above as VALIDSIG, but we err on the very safe side.
Introduce additional status codes E, X, Y, R for ERRSIG, EXPSIG,
EXPKEYSIG, and REVKEYSIG so that a user of %G? gets more information
about the absence of a 'G' on first glance.
Requested-by: Alex <agrambot@gmail.com>
Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-10-12 21:04:15 +08:00
|
|
|
test_expect_success GPG 'show untrusted signature with custom format' '
|
2014-06-17 08:06:24 +08:00
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
U
|
|
|
|
61092E85B7227189
|
|
|
|
Eris Discordia <discord@example.net>
|
|
|
|
EOF
|
|
|
|
git log -1 --format="%G?%n%GK%n%GS" eighth-signed-alt >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
gpg-interface: use more status letters
According to gpg2's doc/DETAILS:
For each signature only one of the codes GOODSIG, BADSIG,
EXPSIG, EXPKEYSIG, REVKEYSIG or ERRSIG will be emitted.
gpg1 ("classic") behaves the same (although doc/DETAILS differs).
Currently, we parse gpg's status output for GOODSIG, BADSIG and
trust information and translate that into status codes G, B, U, N
for the %G? format specifier.
git-verify-* returns success in the GOODSIG case only. This is
somewhat in disagreement with gpg, which considers the first 5 of
the 6 above as VALIDSIG, but we err on the very safe side.
Introduce additional status codes E, X, Y, R for ERRSIG, EXPSIG,
EXPKEYSIG, and REVKEYSIG so that a user of %G? gets more information
about the absence of a 'G' on first glance.
Requested-by: Alex <agrambot@gmail.com>
Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-10-12 21:04:15 +08:00
|
|
|
test_expect_success GPG 'show unknown signature with custom format' '
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
E
|
|
|
|
61092E85B7227189
|
|
|
|
|
|
|
|
EOF
|
|
|
|
GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GK%n%GS" eighth-signed-alt >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2014-06-17 08:06:24 +08:00
|
|
|
test_expect_success GPG 'show lack of signature with custom format' '
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
N
|
|
|
|
|
|
|
|
|
|
|
|
EOF
|
|
|
|
git log -1 --format="%G?%n%GK%n%GS" seventh-unsigned >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2016-06-23 00:51:26 +08:00
|
|
|
test_expect_success GPG 'log.showsignature behaves like --show-signature' '
|
|
|
|
test_config log.showsignature true &&
|
|
|
|
git show initial >actual &&
|
|
|
|
grep "gpg: Signature made" actual &&
|
|
|
|
grep "gpg: Good signature" actual
|
|
|
|
'
|
|
|
|
|
2011-10-20 08:15:05 +08:00
|
|
|
test_done
|