@@ -39,7 +39,7 @@ for later use.
If the action is `reject`, git-credential will send the description to
any configured credential helpers, which may erase any stored
-credential matching the description.
+credentials matching the description.
If the action is `approve` or `reject`, no output should be emitted.
@@ -260,7 +260,7 @@ appended to its command line, which is one of:
`erase`::
- Remove a matching credential, if any, from the helper's storage.
+ Remove matching credentials, if any, from the helper's storage.
The details of the credential will be provided on the helper's stdin
stream. The exact format is the same as the input/output format of the
@@ -33,12 +33,12 @@ static void cache_credential(struct credential *c, int timeout)
e->expiration = time(NULL) + timeout;
}
-static struct credential_cache_entry *lookup_credential(const struct credential *c, int match_password)
+static struct credential_cache_entry *lookup_credential(const struct credential *c)
{
int i;
for (i = 0; i < entries_nr; i++) {
struct credential *e = &entries[i].item;
- if (credential_match(c, e, match_password))
+ if (credential_match(c, e, 0))
return &entries[i];
}
return NULL;
@@ -48,9 +48,12 @@ static void remove_credential(const struct credential *c, int match_password)
{
struct credential_cache_entry *e;
- e = lookup_credential(c, match_password);
- if (e)
- e->expiration = 0;
+ int i;
+ for (i = 0; i < entries_nr; i++) {
+ e = &entries[i];
+ if (credential_match(c, &e->item, match_password))
+ e->expiration = 0;
+ }
}
static timestamp_t check_expirations(void)
@@ -127,7 +130,7 @@ static void serve_one_client(FILE *in, FILE *out)
if (read_request(in, &c, &action, &timeout) < 0)
/* ignore error */ ;
else if (!strcmp(action.buf, "get")) {
- struct credential_cache_entry *e = lookup_credential(&c, 0);
+ struct credential_cache_entry *e = lookup_credential(&c);
if (e) {
fprintf(out, "username=%s\n", e->item.username);
fprintf(out, "password=%s\n", e->item.password);
@@ -35,7 +35,6 @@ static int parse_credential_file(const char *fn,
found_credential = 1;
if (match_cb) {
match_cb(&entry);
- break;
}
}
else if (other_cb)
@@ -45,6 +45,8 @@ helper_test_clean() {
reject $1 https example.com user2
reject $1 https example.com user4
reject $1 https example.com user5
+ reject $1 https example.com user6
+ reject $1 https example.com user7
reject $1 https example.com user8
reject $1 http path.tld user
reject $1 https timeout.tld user
@@ -342,6 +344,37 @@ helper_test() {
EOF
'
+ test_expect_success "helper ($HELPER) erases all matching credentials" '
+ check approve $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user6
+ password=pass1
+ EOF
+ check approve $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ username=user7
+ password=pass1
+ EOF
+ check reject $HELPER <<-\EOF &&
+ protocol=https
+ host=example.com
+ EOF
+ check fill $HELPER <<-\EOF
+ protocol=https
+ host=example.com
+ --
+ protocol=https
+ host=example.com
+ username=askpass-username
+ password=askpass-password
+ --
+ askpass: Username for '\''https://example.com'\'':
+ askpass: Password for '\''https://askpass-username@example.com'\'':
+ EOF
+ '
+
: ${GIT_TEST_LONG_CRED_BUFFER:=1024}
# 23 bytes accounts for "wwwauth[]=basic realm=" plus NUL
LONG_VALUE_LEN=$((GIT_TEST_LONG_CRED_BUFFER - 23))