http transport: further refactor credential handling Prepare credential handling to understand both git server and proxy server authentication.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
diff --git a/src/transports/http.c b/src/transports/http.c
index 6f46094..57aa9f7 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) {