Message ID | 09164f77d56e8efd1450091cf1b12af2bc6cf2f5.1674252531.git.gitgitgadget@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Commit | 026012ce26e8fac0a1a506546f0c6542ea8178c2 |
Headers | show |
Series | Enhance credential helper protocol to include auth headers | expand |
On Fri, Jan 20, 2023 at 10:08:50PM +0000, Matthew John Cheetham via GitGitGadget wrote: > From: Matthew John Cheetham <mjcheetham@outlook.com> > > Add the value of the WWW-Authenticate response header to credential > requests. Credential helpers that understand and support HTTP > authentication and authorization can use this standard header (RFC 2616 > Section 14.47 [1]) to generate valid credentials. > > WWW-Authenticate headers can contain information pertaining to the > authority, authentication mechanism, or extra parameters/scopes that are > required. I'm definitely on board with sending these to the helpers. It does feel a bit weird that we don't parse them at all, and just foist that on the helpers. If I understand the RFC correctly, you can have multiple challenges per header, but also multiple headers. So: WWW-Authenticate: Basic realm="foo", OtherAuth realm="bar" WWW-Authenticate: YetAnotherScheme some-token could be normalized as: www-auth-challenge=Basic realm="foo" www-auth-challenge=OtherAuth realm="bar" www-auth-challenge=YetAnotherScheme some-token which saves each helper from having to do the same work. Likewise, we can do a _little_ more parsing to get: www-auth-basic=realm="foo" www-auth-otherauth=realm="bar" www-auth-yetanotherscheme=some-token I don't think we can go beyond there, though, without understanding the syntax of individual schemes. Which is a shame, as one of the goals of the credential format was to let the helpers do as little as possible (so they can't get it wrong!). But helpers are stuck doing things like handling backslashed double-quotes, soaking up extra whitespace, etc. I'm not really sure what we expect to see in the real world. I guess for your purposes, you are working on an already-big helper that is happy to just get the raw values and process them according to the rfc. I'm just wondering if there are use cases where somebody might want to do something with this header, but in a quick shell script kind of way. For example, my credential config is still: [credential "https://github.com"] username = peff helper = "!f() { test $1 = get && echo password=$(pass ...); }; f" That's an extreme example, but I'm wondering if there's _anything_ useful somebody would want to do in a similar quick-and-dirty kind of way. For example, deciding which cred to use based on basic realm, like: realm=foo while read line; do case "$line" in www-auth-basic=) value=${line#*=} # oops, we're just assuming it's realm= here, and we're # not handling quotes at all. I think it could technically be # realm=foo or realm="foo" realm=${value#realm=} ;; esac done echo password=$(pass "pats-by-realm/$realm") which could be made a lot easier if we did more parsing (e.g., www-auth-basic-realm or something). I dunno. Maybe that is just opening up a can of worms, as we're stuffing structured data into a linearized key-value list. The nice thing about your proposal is that Git does not even have to know anything about these schemes; it's all the problem of the helper. My biggest fear is just that we'll want to shift that later, and we'll be stuck with this microformat forever. > The current I/O format for credential helpers only allows for unique > names for properties/attributes, so in order to transmit multiple header > values (with a specific order) we introduce a new convention whereby a > C-style array syntax is used in the property name to denote multiple > ordered values for the same property. I don't know if this is strictly necessary. The semantics of duplicate keys are not really defined anywhere, and just because the implementations of current readers happen to replace duplicates for the current set of keys doesn't mean everything has to. So you could just define "wwwauth" to behave differently. But I don't mind having a syntactic marker to indicate this new type. If you're at all convinced by what I said above, then we also might be able to get away with having unique keys anyway. > Documentation/git-credential.txt | 19 ++- > credential.c | 11 ++ > t/lib-credential-helper.sh | 27 ++++ > t/t5556-http-auth.sh | 242 +++++++++++++++++++++++++++++++ > 4 files changed, 298 insertions(+), 1 deletion(-) > create mode 100644 t/lib-credential-helper.sh The patch itself looks pretty reasonable to me. One small thing I noticed: > + git -c "credential.helper=!\"$CREDENTIAL_HELPER\"" ls-remote $ORIGIN_URL && As you undoubtedly figured out, the helper path is fed to the shell, so spaces in the trash directory are a problem. You've solved it here by adding a layer of double quotes, which handles spaces. But you'd run into problems if the absolute path that somebody is using for the test suite has a backslash or a double quote in it. I don't know how careful we want to be here (or how careful we already are[1]), but one simple-ish solution is: export CREDENTIAL_HELPER git -c "credential.helper=!\"\$CREDENTIAL_HELPER\"" ... I.e., letting the inner shell expand the variable itself. Another option is to put the helper into $TRASH_DIRECTORY/bin and add that to the $PATH. I also wondered if it was worth having setup_credential_helper() just stick it in $TRASH_DIRECTORY/.gitconfig so that individual tests don't have to keep doing that ugly "-c" invocation. Or if you really want to have each test enable it, perhaps have set_credential_reply() turn it on via test_config (which will auto-remove it at the end of the test). -Peff [1] Curious, I tried cloning git into this directory: mkdir '/tmp/foo/"horrible \"path\"' and we do indeed already fail. The first breakage I saw was recent, but going further back, it looks like bin-wrappers don't correctly handle this case anyway. So maybe that's evidence that nobody would do something so ridiculous in practice.
On 2023-01-26 03:25, Jeff King wrote: > On Fri, Jan 20, 2023 at 10:08:50PM +0000, Matthew John Cheetham via GitGitGadget wrote: > >> From: Matthew John Cheetham <mjcheetham@outlook.com> >> >> Add the value of the WWW-Authenticate response header to credential >> requests. Credential helpers that understand and support HTTP >> authentication and authorization can use this standard header (RFC 2616 >> Section 14.47 [1]) to generate valid credentials. >> >> WWW-Authenticate headers can contain information pertaining to the >> authority, authentication mechanism, or extra parameters/scopes that are >> required. > > I'm definitely on board with sending these to the helpers. It does feel > a bit weird that we don't parse them at all, and just foist that on the > helpers. > > If I understand the RFC correctly, you can have multiple challenges per > header, but also multiple headers. So: > > WWW-Authenticate: Basic realm="foo", OtherAuth realm="bar" > WWW-Authenticate: YetAnotherScheme some-token That is correct. It would be strange that server would respond with a mix of styles, but I guess it's not forbidden. > could be normalized as: > > www-auth-challenge=Basic realm="foo" > www-auth-challenge=OtherAuth realm="bar" > www-auth-challenge=YetAnotherScheme some-token > > which saves each helper from having to do the same work. Likewise, we > can do a _little_ more parsing to get: > > www-auth-basic=realm="foo" > www-auth-otherauth=realm="bar" > www-auth-yetanotherscheme=some-token > > I don't think we can go beyond there, though, without understanding the > syntax of individual schemes. Which is a shame, as one of the goals of > the credential format was to let the helpers do as little as possible > (so they can't get it wrong!). But helpers are stuck doing things like > handling backslashed double-quotes, soaking up extra whitespace, etc. This key format wouldn't make it obviously easier for simple helpers to understand. Now they no longer have well-known keys but a key prefix. My overall goal here is to have Git know less about auth, so it treats all values as totally opaque. The only logic added is around reconstructing folded headers, which is just HTTP and not auth specific. > I'm not really sure what we expect to see in the real world. I guess for > your purposes, you are working on an already-big helper that is happy to > just get the raw values and process them according to the rfc. I'm just > wondering if there are use cases where somebody might want to do > something with this header, but in a quick shell script kind of way. For > example, my credential config is still: > > [credential "https://github.com"] > username = peff > helper = "!f() { test $1 = get && echo password=$(pass ...); }; f" > > That's an extreme example, but I'm wondering if there's _anything_ > useful somebody would want to do in a similar quick-and-dirty kind of > way. For example, deciding which cred to use based on basic realm, like: > > realm=foo > while read line; do > case "$line" in > www-auth-basic=) > value=${line#*=} > # oops, we're just assuming it's realm= here, and we're > # not handling quotes at all. I think it could technically be > # realm=foo or realm="foo" > realm=${value#realm=} > ;; > esac > done > echo password=$(pass "pats-by-realm/$realm") > > which could be made a lot easier if we did more parsing (e.g., > www-auth-basic-realm or something). I dunno. Maybe that is just opening > up a can of worms, as we're stuffing structured data into a linearized > key-value list. The nice thing about your proposal is that Git does not > even have to know anything about these schemes; it's all the problem of > the helper. My biggest fear is just that we'll want to shift that later, > and we'll be stuck with this microformat forever. I'm not sure there's such a continuous scale between simple and 'complex' helpers that would mean there'd be a simple shell script generating OAuth or DPoP credentials instead of a helper written in a higher-level language where parsing the headers is one of the simpler challenges faced. >> The current I/O format for credential helpers only allows for unique >> names for properties/attributes, so in order to transmit multiple header >> values (with a specific order) we introduce a new convention whereby a >> C-style array syntax is used in the property name to denote multiple >> ordered values for the same property. > > I don't know if this is strictly necessary. The semantics of duplicate > keys are not really defined anywhere, and just because the > implementations of current readers happen to replace duplicates for the > current set of keys doesn't mean everything has to. So you could just > define "wwwauth" to behave differently. But I don't mind having a > syntactic marker to indicate this new type. I had considered another model whereby we forgo the key=value line model, and hide another format behind the 'final' terminating new-line. However I thought this would be even more distuptive. > If you're at all convinced by what I said above, then we also might be > able to get away with having unique keys anyway. > >> Documentation/git-credential.txt | 19 ++- >> credential.c | 11 ++ >> t/lib-credential-helper.sh | 27 ++++ >> t/t5556-http-auth.sh | 242 +++++++++++++++++++++++++++++++ >> 4 files changed, 298 insertions(+), 1 deletion(-) >> create mode 100644 t/lib-credential-helper.sh > > The patch itself looks pretty reasonable to me. > > One small thing I noticed: > >> + git -c "credential.helper=!\"$CREDENTIAL_HELPER\"" ls-remote $ORIGIN_URL && > > As you undoubtedly figured out, the helper path is fed to the shell, so > spaces in the trash directory are a problem. You've solved it here by > adding a layer of double quotes, which handles spaces. But you'd run > into problems if the absolute path that somebody is using for the test > suite has a backslash or a double quote in it. > > I don't know how careful we want to be here (or how careful we already > are[1]), but one simple-ish solution is: > > export CREDENTIAL_HELPER > git -c "credential.helper=!\"\$CREDENTIAL_HELPER\"" ... > > I.e., letting the inner shell expand the variable itself. Another option > is to put the helper into $TRASH_DIRECTORY/bin and add that to the > $PATH. > > I also wondered if it was worth having setup_credential_helper() just > stick it in $TRASH_DIRECTORY/.gitconfig so that individual tests don't > have to keep doing that ugly "-c" invocation. Or if you really want to > have each test enable it, perhaps have set_credential_reply() turn it on > via test_config (which will auto-remove it at the end of the test). Good ideas! I shall try those. > -Peff > > [1] Curious, I tried cloning git into this directory: > > mkdir '/tmp/foo/"horrible \"path\"' > > and we do indeed already fail. The first breakage I saw was recent, > but going further back, it looks like bin-wrappers don't correctly > handle this case anyway. So maybe that's evidence that nobody would > do something so ridiculous in practice.
On Mon, Feb 06, 2023 at 11:18:03AM -0800, Matthew John Cheetham wrote: > > could be normalized as: > > > > www-auth-challenge=Basic realm="foo" > > www-auth-challenge=OtherAuth realm="bar" > > www-auth-challenge=YetAnotherScheme some-token > > > > which saves each helper from having to do the same work. Likewise, we > > can do a _little_ more parsing to get: > > > > www-auth-basic=realm="foo" > > www-auth-otherauth=realm="bar" > > www-auth-yetanotherscheme=some-token > > > > I don't think we can go beyond there, though, without understanding the > > syntax of individual schemes. Which is a shame, as one of the goals of > > the credential format was to let the helpers do as little as possible > > (so they can't get it wrong!). But helpers are stuck doing things like > > handling backslashed double-quotes, soaking up extra whitespace, etc. > > This key format wouldn't make it obviously easier for simple helpers to > understand. Now they no longer have well-known keys but a key prefix. Yes, though I don't think that's particularly complicated to parse. Either way we're just flattening a tuple of (a, b, c) from "a=b c" to "a-b=c". The value is in normalizing the syntax, so that helpers don't have to deal with both "a=b c d e" and ("a=b c", "a=d e") themselves. Another way to do that normalization would be to have Git convert: WWW-Authenticate: Basic realm="foo" OtherAuth realm="bar" into: WWW-Authenticate: Basic realm="foo" WWW-Authenticate: OtherAuth realm="bar" which then becomes (at the credential level): www-auth[]=Basic realm="foo" www-auth[]=OtherAuth realm="bar" And likewise to normalize whitespace, etc, so each individual helper doesn't have to (or risk getting confused/exploited). That said... > My overall goal here is to have Git know less about auth, so it treats > all values as totally opaque. The only logic added is around reconstructing > folded headers, which is just HTTP and not auth specific. Yeah, in general I agree with the notion that Git is mostly just passing around opaque tokens. We do have to understand some syntax (like folding!) at the HTTP level, so I think some syntactic normalization / simplification is reasonable. BUT. I think you are right that embedding it into the schema of the helper protocol is probably bad. If the point is that the two forms of my Basic / OtherAuth example are semantically equivalent, then we can always decide later to convert between one and the other as a favor to helpers. Whereas baking it into the schema is a promise for Git to always parse and understand the headers. So let me retract my suggestion, and we can leave "maybe normalize headers to save helpers some work" as a possible topic for later (if indeed it ever even becomes a problem in practice). > > realm=foo > > while read line; do > > case "$line" in > > www-auth-basic=) > > value=${line#*=} > > # oops, we're just assuming it's realm= here, and we're > > # not handling quotes at all. I think it could technically be > > # realm=foo or realm="foo" > > realm=${value#realm=} > > ;; > > esac > > done > > echo password=$(pass "pats-by-realm/$realm") > > > > which could be made a lot easier if we did more parsing (e.g., > > www-auth-basic-realm or something). I dunno. Maybe that is just opening > > up a can of worms, as we're stuffing structured data into a linearized > > key-value list. The nice thing about your proposal is that Git does not > > even have to know anything about these schemes; it's all the problem of > > the helper. My biggest fear is just that we'll want to shift that later, > > and we'll be stuck with this microformat forever. > > I'm not sure there's such a continuous scale between simple and 'complex' > helpers that would mean there'd be a simple shell script generating > OAuth or DPoP credentials instead of a helper written in a higher-level > language where parsing the headers is one of the simpler challenges faced. For the most part, yeah. I tried to form the above example as something that was really just relying on "basic", but taking in more information / context than we currently provide (and that your patch would provide). I admit it's a stretch, though. Are there any servers which actually use a Basic realm to distinguish between two credential's you'd want to provide? I don't think I've seen one. (Not to mention that people scripting helpers like this is probably pretty rare; I do, but you can probably consider me a special case. And if things got more complicated I'd just turn to Perl anyway. ;) ). > I had considered another model whereby we forgo the key=value line model, > and hide another format behind the 'final' terminating new-line. However > I thought this would be even more distuptive. Yeah, if we can shoe-horn this into the existing key/value model, that's much better. The original intent with the final newline is that you could read multiple credentials in a list, though in the end I don't recall that we ever used that feature anyway. -Peff
diff --git a/Documentation/git-credential.txt b/Documentation/git-credential.txt index ac2818b9f66..50759153ef1 100644 --- a/Documentation/git-credential.txt +++ b/Documentation/git-credential.txt @@ -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 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 attributes is terminated by a blank line or end-of-file. @@ -160,6 +166,17 @@ empty string. Components which are missing from the URL (e.g., there is no 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. GIT diff --git a/credential.c b/credential.c index 897b4679333..9f39ebc3c7e 100644 --- a/credential.c +++ b/credential.c @@ -263,6 +263,16 @@ static void credential_write_item(FILE *fp, const char *key, const char *value, fprintf(fp, "%s=%s\n", key, value); } +static void credential_write_strvec(FILE *fp, const char *key, + const struct strvec *vec) +{ + char *full_key = xstrfmt("%s[]", key); + for (size_t i = 0; i < vec->nr; i++) { + credential_write_item(fp, full_key, vec->v[i], 0); + } + free(full_key); +} + void credential_write(const struct credential *c, FILE *fp) { credential_write_item(fp, "protocol", c->protocol, 1); @@ -270,6 +280,7 @@ void credential_write(const struct credential *c, FILE *fp) credential_write_item(fp, "path", c->path, 0); credential_write_item(fp, "username", c->username, 0); credential_write_item(fp, "password", c->password, 0); + credential_write_strvec(fp, "wwwauth", &c->wwwauth_headers); } static int run_credential_helper(struct credential *c, diff --git a/t/lib-credential-helper.sh b/t/lib-credential-helper.sh new file mode 100644 index 00000000000..8b0e4414234 --- /dev/null +++ b/t/lib-credential-helper.sh @@ -0,0 +1,27 @@ +setup_credential_helper() { + test_expect_success 'setup credential helper' ' + CREDENTIAL_HELPER="$TRASH_DIRECTORY/credential-helper.sh" && + export CREDENTIAL_HELPER && + echo $CREDENTIAL_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" +} diff --git a/t/t5556-http-auth.sh b/t/t5556-http-auth.sh index 2c16c8f72a5..93b7c178da6 100755 --- a/t/t5556-http-auth.sh +++ b/t/t5556-http-auth.sh @@ -4,6 +4,7 @@ test_description='test http auth header and credential helper interop' TEST_NO_CREATE_REPO=1 . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-credential-helper.sh test_set_port GIT_TEST_HTTP_PROTOCOL_PORT @@ -33,6 +34,8 @@ test_expect_success 'setup repos' ' git -C "$REPO_DIR" branch -M main ' +setup_credential_helper + run_http_server_worker() { ( cd "$REPO_DIR" @@ -101,6 +104,7 @@ per_test_cleanup () { stop_http_server && rm -f OUT.* && rm -f IN.* && + rm -f *.cred && rm -f auth.config } @@ -218,4 +222,242 @@ test_expect_success 'http auth anonymous no challenge' ' git ls-remote $ORIGIN_URL ' +test_expect_success 'http auth www-auth headers to credential helper basic valid' ' + test_when_finished "per_test_cleanup" && + # base64("alice:secret-passwd") + USERPASS64=YWxpY2U6c2VjcmV0LXBhc3N3ZA== && + export USERPASS64 && + + cat >auth.config <<-EOF && + [auth] + challenge = basic:realm=\"example.com\" + token = basic:$USERPASS64 + EOF + + start_http_server --auth-config="$TRASH_DIRECTORY/auth.config" && + + set_credential_reply get <<-EOF && + protocol=http + host=$HOST_PORT + username=alice + password=secret-passwd + EOF + + git -c "credential.helper=!\"$CREDENTIAL_HELPER\"" ls-remote $ORIGIN_URL && + + expect_credential_query get <<-EOF && + protocol=http + host=$HOST_PORT + wwwauth[]=basic realm="example.com" + EOF + + expect_credential_query store <<-EOF + protocol=http + host=$HOST_PORT + username=alice + password=secret-passwd + EOF +' + +test_expect_success 'http auth www-auth headers to credential helper ignore case valid' ' + test_when_finished "per_test_cleanup" && + # base64("alice:secret-passwd") + USERPASS64=YWxpY2U6c2VjcmV0LXBhc3N3ZA== && + export USERPASS64 && + + cat >auth.config <<-EOF && + [auth] + challenge = basic:realm=\"example.com\" + token = basic:$USERPASS64 + extraHeader = wWw-aUtHeNtIcAtE: bEaRer auThoRiTy=\"id.example.com\" + EOF + + start_http_server --auth-config="$TRASH_DIRECTORY/auth.config" && + + set_credential_reply get <<-EOF && + protocol=http + host=$HOST_PORT + username=alice + password=secret-passwd + EOF + + git -c "credential.helper=!\"$CREDENTIAL_HELPER\"" ls-remote $ORIGIN_URL && + + expect_credential_query get <<-EOF && + protocol=http + host=$HOST_PORT + wwwauth[]=basic realm="example.com" + wwwauth[]=bEaRer auThoRiTy="id.example.com" + EOF + + expect_credential_query store <<-EOF + protocol=http + host=$HOST_PORT + username=alice + password=secret-passwd + EOF +' + +test_expect_success 'http auth www-auth headers to credential helper continuation hdr' ' + test_when_finished "per_test_cleanup" && + # base64("alice:secret-passwd") + USERPASS64=YWxpY2U6c2VjcmV0LXBhc3N3ZA== && + export USERPASS64 && + + cat >auth.config <<-EOF && + [auth] + challenge = "bearer:authority=\"id.example.com\"\\n q=1\\n \\t p=0" + challenge = basic:realm=\"example.com\" + token = basic:$USERPASS64 + EOF + + start_http_server --auth-config="$TRASH_DIRECTORY/auth.config" && + + set_credential_reply get <<-EOF && + protocol=http + host=$HOST_PORT + username=alice + password=secret-passwd + EOF + + git -c "credential.helper=!\"$CREDENTIAL_HELPER\"" ls-remote $ORIGIN_URL && + + expect_credential_query get <<-EOF && + protocol=http + host=$HOST_PORT + wwwauth[]=bearer authority="id.example.com" q=1 p=0 + wwwauth[]=basic realm="example.com" + EOF + + expect_credential_query store <<-EOF + protocol=http + host=$HOST_PORT + username=alice + password=secret-passwd + EOF +' + +test_expect_success 'http auth www-auth headers to credential helper empty continuation hdrs' ' + test_when_finished "per_test_cleanup" && + # base64("alice:secret-passwd") + USERPASS64=YWxpY2U6c2VjcmV0LXBhc3N3ZA== && + export USERPASS64 && + + cat >auth.config <<-EOF && + [auth] + challenge = basic:realm=\"example.com\" + token = basic:$USERPASS64 + extraheader = "WWW-Authenticate:" + extraheader = " " + extraheader = " bearer authority=\"id.example.com\"" + EOF + + start_http_server --auth-config="$TRASH_DIRECTORY/auth.config" && + + set_credential_reply get <<-EOF && + protocol=http + host=$HOST_PORT + username=alice + password=secret-passwd + EOF + + git -c "credential.helper=!\"$CREDENTIAL_HELPER\"" ls-remote $ORIGIN_URL && + + expect_credential_query get <<-EOF && + protocol=http + host=$HOST_PORT + wwwauth[]=basic realm="example.com" + wwwauth[]=bearer authority="id.example.com" + EOF + + expect_credential_query store <<-EOF + protocol=http + host=$HOST_PORT + username=alice + password=secret-passwd + EOF +' + +test_expect_success 'http auth www-auth headers to credential helper custom schemes' ' + test_when_finished "per_test_cleanup" && + # base64("alice:secret-passwd") + USERPASS64=YWxpY2U6c2VjcmV0LXBhc3N3ZA== && + export USERPASS64 && + + cat >auth.config <<-EOF && + [auth] + challenge = "foobar:alg=test widget=1" + challenge = "bearer:authority=\"id.example.com\" q=1 p=0" + challenge = basic:realm=\"example.com\" + token = basic:$USERPASS64 + EOF + + start_http_server --auth-config="$TRASH_DIRECTORY/auth.config" && + + set_credential_reply get <<-EOF && + protocol=http + host=$HOST_PORT + username=alice + password=secret-passwd + EOF + + git -c "credential.helper=!\"$CREDENTIAL_HELPER\"" ls-remote $ORIGIN_URL && + + expect_credential_query get <<-EOF && + protocol=http + host=$HOST_PORT + wwwauth[]=foobar alg=test widget=1 + wwwauth[]=bearer authority="id.example.com" q=1 p=0 + wwwauth[]=basic realm="example.com" + EOF + + expect_credential_query store <<-EOF + protocol=http + host=$HOST_PORT + username=alice + password=secret-passwd + EOF +' + +test_expect_success 'http auth www-auth headers to credential helper invalid' ' + test_when_finished "per_test_cleanup" && + # base64("alice:secret-passwd") + USERPASS64=YWxpY2U6c2VjcmV0LXBhc3N3ZA== && + export USERPASS64 && + + cat >auth.config <<-EOF && + [auth] + challenge = "bearer:authority=\"id.example.com\" q=1 p=0" + challenge = basic:realm=\"example.com\" + token = basic:$USERPASS64 + EOF + + start_http_server --auth-config="$TRASH_DIRECTORY/auth.config" && + + set_credential_reply get <<-EOF && + protocol=http + host=$HOST_PORT + username=alice + password=invalid-passwd + EOF + + test_must_fail git -c "credential.helper=!\"$CREDENTIAL_HELPER\"" ls-remote $ORIGIN_URL && + + expect_credential_query get <<-EOF && + protocol=http + host=$HOST_PORT + wwwauth[]=bearer authority="id.example.com" q=1 p=0 + wwwauth[]=basic realm="example.com" + EOF + + expect_credential_query erase <<-EOF + protocol=http + host=$HOST_PORT + username=alice + password=invalid-passwd + wwwauth[]=bearer authority="id.example.com" q=1 p=0 + wwwauth[]=basic realm="example.com" + EOF +' + test_done