credential: add a field for pre-encoded credentials

At the moment, our credential code wants to find a username and password for access, which, for HTTP, it will pass to libcurl to encode and process. However, many users want to use authentication schemes that libcurl doesn't support, such as Bearer authentication. In these schemes, the secret is not a username and password pair, but some sort of token that meets the production for authentication data in the RFC. In fact, in general, it's useful to allow our credential helper to have knowledge about what specifically to put in the protocol header. Thus, add a field, credential, which contains data that's preencoded to be suitable for the protocol in question. If we have such data, we need neither a username nor a password, so make that adjustment as well. It is in theory possible to reuse the password field for this. However, if we do so, we must know whether the credential helper supports our new scheme before sending it data, which necessitates some sort of capability inquiry, because otherwise an uninformed credential helper would store our preencoded data as a password, which would fail the next time we attempted to connect to the remote server. This design is substantially simpler, and we can hint to the credential helper that we support this approach with a simple new field instead of needing to query it first. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

brian m. carlson committed Apr 17, 2024 at 00:02 UTC 6a6d6fb12e485a580fc3f219cbee1575481b56eb
2 files changed +11 -4
credential.c
+10 -4
@@ -25,6 +25,7 @@ void credential_clear(struct credential *c)
25 free(c->path);
26 free(c->username);
27 free(c->password);
28 + free(c->credential);
29 free(c->oauth_refresh_token);
30 free(c->authtype);
31 string_list_clear(&c->helpers, 0);
@@ -234,6 +235,9 @@ int credential_read(struct credential *c, FILE *fp)
235 } else if (!strcmp(key, "password")) {
236 free(c->password);
237 c->password = xstrdup(value);
238 + } else if (!strcmp(key, "credential")) {
239 + free(c->credential);
240 + c->credential = xstrdup(value);
241 } else if (!strcmp(key, "protocol")) {
242 free(c->protocol);
243 c->protocol = xstrdup(value);
@@ -291,6 +295,7 @@ void credential_write(const struct credential *c, FILE *fp)
295 credential_write_item(fp, "path", c->path, 0);
296 credential_write_item(fp, "username", c->username, 0);
297 credential_write_item(fp, "password", c->password, 0);
298 + credential_write_item(fp, "credential", c->credential, 0);
299 credential_write_item(fp, "oauth_refresh_token", c->oauth_refresh_token, 0);
300 if (c->password_expiry_utc != TIME_MAX) {
301 char *s = xstrfmt("%"PRItime, c->password_expiry_utc);
@@ -366,7 +371,7 @@ void credential_fill(struct credential *c)
371 {
372 int i;
373
369 - if (c->username && c->password)
374 + if ((c->username && c->password) || c->credential)
375 return;
376
377 credential_apply_config(c);
@@ -379,7 +384,7 @@ void credential_fill(struct credential *c)
384 /* Reset expiry to maintain consistency */
385 c->password_expiry_utc = TIME_MAX;
386 }
382 - if (c->username && c->password)
387 + if ((c->username && c->password) || c->credential)
388 return;
389 if (c->quit)
390 die("credential helper '%s' told us to quit",
@@ -387,7 +392,7 @@ void credential_fill(struct credential *c)
392 }
393
394 credential_getpass(c);
390 - if (!c->username && !c->password)
395 + if (!c->username && !c->password && !c->credential)
396 die("unable to get password from user");
397 }
398
@@ -397,7 +402,7 @@ void credential_approve(struct credential *c)
402
403 if (c->approved)
404 return;
400 - if (!c->username || !c->password || c->password_expiry_utc < time(NULL))
405 + if (((!c->username || !c->password) && !c->credential) || c->password_expiry_utc < time(NULL))
406 return;
407
408 credential_apply_config(c);
@@ -418,6 +423,7 @@ void credential_reject(struct credential *c)
423
424 FREE_AND_NULL(c->username);
425 FREE_AND_NULL(c->password);
426 + FREE_AND_NULL(c->credential);
427 FREE_AND_NULL(c->oauth_refresh_token);
428 c->password_expiry_utc = TIME_MAX;
429 c->approved = 0;
credential.h
+1
@@ -138,6 +138,7 @@ struct credential {
138
139 char *username;
140 char *password;
141 + char *credential;
142 char *protocol;
143 char *host;
144 char *path;