Raw
1 #!/bin/sh
2
3 test_description='git fast-import --signed-commits=<mode>'
4
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6
7 . ./test-lib.sh
8 . "$TEST_DIRECTORY/lib-gpg.sh"
9
10 test_expect_success 'set up unsigned initial commit and import repo' '
11 test_commit first &&
12 git init new
13 '
14
15 test_expect_success GPG 'set up OpenPGP signed commit' '
16 git checkout -b openpgp-signing main &&
17 echo "Content for OpenPGP signing." >file-sign &&
18 git add file-sign &&
19 git commit -S -m "OpenPGP signed commit" &&
20 OPENPGP_SIGNING=$(git rev-parse --verify openpgp-signing)
21 '
22
23 test_expect_success GPG 'import OpenPGP signature with --signed-commits=verbatim' '
24 git fast-export --signed-commits=verbatim openpgp-signing >output &&
25 git -C new fast-import --quiet --signed-commits=verbatim <output >log 2>&1 &&
26 IMPORTED=$(git -C new rev-parse --verify refs/heads/openpgp-signing) &&
27 test $OPENPGP_SIGNING = $IMPORTED &&
28 test_must_be_empty log
29 '
30
31 test_expect_success GPGSM 'set up X.509 signed commit' '
32 git checkout -b x509-signing main &&
33 test_config gpg.format x509 &&
34 test_config user.signingkey $GIT_COMMITTER_EMAIL &&
35 echo "Content for X.509 signing." >file-sign &&
36 git add file-sign &&
37 git commit -S -m "X.509 signed commit" &&
38 X509_SIGNING=$(git rev-parse HEAD)
39 '
40
41 test_expect_success GPGSM 'import X.509 signature fails with --signed-commits=abort' '
42 git fast-export --signed-commits=verbatim x509-signing >output &&
43 test_must_fail git -C new fast-import --quiet --signed-commits=abort <output
44 '
45
46 test_expect_success GPGSM 'import X.509 signature with --signed-commits=warn-verbatim' '
47 git -C new fast-import --quiet --signed-commits=warn-verbatim <output >log 2>&1 &&
48 IMPORTED=$(git -C new rev-parse --verify refs/heads/x509-signing) &&
49 test $X509_SIGNING = $IMPORTED &&
50 test_grep "importing a commit signature" log
51 '
52
53 test_expect_success GPGSSH 'set up SSH signed commit' '
54 git checkout -b ssh-signing main &&
55 test_config gpg.format ssh &&
56 test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
57 echo "Content for SSH signing." >file-sign &&
58 git add file-sign &&
59 git commit -S -m "SSH signed commit" &&
60 SSH_SIGNING=$(git rev-parse HEAD)
61 '
62
63 test_expect_success GPGSSH 'strip SSH signature with --signed-commits=strip' '
64 git fast-export --signed-commits=verbatim ssh-signing >output &&
65 git -C new fast-import --quiet --signed-commits=strip <output >log 2>&1 &&
66 IMPORTED=$(git -C new rev-parse --verify refs/heads/ssh-signing) &&
67 test $SSH_SIGNING != $IMPORTED &&
68 git -C new cat-file commit "$IMPORTED" >actual &&
69 test_grep ! -E "^gpgsig" actual &&
70 test_must_be_empty log
71 '
72
73 test_expect_success RUST,GPG 'setup a commit with dual OpenPGP signatures on its SHA-1 and SHA-256 formats' '
74 # Create a signed SHA-256 commit
75 git init --object-format=sha256 explicit-sha256 &&
76 git -C explicit-sha256 config extensions.compatObjectFormat sha1 &&
77 git -C explicit-sha256 checkout -b dual-signed &&
78 test_commit -C explicit-sha256 A &&
79 echo B >explicit-sha256/B &&
80 git -C explicit-sha256 add B &&
81 test_tick &&
82 git -C explicit-sha256 commit -S -m "signed commit" B &&
83 SHA256_B=$(git -C explicit-sha256 rev-parse dual-signed) &&
84
85 # Create the corresponding SHA-1 commit
86 SHA1_B=$(git -C explicit-sha256 rev-parse --output-object-format=sha1 dual-signed) &&
87
88 # Check that the resulting SHA-1 commit has both signatures
89 git -C explicit-sha256 cat-file -p $SHA1_B >out &&
90 test_grep -E "^gpgsig " out &&
91 test_grep -E "^gpgsig-sha256 " out
92 '
93
94 test_expect_success RUST,GPG 'strip both OpenPGP signatures with --signed-commits=warn-strip' '
95 git -C explicit-sha256 fast-export --signed-commits=verbatim dual-signed >output &&
96 test_grep -E "^gpgsig sha1 openpgp" output &&
97 test_grep -E "^gpgsig sha256 openpgp" output &&
98 git -C new fast-import --quiet --signed-commits=warn-strip <output >log 2>&1 &&
99 git -C new cat-file commit refs/heads/dual-signed >actual &&
100 test_grep ! -E "^gpgsig " actual &&
101 test_grep ! -E "^gpgsig-sha256 " actual &&
102 test_grep "stripping a commit signature" log >out &&
103 test_line_count = 2 out
104 '
105
106 for mode in strip-if-invalid sign-if-invalid abort-if-invalid
107 do
108 test_expect_success GPG "import commit with no signature with --signed-commits=$mode" '
109 git fast-export main >output &&
110 git -C new fast-import --quiet --signed-commits=$mode <output >log 2>&1 &&
111 test_must_be_empty log
112 '
113
114 test_expect_success GPG "keep valid OpenPGP signature with --signed-commits=$mode" '
115 rm -rf new &&
116 git init new &&
117
118 git fast-export --signed-commits=verbatim openpgp-signing >output &&
119 git -C new fast-import --quiet --signed-commits=$mode <output >log 2>&1 &&
120 IMPORTED=$(git -C new rev-parse --verify refs/heads/openpgp-signing) &&
121 test $OPENPGP_SIGNING = $IMPORTED &&
122 git -C new cat-file commit "$IMPORTED" >actual &&
123 test_grep -E "^gpgsig(-sha256)? " actual &&
124 test_must_be_empty log
125 '
126
127 test_expect_success GPG "handle signature invalidated by message change with --signed-commits=$mode" '
128 rm -rf new &&
129 git init new &&
130
131 git fast-export --signed-commits=verbatim openpgp-signing >output &&
132
133 # Change the commit message, which invalidates the signature.
134 # The commit message length should not change though, otherwise the
135 # corresponding `data <length>` command would have to be changed too.
136 sed "s/OpenPGP signed commit/OpenPGP forged commit/" output >modified &&
137
138 if test "$mode" = abort-if-invalid
139 then
140 test_must_fail git -C new fast-import --quiet \
141 --signed-commits=$mode <modified >log 2>&1 &&
142 test_grep "aborting due to invalid signature" log &&
143 return 0
144 fi &&
145
146 git -C new fast-import --quiet --signed-commits=$mode <modified >log 2>&1 &&
147
148 IMPORTED=$(git -C new rev-parse --verify refs/heads/openpgp-signing) &&
149 test $OPENPGP_SIGNING != $IMPORTED &&
150 git -C new cat-file commit "$IMPORTED" >actual &&
151
152 if test "$mode" = strip-if-invalid
153 then
154 test_grep "stripping invalid signature" log &&
155 test_grep ! -E "^gpgsig" actual
156 else
157 test_grep "replacing invalid signature" log &&
158 test_grep -E "^gpgsig(-sha256)? " actual &&
159 git -C new verify-commit "$IMPORTED"
160 fi
161 '
162
163 test_expect_success GPGSM "keep valid X.509 signature with --signed-commits=$mode" '
164 rm -rf new &&
165 git init new &&
166
167 git fast-export --signed-commits=verbatim x509-signing >output &&
168 git -C new fast-import --quiet --signed-commits=$mode <output >log 2>&1 &&
169 IMPORTED=$(git -C new rev-parse --verify refs/heads/x509-signing) &&
170 test $X509_SIGNING = $IMPORTED &&
171 git -C new cat-file commit "$IMPORTED" >actual &&
172 test_grep -E "^gpgsig(-sha256)? " actual &&
173 test_must_be_empty log
174 '
175
176 test_expect_success GPGSSH "keep valid SSH signature with --signed-commits=$mode" '
177 rm -rf new &&
178 git init new &&
179
180 test_config -C new gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
181
182 git fast-export --signed-commits=verbatim ssh-signing >output &&
183 git -C new fast-import --quiet --signed-commits=$mode <output >log 2>&1 &&
184 IMPORTED=$(git -C new rev-parse --verify refs/heads/ssh-signing) &&
185 test $SSH_SIGNING = $IMPORTED &&
186 git -C new cat-file commit "$IMPORTED" >actual &&
187 test_grep -E "^gpgsig(-sha256)? " actual &&
188 test_must_be_empty log
189 '
190 done
191
192 test_expect_success GPGSSH "sign invalid commit with explicit keyid" '
193 rm -rf new &&
194 git init new &&
195
196 git fast-export --signed-commits=verbatim ssh-signing >output &&
197
198 # Change the commit message, which invalidates the signature.
199 # The commit message length should not change though, otherwise the
200 # corresponding `data <length>` command would have to be changed too.
201 sed "s/SSH signed commit/SSH forged commit/" output >modified &&
202
203 # Configure the target repository with an invalid default signing key.
204 test_config -C new user.signingkey "not-a-real-key-id" &&
205 test_config -C new gpg.format ssh &&
206 test_config -C new gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
207 test_must_fail git -C new fast-import --quiet \
208 --signed-commits=sign-if-invalid <modified >/dev/null 2>&1 &&
209
210 # Import using explicitly provided signing key.
211 git -C new fast-import --quiet \
212 --signed-commits=sign-if-invalid="${GPGSSH_KEY_PRIMARY}" <modified &&
213
214 IMPORTED=$(git -C new rev-parse --verify refs/heads/ssh-signing) &&
215 test $SSH_SIGNING != $IMPORTED &&
216 git -C new cat-file commit "$IMPORTED" >actual &&
217 test_grep -E "^gpgsig(-sha256)? " actual &&
218 git -C new verify-commit "$IMPORTED"
219 '
220
221 test_done