summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2018-10-22 10:16:54 +0100
committerEdward Thomson <ethomson@edwardthomson.com>2018-11-28 15:22:37 +0000
commit32cb56ceedc5bb5738c4461bbb4e65e2314d6b66 (patch)
treefdee5fb07630991a801a1293412e3aedc5787536
parente6e399ab367f300f76903099462b8e06846fccc3 (diff)
downloadlibgit2-32cb56ceedc5bb5738c4461bbb4e65e2314d6b66.tar.gz
http transport: refactor credential handling
Factor credential handling into its own function. Additionally, add safety checks to ensure that we are in a valid state - that we have received a valid challenge from the server and that we have configuration to respond to that challenge.
-rw-r--r--src/transports/http.c105
1 files changed, 58 insertions, 47 deletions
diff --git a/src/transports/http.c b/src/transports/http.c
index 7df139b07..6f46094e5 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -346,13 +346,63 @@ 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)
+{
+ parser_context *ctx = (parser_context *) parser->data;
+ http_subtransport *t = ctx->t;
+ int ret;
+
+ if (!allowed_types) {
+ giterr_set(GITERR_NET, "remote did not prompt for authentication mechanisms");
+ t->parse_error = PARSE_ERROR_GENERIC;
+ return t->parse_error;
+ }
+
+ if (t->owner->cred_acquire_cb) {
+ if (t->cred) {
+ t->cred->free(t->cred);
+ t->cred = NULL;
+ }
+
+ ret = t->owner->cred_acquire_cb(&t->cred,
+ t->owner->url,
+ t->gitserver_data.user,
+ allowed_types,
+ t->owner->cred_acquire_payload);
+
+ if (ret == GIT_PASSTHROUGH) {
+ /* treat GIT_PASSTHROUGH as if callback isn't set */
+ } else if (ret < 0) {
+ t->error = ret;
+ t->parse_error = PARSE_ERROR_EXT;
+ return t->parse_error;
+ } else {
+ assert(t->cred);
+
+ if (!(t->cred->credtype & allowed_types)) {
+ giterr_set(GITERR_NET, "credential provider returned an invalid cred type");
+ t->parse_error = PARSE_ERROR_GENERIC;
+ return t->parse_error;
+ }
+
+ /* Successfully acquired a credential. */
+ t->parse_error = PARSE_ERROR_REPLAY;
+ return 0;
+ }
+ }
+
+ giterr_set(GITERR_NET, "authentication required but no callback set");
+ t->parse_error = PARSE_ERROR_GENERIC;
+ return t->parse_error;
+}
+
static int on_headers_complete(http_parser *parser)
{
parser_context *ctx = (parser_context *) parser->data;
http_subtransport *t = ctx->t;
http_stream *s = ctx->s;
git_buf buf = GIT_BUF_INIT;
- int error = 0, no_callback = 0, allowed_auth_types = 0;
+ int allowed_www_auth_types = 0;
/* Both parse_header_name and parse_header_value are populated
* and ready for consumption. */
@@ -360,57 +410,18 @@ static int on_headers_complete(http_parser *parser)
if (on_header_ready(t) < 0)
return t->parse_error = PARSE_ERROR_GENERIC;
- /* Capture authentication headers which may be a 401 (authentication
- * is not complete) or a 200 (simply informing us that auth *is*
- * complete.)
+ /*
+ * Capture authentication headers for the proxy or final endpoint,
+ * 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,
- &allowed_auth_types) < 0)
+ &allowed_www_auth_types) < 0)
return t->parse_error = PARSE_ERROR_GENERIC;
/* Check for an authentication failure. */
- if (parser->status_code == 401 && get_verb == s->verb) {
- if (!t->owner->cred_acquire_cb) {
- no_callback = 1;
- } else {
- if (allowed_auth_types) {
- if (t->cred) {
- t->cred->free(t->cred);
- t->cred = NULL;
- }
-
- error = t->owner->cred_acquire_cb(&t->cred,
- t->owner->url,
- t->gitserver_data.user,
- allowed_auth_types,
- t->owner->cred_acquire_payload);
-
- /* treat GIT_PASSTHROUGH as if callback isn't set */
- if (error == GIT_PASSTHROUGH) {
- no_callback = 1;
- } else if (error < 0) {
- t->error = error;
- return t->parse_error = PARSE_ERROR_EXT;
- } else {
- assert(t->cred);
-
- if (!(t->cred->credtype & allowed_auth_types)) {
- giterr_set(GITERR_NET, "credentials callback returned an invalid cred type");
- return t->parse_error = PARSE_ERROR_GENERIC;
- }
-
- /* Successfully acquired a credential. */
- t->parse_error = PARSE_ERROR_REPLAY;
- return 0;
- }
- }
- }
-
- if (no_callback) {
- giterr_set(GITERR_NET, "authentication required but no callback set");
- return t->parse_error = PARSE_ERROR_GENERIC;
- }
- }
+ if (parser->status_code == 401 && get_verb == s->verb)
+ return on_auth_required(parser, allowed_www_auth_types);
/* Check for a redirect.
* Right now we only permit a redirect to the same hostname. */