Git fork
1# Shell library for testing credential handling including helpers. See t0302
2# for an example of testing a specific helper.
3
4# Try a set of credential helpers; the expected stdin,
5# stdout and stderr should be provided on stdin,
6# separated by "--".
7check() {
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
24}
25
26read_chunk() {
27 while read line; do
28 case "$line" in
29 --) break ;;
30 *) echo "$line" ;;
31 esac
32 done
33}
34
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.
42helper_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
57}
58
59reject() {
60 (
61 echo protocol=$2
62 echo host=$3
63 echo username=$4
64 ) | git -c credential.helper=$1 credential reject
65}
66
67helper_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 --
75 protocol=https
76 host=example.com
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 --
99 protocol=https
100 host=example.com
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 --
112 protocol=http
113 host=example.com
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 --
127 protocol=https
128 host=other.tld
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 --
143 protocol=https
144 host=example.com
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 --
166 protocol=http
167 host=path.tld
168 path=bar.git
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
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
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 --
229 protocol=https
230 host=example.com
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 --
257 protocol=https
258 host=example.com
259 username=user1
260 password=pass1
261 EOF
262 check fill $HELPER <<-\EOF
263 protocol=https
264 host=example.com
265 username=user2
266 --
267 protocol=https
268 host=example.com
269 username=user2
270 password=pass2
271 EOF
272 '
273
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
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 --
310 protocol=https
311 host=example.com
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 --
325 protocol=https
326 host=example.com
327 username=user2
328 password=pass2
329 EOF
330 '
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 '
349
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
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 '
409}
410
411helper_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 --
426 protocol=https
427 host=timeout.tld
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}
436
437helper_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
512helper_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
541helper_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) gets authtype and credential only if request has authtype capability" '
570 check fill $HELPER <<-\EOF
571 protocol=https
572 host=git.example.com
573 --
574 protocol=https
575 host=git.example.com
576 username=askpass-username
577 password=askpass-password
578 --
579 askpass: Username for '\''https://git.example.com'\'':
580 askpass: Password for '\''https://askpass-username@git.example.com'\'':
581 EOF
582 '
583
584 test_expect_success "helper ($HELPER) stores authtype and credential with username" '
585 check approve $HELPER <<-\EOF
586 capability[]=authtype
587 authtype=Bearer
588 credential=other-token
589 protocol=https
590 host=git.example.com
591 username=foobar
592 EOF
593 '
594
595 test_expect_success "helper ($HELPER) gets authtype and credential with username" '
596 check fill $HELPER <<-\EOF
597 capability[]=authtype
598 protocol=https
599 host=git.example.com
600 username=foobar
601 --
602 capability[]=authtype
603 authtype=Bearer
604 credential=other-token
605 protocol=https
606 host=git.example.com
607 username=foobar
608 --
609 EOF
610 '
611
612 test_expect_success "helper ($HELPER) does not get authtype and credential with different username" '
613 check fill $HELPER <<-\EOF
614 capability[]=authtype
615 protocol=https
616 host=git.example.com
617 username=barbaz
618 --
619 protocol=https
620 host=git.example.com
621 username=barbaz
622 password=askpass-password
623 --
624 askpass: Password for '\''https://barbaz@git.example.com'\'':
625 EOF
626 '
627
628 test_expect_success "helper ($HELPER) does not store ephemeral authtype and credential" '
629 check approve $HELPER <<-\EOF &&
630 capability[]=authtype
631 authtype=Bearer
632 credential=git2-token
633 protocol=https
634 host=git2.example.com
635 ephemeral=1
636 EOF
637
638 check fill $HELPER <<-\EOF
639 capability[]=authtype
640 protocol=https
641 host=git2.example.com
642 --
643 protocol=https
644 host=git2.example.com
645 username=askpass-username
646 password=askpass-password
647 --
648 askpass: Username for '\''https://git2.example.com'\'':
649 askpass: Password for '\''https://askpass-username@git2.example.com'\'':
650 EOF
651 '
652
653 test_expect_success "helper ($HELPER) does not store ephemeral username and password" '
654 check approve $HELPER <<-\EOF &&
655 capability[]=authtype
656 protocol=https
657 host=git2.example.com
658 user=barbaz
659 password=secret
660 ephemeral=1
661 EOF
662
663 check fill $HELPER <<-\EOF
664 capability[]=authtype
665 protocol=https
666 host=git2.example.com
667 --
668 protocol=https
669 host=git2.example.com
670 username=askpass-username
671 password=askpass-password
672 --
673 askpass: Username for '\''https://git2.example.com'\'':
674 askpass: Password for '\''https://askpass-username@git2.example.com'\'':
675 EOF
676 '
677}
678
679write_script askpass <<\EOF
680echo >&2 askpass: $*
681what=$(echo $1 | cut -d" " -f1 | tr A-Z a-z | tr -cd a-z)
682echo "askpass-$what"
683EOF
684GIT_ASKPASS="$PWD/askpass"
685export GIT_ASKPASS