summaryrefslogtreecommitdiff
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
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.
-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;
}