]>
Commit | Line | Data |
---|---|---|
f27491d5 JK |
1 | # Shell library for testing credential handling including helpers. See t0302 |
2 | # for an example of testing a specific helper. | |
abca927d JK |
3 | |
4 | # Try a set of credential helpers; the expected stdin, | |
5 | # stdout and stderr should be provided on stdin, | |
6 | # separated by "--". | |
7 | check() { | |
e30b2feb JRI |
8 | credential_opts= |
9 | credential_cmd=$1 | |
10 | shift | |
11 | for arg in "$@"; do | |
12 | credential_opts="$credential_opts -c credential.helper='$arg'" | |
13 | done | |
abca927d JK |
14 | read_chunk >stdin && |
15 | read_chunk >expect-stdout && | |
16 | read_chunk >expect-stderr && | |
e30b2feb JRI |
17 | if ! eval "git $credential_opts credential $credential_cmd <stdin >stdout 2>stderr"; then |
18 | echo "git credential failed with code $?" && | |
19 | cat stderr && | |
20 | false | |
21 | fi && | |
abca927d | 22 | test_cmp expect-stdout stdout && |
1108cea7 | 23 | test_cmp expect-stderr stderr |
abca927d JK |
24 | } |
25 | ||
26 | read_chunk() { | |
27 | while read line; do | |
28 | case "$line" in | |
29 | --) break ;; | |
30 | *) echo "$line" ;; | |
31 | esac | |
32 | done | |
33 | } | |
34 | ||
e2770979 JK |
35 | # Clear any residual data from previous tests. We only |
36 | # need this when testing third-party helpers which read and | |
37 | # write outside of our trash-directory sandbox. | |
38 | # | |
39 | # Don't bother checking for success here, as it is | |
40 | # outside the scope of tests and represents a best effort to | |
41 | # clean up after ourselves. | |
42 | helper_test_clean() { | |
43 | reject $1 https example.com store-user | |
44 | reject $1 https example.com user1 | |
45 | reject $1 https example.com user2 | |
0ce02e2f H |
46 | reject $1 https example.com user-expiry |
47 | reject $1 https example.com user-expiry-overwrite | |
a5c76569 | 48 | reject $1 https example.com user4 |
aeb21ce2 H |
49 | reject $1 https example.com user-distinct-pass |
50 | reject $1 https example.com user-overwrite | |
6c26da84 H |
51 | reject $1 https example.com user-erase1 |
52 | reject $1 https example.com user-erase2 | |
83e6eb7d | 53 | reject $1 https victim.example.com user |
e2770979 JK |
54 | reject $1 http path.tld user |
55 | reject $1 https timeout.tld user | |
3c90bda6 | 56 | reject $1 https sso.tld |
e2770979 JK |
57 | } |
58 | ||
59 | reject() { | |
60 | ( | |
61 | echo protocol=$2 | |
62 | echo host=$3 | |
63 | echo username=$4 | |
e30b2feb | 64 | ) | git -c credential.helper=$1 credential reject |
e2770979 JK |
65 | } |
66 | ||
67 | helper_test() { | |
68 | HELPER=$1 | |
69 | ||
70 | test_expect_success "helper ($HELPER) has no existing data" ' | |
71 | check fill $HELPER <<-\EOF | |
72 | protocol=https | |
73 | host=example.com | |
74 | -- | |
2d6dc182 MM |
75 | protocol=https |
76 | host=example.com | |
e2770979 JK |
77 | username=askpass-username |
78 | password=askpass-password | |
79 | -- | |
80 | askpass: Username for '\''https://example.com'\'': | |
81 | askpass: Password for '\''https://askpass-username@example.com'\'': | |
82 | EOF | |
83 | ' | |
84 | ||
85 | test_expect_success "helper ($HELPER) stores password" ' | |
86 | check approve $HELPER <<-\EOF | |
87 | protocol=https | |
88 | host=example.com | |
89 | username=store-user | |
90 | password=store-pass | |
91 | EOF | |
92 | ' | |
93 | ||
94 | test_expect_success "helper ($HELPER) can retrieve password" ' | |
95 | check fill $HELPER <<-\EOF | |
96 | protocol=https | |
97 | host=example.com | |
98 | -- | |
2d6dc182 MM |
99 | protocol=https |
100 | host=example.com | |
e2770979 JK |
101 | username=store-user |
102 | password=store-pass | |
103 | -- | |
104 | EOF | |
105 | ' | |
106 | ||
107 | test_expect_success "helper ($HELPER) requires matching protocol" ' | |
108 | check fill $HELPER <<-\EOF | |
109 | protocol=http | |
110 | host=example.com | |
111 | -- | |
2d6dc182 MM |
112 | protocol=http |
113 | host=example.com | |
e2770979 JK |
114 | username=askpass-username |
115 | password=askpass-password | |
116 | -- | |
117 | askpass: Username for '\''http://example.com'\'': | |
118 | askpass: Password for '\''http://askpass-username@example.com'\'': | |
119 | EOF | |
120 | ' | |
121 | ||
122 | test_expect_success "helper ($HELPER) requires matching host" ' | |
123 | check fill $HELPER <<-\EOF | |
124 | protocol=https | |
125 | host=other.tld | |
126 | -- | |
2d6dc182 MM |
127 | protocol=https |
128 | host=other.tld | |
e2770979 JK |
129 | username=askpass-username |
130 | password=askpass-password | |
131 | -- | |
132 | askpass: Username for '\''https://other.tld'\'': | |
133 | askpass: Password for '\''https://askpass-username@other.tld'\'': | |
134 | EOF | |
135 | ' | |
136 | ||
137 | test_expect_success "helper ($HELPER) requires matching username" ' | |
138 | check fill $HELPER <<-\EOF | |
139 | protocol=https | |
140 | host=example.com | |
141 | username=other | |
142 | -- | |
2d6dc182 MM |
143 | protocol=https |
144 | host=example.com | |
e2770979 JK |
145 | username=other |
146 | password=askpass-password | |
147 | -- | |
148 | askpass: Password for '\''https://other@example.com'\'': | |
149 | EOF | |
150 | ' | |
151 | ||
152 | test_expect_success "helper ($HELPER) requires matching path" ' | |
153 | test_config credential.usehttppath true && | |
154 | check approve $HELPER <<-\EOF && | |
155 | protocol=http | |
156 | host=path.tld | |
157 | path=foo.git | |
158 | username=user | |
159 | password=pass | |
160 | EOF | |
161 | check fill $HELPER <<-\EOF | |
162 | protocol=http | |
163 | host=path.tld | |
164 | path=bar.git | |
165 | -- | |
2d6dc182 MM |
166 | protocol=http |
167 | host=path.tld | |
168 | path=bar.git | |
e2770979 JK |
169 | username=askpass-username |
170 | password=askpass-password | |
171 | -- | |
172 | askpass: Username for '\''http://path.tld/bar.git'\'': | |
173 | askpass: Password for '\''http://askpass-username@path.tld/bar.git'\'': | |
174 | EOF | |
175 | ' | |
176 | ||
aeb21ce2 H |
177 | test_expect_success "helper ($HELPER) overwrites on store" ' |
178 | check approve $HELPER <<-\EOF && | |
179 | protocol=https | |
180 | host=example.com | |
181 | username=user-overwrite | |
182 | password=pass1 | |
183 | EOF | |
184 | check approve $HELPER <<-\EOF && | |
185 | protocol=https | |
186 | host=example.com | |
187 | username=user-overwrite | |
188 | password=pass2 | |
189 | EOF | |
190 | check fill $HELPER <<-\EOF && | |
191 | protocol=https | |
192 | host=example.com | |
193 | username=user-overwrite | |
194 | -- | |
195 | protocol=https | |
196 | host=example.com | |
197 | username=user-overwrite | |
198 | password=pass2 | |
199 | EOF | |
200 | check reject $HELPER <<-\EOF && | |
201 | protocol=https | |
202 | host=example.com | |
203 | username=user-overwrite | |
204 | password=pass2 | |
205 | EOF | |
206 | check fill $HELPER <<-\EOF | |
207 | protocol=https | |
208 | host=example.com | |
209 | username=user-overwrite | |
210 | -- | |
211 | protocol=https | |
212 | host=example.com | |
213 | username=user-overwrite | |
214 | password=askpass-password | |
215 | -- | |
216 | askpass: Password for '\''https://user-overwrite@example.com'\'': | |
217 | EOF | |
218 | ' | |
219 | ||
e2770979 JK |
220 | test_expect_success "helper ($HELPER) can forget host" ' |
221 | check reject $HELPER <<-\EOF && | |
222 | protocol=https | |
223 | host=example.com | |
224 | EOF | |
225 | check fill $HELPER <<-\EOF | |
226 | protocol=https | |
227 | host=example.com | |
228 | -- | |
2d6dc182 MM |
229 | protocol=https |
230 | host=example.com | |
e2770979 JK |
231 | username=askpass-username |
232 | password=askpass-password | |
233 | -- | |
234 | askpass: Username for '\''https://example.com'\'': | |
235 | askpass: Password for '\''https://askpass-username@example.com'\'': | |
236 | EOF | |
237 | ' | |
238 | ||
239 | test_expect_success "helper ($HELPER) can store multiple users" ' | |
240 | check approve $HELPER <<-\EOF && | |
241 | protocol=https | |
242 | host=example.com | |
243 | username=user1 | |
244 | password=pass1 | |
245 | EOF | |
246 | check approve $HELPER <<-\EOF && | |
247 | protocol=https | |
248 | host=example.com | |
249 | username=user2 | |
250 | password=pass2 | |
251 | EOF | |
252 | check fill $HELPER <<-\EOF && | |
253 | protocol=https | |
254 | host=example.com | |
255 | username=user1 | |
256 | -- | |
2d6dc182 MM |
257 | protocol=https |
258 | host=example.com | |
e2770979 JK |
259 | username=user1 |
260 | password=pass1 | |
261 | EOF | |
262 | check fill $HELPER <<-\EOF | |
263 | protocol=https | |
264 | host=example.com | |
265 | username=user2 | |
266 | -- | |
2d6dc182 MM |
267 | protocol=https |
268 | host=example.com | |
e2770979 JK |
269 | username=user2 |
270 | password=pass2 | |
271 | EOF | |
272 | ' | |
273 | ||
aeb21ce2 H |
274 | test_expect_success "helper ($HELPER) does not erase a password distinct from input" ' |
275 | check approve $HELPER <<-\EOF && | |
276 | protocol=https | |
277 | host=example.com | |
278 | username=user-distinct-pass | |
279 | password=pass1 | |
280 | EOF | |
281 | check reject $HELPER <<-\EOF && | |
282 | protocol=https | |
283 | host=example.com | |
284 | username=user-distinct-pass | |
285 | password=pass2 | |
286 | EOF | |
287 | check fill $HELPER <<-\EOF | |
288 | protocol=https | |
289 | host=example.com | |
290 | username=user-distinct-pass | |
291 | -- | |
292 | protocol=https | |
293 | host=example.com | |
294 | username=user-distinct-pass | |
295 | password=pass1 | |
296 | EOF | |
297 | ' | |
298 | ||
e2770979 JK |
299 | test_expect_success "helper ($HELPER) can forget user" ' |
300 | check reject $HELPER <<-\EOF && | |
301 | protocol=https | |
302 | host=example.com | |
303 | username=user1 | |
304 | EOF | |
305 | check fill $HELPER <<-\EOF | |
306 | protocol=https | |
307 | host=example.com | |
308 | username=user1 | |
309 | -- | |
2d6dc182 MM |
310 | protocol=https |
311 | host=example.com | |
e2770979 JK |
312 | username=user1 |
313 | password=askpass-password | |
314 | -- | |
315 | askpass: Password for '\''https://user1@example.com'\'': | |
316 | EOF | |
317 | ' | |
318 | ||
319 | test_expect_success "helper ($HELPER) remembers other user" ' | |
320 | check fill $HELPER <<-\EOF | |
321 | protocol=https | |
322 | host=example.com | |
323 | username=user2 | |
324 | -- | |
2d6dc182 MM |
325 | protocol=https |
326 | host=example.com | |
e2770979 JK |
327 | username=user2 |
328 | password=pass2 | |
329 | EOF | |
330 | ' | |
3c90bda6 JB |
331 | |
332 | test_expect_success "helper ($HELPER) can store empty username" ' | |
333 | check approve $HELPER <<-\EOF && | |
334 | protocol=https | |
335 | host=sso.tld | |
336 | username= | |
337 | password= | |
338 | EOF | |
339 | check fill $HELPER <<-\EOF | |
340 | protocol=https | |
341 | host=sso.tld | |
342 | -- | |
343 | protocol=https | |
344 | host=sso.tld | |
345 | username= | |
346 | password= | |
347 | EOF | |
348 | ' | |
71201ab0 | 349 | |
6c26da84 H |
350 | test_expect_success "helper ($HELPER) erases all matching credentials" ' |
351 | check approve $HELPER <<-\EOF && | |
352 | protocol=https | |
353 | host=example.com | |
354 | username=user-erase1 | |
355 | password=pass1 | |
356 | EOF | |
357 | check approve $HELPER <<-\EOF && | |
358 | protocol=https | |
359 | host=example.com | |
360 | username=user-erase2 | |
361 | password=pass1 | |
362 | EOF | |
363 | check reject $HELPER <<-\EOF && | |
364 | protocol=https | |
365 | host=example.com | |
366 | EOF | |
367 | check fill $HELPER <<-\EOF | |
368 | protocol=https | |
369 | host=example.com | |
370 | -- | |
371 | protocol=https | |
372 | host=example.com | |
373 | username=askpass-username | |
374 | password=askpass-password | |
375 | -- | |
376 | askpass: Username for '\''https://example.com'\'': | |
377 | askpass: Password for '\''https://askpass-username@example.com'\'': | |
378 | EOF | |
379 | ' | |
380 | ||
71201ab0 TB |
381 | : ${GIT_TEST_LONG_CRED_BUFFER:=1024} |
382 | # 23 bytes accounts for "wwwauth[]=basic realm=" plus NUL | |
383 | LONG_VALUE_LEN=$((GIT_TEST_LONG_CRED_BUFFER - 23)) | |
384 | LONG_VALUE=$(perl -e 'print "a" x shift' $LONG_VALUE_LEN) | |
385 | ||
386 | test_expect_success "helper ($HELPER) not confused by long header" ' | |
387 | check approve $HELPER <<-\EOF && | |
388 | protocol=https | |
389 | host=victim.example.com | |
390 | username=user | |
391 | password=to-be-stolen | |
392 | EOF | |
393 | ||
394 | check fill $HELPER <<-EOF | |
395 | protocol=https | |
396 | host=badguy.example.com | |
397 | wwwauth[]=basic realm=${LONG_VALUE}host=victim.example.com | |
398 | -- | |
399 | protocol=https | |
400 | host=badguy.example.com | |
401 | username=askpass-username | |
402 | password=askpass-password | |
403 | wwwauth[]=basic realm=${LONG_VALUE}host=victim.example.com | |
404 | -- | |
405 | askpass: Username for '\''https://badguy.example.com'\'': | |
406 | askpass: Password for '\''https://askpass-username@badguy.example.com'\'': | |
407 | EOF | |
408 | ' | |
e2770979 JK |
409 | } |
410 | ||
411 | helper_test_timeout() { | |
412 | HELPER="$*" | |
413 | ||
414 | test_expect_success "helper ($HELPER) times out" ' | |
415 | check approve "$HELPER" <<-\EOF && | |
416 | protocol=https | |
417 | host=timeout.tld | |
418 | username=user | |
419 | password=pass | |
420 | EOF | |
421 | sleep 2 && | |
422 | check fill "$HELPER" <<-\EOF | |
423 | protocol=https | |
424 | host=timeout.tld | |
425 | -- | |
2d6dc182 MM |
426 | protocol=https |
427 | host=timeout.tld | |
e2770979 JK |
428 | username=askpass-username |
429 | password=askpass-password | |
430 | -- | |
431 | askpass: Username for '\''https://timeout.tld'\'': | |
432 | askpass: Password for '\''https://askpass-username@timeout.tld'\'': | |
433 | EOF | |
434 | ' | |
435 | } | |
abca927d | 436 | |
0ce02e2f H |
437 | helper_test_password_expiry_utc() { |
438 | HELPER=$1 | |
439 | ||
440 | test_expect_success "helper ($HELPER) stores password_expiry_utc" ' | |
441 | check approve $HELPER <<-\EOF | |
442 | protocol=https | |
443 | host=example.com | |
444 | username=user-expiry | |
445 | password=pass | |
446 | password_expiry_utc=9999999999 | |
447 | EOF | |
448 | ' | |
449 | ||
450 | test_expect_success "helper ($HELPER) gets password_expiry_utc" ' | |
451 | check fill $HELPER <<-\EOF | |
452 | protocol=https | |
453 | host=example.com | |
454 | username=user-expiry | |
455 | -- | |
456 | protocol=https | |
457 | host=example.com | |
458 | username=user-expiry | |
459 | password=pass | |
460 | password_expiry_utc=9999999999 | |
461 | -- | |
462 | EOF | |
463 | ' | |
464 | ||
465 | test_expect_success "helper ($HELPER) overwrites when password_expiry_utc changes" ' | |
466 | check approve $HELPER <<-\EOF && | |
467 | protocol=https | |
468 | host=example.com | |
469 | username=user-expiry-overwrite | |
470 | password=pass1 | |
471 | password_expiry_utc=9999999998 | |
472 | EOF | |
473 | check approve $HELPER <<-\EOF && | |
474 | protocol=https | |
475 | host=example.com | |
476 | username=user-expiry-overwrite | |
477 | password=pass2 | |
478 | password_expiry_utc=9999999999 | |
479 | EOF | |
480 | check fill $HELPER <<-\EOF && | |
481 | protocol=https | |
482 | host=example.com | |
483 | username=user-expiry-overwrite | |
484 | -- | |
485 | protocol=https | |
486 | host=example.com | |
487 | username=user-expiry-overwrite | |
488 | password=pass2 | |
489 | password_expiry_utc=9999999999 | |
490 | EOF | |
491 | check reject $HELPER <<-\EOF && | |
492 | protocol=https | |
493 | host=example.com | |
494 | username=user-expiry-overwrite | |
495 | password=pass2 | |
496 | EOF | |
497 | check fill $HELPER <<-\EOF | |
498 | protocol=https | |
499 | host=example.com | |
500 | username=user-expiry-overwrite | |
501 | -- | |
502 | protocol=https | |
503 | host=example.com | |
504 | username=user-expiry-overwrite | |
505 | password=askpass-password | |
506 | -- | |
507 | askpass: Password for '\''https://user-expiry-overwrite@example.com'\'': | |
508 | EOF | |
509 | ' | |
510 | } | |
511 | ||
a5c76569 H |
512 | helper_test_oauth_refresh_token() { |
513 | HELPER=$1 | |
514 | ||
515 | test_expect_success "helper ($HELPER) stores oauth_refresh_token" ' | |
516 | check approve $HELPER <<-\EOF | |
517 | protocol=https | |
518 | host=example.com | |
519 | username=user4 | |
520 | password=pass | |
521 | oauth_refresh_token=xyzzy | |
522 | EOF | |
523 | ' | |
524 | ||
525 | test_expect_success "helper ($HELPER) gets oauth_refresh_token" ' | |
526 | check fill $HELPER <<-\EOF | |
527 | protocol=https | |
528 | host=example.com | |
529 | username=user4 | |
530 | -- | |
531 | protocol=https | |
532 | host=example.com | |
533 | username=user4 | |
534 | password=pass | |
535 | oauth_refresh_token=xyzzy | |
536 | -- | |
537 | EOF | |
538 | ' | |
539 | } | |
540 | ||
30c0a303 | 541 | helper_test_authtype() { |
542 | HELPER=$1 | |
543 | ||
544 | test_expect_success "helper ($HELPER) stores authtype and credential" ' | |
545 | check approve $HELPER <<-\EOF | |
546 | capability[]=authtype | |
547 | authtype=Bearer | |
548 | credential=random-token | |
549 | protocol=https | |
550 | host=git.example.com | |
551 | EOF | |
552 | ' | |
553 | ||
554 | test_expect_success "helper ($HELPER) gets authtype and credential" ' | |
555 | check fill $HELPER <<-\EOF | |
556 | capability[]=authtype | |
557 | protocol=https | |
558 | host=git.example.com | |
559 | -- | |
560 | capability[]=authtype | |
561 | authtype=Bearer | |
562 | credential=random-token | |
563 | protocol=https | |
564 | host=git.example.com | |
565 | -- | |
566 | EOF | |
567 | ' | |
568 | ||
569 | test_expect_success "helper ($HELPER) stores authtype and credential with username" ' | |
570 | check approve $HELPER <<-\EOF | |
571 | capability[]=authtype | |
572 | authtype=Bearer | |
573 | credential=other-token | |
574 | protocol=https | |
575 | host=git.example.com | |
576 | username=foobar | |
577 | EOF | |
578 | ' | |
579 | ||
580 | test_expect_success "helper ($HELPER) gets authtype and credential with username" ' | |
581 | check fill $HELPER <<-\EOF | |
582 | capability[]=authtype | |
583 | protocol=https | |
584 | host=git.example.com | |
585 | username=foobar | |
586 | -- | |
587 | capability[]=authtype | |
588 | authtype=Bearer | |
589 | credential=other-token | |
590 | protocol=https | |
591 | host=git.example.com | |
592 | username=foobar | |
593 | -- | |
594 | EOF | |
595 | ' | |
596 | ||
597 | test_expect_success "helper ($HELPER) does not get authtype and credential with different username" ' | |
598 | check fill $HELPER <<-\EOF | |
599 | capability[]=authtype | |
600 | protocol=https | |
601 | host=git.example.com | |
602 | username=barbaz | |
603 | -- | |
604 | protocol=https | |
605 | host=git.example.com | |
606 | username=barbaz | |
607 | password=askpass-password | |
608 | -- | |
609 | askpass: Password for '\''https://barbaz@git.example.com'\'': | |
610 | EOF | |
611 | ' | |
612 | ||
613 | test_expect_success "helper ($HELPER) does not store ephemeral authtype and credential" ' | |
614 | check approve $HELPER <<-\EOF && | |
615 | capability[]=authtype | |
616 | authtype=Bearer | |
617 | credential=git2-token | |
618 | protocol=https | |
619 | host=git2.example.com | |
620 | ephemeral=1 | |
621 | EOF | |
622 | ||
623 | check fill $HELPER <<-\EOF | |
624 | capability[]=authtype | |
625 | protocol=https | |
626 | host=git2.example.com | |
627 | -- | |
628 | protocol=https | |
629 | host=git2.example.com | |
630 | username=askpass-username | |
631 | password=askpass-password | |
632 | -- | |
633 | askpass: Username for '\''https://git2.example.com'\'': | |
634 | askpass: Password for '\''https://askpass-username@git2.example.com'\'': | |
635 | EOF | |
636 | ' | |
637 | ||
638 | test_expect_success "helper ($HELPER) does not store ephemeral username and password" ' | |
639 | check approve $HELPER <<-\EOF && | |
640 | capability[]=authtype | |
641 | protocol=https | |
642 | host=git2.example.com | |
643 | user=barbaz | |
644 | password=secret | |
645 | ephemeral=1 | |
646 | EOF | |
647 | ||
648 | check fill $HELPER <<-\EOF | |
649 | capability[]=authtype | |
650 | protocol=https | |
651 | host=git2.example.com | |
652 | -- | |
653 | protocol=https | |
654 | host=git2.example.com | |
655 | username=askpass-username | |
656 | password=askpass-password | |
657 | -- | |
658 | askpass: Username for '\''https://git2.example.com'\'': | |
659 | askpass: Password for '\''https://askpass-username@git2.example.com'\'': | |
660 | EOF | |
661 | ' | |
662 | } | |
663 | ||
c049216f | 664 | write_script askpass <<\EOF |
abca927d | 665 | echo >&2 askpass: $* |
5a435202 | 666 | what=$(echo $1 | cut -d" " -f1 | tr A-Z a-z | tr -cd a-z) |
abca927d JK |
667 | echo "askpass-$what" |
668 | EOF | |
abca927d JK |
669 | GIT_ASKPASS="$PWD/askpass" |
670 | export GIT_ASKPASS |