Commit 10e8fe555e55d6b28b7e601acbc6d52159735069

Edward Thomson 2019-03-21T13:55:54

transports: add an `is_complete` function for auth Some authentication mechanisms (like HTTP Basic and Digest) have a one-step mechanism to create credentials, but there are more complex mechanisms like NTLM and Negotiate that require challenge/response after negotiation, requiring several round-trips. Add an `is_complete` function to know when they have round-tripped enough to be a single authentication and should now either have succeeded or failed to authenticate.

diff --git a/src/transports/auth.c b/src/transports/auth.c
index ea6cb65..849a6ce 100644
--- a/src/transports/auth.c
+++ b/src/transports/auth.c
@@ -52,6 +52,7 @@ static git_http_auth_context basic_context = {
 	GIT_CREDTYPE_USERPASS_PLAINTEXT,
 	NULL,
 	basic_next_token,
+	NULL,
 	NULL
 };
 
diff --git a/src/transports/auth.h b/src/transports/auth.h
index 7b64770..9ead558 100644
--- a/src/transports/auth.h
+++ b/src/transports/auth.h
@@ -33,6 +33,9 @@ struct git_http_auth_context {
 	/** Gets the next authentication token from the context */
 	int (*next_token)(git_buf *out, git_http_auth_context *ctx, const char *header_name, git_cred *cred);
 
+	/** Examines if all tokens have been presented. */
+	int (*is_complete)(git_http_auth_context *ctx);
+
 	/** Frees the authentication context */
 	void (*free)(git_http_auth_context *ctx);
 };
diff --git a/src/transports/auth_negotiate.c b/src/transports/auth_negotiate.c
index 03d3336..d5c3d16 100644
--- a/src/transports/auth_negotiate.c
+++ b/src/transports/auth_negotiate.c
@@ -170,6 +170,15 @@ done:
 	return error;
 }
 
+static int negotiate_is_complete(git_http_auth_context *c)
+{
+	http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c;
+
+	assert(ctx);
+
+	return (ctx->complete == 1);
+}
+
 static void negotiate_context_free(git_http_auth_context *c)
 {
 	http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c;
@@ -266,6 +275,7 @@ int git_http_auth_negotiate(
 	ctx->parent.credtypes = GIT_CREDTYPE_DEFAULT;
 	ctx->parent.set_challenge = negotiate_set_challenge;
 	ctx->parent.next_token = negotiate_next_token;
+	ctx->parent.is_complete = negotiate_is_complete;
 	ctx->parent.free = negotiate_context_free;
 
 	*out = (git_http_auth_context *)ctx;