]>
Commit | Line | Data |
---|---|---|
abca927d JK |
1 | #!/bin/sh |
2 | ||
3 | test_description='basic credential helper tests' | |
4 | . ./test-lib.sh | |
5 | . "$TEST_DIRECTORY"/lib-credential.sh | |
6 | ||
7 | test_expect_success 'setup helper scripts' ' | |
8 | cat >dump <<-\EOF && | |
dd64267f | 9 | whoami=$(echo $0 | sed s/.*git-credential-//) |
abca927d | 10 | echo >&2 "$whoami: $*" |
78ed1d2d MG |
11 | OIFS=$IFS |
12 | IFS== | |
13 | while read key value; do | |
abca927d JK |
14 | echo >&2 "$whoami: $key=$value" |
15 | eval "$key=$value" | |
16 | done | |
78ed1d2d | 17 | IFS=$OIFS |
abca927d JK |
18 | EOF |
19 | ||
3d9f5b67 | 20 | write_script git-credential-useless <<-\EOF && |
abca927d JK |
21 | . ./dump |
22 | exit 0 | |
23 | EOF | |
abca927d | 24 | |
a88dbd2f JK |
25 | write_script git-credential-quit <<-\EOF && |
26 | . ./dump | |
27 | echo quit=1 | |
28 | EOF | |
29 | ||
3d9f5b67 | 30 | write_script git-credential-verbatim <<-\EOF && |
abca927d JK |
31 | user=$1; shift |
32 | pass=$1; shift | |
33 | . ./dump | |
34 | test -z "$user" || echo username=$user | |
35 | test -z "$pass" || echo password=$pass | |
36 | EOF | |
abca927d JK |
37 | |
38 | PATH="$PWD:$PATH" | |
39 | ' | |
40 | ||
41 | test_expect_success 'credential_fill invokes helper' ' | |
42 | check fill "verbatim foo bar" <<-\EOF | |
73aafe9b JK |
43 | protocol=http |
44 | host=example.com | |
abca927d | 45 | -- |
73aafe9b JK |
46 | protocol=http |
47 | host=example.com | |
abca927d JK |
48 | username=foo |
49 | password=bar | |
50 | -- | |
51 | verbatim: get | |
73aafe9b JK |
52 | verbatim: protocol=http |
53 | verbatim: host=example.com | |
abca927d JK |
54 | EOF |
55 | ' | |
56 | ||
57 | test_expect_success 'credential_fill invokes multiple helpers' ' | |
58 | check fill useless "verbatim foo bar" <<-\EOF | |
73aafe9b JK |
59 | protocol=http |
60 | host=example.com | |
abca927d | 61 | -- |
73aafe9b JK |
62 | protocol=http |
63 | host=example.com | |
abca927d JK |
64 | username=foo |
65 | password=bar | |
66 | -- | |
67 | useless: get | |
73aafe9b JK |
68 | useless: protocol=http |
69 | useless: host=example.com | |
abca927d | 70 | verbatim: get |
73aafe9b JK |
71 | verbatim: protocol=http |
72 | verbatim: host=example.com | |
abca927d JK |
73 | EOF |
74 | ' | |
75 | ||
76 | test_expect_success 'credential_fill stops when we get a full response' ' | |
77 | check fill "verbatim one two" "verbatim three four" <<-\EOF | |
73aafe9b JK |
78 | protocol=http |
79 | host=example.com | |
abca927d | 80 | -- |
73aafe9b JK |
81 | protocol=http |
82 | host=example.com | |
abca927d JK |
83 | username=one |
84 | password=two | |
85 | -- | |
86 | verbatim: get | |
73aafe9b JK |
87 | verbatim: protocol=http |
88 | verbatim: host=example.com | |
abca927d JK |
89 | EOF |
90 | ' | |
91 | ||
92 | test_expect_success 'credential_fill continues through partial response' ' | |
93 | check fill "verbatim one \"\"" "verbatim two three" <<-\EOF | |
73aafe9b JK |
94 | protocol=http |
95 | host=example.com | |
abca927d | 96 | -- |
73aafe9b JK |
97 | protocol=http |
98 | host=example.com | |
abca927d JK |
99 | username=two |
100 | password=three | |
101 | -- | |
102 | verbatim: get | |
73aafe9b JK |
103 | verbatim: protocol=http |
104 | verbatim: host=example.com | |
abca927d | 105 | verbatim: get |
73aafe9b JK |
106 | verbatim: protocol=http |
107 | verbatim: host=example.com | |
abca927d JK |
108 | verbatim: username=one |
109 | EOF | |
110 | ' | |
111 | ||
112 | test_expect_success 'credential_fill passes along metadata' ' | |
113 | check fill "verbatim one two" <<-\EOF | |
114 | protocol=ftp | |
115 | host=example.com | |
116 | path=foo.git | |
117 | -- | |
2d6dc182 MM |
118 | protocol=ftp |
119 | host=example.com | |
120 | path=foo.git | |
abca927d JK |
121 | username=one |
122 | password=two | |
123 | -- | |
124 | verbatim: get | |
125 | verbatim: protocol=ftp | |
126 | verbatim: host=example.com | |
127 | verbatim: path=foo.git | |
128 | EOF | |
129 | ' | |
130 | ||
131 | test_expect_success 'credential_approve calls all helpers' ' | |
132 | check approve useless "verbatim one two" <<-\EOF | |
73aafe9b JK |
133 | protocol=http |
134 | host=example.com | |
abca927d JK |
135 | username=foo |
136 | password=bar | |
137 | -- | |
138 | -- | |
139 | useless: store | |
73aafe9b JK |
140 | useless: protocol=http |
141 | useless: host=example.com | |
abca927d JK |
142 | useless: username=foo |
143 | useless: password=bar | |
144 | verbatim: store | |
73aafe9b JK |
145 | verbatim: protocol=http |
146 | verbatim: host=example.com | |
abca927d JK |
147 | verbatim: username=foo |
148 | verbatim: password=bar | |
149 | EOF | |
150 | ' | |
151 | ||
152 | test_expect_success 'do not bother storing password-less credential' ' | |
153 | check approve useless <<-\EOF | |
73aafe9b JK |
154 | protocol=http |
155 | host=example.com | |
abca927d JK |
156 | username=foo |
157 | -- | |
158 | -- | |
159 | EOF | |
160 | ' | |
161 | ||
162 | ||
163 | test_expect_success 'credential_reject calls all helpers' ' | |
164 | check reject useless "verbatim one two" <<-\EOF | |
73aafe9b JK |
165 | protocol=http |
166 | host=example.com | |
abca927d JK |
167 | username=foo |
168 | password=bar | |
169 | -- | |
170 | -- | |
171 | useless: erase | |
73aafe9b JK |
172 | useless: protocol=http |
173 | useless: host=example.com | |
abca927d JK |
174 | useless: username=foo |
175 | useless: password=bar | |
176 | verbatim: erase | |
73aafe9b JK |
177 | verbatim: protocol=http |
178 | verbatim: host=example.com | |
abca927d JK |
179 | verbatim: username=foo |
180 | verbatim: password=bar | |
181 | EOF | |
182 | ' | |
183 | ||
184 | test_expect_success 'usernames can be preserved' ' | |
185 | check fill "verbatim \"\" three" <<-\EOF | |
73aafe9b JK |
186 | protocol=http |
187 | host=example.com | |
abca927d JK |
188 | username=one |
189 | -- | |
73aafe9b JK |
190 | protocol=http |
191 | host=example.com | |
abca927d JK |
192 | username=one |
193 | password=three | |
194 | -- | |
195 | verbatim: get | |
73aafe9b JK |
196 | verbatim: protocol=http |
197 | verbatim: host=example.com | |
abca927d JK |
198 | verbatim: username=one |
199 | EOF | |
200 | ' | |
201 | ||
202 | test_expect_success 'usernames can be overridden' ' | |
203 | check fill "verbatim two three" <<-\EOF | |
73aafe9b JK |
204 | protocol=http |
205 | host=example.com | |
abca927d JK |
206 | username=one |
207 | -- | |
73aafe9b JK |
208 | protocol=http |
209 | host=example.com | |
abca927d JK |
210 | username=two |
211 | password=three | |
212 | -- | |
213 | verbatim: get | |
73aafe9b JK |
214 | verbatim: protocol=http |
215 | verbatim: host=example.com | |
abca927d JK |
216 | verbatim: username=one |
217 | EOF | |
218 | ' | |
219 | ||
220 | test_expect_success 'do not bother completing already-full credential' ' | |
221 | check fill "verbatim three four" <<-\EOF | |
73aafe9b JK |
222 | protocol=http |
223 | host=example.com | |
abca927d JK |
224 | username=one |
225 | password=two | |
226 | -- | |
73aafe9b JK |
227 | protocol=http |
228 | host=example.com | |
abca927d JK |
229 | username=one |
230 | password=two | |
231 | -- | |
232 | EOF | |
233 | ' | |
234 | ||
235 | # We can't test the basic terminal password prompt here because | |
236 | # getpass() tries too hard to find the real terminal. But if our | |
237 | # askpass helper is run, we know the internal getpass is working. | |
238 | test_expect_success 'empty helper list falls back to internal getpass' ' | |
239 | check fill <<-\EOF | |
73aafe9b JK |
240 | protocol=http |
241 | host=example.com | |
abca927d | 242 | -- |
73aafe9b JK |
243 | protocol=http |
244 | host=example.com | |
abca927d JK |
245 | username=askpass-username |
246 | password=askpass-password | |
247 | -- | |
73aafe9b JK |
248 | askpass: Username for '\''http://example.com'\'': |
249 | askpass: Password for '\''http://askpass-username@example.com'\'': | |
abca927d JK |
250 | EOF |
251 | ' | |
252 | ||
253 | test_expect_success 'internal getpass does not ask for known username' ' | |
254 | check fill <<-\EOF | |
73aafe9b JK |
255 | protocol=http |
256 | host=example.com | |
abca927d JK |
257 | username=foo |
258 | -- | |
73aafe9b JK |
259 | protocol=http |
260 | host=example.com | |
abca927d JK |
261 | username=foo |
262 | password=askpass-password | |
263 | -- | |
73aafe9b | 264 | askpass: Password for '\''http://foo@example.com'\'': |
abca927d JK |
265 | EOF |
266 | ' | |
267 | ||
11825072 JK |
268 | HELPER="!f() { |
269 | cat >/dev/null | |
270 | echo username=foo | |
271 | echo password=bar | |
272 | }; f" | |
273 | test_expect_success 'respect configured credentials' ' | |
274 | test_config credential.helper "$HELPER" && | |
275 | check fill <<-\EOF | |
73aafe9b JK |
276 | protocol=http |
277 | host=example.com | |
11825072 | 278 | -- |
73aafe9b JK |
279 | protocol=http |
280 | host=example.com | |
11825072 JK |
281 | username=foo |
282 | password=bar | |
283 | -- | |
284 | EOF | |
285 | ' | |
286 | ||
287 | test_expect_success 'match configured credential' ' | |
288 | test_config credential.https://example.com.helper "$HELPER" && | |
289 | check fill <<-\EOF | |
290 | protocol=https | |
291 | host=example.com | |
292 | path=repo.git | |
293 | -- | |
2d6dc182 MM |
294 | protocol=https |
295 | host=example.com | |
11825072 JK |
296 | username=foo |
297 | password=bar | |
298 | -- | |
299 | EOF | |
300 | ' | |
301 | ||
302 | test_expect_success 'do not match configured credential' ' | |
303 | test_config credential.https://foo.helper "$HELPER" && | |
304 | check fill <<-\EOF | |
305 | protocol=https | |
306 | host=bar | |
307 | -- | |
2d6dc182 MM |
308 | protocol=https |
309 | host=bar | |
11825072 JK |
310 | username=askpass-username |
311 | password=askpass-password | |
312 | -- | |
313 | askpass: Username for '\''https://bar'\'': | |
314 | askpass: Password for '\''https://askpass-username@bar'\'': | |
315 | EOF | |
316 | ' | |
317 | ||
588c70e1 | 318 | test_expect_success 'match multiple configured helpers' ' |
319 | test_config credential.helper "verbatim \"\" \"\"" && | |
320 | test_config credential.https://example.com.helper "$HELPER" && | |
321 | check fill <<-\EOF | |
322 | protocol=https | |
323 | host=example.com | |
324 | path=repo.git | |
325 | -- | |
326 | protocol=https | |
327 | host=example.com | |
328 | username=foo | |
329 | password=bar | |
330 | -- | |
331 | verbatim: get | |
332 | verbatim: protocol=https | |
333 | verbatim: host=example.com | |
334 | EOF | |
335 | ' | |
336 | ||
337 | test_expect_success 'match multiple configured helpers with URLs' ' | |
338 | test_config credential.https://example.com/repo.git.helper "verbatim \"\" \"\"" && | |
339 | test_config credential.https://example.com.helper "$HELPER" && | |
340 | check fill <<-\EOF | |
341 | protocol=https | |
342 | host=example.com | |
343 | path=repo.git | |
344 | -- | |
345 | protocol=https | |
346 | host=example.com | |
347 | username=foo | |
348 | password=bar | |
349 | -- | |
350 | verbatim: get | |
351 | verbatim: protocol=https | |
352 | verbatim: host=example.com | |
353 | EOF | |
354 | ' | |
355 | ||
356 | test_expect_success 'match percent-encoded values' ' | |
357 | test_config credential.https://example.com/%2566.git.helper "$HELPER" && | |
358 | check fill <<-\EOF | |
359 | url=https://example.com/%2566.git | |
360 | -- | |
361 | protocol=https | |
362 | host=example.com | |
363 | username=foo | |
364 | password=bar | |
365 | -- | |
366 | EOF | |
367 | ' | |
368 | ||
d5742425 JK |
369 | test_expect_success 'pull username from config' ' |
370 | test_config credential.https://example.com.username foo && | |
371 | check fill <<-\EOF | |
372 | protocol=https | |
373 | host=example.com | |
374 | -- | |
2d6dc182 MM |
375 | protocol=https |
376 | host=example.com | |
d5742425 JK |
377 | username=foo |
378 | password=askpass-password | |
379 | -- | |
380 | askpass: Password for '\''https://foo@example.com'\'': | |
381 | EOF | |
382 | ' | |
383 | ||
588c70e1 | 384 | test_expect_success 'honors username from URL over helper (URL)' ' |
385 | test_config credential.https://example.com.username bob && | |
386 | test_config credential.https://example.com.helper "verbatim \"\" bar" && | |
387 | check fill <<-\EOF | |
388 | url=https://alice@example.com | |
389 | -- | |
390 | protocol=https | |
391 | host=example.com | |
392 | username=alice | |
393 | password=bar | |
394 | -- | |
395 | verbatim: get | |
396 | verbatim: protocol=https | |
397 | verbatim: host=example.com | |
398 | verbatim: username=alice | |
399 | EOF | |
400 | ' | |
401 | ||
402 | test_expect_success 'honors username from URL over helper (components)' ' | |
403 | test_config credential.https://example.com.username bob && | |
404 | test_config credential.https://example.com.helper "verbatim \"\" bar" && | |
405 | check fill <<-\EOF | |
406 | protocol=https | |
407 | host=example.com | |
408 | username=alice | |
409 | -- | |
410 | protocol=https | |
411 | host=example.com | |
412 | username=alice | |
413 | password=bar | |
414 | -- | |
415 | verbatim: get | |
416 | verbatim: protocol=https | |
417 | verbatim: host=example.com | |
418 | verbatim: username=alice | |
419 | EOF | |
420 | ' | |
421 | ||
82eb2498 | 422 | test_expect_success 'last matching username wins' ' |
588c70e1 | 423 | test_config credential.https://example.com/path.git.username bob && |
424 | test_config credential.https://example.com.username alice && | |
425 | test_config credential.https://example.com.helper "verbatim \"\" bar" && | |
426 | check fill <<-\EOF | |
427 | url=https://example.com/path.git | |
428 | -- | |
429 | protocol=https | |
430 | host=example.com | |
431 | username=alice | |
432 | password=bar | |
433 | -- | |
434 | verbatim: get | |
435 | verbatim: protocol=https | |
436 | verbatim: host=example.com | |
437 | verbatim: username=alice | |
438 | EOF | |
439 | ' | |
440 | ||
a78fbb4f JK |
441 | test_expect_success 'http paths can be part of context' ' |
442 | check fill "verbatim foo bar" <<-\EOF && | |
443 | protocol=https | |
444 | host=example.com | |
445 | path=foo.git | |
446 | -- | |
2d6dc182 MM |
447 | protocol=https |
448 | host=example.com | |
a78fbb4f JK |
449 | username=foo |
450 | password=bar | |
451 | -- | |
452 | verbatim: get | |
453 | verbatim: protocol=https | |
454 | verbatim: host=example.com | |
455 | EOF | |
456 | test_config credential.https://example.com.useHttpPath true && | |
457 | check fill "verbatim foo bar" <<-\EOF | |
458 | protocol=https | |
459 | host=example.com | |
460 | path=foo.git | |
461 | -- | |
2d6dc182 MM |
462 | protocol=https |
463 | host=example.com | |
464 | path=foo.git | |
a78fbb4f JK |
465 | username=foo |
466 | password=bar | |
467 | -- | |
468 | verbatim: get | |
469 | verbatim: protocol=https | |
470 | verbatim: host=example.com | |
471 | verbatim: path=foo.git | |
472 | EOF | |
473 | ' | |
474 | ||
46fd7b39 | 475 | test_expect_success 'context uses urlmatch' ' |
476 | test_config "credential.https://*.org.useHttpPath" true && | |
477 | check fill "verbatim foo bar" <<-\EOF | |
478 | protocol=https | |
479 | host=example.org | |
480 | path=foo.git | |
481 | -- | |
482 | protocol=https | |
483 | host=example.org | |
484 | path=foo.git | |
485 | username=foo | |
486 | password=bar | |
487 | -- | |
488 | verbatim: get | |
489 | verbatim: protocol=https | |
490 | verbatim: host=example.org | |
491 | verbatim: path=foo.git | |
492 | EOF | |
493 | ' | |
494 | ||
59b38652 JK |
495 | test_expect_success 'helpers can abort the process' ' |
496 | test_must_fail git \ | |
a88dbd2f | 497 | -c credential.helper=quit \ |
59b38652 | 498 | -c credential.helper="verbatim foo bar" \ |
73aafe9b JK |
499 | credential fill >stdout 2>stderr <<-\EOF && |
500 | protocol=http | |
501 | host=example.com | |
502 | EOF | |
76b54ee9 | 503 | test_must_be_empty stdout && |
a88dbd2f JK |
504 | cat >expect <<-\EOF && |
505 | quit: get | |
73aafe9b JK |
506 | quit: protocol=http |
507 | quit: host=example.com | |
a88dbd2f JK |
508 | fatal: credential helper '\''quit'\'' told us to quit |
509 | EOF | |
510 | test_i18ncmp expect stderr | |
59b38652 JK |
511 | ' |
512 | ||
24321375 JK |
513 | test_expect_success 'empty helper spec resets helper list' ' |
514 | test_config credential.helper "verbatim file file" && | |
515 | check fill "" "verbatim cmdline cmdline" <<-\EOF | |
73aafe9b JK |
516 | protocol=http |
517 | host=example.com | |
24321375 | 518 | -- |
73aafe9b JK |
519 | protocol=http |
520 | host=example.com | |
24321375 JK |
521 | username=cmdline |
522 | password=cmdline | |
523 | -- | |
524 | verbatim: get | |
73aafe9b JK |
525 | verbatim: protocol=http |
526 | verbatim: host=example.com | |
24321375 JK |
527 | EOF |
528 | ' | |
529 | ||
8ba8ed56 JK |
530 | test_expect_success 'url parser rejects embedded newlines' ' |
531 | test_must_fail git credential fill 2>stderr <<-\EOF && | |
9a6bbee8 | 532 | url=https://one.example.com?%0ahost=two.example.com/ |
8ba8ed56 JK |
533 | EOF |
534 | cat >expect <<-\EOF && | |
c716fe4b | 535 | warning: url contains a newline in its host component: https://one.example.com?%0ahost=two.example.com/ |
fe29a9b7 | 536 | fatal: credential url cannot be parsed: https://one.example.com?%0ahost=two.example.com/ |
9a6bbee8 | 537 | EOF |
8ba8ed56 | 538 | test_i18ncmp expect stderr |
9a6bbee8 JK |
539 | ' |
540 | ||
24036686 JK |
541 | test_expect_success 'host-less URLs are parsed as empty host' ' |
542 | check fill "verbatim foo bar" <<-\EOF | |
543 | url=cert:///path/to/cert.pem | |
c716fe4b | 544 | -- |
24036686 JK |
545 | protocol=cert |
546 | host= | |
547 | path=path/to/cert.pem | |
548 | username=foo | |
549 | password=bar | |
c716fe4b | 550 | -- |
24036686 JK |
551 | verbatim: get |
552 | verbatim: protocol=cert | |
553 | verbatim: host= | |
554 | verbatim: path=path/to/cert.pem | |
555 | EOF | |
556 | ' | |
557 | ||
8ba8ed56 JK |
558 | test_expect_success 'credential system refuses to work with missing host' ' |
559 | test_must_fail git credential fill 2>stderr <<-\EOF && | |
560 | protocol=http | |
561 | EOF | |
562 | cat >expect <<-\EOF && | |
563 | fatal: refusing to work with credential missing host field | |
564 | EOF | |
565 | test_i18ncmp expect stderr | |
566 | ' | |
567 | ||
568 | test_expect_success 'credential system refuses to work with missing protocol' ' | |
569 | test_must_fail git credential fill 2>stderr <<-\EOF && | |
570 | host=example.com | |
571 | EOF | |
572 | cat >expect <<-\EOF && | |
573 | fatal: refusing to work with credential missing protocol field | |
9a6bbee8 | 574 | EOF |
8ba8ed56 | 575 | test_i18ncmp expect stderr |
9a6bbee8 JK |
576 | ' |
577 | ||
abca927d | 578 | test_done |