run-command(win32): resolve the path to the Unix shell early
[git.git] / t / lib-credential.sh
blob58b9c7406058904838832d35719478797a01d1ee
1 # Shell library for testing credential handling including helpers. See t0302
2 # for an example of testing a specific helper.
4 # Try a set of credential helpers; the expected stdin,
5 # stdout and stderr should be provided on stdin,
6 # separated by "--".
7 check() {
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
14 read_chunk >stdin &&
15 read_chunk >expect-stdout &&
16 read_chunk >expect-stderr &&
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 &&
22 test_cmp expect-stdout stdout &&
23 test_cmp expect-stderr stderr
26 read_chunk() {
27 while read line; do
28 case "$line" in
29 --) break ;;
30 *) echo "$line" ;;
31 esac
32 done
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.
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
46 reject $1 https example.com user-expiry
47 reject $1 https example.com user-expiry-overwrite
48 reject $1 https example.com user4
49 reject $1 https example.com user-distinct-pass
50 reject $1 https example.com user-overwrite
51 reject $1 https example.com user-erase1
52 reject $1 https example.com user-erase2
53 reject $1 https victim.example.com user
54 reject $1 http path.tld user
55 reject $1 https timeout.tld user
56 reject $1 https sso.tld
59 reject() {
61 echo protocol=$2
62 echo host=$3
63 echo username=$4
64 ) | git -c credential.helper=$1 credential reject
67 helper_test() {
68 HELPER=$1
70 test_expect_success "helper ($HELPER) has no existing data" '
71 check fill $HELPER <<-\EOF
72 protocol=https
73 host=example.com
75 protocol=https
76 host=example.com
77 username=askpass-username
78 password=askpass-password
80 askpass: Username for '\''https://example.com'\'':
81 askpass: Password for '\''https://askpass-username@example.com'\'':
82 EOF
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
94 test_expect_success "helper ($HELPER) can retrieve password" '
95 check fill $HELPER <<-\EOF
96 protocol=https
97 host=example.com
99 protocol=https
100 host=example.com
101 username=store-user
102 password=store-pass
107 test_expect_success "helper ($HELPER) requires matching protocol" '
108 check fill $HELPER <<-\EOF
109 protocol=http
110 host=example.com
112 protocol=http
113 host=example.com
114 username=askpass-username
115 password=askpass-password
117 askpass: Username for '\''http://example.com'\'':
118 askpass: Password for '\''http://askpass-username@example.com'\'':
122 test_expect_success "helper ($HELPER) requires matching host" '
123 check fill $HELPER <<-\EOF
124 protocol=https
125 host=other.tld
127 protocol=https
128 host=other.tld
129 username=askpass-username
130 password=askpass-password
132 askpass: Username for '\''https://other.tld'\'':
133 askpass: Password for '\''https://askpass-username@other.tld'\'':
137 test_expect_success "helper ($HELPER) requires matching username" '
138 check fill $HELPER <<-\EOF
139 protocol=https
140 host=example.com
141 username=other
143 protocol=https
144 host=example.com
145 username=other
146 password=askpass-password
148 askpass: Password for '\''https://other@example.com'\'':
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
161 check fill $HELPER <<-\EOF
162 protocol=http
163 host=path.tld
164 path=bar.git
166 protocol=http
167 host=path.tld
168 path=bar.git
169 username=askpass-username
170 password=askpass-password
172 askpass: Username for '\''http://path.tld/bar.git'\'':
173 askpass: Password for '\''http://askpass-username@path.tld/bar.git'\'':
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
184 check approve $HELPER <<-\EOF &&
185 protocol=https
186 host=example.com
187 username=user-overwrite
188 password=pass2
190 check fill $HELPER <<-\EOF &&
191 protocol=https
192 host=example.com
193 username=user-overwrite
195 protocol=https
196 host=example.com
197 username=user-overwrite
198 password=pass2
200 check reject $HELPER <<-\EOF &&
201 protocol=https
202 host=example.com
203 username=user-overwrite
204 password=pass2
206 check fill $HELPER <<-\EOF
207 protocol=https
208 host=example.com
209 username=user-overwrite
211 protocol=https
212 host=example.com
213 username=user-overwrite
214 password=askpass-password
216 askpass: Password for '\''https://user-overwrite@example.com'\'':
220 test_expect_success "helper ($HELPER) can forget host" '
221 check reject $HELPER <<-\EOF &&
222 protocol=https
223 host=example.com
225 check fill $HELPER <<-\EOF
226 protocol=https
227 host=example.com
229 protocol=https
230 host=example.com
231 username=askpass-username
232 password=askpass-password
234 askpass: Username for '\''https://example.com'\'':
235 askpass: Password for '\''https://askpass-username@example.com'\'':
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
246 check approve $HELPER <<-\EOF &&
247 protocol=https
248 host=example.com
249 username=user2
250 password=pass2
252 check fill $HELPER <<-\EOF &&
253 protocol=https
254 host=example.com
255 username=user1
257 protocol=https
258 host=example.com
259 username=user1
260 password=pass1
262 check fill $HELPER <<-\EOF
263 protocol=https
264 host=example.com
265 username=user2
267 protocol=https
268 host=example.com
269 username=user2
270 password=pass2
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
281 check reject $HELPER <<-\EOF &&
282 protocol=https
283 host=example.com
284 username=user-distinct-pass
285 password=pass2
287 check fill $HELPER <<-\EOF
288 protocol=https
289 host=example.com
290 username=user-distinct-pass
292 protocol=https
293 host=example.com
294 username=user-distinct-pass
295 password=pass1
299 test_expect_success "helper ($HELPER) can forget user" '
300 check reject $HELPER <<-\EOF &&
301 protocol=https
302 host=example.com
303 username=user1
305 check fill $HELPER <<-\EOF
306 protocol=https
307 host=example.com
308 username=user1
310 protocol=https
311 host=example.com
312 username=user1
313 password=askpass-password
315 askpass: Password for '\''https://user1@example.com'\'':
319 test_expect_success "helper ($HELPER) remembers other user" '
320 check fill $HELPER <<-\EOF
321 protocol=https
322 host=example.com
323 username=user2
325 protocol=https
326 host=example.com
327 username=user2
328 password=pass2
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=
339 check fill $HELPER <<-\EOF
340 protocol=https
341 host=sso.tld
343 protocol=https
344 host=sso.tld
345 username=
346 password=
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
357 check approve $HELPER <<-\EOF &&
358 protocol=https
359 host=example.com
360 username=user-erase2
361 password=pass1
363 check reject $HELPER <<-\EOF &&
364 protocol=https
365 host=example.com
367 check fill $HELPER <<-\EOF
368 protocol=https
369 host=example.com
371 protocol=https
372 host=example.com
373 username=askpass-username
374 password=askpass-password
376 askpass: Username for '\''https://example.com'\'':
377 askpass: Password for '\''https://askpass-username@example.com'\'':
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)
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
394 check fill $HELPER <<-EOF
395 protocol=https
396 host=badguy.example.com
397 wwwauth[]=basic realm=${LONG_VALUE}host=victim.example.com
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
405 askpass: Username for '\''https://badguy.example.com'\'':
406 askpass: Password for '\''https://askpass-username@badguy.example.com'\'':
411 helper_test_timeout() {
412 HELPER="$*"
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
421 sleep 2 &&
422 check fill "$HELPER" <<-\EOF
423 protocol=https
424 host=timeout.tld
426 protocol=https
427 host=timeout.tld
428 username=askpass-username
429 password=askpass-password
431 askpass: Username for '\''https://timeout.tld'\'':
432 askpass: Password for '\''https://askpass-username@timeout.tld'\'':
437 helper_test_password_expiry_utc() {
438 HELPER=$1
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
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
456 protocol=https
457 host=example.com
458 username=user-expiry
459 password=pass
460 password_expiry_utc=9999999999
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
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
480 check fill $HELPER <<-\EOF &&
481 protocol=https
482 host=example.com
483 username=user-expiry-overwrite
485 protocol=https
486 host=example.com
487 username=user-expiry-overwrite
488 password=pass2
489 password_expiry_utc=9999999999
491 check reject $HELPER <<-\EOF &&
492 protocol=https
493 host=example.com
494 username=user-expiry-overwrite
495 password=pass2
497 check fill $HELPER <<-\EOF
498 protocol=https
499 host=example.com
500 username=user-expiry-overwrite
502 protocol=https
503 host=example.com
504 username=user-expiry-overwrite
505 password=askpass-password
507 askpass: Password for '\''https://user-expiry-overwrite@example.com'\'':
512 helper_test_oauth_refresh_token() {
513 HELPER=$1
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
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
531 protocol=https
532 host=example.com
533 username=user4
534 password=pass
535 oauth_refresh_token=xyzzy
541 helper_test_authtype() {
542 HELPER=$1
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
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
560 capability[]=authtype
561 authtype=Bearer
562 credential=random-token
563 protocol=https
564 host=git.example.com
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
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
587 capability[]=authtype
588 authtype=Bearer
589 credential=other-token
590 protocol=https
591 host=git.example.com
592 username=foobar
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
604 protocol=https
605 host=git.example.com
606 username=barbaz
607 password=askpass-password
609 askpass: Password for '\''https://barbaz@git.example.com'\'':
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
623 check fill $HELPER <<-\EOF
624 capability[]=authtype
625 protocol=https
626 host=git2.example.com
628 protocol=https
629 host=git2.example.com
630 username=askpass-username
631 password=askpass-password
633 askpass: Username for '\''https://git2.example.com'\'':
634 askpass: Password for '\''https://askpass-username@git2.example.com'\'':
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
648 check fill $HELPER <<-\EOF
649 capability[]=authtype
650 protocol=https
651 host=git2.example.com
653 protocol=https
654 host=git2.example.com
655 username=askpass-username
656 password=askpass-password
658 askpass: Username for '\''https://git2.example.com'\'':
659 askpass: Password for '\''https://askpass-username@git2.example.com'\'':
664 write_script askpass <<\EOF
665 echo >&2 askpass: $*
666 what=$(echo $1 | cut -d" " -f1 | tr A-Z a-z | tr -cd a-z)
667 echo "askpass-$what"
669 GIT_ASKPASS="$PWD/askpass"
670 export GIT_ASKPASS