summaryrefslogtreecommitdiff
path: root/src/transports/http.c
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2018-07-25 19:07:35 +0100
committerEdward Thomson <ethomson@edwardthomson.com>2018-07-25 19:07:35 +0100
commit2115230e8c45fd81640ea5a498ab3fc22e4e8925 (patch)
treee4e73c3de40903fab9b850a5b59d3310100b5295 /src/transports/http.c
parent37a4d007e8fcc9b7846ed90baddc7fd7263276c5 (diff)
downloadlibgit2-ethomson/winauth.tar.gz
http: match mechs with the cred types they supportethomson/winauth
Record the server's mechanisms, along with the supported credential types. We will prompt for credentials with the callback, then we must ensure that we do not assume that a server can support any mech for the given type. Instead, use the first mechanism that the server supports that also supports the credential type we want to use.
Diffstat (limited to 'src/transports/http.c')
-rw-r--r--src/transports/http.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/src/transports/http.c b/src/transports/http.c
index c1a502a1d..c0e0d31e3 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -89,6 +89,7 @@ typedef struct {
unsigned parse_finished : 1;
/* Authentication */
+ git_http_authtype_t auth_server_types;
git_cred *cred;
git_cred *url_cred;
git_vector auth_contexts;
@@ -110,11 +111,17 @@ static bool preauth_match(git_http_auth_scheme *scheme, void *data)
return scheme->preauth && !!(scheme->credtypes & credtype);
}
-static bool credtype_match(git_http_auth_scheme *scheme, void *data)
+typedef struct {
+ git_http_authtype_t server_types;
+ unsigned int credtype;
+} auth_match_data;
+
+static bool auth_match(git_http_auth_scheme *scheme, void *_data)
{
- unsigned int credtype = *(unsigned int *)data;
+ auth_match_data *data = (auth_match_data *)_data;
- return !!(scheme->credtypes & credtype);
+ return !!(data->server_types & scheme->type) &&
+ !!(scheme->credtypes & data->credtype);
}
static bool challenge_match(git_http_auth_scheme *scheme, void *data)
@@ -188,6 +195,8 @@ static int apply_preauthentication(git_buf *buf, http_subtransport *t)
if (!t->url_cred)
return 0;
+ printf("url creds!\n");
+
credtype = t->url_cred->credtype;
if (auth_context_match(&context, t, preauth_match, &credtype) < 0)
@@ -201,20 +210,28 @@ static int apply_preauthentication(git_buf *buf, http_subtransport *t)
static int apply_authentication(git_buf *buf, http_subtransport *t)
{
git_http_auth_context *context;
+ auth_match_data data = {0};
git_cred *cred = t->cred;
/*
* We've not asked the caller for credentials but they've pre-
* provided us with some (in the URL for example) so let's try them.
*/
-
if (!cred)
return apply_preauthentication(buf, t);
+ data.server_types = t->auth_server_types;
+ data.credtype = cred->credtype;
+
/* Get or create a context for the best scheme for this cred type */
- if (auth_context_match(&context, t, credtype_match, &cred->credtype) < 0)
+ if (auth_context_match(&context, t, auth_match, &data) < 0)
return -1;
+ if (!context) {
+ giterr_set(GITERR_NET, "no mechanism to authenticate with credential type");
+ return -1;
+ }
+
return context->next_token(buf, context, cred);
}
@@ -281,6 +298,12 @@ static int parse_authenticate_response(
context->set_challenge(context, challenge) < 0)
return -1;
+ /*
+ * Record both the supported mechs on the server and the
+ * corresponding credential types so that we know what mech
+ * to respond with when the user gives us a given cred type.
+ */
+ t->auth_server_types |= context->type;
*allowed_types |= context->credtypes;
}