Some HTTP authentication schemes, such as NTLM- and Kerberos-based options, require more than one round trip to authenticate. Currently, these can only be supported in libcurl, since Git does not have support for this in the credential helper protocol. However, in a future commit, we'll add support for this functionality into the credential helper protocol and Git itself. Because we don't really want to implement either NTLM or Kerberos, both of which are complex protocols, we'll want to test this using a fake credential authentication scheme. In order to do so, update t5563 and its backend to allow us to accept multiple sets of credentials and respond with different behavior in each case. Since we can now provide any number of possible status codes, provide a non-specific reason phrase so we don't have to generate a more specific one based on the response. The reason phrase is mandatory according to the status-line production in RFC 7230, but clients SHOULD ignore it, and curl does (except to print it). Each entry in the authorization and challenge fields contains an ID, which indicates a corresponding credential and response. If the response is a 200 status, then we continue to execute git-http-backend. Otherwise, we print the corresponding status and response. If no ID is matched, we use the default response with a status of 401. Note that there is an implicit order to the parameters. The ID is always first and the creds or response value is always last, and therefore may contain spaces, equals signs, or other arbitrary data. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
483 lines
13 KiB
Bash
Executable File
483 lines
13 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='test http auth header and credential helper interop'
|
|
|
|
. ./test-lib.sh
|
|
. "$TEST_DIRECTORY"/lib-httpd.sh
|
|
|
|
enable_cgipassauth
|
|
if ! test_have_prereq CGIPASSAUTH
|
|
then
|
|
skip_all="no CGIPassAuth support"
|
|
test_done
|
|
fi
|
|
start_httpd
|
|
|
|
test_expect_success 'setup_credential_helper' '
|
|
mkdir "$TRASH_DIRECTORY/bin" &&
|
|
PATH=$PATH:"$TRASH_DIRECTORY/bin" &&
|
|
export PATH &&
|
|
|
|
CREDENTIAL_HELPER="$TRASH_DIRECTORY/bin/git-credential-test-helper" &&
|
|
write_script "$CREDENTIAL_HELPER" <<-\EOF
|
|
cmd=$1
|
|
teefile=$cmd-query.cred
|
|
catfile=$cmd-reply.cred
|
|
sed -n -e "/^$/q" -e "p" >>$teefile
|
|
if test "$cmd" = "get"
|
|
then
|
|
cat $catfile
|
|
fi
|
|
EOF
|
|
'
|
|
|
|
set_credential_reply () {
|
|
cat >"$TRASH_DIRECTORY/$1-reply.cred"
|
|
}
|
|
|
|
expect_credential_query () {
|
|
cat >"$TRASH_DIRECTORY/$1-expect.cred" &&
|
|
test_cmp "$TRASH_DIRECTORY/$1-expect.cred" \
|
|
"$TRASH_DIRECTORY/$1-query.cred"
|
|
}
|
|
|
|
per_test_cleanup () {
|
|
rm -f *.cred &&
|
|
rm -f "$HTTPD_ROOT_PATH"/custom-auth.valid \
|
|
"$HTTPD_ROOT_PATH"/custom-auth.challenge
|
|
}
|
|
|
|
test_expect_success 'setup repository' '
|
|
test_commit foo &&
|
|
git init --bare "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
|
|
git push --mirror "$HTTPD_DOCUMENT_ROOT_PATH/repo.git"
|
|
'
|
|
|
|
test_expect_success 'access using basic auth' '
|
|
test_when_finished "per_test_cleanup" &&
|
|
|
|
set_credential_reply get <<-EOF &&
|
|
username=alice
|
|
password=secret-passwd
|
|
EOF
|
|
|
|
# Basic base64(alice:secret-passwd)
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
|
|
id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
|
EOF
|
|
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
|
|
id=1 status=200
|
|
id=default response=WWW-Authenticate: Basic realm="example.com"
|
|
EOF
|
|
|
|
test_config_global credential.helper test-helper &&
|
|
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
|
|
|
|
expect_credential_query get <<-EOF &&
|
|
capability[]=authtype
|
|
capability[]=state
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
wwwauth[]=Basic realm="example.com"
|
|
EOF
|
|
|
|
expect_credential_query store <<-EOF
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
username=alice
|
|
password=secret-passwd
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'access using basic auth via authtype' '
|
|
test_when_finished "per_test_cleanup" &&
|
|
|
|
set_credential_reply get <<-EOF &&
|
|
capability[]=authtype
|
|
authtype=Basic
|
|
credential=YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
|
EOF
|
|
|
|
# Basic base64(alice:secret-passwd)
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
|
|
id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
|
EOF
|
|
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
|
|
id=1 status=200
|
|
id=default response=WWW-Authenticate: Basic realm="example.com"
|
|
EOF
|
|
|
|
test_config_global credential.helper test-helper &&
|
|
GIT_CURL_VERBOSE=1 git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
|
|
|
|
expect_credential_query get <<-EOF &&
|
|
capability[]=authtype
|
|
capability[]=state
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
wwwauth[]=Basic realm="example.com"
|
|
EOF
|
|
|
|
expect_credential_query store <<-EOF
|
|
capability[]=authtype
|
|
authtype=Basic
|
|
credential=YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'access using basic auth invalid credentials' '
|
|
test_when_finished "per_test_cleanup" &&
|
|
|
|
set_credential_reply get <<-EOF &&
|
|
username=baduser
|
|
password=wrong-passwd
|
|
EOF
|
|
|
|
# Basic base64(alice:secret-passwd)
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
|
|
id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
|
EOF
|
|
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
|
|
id=1 status=200
|
|
id=default response=WWW-Authenticate: Basic realm="example.com"
|
|
EOF
|
|
|
|
test_config_global credential.helper test-helper &&
|
|
test_must_fail git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
|
|
|
|
expect_credential_query get <<-EOF &&
|
|
capability[]=authtype
|
|
capability[]=state
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
wwwauth[]=Basic realm="example.com"
|
|
EOF
|
|
|
|
expect_credential_query erase <<-EOF
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
username=baduser
|
|
password=wrong-passwd
|
|
wwwauth[]=Basic realm="example.com"
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'access using basic auth with extra challenges' '
|
|
test_when_finished "per_test_cleanup" &&
|
|
|
|
set_credential_reply get <<-EOF &&
|
|
username=alice
|
|
password=secret-passwd
|
|
EOF
|
|
|
|
# Basic base64(alice:secret-passwd)
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
|
|
id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
|
EOF
|
|
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
|
|
id=1 status=200
|
|
id=default response=WWW-Authenticate: FooBar param1="value1" param2="value2"
|
|
id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
|
|
id=default response=WWW-Authenticate: Basic realm="example.com"
|
|
EOF
|
|
|
|
test_config_global credential.helper test-helper &&
|
|
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
|
|
|
|
expect_credential_query get <<-EOF &&
|
|
capability[]=authtype
|
|
capability[]=state
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
wwwauth[]=FooBar param1="value1" param2="value2"
|
|
wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
|
|
wwwauth[]=Basic realm="example.com"
|
|
EOF
|
|
|
|
expect_credential_query store <<-EOF
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
username=alice
|
|
password=secret-passwd
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'access using basic auth mixed-case wwwauth header name' '
|
|
test_when_finished "per_test_cleanup" &&
|
|
|
|
set_credential_reply get <<-EOF &&
|
|
username=alice
|
|
password=secret-passwd
|
|
EOF
|
|
|
|
# Basic base64(alice:secret-passwd)
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
|
|
id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
|
EOF
|
|
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
|
|
id=1 status=200
|
|
id=default response=www-authenticate: foobar param1="value1" param2="value2"
|
|
id=default response=WWW-AUTHENTICATE: BEARER authorize_uri="id.example.com" p=1 q=0
|
|
id=default response=WwW-aUtHeNtIcAtE: baSiC realm="example.com"
|
|
EOF
|
|
|
|
test_config_global credential.helper test-helper &&
|
|
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
|
|
|
|
expect_credential_query get <<-EOF &&
|
|
capability[]=authtype
|
|
capability[]=state
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
wwwauth[]=foobar param1="value1" param2="value2"
|
|
wwwauth[]=BEARER authorize_uri="id.example.com" p=1 q=0
|
|
wwwauth[]=baSiC realm="example.com"
|
|
EOF
|
|
|
|
expect_credential_query store <<-EOF
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
username=alice
|
|
password=secret-passwd
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'access using basic auth with wwwauth header continuations' '
|
|
test_when_finished "per_test_cleanup" &&
|
|
|
|
set_credential_reply get <<-EOF &&
|
|
username=alice
|
|
password=secret-passwd
|
|
EOF
|
|
|
|
# Basic base64(alice:secret-passwd)
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
|
|
id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
|
EOF
|
|
|
|
# Note that leading and trailing whitespace is important to correctly
|
|
# simulate a continuation/folded header.
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
|
|
id=1 status=200
|
|
id=default response=WWW-Authenticate: FooBar param1="value1"
|
|
id=default response= param2="value2"
|
|
id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com"
|
|
id=default response= p=1
|
|
id=default response= q=0
|
|
id=default response=WWW-Authenticate: Basic realm="example.com"
|
|
EOF
|
|
|
|
test_config_global credential.helper test-helper &&
|
|
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
|
|
|
|
expect_credential_query get <<-EOF &&
|
|
capability[]=authtype
|
|
capability[]=state
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
wwwauth[]=FooBar param1="value1" param2="value2"
|
|
wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
|
|
wwwauth[]=Basic realm="example.com"
|
|
EOF
|
|
|
|
expect_credential_query store <<-EOF
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
username=alice
|
|
password=secret-passwd
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'access using basic auth with wwwauth header empty continuations' '
|
|
test_when_finished "per_test_cleanup" &&
|
|
|
|
set_credential_reply get <<-EOF &&
|
|
username=alice
|
|
password=secret-passwd
|
|
EOF
|
|
|
|
# Basic base64(alice:secret-passwd)
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
|
|
id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
|
EOF
|
|
|
|
CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
|
|
|
|
# Note that leading and trailing whitespace is important to correctly
|
|
# simulate a continuation/folded header.
|
|
printf "id=1 status=200\n" >"$CHALLENGE" &&
|
|
printf "id=default response=WWW-Authenticate: FooBar param1=\"value1\"\r\n" >>"$CHALLENGE" &&
|
|
printf "id=default response= \r\n" >>"$CHALLENGE" &&
|
|
printf "id=default response= param2=\"value2\"\r\n" >>"$CHALLENGE" &&
|
|
printf "id=default response=WWW-Authenticate: Bearer authorize_uri=\"id.example.com\"\r\n" >>"$CHALLENGE" &&
|
|
printf "id=default response= p=1\r\n" >>"$CHALLENGE" &&
|
|
printf "id=default response= \r\n" >>"$CHALLENGE" &&
|
|
printf "id=default response= q=0\r\n" >>"$CHALLENGE" &&
|
|
printf "id=default response=WWW-Authenticate: Basic realm=\"example.com\"\r\n" >>"$CHALLENGE" &&
|
|
|
|
test_config_global credential.helper test-helper &&
|
|
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
|
|
|
|
expect_credential_query get <<-EOF &&
|
|
capability[]=authtype
|
|
capability[]=state
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
wwwauth[]=FooBar param1="value1" param2="value2"
|
|
wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
|
|
wwwauth[]=Basic realm="example.com"
|
|
EOF
|
|
|
|
expect_credential_query store <<-EOF
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
username=alice
|
|
password=secret-passwd
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'access using basic auth with wwwauth header mixed line-endings' '
|
|
test_when_finished "per_test_cleanup" &&
|
|
|
|
set_credential_reply get <<-EOF &&
|
|
username=alice
|
|
password=secret-passwd
|
|
EOF
|
|
|
|
# Basic base64(alice:secret-passwd)
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
|
|
id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
|
EOF
|
|
|
|
CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
|
|
|
|
# Note that leading and trailing whitespace is important to correctly
|
|
# simulate a continuation/folded header.
|
|
printf "id=1 status=200\n" >"$CHALLENGE" &&
|
|
printf "id=default response=WWW-Authenticate: FooBar param1=\"value1\"\r\n" >>"$CHALLENGE" &&
|
|
printf "id=default response= \r\n" >>"$CHALLENGE" &&
|
|
printf "id=default response=\tparam2=\"value2\"\r\n" >>"$CHALLENGE" &&
|
|
printf "id=default response=WWW-Authenticate: Basic realm=\"example.com\"" >>"$CHALLENGE" &&
|
|
|
|
test_config_global credential.helper test-helper &&
|
|
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
|
|
|
|
expect_credential_query get <<-EOF &&
|
|
capability[]=authtype
|
|
capability[]=state
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
wwwauth[]=FooBar param1="value1" param2="value2"
|
|
wwwauth[]=Basic realm="example.com"
|
|
EOF
|
|
|
|
expect_credential_query store <<-EOF
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
username=alice
|
|
password=secret-passwd
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'access using bearer auth' '
|
|
test_when_finished "per_test_cleanup" &&
|
|
|
|
set_credential_reply get <<-EOF &&
|
|
capability[]=authtype
|
|
authtype=Bearer
|
|
credential=YS1naXQtdG9rZW4=
|
|
EOF
|
|
|
|
# Basic base64(a-git-token)
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
|
|
id=1 creds=Bearer YS1naXQtdG9rZW4=
|
|
EOF
|
|
|
|
CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
|
|
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
|
|
id=1 status=200
|
|
id=default response=WWW-Authenticate: FooBar param1="value1" param2="value2"
|
|
id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
|
|
id=default response=WWW-Authenticate: Basic realm="example.com"
|
|
EOF
|
|
|
|
test_config_global credential.helper test-helper &&
|
|
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
|
|
|
|
expect_credential_query get <<-EOF &&
|
|
capability[]=authtype
|
|
capability[]=state
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
wwwauth[]=FooBar param1="value1" param2="value2"
|
|
wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
|
|
wwwauth[]=Basic realm="example.com"
|
|
EOF
|
|
|
|
expect_credential_query store <<-EOF
|
|
capability[]=authtype
|
|
authtype=Bearer
|
|
credential=YS1naXQtdG9rZW4=
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'access using bearer auth with invalid credentials' '
|
|
test_when_finished "per_test_cleanup" &&
|
|
|
|
set_credential_reply get <<-EOF &&
|
|
capability[]=authtype
|
|
authtype=Bearer
|
|
credential=incorrect-token
|
|
EOF
|
|
|
|
# Basic base64(a-git-token)
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
|
|
id=1 creds=Bearer YS1naXQtdG9rZW4=
|
|
EOF
|
|
|
|
CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
|
|
|
|
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
|
|
id=1 status=200
|
|
id=default response=WWW-Authenticate: FooBar param1="value1" param2="value2"
|
|
id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
|
|
id=default response=WWW-Authenticate: Basic realm="example.com"
|
|
EOF
|
|
|
|
test_config_global credential.helper test-helper &&
|
|
test_must_fail git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
|
|
|
|
expect_credential_query get <<-EOF &&
|
|
capability[]=authtype
|
|
capability[]=state
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
wwwauth[]=FooBar param1="value1" param2="value2"
|
|
wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
|
|
wwwauth[]=Basic realm="example.com"
|
|
EOF
|
|
|
|
expect_credential_query erase <<-EOF
|
|
capability[]=authtype
|
|
authtype=Bearer
|
|
credential=incorrect-token
|
|
protocol=http
|
|
host=$HTTPD_DEST
|
|
wwwauth[]=FooBar param1="value1" param2="value2"
|
|
wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
|
|
wwwauth[]=Basic realm="example.com"
|
|
EOF
|
|
'
|
|
|
|
test_done
|