Merge branch 'mc/credential-helper-www-authenticate'
Allow information carried on the WWW-AUthenticate header to be passed to the credential helpers. * mc/credential-helper-www-authenticate: credential: add WWW-Authenticate header to cred requests http: read HTTP WWW-Authenticate response headers t5563: add tests for basic and anoymous HTTP access
This commit is contained in:
commit
92c56da096
@ -113,7 +113,13 @@ separated by an `=` (equals) sign, followed by a newline.
|
|||||||
The key may contain any bytes except `=`, newline, or NUL. The value may
|
The key may contain any bytes except `=`, newline, or NUL. The value may
|
||||||
contain any bytes except newline or NUL.
|
contain any bytes except newline or NUL.
|
||||||
|
|
||||||
In both cases, all bytes are treated as-is (i.e., there is no quoting,
|
Attributes with keys that end with C-style array brackets `[]` can have
|
||||||
|
multiple values. Each instance of a multi-valued attribute forms an
|
||||||
|
ordered list of values - the order of the repeated attributes defines
|
||||||
|
the order of the values. An empty multi-valued attribute (`key[]=\n`)
|
||||||
|
acts to clear any previous entries and reset the list.
|
||||||
|
|
||||||
|
In all cases, all bytes are treated as-is (i.e., there is no quoting,
|
||||||
and one cannot transmit a value with newline or NUL in it). The list of
|
and one cannot transmit a value with newline or NUL in it). The list of
|
||||||
attributes is terminated by a blank line or end-of-file.
|
attributes is terminated by a blank line or end-of-file.
|
||||||
|
|
||||||
@ -166,6 +172,17 @@ empty string.
|
|||||||
Components which are missing from the URL (e.g., there is no
|
Components which are missing from the URL (e.g., there is no
|
||||||
username in the example above) will be left unset.
|
username in the example above) will be left unset.
|
||||||
|
|
||||||
|
`wwwauth[]`::
|
||||||
|
|
||||||
|
When an HTTP response is received by Git that includes one or more
|
||||||
|
'WWW-Authenticate' authentication headers, these will be passed by Git
|
||||||
|
to credential helpers.
|
||||||
|
+
|
||||||
|
Each 'WWW-Authenticate' header value is passed as a multi-valued
|
||||||
|
attribute 'wwwauth[]', where the order of the attributes is the same as
|
||||||
|
they appear in the HTTP response. This attribute is 'one-way' from Git
|
||||||
|
to pass additional information to credential helpers.
|
||||||
|
|
||||||
Unrecognised attributes are silently discarded.
|
Unrecognised attributes are silently discarded.
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
|
@ -23,6 +23,7 @@ void credential_clear(struct credential *c)
|
|||||||
free(c->username);
|
free(c->username);
|
||||||
free(c->password);
|
free(c->password);
|
||||||
string_list_clear(&c->helpers, 0);
|
string_list_clear(&c->helpers, 0);
|
||||||
|
strvec_clear(&c->wwwauth_headers);
|
||||||
|
|
||||||
credential_init(c);
|
credential_init(c);
|
||||||
}
|
}
|
||||||
@ -280,6 +281,8 @@ void credential_write(const struct credential *c, FILE *fp)
|
|||||||
credential_write_item(fp, "password_expiry_utc", s, 0);
|
credential_write_item(fp, "password_expiry_utc", s, 0);
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
|
for (size_t i = 0; i < c->wwwauth_headers.nr; i++)
|
||||||
|
credential_write_item(fp, "wwwauth[]", c->wwwauth_headers.v[i], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_credential_helper(struct credential *c,
|
static int run_credential_helper(struct credential *c,
|
||||||
|
16
credential.h
16
credential.h
@ -2,6 +2,7 @@
|
|||||||
#define CREDENTIAL_H
|
#define CREDENTIAL_H
|
||||||
|
|
||||||
#include "string-list.h"
|
#include "string-list.h"
|
||||||
|
#include "strvec.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The credentials API provides an abstracted way of gathering username and
|
* The credentials API provides an abstracted way of gathering username and
|
||||||
@ -115,6 +116,20 @@ struct credential {
|
|||||||
*/
|
*/
|
||||||
struct string_list helpers;
|
struct string_list helpers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A `strvec` of WWW-Authenticate header values. Each string
|
||||||
|
* is the value of a WWW-Authenticate header in an HTTP response,
|
||||||
|
* in the order they were received in the response.
|
||||||
|
*/
|
||||||
|
struct strvec wwwauth_headers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal use only. Keeps track of if we previously matched against a
|
||||||
|
* WWW-Authenticate header line in order to re-fold future continuation
|
||||||
|
* lines into one value.
|
||||||
|
*/
|
||||||
|
unsigned header_is_last_match:1;
|
||||||
|
|
||||||
unsigned approved:1,
|
unsigned approved:1,
|
||||||
configured:1,
|
configured:1,
|
||||||
quit:1,
|
quit:1,
|
||||||
@ -132,6 +147,7 @@ struct credential {
|
|||||||
#define CREDENTIAL_INIT { \
|
#define CREDENTIAL_INIT { \
|
||||||
.helpers = STRING_LIST_INIT_DUP, \
|
.helpers = STRING_LIST_INIT_DUP, \
|
||||||
.password_expiry_utc = TIME_MAX, \
|
.password_expiry_utc = TIME_MAX, \
|
||||||
|
.wwwauth_headers = STRVEC_INIT, \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize a credential structure, setting all fields to empty. */
|
/* Initialize a credential structure, setting all fields to empty. */
|
||||||
|
@ -1288,6 +1288,25 @@ static inline int skip_iprefix(const char *str, const char *prefix,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like skip_prefix_mem, but compare case-insensitively. Note that the
|
||||||
|
* comparison is done via tolower(), so it is strictly ASCII (no multi-byte
|
||||||
|
* characters or locale-specific conversions).
|
||||||
|
*/
|
||||||
|
static inline int skip_iprefix_mem(const char *buf, size_t len,
|
||||||
|
const char *prefix,
|
||||||
|
const char **out, size_t *outlen)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
if (!*prefix) {
|
||||||
|
*out = buf;
|
||||||
|
*outlen = len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} while (len-- > 0 && tolower(*buf++) == tolower(*prefix++));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int strtoul_ui(char const *s, int base, unsigned int *result)
|
static inline int strtoul_ui(char const *s, int base, unsigned int *result)
|
||||||
{
|
{
|
||||||
unsigned long ul;
|
unsigned long ul;
|
||||||
|
111
http.c
111
http.c
@ -182,6 +182,115 @@ size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
|
|||||||
return nmemb;
|
return nmemb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A folded header continuation line starts with any number of spaces or
|
||||||
|
* horizontal tab characters (SP or HTAB) as per RFC 7230 section 3.2.
|
||||||
|
* It is not a continuation line if the line starts with any other character.
|
||||||
|
*/
|
||||||
|
static inline int is_hdr_continuation(const char *ptr, const size_t size)
|
||||||
|
{
|
||||||
|
return size && (*ptr == ' ' || *ptr == '\t');
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t fwrite_wwwauth(char *ptr, size_t eltsize, size_t nmemb, void *p)
|
||||||
|
{
|
||||||
|
size_t size = eltsize * nmemb;
|
||||||
|
struct strvec *values = &http_auth.wwwauth_headers;
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
const char *val;
|
||||||
|
size_t val_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Header lines may not come NULL-terminated from libcurl so we must
|
||||||
|
* limit all scans to the maximum length of the header line, or leverage
|
||||||
|
* strbufs for all operations.
|
||||||
|
*
|
||||||
|
* In addition, it is possible that header values can be split over
|
||||||
|
* multiple lines as per RFC 7230. 'Line folding' has been deprecated
|
||||||
|
* but older servers may still emit them. A continuation header field
|
||||||
|
* value is identified as starting with a space or horizontal tab.
|
||||||
|
*
|
||||||
|
* The formal definition of a header field as given in RFC 7230 is:
|
||||||
|
*
|
||||||
|
* header-field = field-name ":" OWS field-value OWS
|
||||||
|
*
|
||||||
|
* field-name = token
|
||||||
|
* field-value = *( field-content / obs-fold )
|
||||||
|
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||||||
|
* field-vchar = VCHAR / obs-text
|
||||||
|
*
|
||||||
|
* obs-fold = CRLF 1*( SP / HTAB )
|
||||||
|
* ; obsolete line folding
|
||||||
|
* ; see Section 3.2.4
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Start of a new WWW-Authenticate header */
|
||||||
|
if (skip_iprefix_mem(ptr, size, "www-authenticate:", &val, &val_len)) {
|
||||||
|
strbuf_add(&buf, val, val_len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Strip the CRLF that should be present at the end of each
|
||||||
|
* field as well as any trailing or leading whitespace from the
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
strbuf_trim(&buf);
|
||||||
|
|
||||||
|
strvec_push(values, buf.buf);
|
||||||
|
http_auth.header_is_last_match = 1;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This line could be a continuation of the previously matched header
|
||||||
|
* field. If this is the case then we should append this value to the
|
||||||
|
* end of the previously consumed value.
|
||||||
|
*/
|
||||||
|
if (http_auth.header_is_last_match && is_hdr_continuation(ptr, size)) {
|
||||||
|
/*
|
||||||
|
* Trim the CRLF and any leading or trailing from this line.
|
||||||
|
*/
|
||||||
|
strbuf_add(&buf, ptr, size);
|
||||||
|
strbuf_trim(&buf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point we should always have at least one existing
|
||||||
|
* value, even if it is empty. Do not bother appending the new
|
||||||
|
* value if this continuation header is itself empty.
|
||||||
|
*/
|
||||||
|
if (!values->nr) {
|
||||||
|
BUG("should have at least one existing header value");
|
||||||
|
} else if (buf.len) {
|
||||||
|
char *prev = xstrdup(values->v[values->nr - 1]);
|
||||||
|
|
||||||
|
/* Join two non-empty values with a single space. */
|
||||||
|
const char *const sp = *prev ? " " : "";
|
||||||
|
|
||||||
|
strvec_pop(values);
|
||||||
|
strvec_pushf(values, "%s%s%s", prev, sp, buf.buf);
|
||||||
|
free(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not a continuation of a previously matched auth header line. */
|
||||||
|
http_auth.header_is_last_match = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is a HTTP status line and not a header field, this signals
|
||||||
|
* a different HTTP response. libcurl writes all the output of all
|
||||||
|
* response headers of all responses, including redirects.
|
||||||
|
* We only care about the last HTTP request response's headers so clear
|
||||||
|
* the existing array.
|
||||||
|
*/
|
||||||
|
if (skip_iprefix_mem(ptr, size, "http/", &val, &val_len))
|
||||||
|
strvec_clear(values);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
strbuf_release(&buf);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf)
|
size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf)
|
||||||
{
|
{
|
||||||
return nmemb;
|
return nmemb;
|
||||||
@ -1896,6 +2005,8 @@ static int http_request(const char *url,
|
|||||||
fwrite_buffer);
|
fwrite_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(slot->curl, CURLOPT_HEADERFUNCTION, fwrite_wwwauth);
|
||||||
|
|
||||||
accept_language = http_get_accept_language_header();
|
accept_language = http_get_accept_language_header();
|
||||||
|
|
||||||
if (accept_language)
|
if (accept_language)
|
||||||
|
@ -142,6 +142,7 @@ prepare_httpd() {
|
|||||||
install_script error-smart-http.sh
|
install_script error-smart-http.sh
|
||||||
install_script error.sh
|
install_script error.sh
|
||||||
install_script apply-one-time-perl.sh
|
install_script apply-one-time-perl.sh
|
||||||
|
install_script nph-custom-auth.sh
|
||||||
|
|
||||||
ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
|
ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
|
||||||
|
|
||||||
|
@ -141,6 +141,11 @@ Alias /auth/dumb/ www/auth/dumb/
|
|||||||
SetEnv GIT_HTTP_EXPORT_ALL
|
SetEnv GIT_HTTP_EXPORT_ALL
|
||||||
SetEnv GIT_PROTOCOL
|
SetEnv GIT_PROTOCOL
|
||||||
</LocationMatch>
|
</LocationMatch>
|
||||||
|
<LocationMatch /custom_auth/>
|
||||||
|
SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
|
||||||
|
SetEnv GIT_HTTP_EXPORT_ALL
|
||||||
|
CGIPassAuth on
|
||||||
|
</LocationMatch>
|
||||||
ScriptAlias /smart/incomplete_length/git-upload-pack incomplete-length-upload-pack-v2-http.sh/
|
ScriptAlias /smart/incomplete_length/git-upload-pack incomplete-length-upload-pack-v2-http.sh/
|
||||||
ScriptAlias /smart/incomplete_body/git-upload-pack incomplete-body-upload-pack-v2-http.sh/
|
ScriptAlias /smart/incomplete_body/git-upload-pack incomplete-body-upload-pack-v2-http.sh/
|
||||||
ScriptAlias /smart/no_report/git-receive-pack error-no-report.sh/
|
ScriptAlias /smart/no_report/git-receive-pack error-no-report.sh/
|
||||||
@ -150,6 +155,7 @@ ScriptAlias /broken_smart/ broken-smart-http.sh/
|
|||||||
ScriptAlias /error_smart/ error-smart-http.sh/
|
ScriptAlias /error_smart/ error-smart-http.sh/
|
||||||
ScriptAlias /error/ error.sh/
|
ScriptAlias /error/ error.sh/
|
||||||
ScriptAliasMatch /one_time_perl/(.*) apply-one-time-perl.sh/$1
|
ScriptAliasMatch /one_time_perl/(.*) apply-one-time-perl.sh/$1
|
||||||
|
ScriptAliasMatch /custom_auth/(.*) nph-custom-auth.sh/$1
|
||||||
<Directory ${GIT_EXEC_PATH}>
|
<Directory ${GIT_EXEC_PATH}>
|
||||||
Options FollowSymlinks
|
Options FollowSymlinks
|
||||||
</Directory>
|
</Directory>
|
||||||
|
39
t/lib-httpd/nph-custom-auth.sh
Normal file
39
t/lib-httpd/nph-custom-auth.sh
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
VALID_CREDS_FILE=custom-auth.valid
|
||||||
|
CHALLENGE_FILE=custom-auth.challenge
|
||||||
|
|
||||||
|
#
|
||||||
|
# If $VALID_CREDS_FILE exists in $HTTPD_ROOT_PATH, consider each line as a valid
|
||||||
|
# credential for the current request. Each line in the file is considered a
|
||||||
|
# valid HTTP Authorization header value. For example:
|
||||||
|
#
|
||||||
|
# Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
||||||
|
#
|
||||||
|
# If $CHALLENGE_FILE exists in $HTTPD_ROOT_PATH, output the contents as headers
|
||||||
|
# in a 401 response if no valid authentication credentials were included in the
|
||||||
|
# request. For example:
|
||||||
|
#
|
||||||
|
# WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
|
||||||
|
# WWW-Authenticate: Basic realm="example.com"
|
||||||
|
#
|
||||||
|
|
||||||
|
if test -n "$HTTP_AUTHORIZATION" && \
|
||||||
|
grep -Fqsx "${HTTP_AUTHORIZATION}" "$VALID_CREDS_FILE"
|
||||||
|
then
|
||||||
|
# Note that although git-http-backend returns a status line, it
|
||||||
|
# does so using a CGI 'Status' header. Because this script is an
|
||||||
|
# No Parsed Headers (NPH) script, we must return a real HTTP
|
||||||
|
# status line.
|
||||||
|
# This is only a test script, so we don't bother to check for
|
||||||
|
# the actual status from git-http-backend and always return 200.
|
||||||
|
echo 'HTTP/1.1 200 OK'
|
||||||
|
exec "$GIT_EXEC_PATH"/git-http-backend
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo 'HTTP/1.1 401 Authorization Required'
|
||||||
|
if test -f "$CHALLENGE_FILE"
|
||||||
|
then
|
||||||
|
cat "$CHALLENGE_FILE"
|
||||||
|
fi
|
||||||
|
echo
|
325
t/t5563-simple-http-auth.sh
Executable file
325
t/t5563-simple-http-auth.sh
Executable file
@ -0,0 +1,325 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='test http auth header and credential helper interop'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
. "$TEST_DIRECTORY"/lib-httpd.sh
|
||||||
|
|
||||||
|
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 &&
|
||||||
|
Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
|
||||||
|
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 &&
|
||||||
|
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 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 &&
|
||||||
|
Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
|
||||||
|
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 &&
|
||||||
|
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 &&
|
||||||
|
Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
|
||||||
|
WWW-Authenticate: FooBar param1="value1" param2="value2"
|
||||||
|
WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
|
||||||
|
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 &&
|
||||||
|
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 &&
|
||||||
|
Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
|
||||||
|
www-authenticate: foobar param1="value1" param2="value2"
|
||||||
|
WWW-AUTHENTICATE: BEARER authorize_uri="id.example.com" p=1 q=0
|
||||||
|
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 &&
|
||||||
|
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 &&
|
||||||
|
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 &&
|
||||||
|
WWW-Authenticate: FooBar param1="value1"
|
||||||
|
param2="value2"
|
||||||
|
WWW-Authenticate: Bearer authorize_uri="id.example.com"
|
||||||
|
p=1
|
||||||
|
q=0
|
||||||
|
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 &&
|
||||||
|
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 &&
|
||||||
|
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 "">$CHALLENGE &&
|
||||||
|
printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >$CHALLENGE &&
|
||||||
|
printf " \r\n" >>$CHALLENGE &&
|
||||||
|
printf " param2=\"value2\"\r\n" >>$CHALLENGE &&
|
||||||
|
printf "WWW-Authenticate: Bearer authorize_uri=\"id.example.com\"\r\n" >>$CHALLENGE &&
|
||||||
|
printf " p=1\r\n" >>$CHALLENGE &&
|
||||||
|
printf " \r\n" >>$CHALLENGE &&
|
||||||
|
printf " q=0\r\n" >>$CHALLENGE &&
|
||||||
|
printf "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 &&
|
||||||
|
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 &&
|
||||||
|
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 "">$CHALLENGE &&
|
||||||
|
printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >$CHALLENGE &&
|
||||||
|
printf " \r\n" >>$CHALLENGE &&
|
||||||
|
printf "\tparam2=\"value2\"\r\n" >>$CHALLENGE &&
|
||||||
|
printf "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 &&
|
||||||
|
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_done
|
Loading…
Reference in New Issue
Block a user