2011-12-10 11:31:11 +01:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='basic credential helper tests'
|
|
|
|
. ./test-lib.sh
|
|
|
|
. "$TEST_DIRECTORY"/lib-credential.sh
|
|
|
|
|
|
|
|
test_expect_success 'setup helper scripts' '
|
|
|
|
cat >dump <<-\EOF &&
|
2014-04-28 14:57:30 +02:00
|
|
|
whoami=$(echo $0 | sed s/.*git-credential-//)
|
2011-12-10 11:31:11 +01:00
|
|
|
echo >&2 "$whoami: $*"
|
t0300: work around bug in dash 0.5.6
The construct 'while IFS== read' makes dash 0.5.6 execute
read without changing IFS, which results in test breakages
all over the place in t0300. Neither dash 0.5.5.1 and older
nor dash 0.5.7 and newer are affected: The problem was
introduded resp. fixed by the commits
55c46b7 ([BUILTIN] Honor tab as IFS whitespace when
splitting fields in readcmd, 2009-08-11)
1d806ac ([VAR] Do not poplocalvars prematurely on regular
utilities, 2010-05-27)
in http://git.kernel.org/?p=utils/dash/dash.git
Putting 'IFS==' before that line makes all versions of dash
work.
This looks like a dash bug, not a misinterpretation of the
standard. However, it's worth working around for two
reasons. One, this version of dash was released in Fedora
14-16, so the bug is found in the wild. And two, at least
one other shell, Solaris /bin/sh, choked on this by
persisting IFS after the read invocation. That is not a
shell we usually care about, and I think this use of IFS is
acceptable by POSIX (which allows other behavior near
"special builtins", but "read" is not one of those). But it
seems that this may be a subtle, not-well-tested case for
some shells. Given that the workaround is so simple, it's
worth just being defensive.
Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-03-03 01:37:35 +01:00
|
|
|
OIFS=$IFS
|
|
|
|
IFS==
|
|
|
|
while read key value; do
|
2011-12-10 11:31:11 +01:00
|
|
|
echo >&2 "$whoami: $key=$value"
|
|
|
|
eval "$key=$value"
|
|
|
|
done
|
t0300: work around bug in dash 0.5.6
The construct 'while IFS== read' makes dash 0.5.6 execute
read without changing IFS, which results in test breakages
all over the place in t0300. Neither dash 0.5.5.1 and older
nor dash 0.5.7 and newer are affected: The problem was
introduded resp. fixed by the commits
55c46b7 ([BUILTIN] Honor tab as IFS whitespace when
splitting fields in readcmd, 2009-08-11)
1d806ac ([VAR] Do not poplocalvars prematurely on regular
utilities, 2010-05-27)
in http://git.kernel.org/?p=utils/dash/dash.git
Putting 'IFS==' before that line makes all versions of dash
work.
This looks like a dash bug, not a misinterpretation of the
standard. However, it's worth working around for two
reasons. One, this version of dash was released in Fedora
14-16, so the bug is found in the wild. And two, at least
one other shell, Solaris /bin/sh, choked on this by
persisting IFS after the read invocation. That is not a
shell we usually care about, and I think this use of IFS is
acceptable by POSIX (which allows other behavior near
"special builtins", but "read" is not one of those). But it
seems that this may be a subtle, not-well-tested case for
some shells. Given that the workaround is so simple, it's
worth just being defensive.
Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-03-03 01:37:35 +01:00
|
|
|
IFS=$OIFS
|
2011-12-10 11:31:11 +01:00
|
|
|
EOF
|
|
|
|
|
2012-02-04 07:30:18 +01:00
|
|
|
write_script git-credential-useless <<-\EOF &&
|
2011-12-10 11:31:11 +01:00
|
|
|
. ./dump
|
|
|
|
exit 0
|
|
|
|
EOF
|
|
|
|
|
2012-02-04 07:30:18 +01:00
|
|
|
write_script git-credential-verbatim <<-\EOF &&
|
2011-12-10 11:31:11 +01:00
|
|
|
user=$1; shift
|
|
|
|
pass=$1; shift
|
|
|
|
. ./dump
|
|
|
|
test -z "$user" || echo username=$user
|
|
|
|
test -z "$pass" || echo password=$pass
|
|
|
|
EOF
|
|
|
|
|
|
|
|
PATH="$PWD:$PATH"
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'credential_fill invokes helper' '
|
|
|
|
check fill "verbatim foo bar" <<-\EOF
|
|
|
|
--
|
|
|
|
username=foo
|
|
|
|
password=bar
|
|
|
|
--
|
|
|
|
verbatim: get
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'credential_fill invokes multiple helpers' '
|
|
|
|
check fill useless "verbatim foo bar" <<-\EOF
|
|
|
|
--
|
|
|
|
username=foo
|
|
|
|
password=bar
|
|
|
|
--
|
|
|
|
useless: get
|
|
|
|
verbatim: get
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'credential_fill stops when we get a full response' '
|
|
|
|
check fill "verbatim one two" "verbatim three four" <<-\EOF
|
|
|
|
--
|
|
|
|
username=one
|
|
|
|
password=two
|
|
|
|
--
|
|
|
|
verbatim: get
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'credential_fill continues through partial response' '
|
|
|
|
check fill "verbatim one \"\"" "verbatim two three" <<-\EOF
|
|
|
|
--
|
|
|
|
username=two
|
|
|
|
password=three
|
|
|
|
--
|
|
|
|
verbatim: get
|
|
|
|
verbatim: get
|
|
|
|
verbatim: username=one
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'credential_fill passes along metadata' '
|
|
|
|
check fill "verbatim one two" <<-\EOF
|
|
|
|
protocol=ftp
|
|
|
|
host=example.com
|
|
|
|
path=foo.git
|
|
|
|
--
|
2012-06-24 13:40:00 +02:00
|
|
|
protocol=ftp
|
|
|
|
host=example.com
|
|
|
|
path=foo.git
|
2011-12-10 11:31:11 +01:00
|
|
|
username=one
|
|
|
|
password=two
|
|
|
|
--
|
|
|
|
verbatim: get
|
|
|
|
verbatim: protocol=ftp
|
|
|
|
verbatim: host=example.com
|
|
|
|
verbatim: path=foo.git
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'credential_approve calls all helpers' '
|
|
|
|
check approve useless "verbatim one two" <<-\EOF
|
|
|
|
username=foo
|
|
|
|
password=bar
|
|
|
|
--
|
|
|
|
--
|
|
|
|
useless: store
|
|
|
|
useless: username=foo
|
|
|
|
useless: password=bar
|
|
|
|
verbatim: store
|
|
|
|
verbatim: username=foo
|
|
|
|
verbatim: password=bar
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'do not bother storing password-less credential' '
|
|
|
|
check approve useless <<-\EOF
|
|
|
|
username=foo
|
|
|
|
--
|
|
|
|
--
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
|
|
test_expect_success 'credential_reject calls all helpers' '
|
|
|
|
check reject useless "verbatim one two" <<-\EOF
|
|
|
|
username=foo
|
|
|
|
password=bar
|
|
|
|
--
|
|
|
|
--
|
|
|
|
useless: erase
|
|
|
|
useless: username=foo
|
|
|
|
useless: password=bar
|
|
|
|
verbatim: erase
|
|
|
|
verbatim: username=foo
|
|
|
|
verbatim: password=bar
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'usernames can be preserved' '
|
|
|
|
check fill "verbatim \"\" three" <<-\EOF
|
|
|
|
username=one
|
|
|
|
--
|
|
|
|
username=one
|
|
|
|
password=three
|
|
|
|
--
|
|
|
|
verbatim: get
|
|
|
|
verbatim: username=one
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'usernames can be overridden' '
|
|
|
|
check fill "verbatim two three" <<-\EOF
|
|
|
|
username=one
|
|
|
|
--
|
|
|
|
username=two
|
|
|
|
password=three
|
|
|
|
--
|
|
|
|
verbatim: get
|
|
|
|
verbatim: username=one
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'do not bother completing already-full credential' '
|
|
|
|
check fill "verbatim three four" <<-\EOF
|
|
|
|
username=one
|
|
|
|
password=two
|
|
|
|
--
|
|
|
|
username=one
|
|
|
|
password=two
|
|
|
|
--
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
# We can't test the basic terminal password prompt here because
|
|
|
|
# getpass() tries too hard to find the real terminal. But if our
|
|
|
|
# askpass helper is run, we know the internal getpass is working.
|
|
|
|
test_expect_success 'empty helper list falls back to internal getpass' '
|
|
|
|
check fill <<-\EOF
|
|
|
|
--
|
|
|
|
username=askpass-username
|
|
|
|
password=askpass-password
|
|
|
|
--
|
|
|
|
askpass: Username:
|
|
|
|
askpass: Password:
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'internal getpass does not ask for known username' '
|
|
|
|
check fill <<-\EOF
|
|
|
|
username=foo
|
|
|
|
--
|
|
|
|
username=foo
|
|
|
|
password=askpass-password
|
|
|
|
--
|
|
|
|
askpass: Password:
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
2011-12-10 11:31:24 +01:00
|
|
|
HELPER="!f() {
|
|
|
|
cat >/dev/null
|
|
|
|
echo username=foo
|
|
|
|
echo password=bar
|
|
|
|
}; f"
|
|
|
|
test_expect_success 'respect configured credentials' '
|
|
|
|
test_config credential.helper "$HELPER" &&
|
|
|
|
check fill <<-\EOF
|
|
|
|
--
|
|
|
|
username=foo
|
|
|
|
password=bar
|
|
|
|
--
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'match configured credential' '
|
|
|
|
test_config credential.https://example.com.helper "$HELPER" &&
|
|
|
|
check fill <<-\EOF
|
|
|
|
protocol=https
|
|
|
|
host=example.com
|
|
|
|
path=repo.git
|
|
|
|
--
|
2012-06-24 13:40:00 +02:00
|
|
|
protocol=https
|
|
|
|
host=example.com
|
2011-12-10 11:31:24 +01:00
|
|
|
username=foo
|
|
|
|
password=bar
|
|
|
|
--
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'do not match configured credential' '
|
|
|
|
test_config credential.https://foo.helper "$HELPER" &&
|
|
|
|
check fill <<-\EOF
|
|
|
|
protocol=https
|
|
|
|
host=bar
|
|
|
|
--
|
2012-06-24 13:40:00 +02:00
|
|
|
protocol=https
|
|
|
|
host=bar
|
2011-12-10 11:31:24 +01:00
|
|
|
username=askpass-username
|
|
|
|
password=askpass-password
|
|
|
|
--
|
|
|
|
askpass: Username for '\''https://bar'\'':
|
|
|
|
askpass: Password for '\''https://askpass-username@bar'\'':
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
2011-12-10 11:31:30 +01:00
|
|
|
test_expect_success 'pull username from config' '
|
|
|
|
test_config credential.https://example.com.username foo &&
|
|
|
|
check fill <<-\EOF
|
|
|
|
protocol=https
|
|
|
|
host=example.com
|
|
|
|
--
|
2012-06-24 13:40:00 +02:00
|
|
|
protocol=https
|
|
|
|
host=example.com
|
2011-12-10 11:31:30 +01:00
|
|
|
username=foo
|
|
|
|
password=askpass-password
|
|
|
|
--
|
|
|
|
askpass: Password for '\''https://foo@example.com'\'':
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
credential: make relevance of http path configurable
When parsing a URL into a credential struct, we carefully
record each part of the URL, including the path on the
remote host, and use the result as part of the credential
context.
This had two practical implications:
1. Credential helpers which store a credential for later
access are likely to use the "path" portion as part of
the storage key. That means that a request to
https://example.com/foo.git
would not use the same credential that was stored in an
earlier request for:
https://example.com/bar.git
2. The prompt shown to the user includes all relevant
context, including the path.
In most cases, however, users will have a single password
per host. The behavior in (1) will be inconvenient, and the
prompt in (2) will be overly long.
This patch introduces a config option to toggle the
relevance of http paths. When turned on, we use the path as
before. When turned off, we drop the path component from the
context: helpers don't see it, and it does not appear in the
prompt.
This is nothing you couldn't do with a clever credential
helper at the start of your stack, like:
[credential "http://"]
helper = "!f() { grep -v ^path= ; }; f"
helper = your_real_helper
But doing this:
[credential]
useHttpPath = false
is way easier and more readable. Furthermore, since most
users will want the "off" behavior, that is the new default.
Users who want it "on" can set the variable (either for all
credentials, or just for a subset using
credential.*.useHttpPath).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-10 11:31:34 +01:00
|
|
|
test_expect_success 'http paths can be part of context' '
|
|
|
|
check fill "verbatim foo bar" <<-\EOF &&
|
|
|
|
protocol=https
|
|
|
|
host=example.com
|
|
|
|
path=foo.git
|
|
|
|
--
|
2012-06-24 13:40:00 +02:00
|
|
|
protocol=https
|
|
|
|
host=example.com
|
credential: make relevance of http path configurable
When parsing a URL into a credential struct, we carefully
record each part of the URL, including the path on the
remote host, and use the result as part of the credential
context.
This had two practical implications:
1. Credential helpers which store a credential for later
access are likely to use the "path" portion as part of
the storage key. That means that a request to
https://example.com/foo.git
would not use the same credential that was stored in an
earlier request for:
https://example.com/bar.git
2. The prompt shown to the user includes all relevant
context, including the path.
In most cases, however, users will have a single password
per host. The behavior in (1) will be inconvenient, and the
prompt in (2) will be overly long.
This patch introduces a config option to toggle the
relevance of http paths. When turned on, we use the path as
before. When turned off, we drop the path component from the
context: helpers don't see it, and it does not appear in the
prompt.
This is nothing you couldn't do with a clever credential
helper at the start of your stack, like:
[credential "http://"]
helper = "!f() { grep -v ^path= ; }; f"
helper = your_real_helper
But doing this:
[credential]
useHttpPath = false
is way easier and more readable. Furthermore, since most
users will want the "off" behavior, that is the new default.
Users who want it "on" can set the variable (either for all
credentials, or just for a subset using
credential.*.useHttpPath).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-10 11:31:34 +01:00
|
|
|
username=foo
|
|
|
|
password=bar
|
|
|
|
--
|
|
|
|
verbatim: get
|
|
|
|
verbatim: protocol=https
|
|
|
|
verbatim: host=example.com
|
|
|
|
EOF
|
|
|
|
test_config credential.https://example.com.useHttpPath true &&
|
|
|
|
check fill "verbatim foo bar" <<-\EOF
|
|
|
|
protocol=https
|
|
|
|
host=example.com
|
|
|
|
path=foo.git
|
|
|
|
--
|
2012-06-24 13:40:00 +02:00
|
|
|
protocol=https
|
|
|
|
host=example.com
|
|
|
|
path=foo.git
|
credential: make relevance of http path configurable
When parsing a URL into a credential struct, we carefully
record each part of the URL, including the path on the
remote host, and use the result as part of the credential
context.
This had two practical implications:
1. Credential helpers which store a credential for later
access are likely to use the "path" portion as part of
the storage key. That means that a request to
https://example.com/foo.git
would not use the same credential that was stored in an
earlier request for:
https://example.com/bar.git
2. The prompt shown to the user includes all relevant
context, including the path.
In most cases, however, users will have a single password
per host. The behavior in (1) will be inconvenient, and the
prompt in (2) will be overly long.
This patch introduces a config option to toggle the
relevance of http paths. When turned on, we use the path as
before. When turned off, we drop the path component from the
context: helpers don't see it, and it does not appear in the
prompt.
This is nothing you couldn't do with a clever credential
helper at the start of your stack, like:
[credential "http://"]
helper = "!f() { grep -v ^path= ; }; f"
helper = your_real_helper
But doing this:
[credential]
useHttpPath = false
is way easier and more readable. Furthermore, since most
users will want the "off" behavior, that is the new default.
Users who want it "on" can set the variable (either for all
credentials, or just for a subset using
credential.*.useHttpPath).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-10 11:31:34 +01:00
|
|
|
username=foo
|
|
|
|
password=bar
|
|
|
|
--
|
|
|
|
verbatim: get
|
|
|
|
verbatim: protocol=https
|
|
|
|
verbatim: host=example.com
|
|
|
|
verbatim: path=foo.git
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
credential: let helpers tell us to quit
When we are trying to fill a credential, we loop over the
set of defined credential-helpers, then fall back to running
askpass, and then finally prompt on the terminal. Helpers
which cannot find a credential are free to tell us nothing,
but they cannot currently ask us to stop prompting.
This patch lets them provide a "quit" attribute, which asks
us to stop the process entirely (avoiding running more
helpers, as well as the askpass/terminal prompt).
This has a few possible uses:
1. A helper which prompts the user itself (e.g., in a
dialog) can provide a "cancel" button to the user to
stop further prompts.
2. Some helpers may know that prompting cannot possibly
work. For example, if their role is to broker a ticket
from an external auth system and that auth system
cannot be contacted, there is no point in continuing
(we need a ticket to authenticate, and the user cannot
provide one by typing it in).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-12-04 04:46:48 +01:00
|
|
|
test_expect_success 'helpers can abort the process' '
|
|
|
|
test_must_fail git \
|
|
|
|
-c credential.helper="!f() { echo quit=1; }; f" \
|
|
|
|
-c credential.helper="verbatim foo bar" \
|
|
|
|
credential fill >stdout &&
|
|
|
|
>expect &&
|
|
|
|
test_cmp expect stdout
|
|
|
|
'
|
|
|
|
|
2011-12-10 11:31:11 +01:00
|
|
|
test_done
|