summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2018-10-22 11:14:06 +0100
committerEdward Thomson <ethomson@edwardthomson.com>2018-11-28 15:27:11 +0000
commit0328eef6aad7861f9dbcb2e5b8e276fe65f98c09 (patch)
tree4bd861db7aef4121eacc319d2cc14b4bac8efc85
parent32cb56ceedc5bb5738c4461bbb4e65e2314d6b66 (diff)
downloadlibgit2-0328eef6aad7861f9dbcb2e5b8e276fe65f98c09.tar.gz
http transport: further refactor credential handling
Prepare credential handling to understand both git server and proxy server authentication.
-rw-r--r--src/transports/http.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/src/transports/http.c b/src/transports/http.c
index 6f46094e5..57aa9f7a2 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -87,6 +87,7 @@ typedef struct {
char parse_buffer_data[NETIO_BUFSIZE];
char *content_type;
char *location;
+ git_vector proxy_authenticate;
git_vector www_authenticate;
enum last_cb last_cb;
int parse_error;
@@ -292,6 +293,12 @@ static int on_header_ready(http_subtransport *t)
GITERR_CHECK_ALLOC(t->content_type);
}
}
+ else if (!strcasecmp("Proxy-Authenticate", git_buf_cstr(name))) {
+ char *dup = git__strdup(git_buf_cstr(value));
+ GITERR_CHECK_ALLOC(dup);
+
+ git_vector_insert(&t->proxy_authenticate, dup);
+ }
else if (!strcasecmp("WWW-Authenticate", git_buf_cstr(name))) {
char *dup = git__strdup(git_buf_cstr(value));
GITERR_CHECK_ALLOC(dup);
@@ -346,7 +353,14 @@ static int on_header_value(http_parser *parser, const char *str, size_t len)
return 0;
}
-static int on_auth_required(http_parser *parser, int allowed_types)
+static int on_auth_required(
+ git_cred **creds,
+ http_parser *parser,
+ const char *url,
+ git_cred_acquire_cb callback,
+ void *callback_payload,
+ const char *username,
+ int allowed_types)
{
parser_context *ctx = (parser_context *) parser->data;
http_subtransport *t = ctx->t;
@@ -358,17 +372,13 @@ static int on_auth_required(http_parser *parser, int allowed_types)
return t->parse_error;
}
- if (t->owner->cred_acquire_cb) {
- if (t->cred) {
- t->cred->free(t->cred);
- t->cred = NULL;
+ if (callback) {
+ if (*creds) {
+ (*creds)->free(*creds);
+ *creds = NULL;
}
- ret = t->owner->cred_acquire_cb(&t->cred,
- t->owner->url,
- t->gitserver_data.user,
- allowed_types,
- t->owner->cred_acquire_payload);
+ ret = callback(creds, url, username, allowed_types, callback_payload);
if (ret == GIT_PASSTHROUGH) {
/* treat GIT_PASSTHROUGH as if callback isn't set */
@@ -377,9 +387,9 @@ static int on_auth_required(http_parser *parser, int allowed_types)
t->parse_error = PARSE_ERROR_EXT;
return t->parse_error;
} else {
- assert(t->cred);
+ assert(*creds);
- if (!(t->cred->credtype & allowed_types)) {
+ if (!((*creds)->credtype & allowed_types)) {
giterr_set(GITERR_NET, "credential provider returned an invalid cred type");
t->parse_error = PARSE_ERROR_GENERIC;
return t->parse_error;
@@ -421,7 +431,13 @@ static int on_headers_complete(http_parser *parser)
/* Check for an authentication failure. */
if (parser->status_code == 401 && get_verb == s->verb)
- return on_auth_required(parser, allowed_www_auth_types);
+ return on_auth_required(&t->cred,
+ parser,
+ t->owner->url,
+ t->owner->cred_acquire_cb,
+ t->owner->cred_acquire_payload,
+ t->gitserver_data.user,
+ allowed_www_auth_types);
/* Check for a redirect.
* Right now we only permit a redirect to the same hostname. */
@@ -554,6 +570,7 @@ static void clear_parser_state(http_subtransport *t)
git__free(t->location);
t->location = NULL;
+ git_vector_free_deep(&t->proxy_authenticate);
git_vector_free_deep(&t->www_authenticate);
}
@@ -1076,10 +1093,8 @@ static int http_action(
assert(t->gitserver_data.host && t->gitserver_data.port && t->gitserver_data.path);
- if ((ret = load_proxy_config(t)) < 0)
- return ret;
-
- if ((ret = http_connect(t)) < 0)
+ if ((ret = load_proxy_config(t)) < 0 ||
+ (ret = http_connect(t)) < 0)
return ret;
switch (action) {