3 test_description
='basic credential helper tests'
5 .
"$TEST_DIRECTORY"/lib-credential.sh
7 test_expect_success
'setup helper scripts' '
9 whoami=$(echo $0 | sed s/.*git-credential-//)
10 echo >&2 "$whoami: $*"
13 while read key value; do
14 echo >&2 "$whoami: $key=$value"
20 write_script git-credential-useless <<-\EOF &&
25 write_script git-credential-quit <<-\EOF &&
30 write_script git-credential-verbatim <<-\EOF &&
34 test -z "$user" || echo username=$user
35 test -z "$pass" || echo password=$pass
38 write_script git-credential-verbatim-with-expiry <<-\EOF &&
43 test -z "$user" || echo username=$user
44 test -z "$pass" || echo password=$pass
45 test -z "$pexpiry" || echo password_expiry_utc=$pexpiry
51 test_expect_success
'credential_fill invokes helper' '
52 check fill "verbatim foo bar" <<-\EOF
62 verbatim: protocol=http
63 verbatim: host=example.com
67 test_expect_success
'credential_fill invokes multiple helpers' '
68 check fill useless "verbatim foo bar" <<-\EOF
78 useless: protocol=http
79 useless: host=example.com
81 verbatim: protocol=http
82 verbatim: host=example.com
86 test_expect_success
'credential_fill stops when we get a full response' '
87 check fill "verbatim one two" "verbatim three four" <<-\EOF
97 verbatim: protocol=http
98 verbatim: host=example.com
102 test_expect_success
'credential_fill continues through partial response' '
103 check fill "verbatim one \"\"" "verbatim two three" <<-\EOF
113 verbatim: protocol=http
114 verbatim: host=example.com
116 verbatim: protocol=http
117 verbatim: host=example.com
118 verbatim: username=one
122 test_expect_success
'credential_fill populates password_expiry_utc' '
123 check fill "verbatim-with-expiry one two 9999999999" <<-\EOF
131 password_expiry_utc=9999999999
133 verbatim-with-expiry: get
134 verbatim-with-expiry: protocol=http
135 verbatim-with-expiry: host=example.com
139 test_expect_success
'credential_fill ignores expired password' '
140 check fill "verbatim-with-expiry one two 5" "verbatim three four" <<-\EOF
149 verbatim-with-expiry: get
150 verbatim-with-expiry: protocol=http
151 verbatim-with-expiry: host=example.com
153 verbatim: protocol=http
154 verbatim: host=example.com
155 verbatim: username=one
159 test_expect_success
'credential_fill passes along metadata' '
160 check fill "verbatim one two" <<-\EOF
172 verbatim: protocol=ftp
173 verbatim: host=example.com
174 verbatim: path=foo.git
178 test_expect_success
'credential_approve calls all helpers' '
179 check approve useless "verbatim one two" <<-\EOF
187 useless: protocol=http
188 useless: host=example.com
189 useless: username=foo
190 useless: password=bar
192 verbatim: protocol=http
193 verbatim: host=example.com
194 verbatim: username=foo
195 verbatim: password=bar
199 test_expect_success
'credential_approve stores password expiry' '
200 check approve useless <<-\EOF
205 password_expiry_utc=9999999999
209 useless: protocol=http
210 useless: host=example.com
211 useless: username=foo
212 useless: password=bar
213 useless: password_expiry_utc=9999999999
217 test_expect_success
'do not bother storing password-less credential' '
218 check approve useless <<-\EOF
227 test_expect_success
'credential_approve does not store expired password' '
228 check approve useless <<-\EOF
233 password_expiry_utc=5
239 test_expect_success
'credential_reject calls all helpers' '
240 check reject useless "verbatim one two" <<-\EOF
248 useless: protocol=http
249 useless: host=example.com
250 useless: username=foo
251 useless: password=bar
253 verbatim: protocol=http
254 verbatim: host=example.com
255 verbatim: username=foo
256 verbatim: password=bar
260 test_expect_success
'credential_reject erases credential regardless of expiry' '
261 check reject useless <<-\EOF
266 password_expiry_utc=5
270 useless: protocol=http
271 useless: host=example.com
272 useless: username=foo
273 useless: password=bar
274 useless: password_expiry_utc=5
278 test_expect_success
'usernames can be preserved' '
279 check fill "verbatim \"\" three" <<-\EOF
290 verbatim: protocol=http
291 verbatim: host=example.com
292 verbatim: username=one
296 test_expect_success
'usernames can be overridden' '
297 check fill "verbatim two three" <<-\EOF
308 verbatim: protocol=http
309 verbatim: host=example.com
310 verbatim: username=one
314 test_expect_success
'do not bother completing already-full credential' '
315 check fill "verbatim three four" <<-\EOF
329 # We can't test the basic terminal password prompt here because
330 # getpass() tries too hard to find the real terminal. But if our
331 # askpass helper is run, we know the internal getpass is working.
332 test_expect_success
'empty helper list falls back to internal getpass' '
339 username=askpass-username
340 password=askpass-password
342 askpass: Username for '\''http://example.com'\'':
343 askpass: Password for '\''http://askpass-username@example.com'\'':
347 test_expect_success
'internal getpass does not ask for known username' '
356 password=askpass-password
358 askpass: Password for '\''http://foo@example.com'\'':
362 test_expect_success
'git-credential respects core.askPass' '
363 write_script alternate-askpass <<-\EOF &&
364 echo >&2 "alternate askpass invoked"
367 test_config core.askpass "$PWD/alternate-askpass" &&
369 # unset GIT_ASKPASS set by lib-credential.sh which would
370 # override our config, but do so in a subshell so that we do
371 # not interfere with other tests
372 sane_unset GIT_ASKPASS &&
379 username=alternate-value
380 password=alternate-value
382 alternate askpass invoked
383 alternate askpass invoked
393 test_expect_success
'respect configured credentials' '
394 test_config credential.helper "$HELPER" &&
407 test_expect_success
'match configured credential' '
408 test_config credential.https://example.com.helper "$HELPER" &&
422 test_expect_success
'do not match configured credential' '
423 test_config credential.https://foo.helper "$HELPER" &&
430 username=askpass-username
431 password=askpass-password
433 askpass: Username for '\''https://bar'\'':
434 askpass: Password for '\''https://askpass-username@bar'\'':
438 test_expect_success
'match multiple configured helpers' '
439 test_config credential.helper "verbatim \"\" \"\"" &&
440 test_config credential.https://example.com.helper "$HELPER" &&
452 verbatim: protocol=https
453 verbatim: host=example.com
457 test_expect_success
'match multiple configured helpers with URLs' '
458 test_config credential.https://example.com/repo.git.helper "verbatim \"\" \"\"" &&
459 test_config credential.https://example.com.helper "$HELPER" &&
471 verbatim: protocol=https
472 verbatim: host=example.com
476 test_expect_success
'match percent-encoded values' '
477 test_config credential.https://example.com/%2566.git.helper "$HELPER" &&
479 url=https://example.com/%2566.git
489 test_expect_success
'match percent-encoded UTF-8 values in path' '
490 test_config credential.https://example.com.useHttpPath true &&
491 test_config credential.https://example.com/perú.git.helper "$HELPER" &&
493 url=https://example.com/per%C3%BA.git
504 test_expect_success
'match percent-encoded values in username' '
505 test_config credential.https://user%2fname@example.com/foo/bar.git.helper "$HELPER" &&
507 url=https://user%2fname@example.com/foo/bar.git
517 test_expect_success
'fetch with multiple path components' '
518 test_unconfig credential.helper &&
519 test_config credential.https://example.com/foo/repo.git.helper "verbatim foo bar" &&
521 url=https://example.com/foo/repo.git
529 verbatim: protocol=https
530 verbatim: host=example.com
534 test_expect_success
'pull username from config' '
535 test_config credential.https://example.com.username foo &&
543 password=askpass-password
545 askpass: Password for '\''https://foo@example.com'\'':
549 test_expect_success
'honors username from URL over helper (URL)' '
550 test_config credential.https://example.com.username bob &&
551 test_config credential.https://example.com.helper "verbatim \"\" bar" &&
553 url=https://alice@example.com
561 verbatim: protocol=https
562 verbatim: host=example.com
563 verbatim: username=alice
567 test_expect_success
'honors username from URL over helper (components)' '
568 test_config credential.https://example.com.username bob &&
569 test_config credential.https://example.com.helper "verbatim \"\" bar" &&
581 verbatim: protocol=https
582 verbatim: host=example.com
583 verbatim: username=alice
587 test_expect_success
'last matching username wins' '
588 test_config credential.https://example.com/path.git.username bob &&
589 test_config credential.https://example.com.username alice &&
590 test_config credential.https://example.com.helper "verbatim \"\" bar" &&
592 url=https://example.com/path.git
600 verbatim: protocol=https
601 verbatim: host=example.com
602 verbatim: username=alice
606 test_expect_success
'http paths can be part of context' '
607 check fill "verbatim foo bar" <<-\EOF &&
618 verbatim: protocol=https
619 verbatim: host=example.com
621 test_config credential.https://example.com.useHttpPath true &&
622 check fill "verbatim foo bar" <<-\EOF
634 verbatim: protocol=https
635 verbatim: host=example.com
636 verbatim: path=foo.git
640 test_expect_success
'context uses urlmatch' '
641 test_config "credential.https://*.org.useHttpPath" true &&
642 check fill "verbatim foo bar" <<-\EOF
654 verbatim: protocol=https
655 verbatim: host=example.org
656 verbatim: path=foo.git
660 test_expect_success
'helpers can abort the process' '
662 -c credential.helper=quit \
663 -c credential.helper="verbatim foo bar" \
664 credential fill >stdout 2>stderr <<-\EOF &&
668 test_must_be_empty stdout &&
669 cat >expect <<-\EOF &&
672 quit: host=example.com
673 fatal: credential helper '\''quit'\'' told us to quit
675 test_cmp expect stderr
678 test_expect_success
'empty helper spec resets helper list' '
679 test_config credential.helper "verbatim file file" &&
680 check fill "" "verbatim cmdline cmdline" <<-\EOF
690 verbatim: protocol=http
691 verbatim: host=example.com
695 test_expect_success
'url parser rejects embedded newlines' '
696 test_must_fail git credential fill 2>stderr <<-\EOF &&
697 url=https://one.example.com?%0ahost=two.example.com/
699 cat >expect <<-\EOF &&
700 warning: url contains a newline in its path component: https://one.example.com?%0ahost=two.example.com/
701 fatal: credential url cannot be parsed: https://one.example.com?%0ahost=two.example.com/
703 test_cmp expect stderr
706 test_expect_success
'host-less URLs are parsed as empty host' '
707 check fill "verbatim foo bar" <<-\EOF
708 url=cert:///path/to/cert.pem
712 path=path/to/cert.pem
717 verbatim: protocol=cert
719 verbatim: path=path/to/cert.pem
723 test_expect_success
'credential system refuses to work with missing host' '
724 test_must_fail git credential fill 2>stderr <<-\EOF &&
727 cat >expect <<-\EOF &&
728 fatal: refusing to work with credential missing host field
730 test_cmp expect stderr
733 test_expect_success
'credential system refuses to work with missing protocol' '
734 test_must_fail git credential fill 2>stderr <<-\EOF &&
737 cat >expect <<-\EOF &&
738 fatal: refusing to work with credential missing protocol field
740 test_cmp expect stderr
743 # usage: check_host_and_path <url> <expected-host> <expected-path>
744 check_host_and_path
() {
745 # we always parse the path component, but we need this to make sure it
746 # is passed to the helper
747 test_config credential.useHTTPPath true
&&
748 check fill
"verbatim user pass" <<-EOF
758 verbatim: protocol=https
764 test_expect_success
'url parser handles bare query marker' '
765 check_host_and_path https://example.com?foo.git example.com ?foo.git
768 test_expect_success
'url parser handles bare fragment marker' '
769 check_host_and_path https://example.com#foo.git example.com "#foo.git"
772 test_expect_success
'url parser not confused by encoded markers' '
773 check_host_and_path https://example.com%23%3f%2f/foo.git \
774 "example.com#?/" foo.git
777 test_expect_success
'credential config with partial URLs' '
778 echo "echo password=yep" | write_script git-credential-yep &&
779 test_write_lines url=https://user@example.com/repo.git >stdin &&
784 https://example.com \
785 https://example.com/ \
786 https://user@example.com \
787 https://user@example.com/ \
788 https://example.com/repo.git \
789 https://user@example.com/repo.git \
792 git -c credential.$partial.helper=yep \
793 credential fill <stdin >stdout &&
803 git -c credential.$partial.helper=yep \
804 credential fill <stdin >stdout &&
809 git -c credential.$partial.helper=yep \
810 -c credential.with%0anewline.username=uh-oh \
811 credential fill <stdin >stdout 2>stderr &&
812 test_i18ngrep "skipping credential lookup for key" stderr