Commit 22654812 by Edward Thomson

http transport: prompt for proxy credentials

Teach the HTTP transport how to prompt for proxy credentials.
parent 0328eef6
...@@ -37,6 +37,9 @@ static const char *receive_pack_service_url = "/git-receive-pack"; ...@@ -37,6 +37,9 @@ static const char *receive_pack_service_url = "/git-receive-pack";
static const char *get_verb = "GET"; static const char *get_verb = "GET";
static const char *post_verb = "POST"; 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 OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport)
#define PARSE_ERROR_GENERIC -1 #define PARSE_ERROR_GENERIC -1
...@@ -97,6 +100,7 @@ typedef struct { ...@@ -97,6 +100,7 @@ typedef struct {
/* Authentication */ /* Authentication */
git_cred *cred; git_cred *cred;
git_cred *url_cred; git_cred *url_cred;
git_cred *proxy_cred;
git_vector auth_contexts; git_vector auth_contexts;
} http_subtransport; } http_subtransport;
...@@ -353,10 +357,19 @@ static int on_header_value(http_parser *parser, const char *str, size_t len) ...@@ -353,10 +357,19 @@ static int on_header_value(http_parser *parser, const char *str, size_t len)
return 0; return 0;
} }
GIT_INLINE(void) free_cred(git_cred **cred)
{
if (*cred) {
git_cred_free(*cred);
(*cred) = NULL;
}
}
static int on_auth_required( static int on_auth_required(
git_cred **creds, git_cred **creds,
http_parser *parser, http_parser *parser,
const char *url, const char *url,
const char *type,
git_cred_acquire_cb callback, git_cred_acquire_cb callback,
void *callback_payload, void *callback_payload,
const char *username, const char *username,
...@@ -367,17 +380,13 @@ static int on_auth_required( ...@@ -367,17 +380,13 @@ static int on_auth_required(
int ret; int ret;
if (!allowed_types) { 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; t->parse_error = PARSE_ERROR_GENERIC;
return t->parse_error; return t->parse_error;
} }
if (callback) { if (callback) {
if (*creds) { free_cred(creds);
(*creds)->free(*creds);
*creds = NULL;
}
ret = callback(creds, url, username, allowed_types, callback_payload); ret = callback(creds, url, username, allowed_types, callback_payload);
if (ret == GIT_PASSTHROUGH) { if (ret == GIT_PASSTHROUGH) {
...@@ -390,7 +399,7 @@ static int on_auth_required( ...@@ -390,7 +399,7 @@ static int on_auth_required(
assert(*creds); assert(*creds);
if (!((*creds)->credtype & allowed_types)) { 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; t->parse_error = PARSE_ERROR_GENERIC;
return t->parse_error; return t->parse_error;
} }
...@@ -401,7 +410,8 @@ static int on_auth_required( ...@@ -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; t->parse_error = PARSE_ERROR_GENERIC;
return t->parse_error; return t->parse_error;
} }
...@@ -412,7 +422,7 @@ static int on_headers_complete(http_parser *parser) ...@@ -412,7 +422,7 @@ static int on_headers_complete(http_parser *parser)
http_subtransport *t = ctx->t; http_subtransport *t = ctx->t;
http_stream *s = ctx->s; http_stream *s = ctx->s;
git_buf buf = GIT_BUF_INIT; 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 /* Both parse_header_name and parse_header_value are populated
* and ready for consumption. */ * and ready for consumption. */
...@@ -425,15 +435,29 @@ static int on_headers_complete(http_parser *parser) ...@@ -425,15 +435,29 @@ static int on_headers_complete(http_parser *parser)
* these may be 407/401 (authentication is not complete) or a 200 * these may be 407/401 (authentication is not complete) or a 200
* (informing us that auth has completed). * (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) &allowed_www_auth_types) < 0)
return t->parse_error = PARSE_ERROR_GENERIC; 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. */ /* Check for an authentication failure. */
if (parser->status_code == 401 && get_verb == s->verb) if (parser->status_code == 401 && get_verb == s->verb)
return on_auth_required(&t->cred, return on_auth_required(&t->cred,
parser, parser,
t->owner->url, t->owner->url,
SERVER_TYPE_REMOTE,
t->owner->cred_acquire_cb, t->owner->cred_acquire_cb,
t->owner->cred_acquire_payload, t->owner->cred_acquire_payload,
t->gitserver_data.user, t->gitserver_data.user,
...@@ -1131,15 +1155,9 @@ static int http_close(git_smart_subtransport *subtransport) ...@@ -1131,15 +1155,9 @@ static int http_close(git_smart_subtransport *subtransport)
t->gitserver_stream = NULL; t->gitserver_stream = NULL;
} }
if (t->cred) { free_cred(&t->cred);
t->cred->free(t->cred); free_cred(&t->url_cred);
t->cred = NULL; free_cred(&t->proxy_cred);
}
if (t->url_cred) {
t->url_cred->free(t->url_cred);
t->url_cred = NULL;
}
git_vector_foreach(&t->auth_contexts, i, context) { git_vector_foreach(&t->auth_contexts, i, context) {
if (context->free) if (context->free)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment