diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2018-07-25 19:07:35 +0100 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2018-07-25 19:07:35 +0100 |
commit | 2115230e8c45fd81640ea5a498ab3fc22e4e8925 (patch) | |
tree | e4e73c3de40903fab9b850a5b59d3310100b5295 | |
parent | 37a4d007e8fcc9b7846ed90baddc7fd7263276c5 (diff) | |
download | libgit2-2115230e8c45fd81640ea5a498ab3fc22e4e8925.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.c | 33 |
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; } |