]>
Commit | Line | Data |
---|---|---|
a85b377d JH |
1 | #!/bin/sh |
2 | ||
3 | test_description='signed push' | |
4 | ||
3ac8f630 | 5 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main |
334afbc7 JS |
6 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
7 | ||
a85b377d JH |
8 | . ./test-lib.sh |
9 | . "$TEST_DIRECTORY"/lib-gpg.sh | |
10 | ||
11 | prepare_dst () { | |
12 | rm -fr dst && | |
13 | test_create_repo dst && | |
14 | ||
3ac8f630 | 15 | git push dst main:noop main:ff main:noff |
a85b377d JH |
16 | } |
17 | ||
18 | test_expect_success setup ' | |
3ac8f630 | 19 | # main, ff and noff branches pointing at the same commit |
a85b377d JH |
20 | test_tick && |
21 | git commit --allow-empty -m initial && | |
22 | ||
23 | git checkout -b noop && | |
24 | git checkout -b ff && | |
25 | git checkout -b noff && | |
26 | ||
27 | # noop stays the same, ff advances, noff rewrites | |
28 | test_tick && | |
29 | git commit --allow-empty --amend -m rewritten && | |
30 | git checkout ff && | |
31 | ||
32 | test_tick && | |
33 | git commit --allow-empty -m second | |
34 | ' | |
35 | ||
36 | test_expect_success 'unsigned push does not send push certificate' ' | |
37 | prepare_dst && | |
38 | mkdir -p dst/.git/hooks && | |
39 | write_script dst/.git/hooks/post-receive <<-\EOF && | |
40 | # discard the update list | |
41 | cat >/dev/null | |
42 | # record the push certificate | |
43 | if test -n "${GIT_PUSH_CERT-}" | |
44 | then | |
45 | git cat-file blob $GIT_PUSH_CERT >../push-cert | |
46 | fi | |
47 | EOF | |
48 | ||
49 | git push dst noop ff +noff && | |
50 | ! test -f dst/push-cert | |
51 | ' | |
52 | ||
53 | test_expect_success 'talking with a receiver without push certificate support' ' | |
54 | prepare_dst && | |
55 | mkdir -p dst/.git/hooks && | |
a85b377d JH |
56 | write_script dst/.git/hooks/post-receive <<-\EOF && |
57 | # discard the update list | |
58 | cat >/dev/null | |
59 | # record the push certificate | |
60 | if test -n "${GIT_PUSH_CERT-}" | |
61 | then | |
62 | git cat-file blob $GIT_PUSH_CERT >../push-cert | |
63 | fi | |
64 | EOF | |
65 | ||
66 | git push dst noop ff +noff && | |
67 | ! test -f dst/push-cert | |
68 | ' | |
69 | ||
70 | test_expect_success 'push --signed fails with a receiver without push certificate support' ' | |
71 | prepare_dst && | |
72 | mkdir -p dst/.git/hooks && | |
a85b377d JH |
73 | test_must_fail git push --signed dst noop ff +noff 2>err && |
74 | test_i18ngrep "the receiving end does not support" err | |
75 | ' | |
76 | ||
46667418 | 77 | test_expect_success 'push --signed=1 is accepted' ' |
c4b71a77 MÅ |
78 | prepare_dst && |
79 | mkdir -p dst/.git/hooks && | |
80 | test_must_fail git push --signed=1 dst noop ff +noff 2>err && | |
81 | test_i18ngrep "the receiving end does not support" err | |
82 | ' | |
83 | ||
20a7558f JH |
84 | test_expect_success GPG 'no certificate for a signed push with no update' ' |
85 | prepare_dst && | |
86 | mkdir -p dst/.git/hooks && | |
87 | write_script dst/.git/hooks/post-receive <<-\EOF && | |
88 | if test -n "${GIT_PUSH_CERT-}" | |
89 | then | |
90 | git cat-file blob $GIT_PUSH_CERT >../push-cert | |
91 | fi | |
92 | EOF | |
93 | git push dst noop && | |
94 | ! test -f dst/push-cert | |
95 | ' | |
96 | ||
a85b377d JH |
97 | test_expect_success GPG 'signed push sends push certificate' ' |
98 | prepare_dst && | |
99 | mkdir -p dst/.git/hooks && | |
b89363e4 | 100 | git -C dst config receive.certnonceseed sekrit && |
a85b377d JH |
101 | write_script dst/.git/hooks/post-receive <<-\EOF && |
102 | # discard the update list | |
103 | cat >/dev/null | |
104 | # record the push certificate | |
105 | if test -n "${GIT_PUSH_CERT-}" | |
106 | then | |
107 | git cat-file blob $GIT_PUSH_CERT >../push-cert | |
d05b9618 JH |
108 | fi && |
109 | ||
110 | cat >../push-cert-status <<E_O_F | |
111 | SIGNER=${GIT_PUSH_CERT_SIGNER-nobody} | |
112 | KEY=${GIT_PUSH_CERT_KEY-nokey} | |
113 | STATUS=${GIT_PUSH_CERT_STATUS-nostatus} | |
b89363e4 JH |
114 | NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus} |
115 | NONCE=${GIT_PUSH_CERT_NONCE-nononce} | |
d05b9618 JH |
116 | E_O_F |
117 | ||
118 | EOF | |
119 | ||
a85b377d | 120 | git push --signed dst noop ff +noff && |
b89363e4 JH |
121 | |
122 | ( | |
123 | cat <<-\EOF && | |
124 | SIGNER=C O Mitter <committer@example.com> | |
125 | KEY=13B6F51ECDDE430D | |
126 | STATUS=G | |
127 | NONCE_STATUS=OK | |
128 | EOF | |
129 | sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert | |
130 | ) >expect && | |
131 | ||
8722947e JS |
132 | noop=$(git rev-parse noop) && |
133 | ff=$(git rev-parse ff) && | |
134 | noff=$(git rev-parse noff) && | |
135 | grep "$noop $ff refs/heads/ff" dst/push-cert && | |
136 | grep "$noop $noff refs/heads/noff" dst/push-cert && | |
d05b9618 | 137 | test_cmp expect dst/push-cert-status |
a85b377d JH |
138 | ' |
139 | ||
cbaf82cc JT |
140 | test_expect_success GPG 'inconsistent push options in signed push not allowed' ' |
141 | # First, invoke receive-pack with dummy input to obtain its preamble. | |
142 | prepare_dst && | |
143 | git -C dst config receive.certnonceseed sekrit && | |
144 | git -C dst config receive.advertisepushoptions 1 && | |
145 | printf xxxx | test_might_fail git receive-pack dst >preamble && | |
146 | ||
147 | # Then, invoke push. Simulate a receive-pack that sends the preamble we | |
148 | # obtained, followed by a dummy packet. | |
149 | write_script myscript <<-\EOF && | |
150 | cat preamble && | |
151 | printf xxxx && | |
152 | cat >push | |
153 | EOF | |
154 | test_might_fail git push --push-option="foo" --push-option="bar" \ | |
155 | --receive-pack="\"$(pwd)/myscript\"" --signed dst --delete ff && | |
156 | ||
157 | # Replay the push output on a fresh dst, checking that ff is truly | |
158 | # deleted. | |
159 | prepare_dst && | |
160 | git -C dst config receive.certnonceseed sekrit && | |
161 | git -C dst config receive.advertisepushoptions 1 && | |
162 | git receive-pack dst <push && | |
163 | test_must_fail git -C dst rev-parse ff && | |
164 | ||
165 | # Tweak the push output to make the push option outside the cert | |
166 | # different, then replay it on a fresh dst, checking that ff is not | |
167 | # deleted. | |
168 | perl -pe "s/([^ ])bar/\$1baz/" push >push.tweak && | |
169 | prepare_dst && | |
170 | git -C dst config receive.certnonceseed sekrit && | |
171 | git -C dst config receive.advertisepushoptions 1 && | |
172 | git receive-pack dst <push.tweak >out && | |
173 | git -C dst rev-parse ff && | |
174 | grep "inconsistent push options" out | |
175 | ' | |
176 | ||
b9459019 MG |
177 | test_expect_success GPG 'fail without key and heed user.signingkey' ' |
178 | prepare_dst && | |
179 | mkdir -p dst/.git/hooks && | |
180 | git -C dst config receive.certnonceseed sekrit && | |
181 | write_script dst/.git/hooks/post-receive <<-\EOF && | |
182 | # discard the update list | |
183 | cat >/dev/null | |
184 | # record the push certificate | |
185 | if test -n "${GIT_PUSH_CERT-}" | |
186 | then | |
187 | git cat-file blob $GIT_PUSH_CERT >../push-cert | |
188 | fi && | |
189 | ||
190 | cat >../push-cert-status <<E_O_F | |
191 | SIGNER=${GIT_PUSH_CERT_SIGNER-nobody} | |
192 | KEY=${GIT_PUSH_CERT_KEY-nokey} | |
193 | STATUS=${GIT_PUSH_CERT_STATUS-nostatus} | |
194 | NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus} | |
195 | NONCE=${GIT_PUSH_CERT_NONCE-nononce} | |
196 | E_O_F | |
197 | ||
198 | EOF | |
199 | ||
53fc9993 HS |
200 | test_config user.email hasnokey@nowhere.com && |
201 | ( | |
202 | sane_unset GIT_COMMITTER_EMAIL && | |
203 | test_must_fail git push --signed dst noop ff +noff | |
204 | ) && | |
205 | test_config user.signingkey $GIT_COMMITTER_EMAIL && | |
b9459019 MG |
206 | git push --signed dst noop ff +noff && |
207 | ||
208 | ( | |
209 | cat <<-\EOF && | |
210 | SIGNER=C O Mitter <committer@example.com> | |
211 | KEY=13B6F51ECDDE430D | |
212 | STATUS=G | |
213 | NONCE_STATUS=OK | |
214 | EOF | |
215 | sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert | |
216 | ) >expect && | |
217 | ||
8722947e JS |
218 | noop=$(git rev-parse noop) && |
219 | ff=$(git rev-parse ff) && | |
220 | noff=$(git rev-parse noff) && | |
221 | grep "$noop $ff refs/heads/ff" dst/push-cert && | |
222 | grep "$noop $noff refs/heads/noff" dst/push-cert && | |
b9459019 MG |
223 | test_cmp expect dst/push-cert-status |
224 | ' | |
225 | ||
53fc9993 HS |
226 | test_expect_success GPGSM 'fail without key and heed user.signingkey x509' ' |
227 | test_config gpg.format x509 && | |
228 | prepare_dst && | |
229 | mkdir -p dst/.git/hooks && | |
230 | git -C dst config receive.certnonceseed sekrit && | |
231 | write_script dst/.git/hooks/post-receive <<-\EOF && | |
232 | # discard the update list | |
233 | cat >/dev/null | |
234 | # record the push certificate | |
235 | if test -n "${GIT_PUSH_CERT-}" | |
236 | then | |
237 | git cat-file blob $GIT_PUSH_CERT >../push-cert | |
238 | fi && | |
239 | ||
240 | cat >../push-cert-status <<E_O_F | |
241 | SIGNER=${GIT_PUSH_CERT_SIGNER-nobody} | |
242 | KEY=${GIT_PUSH_CERT_KEY-nokey} | |
243 | STATUS=${GIT_PUSH_CERT_STATUS-nostatus} | |
244 | NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus} | |
245 | NONCE=${GIT_PUSH_CERT_NONCE-nononce} | |
246 | E_O_F | |
247 | ||
248 | EOF | |
249 | ||
250 | test_config user.email hasnokey@nowhere.com && | |
251 | test_config user.signingkey "" && | |
252 | ( | |
253 | sane_unset GIT_COMMITTER_EMAIL && | |
254 | test_must_fail git push --signed dst noop ff +noff | |
255 | ) && | |
256 | test_config user.signingkey $GIT_COMMITTER_EMAIL && | |
257 | git push --signed dst noop ff +noff && | |
258 | ||
259 | ( | |
260 | cat <<-\EOF && | |
261 | SIGNER=/CN=C O Mitter/O=Example/SN=C O/GN=Mitter | |
262 | KEY= | |
263 | STATUS=G | |
264 | NONCE_STATUS=OK | |
265 | EOF | |
266 | sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert | |
267 | ) >expect.in && | |
268 | key=$(cat "${GNUPGHOME}/trustlist.txt" | cut -d" " -f1 | tr -d ":") && | |
269 | sed -e "s/^KEY=/KEY=${key}/" expect.in >expect && | |
270 | ||
271 | noop=$(git rev-parse noop) && | |
272 | ff=$(git rev-parse ff) && | |
273 | noff=$(git rev-parse noff) && | |
274 | grep "$noop $ff refs/heads/ff" dst/push-cert && | |
275 | grep "$noop $noff refs/heads/noff" dst/push-cert && | |
276 | test_cmp expect dst/push-cert-status | |
277 | ' | |
278 | ||
a4f324a4 HX |
279 | test_expect_success GPG 'failed atomic push does not execute GPG' ' |
280 | prepare_dst && | |
281 | git -C dst config receive.certnonceseed sekrit && | |
282 | write_script gpg <<-EOF && | |
283 | # should check atomic push locally before running GPG. | |
284 | exit 1 | |
285 | EOF | |
286 | test_must_fail env PATH="$TRASH_DIRECTORY:$PATH" git push \ | |
287 | --signed --atomic --porcelain \ | |
2cd6e1d5 | 288 | dst noop ff noff >out 2>err && |
a4f324a4 | 289 | |
2cd6e1d5 | 290 | test_i18ngrep ! "gpg failed to sign" err && |
a4f324a4 HX |
291 | cat >expect <<-EOF && |
292 | To dst | |
293 | = refs/heads/noop:refs/heads/noop [up to date] | |
294 | ! refs/heads/ff:refs/heads/ff [rejected] (atomic push failed) | |
295 | ! refs/heads/noff:refs/heads/noff [rejected] (non-fast-forward) | |
296 | Done | |
297 | EOF | |
2cd6e1d5 | 298 | test_cmp expect out |
a4f324a4 HX |
299 | ' |
300 | ||
a85b377d | 301 | test_done |