diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2018-10-22 11:24:05 +0100 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2018-11-28 15:30:16 +0000 |
commit | 2265481261c63a562e4d07f624f7888a5ee0c50c (patch) | |
tree | 4a705ad793187f75baf5e1c1c2e18ce5a0577b98 | |
parent | 0328eef6aad7861f9dbcb2e5b8e276fe65f98c09 (diff) | |
download | libgit2-2265481261c63a562e4d07f624f7888a5ee0c50c.tar.gz |
http transport: prompt for proxy credentials
Teach the HTTP transport how to prompt for proxy credentials.
-rw-r--r-- | src/transports/http.c | 56 |
1 files changed, 37 insertions, 19 deletions
diff --git a/src/transports/http.c b/src/transports/http.c index 57aa9f7a2..29924a0c2 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -37,6 +37,9 @@ static const char *receive_pack_service_url = "/git-receive-pack"; static const char *get_verb = "GET"; static const char *post_verb = "POST"; +#define SERVER_TYPE_REMOTE "remote" +#define SERVER_TYPE_PROXY "proxy" + #define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport) #define PARSE_ERROR_GENERIC -1 @@ -97,6 +100,7 @@ typedef struct { /* Authentication */ git_cred *cred; git_cred *url_cred; + git_cred *proxy_cred; git_vector auth_contexts; } http_subtransport; @@ -353,10 +357,19 @@ static int on_header_value(http_parser *parser, const char *str, size_t len) return 0; } +GIT_INLINE(void) free_cred(git_cred **cred) +{ + if (*cred) { + git_cred_free(*cred); + (*cred) = NULL; + } +} + static int on_auth_required( git_cred **creds, http_parser *parser, const char *url, + const char *type, git_cred_acquire_cb callback, void *callback_payload, const char *username, @@ -367,17 +380,13 @@ static int on_auth_required( int ret; if (!allowed_types) { - giterr_set(GITERR_NET, "remote did not prompt for authentication mechanisms"); + giterr_set(GITERR_NET, "%s requested authentication but did not negotiate mechanisms", type); t->parse_error = PARSE_ERROR_GENERIC; return t->parse_error; } if (callback) { - if (*creds) { - (*creds)->free(*creds); - *creds = NULL; - } - + free_cred(creds); ret = callback(creds, url, username, allowed_types, callback_payload); if (ret == GIT_PASSTHROUGH) { @@ -390,7 +399,7 @@ static int on_auth_required( assert(*creds); if (!((*creds)->credtype & allowed_types)) { - giterr_set(GITERR_NET, "credential provider returned an invalid cred type"); + giterr_set(GITERR_NET, "%s credential provider returned an invalid cred type", type); t->parse_error = PARSE_ERROR_GENERIC; return t->parse_error; } @@ -401,7 +410,8 @@ static int on_auth_required( } } - giterr_set(GITERR_NET, "authentication required but no callback set"); + giterr_set(GITERR_NET, "%s authentication required but no callback set", + type); t->parse_error = PARSE_ERROR_GENERIC; return t->parse_error; } @@ -412,7 +422,7 @@ static int on_headers_complete(http_parser *parser) http_subtransport *t = ctx->t; http_stream *s = ctx->s; git_buf buf = GIT_BUF_INIT; - int allowed_www_auth_types = 0; + int allowed_proxy_auth_types = 0, allowed_www_auth_types = 0; /* Both parse_header_name and parse_header_value are populated * and ready for consumption. */ @@ -425,15 +435,29 @@ static int on_headers_complete(http_parser *parser) * these may be 407/401 (authentication is not complete) or a 200 * (informing us that auth has completed). */ - if (parse_authenticate_response(&t->www_authenticate, t, + if (parse_authenticate_response(&t->proxy_authenticate, t, + &allowed_proxy_auth_types) < 0 || + parse_authenticate_response(&t->www_authenticate, t, &allowed_www_auth_types) < 0) return t->parse_error = PARSE_ERROR_GENERIC; + /* Check for a proxy authentication failure. */ + if (parser->status_code == 407 && get_verb == s->verb) + return on_auth_required(&t->proxy_cred, + parser, + t->proxy.url, + SERVER_TYPE_PROXY, + t->proxy.credentials, + t->proxy.payload, + t->proxy_data.user, + allowed_proxy_auth_types); + /* Check for an authentication failure. */ if (parser->status_code == 401 && get_verb == s->verb) return on_auth_required(&t->cred, parser, t->owner->url, + SERVER_TYPE_REMOTE, t->owner->cred_acquire_cb, t->owner->cred_acquire_payload, t->gitserver_data.user, @@ -1131,15 +1155,9 @@ static int http_close(git_smart_subtransport *subtransport) t->gitserver_stream = NULL; } - if (t->cred) { - t->cred->free(t->cred); - t->cred = NULL; - } - - if (t->url_cred) { - t->url_cred->free(t->url_cred); - t->url_cred = NULL; - } + free_cred(&t->cred); + free_cred(&t->url_cred); + free_cred(&t->proxy_cred); git_vector_foreach(&t->auth_contexts, i, context) { if (context->free) |