gssapi: dispose after completion for retry Disposal pattern; dispose on completion, allowing us to retry authentication, which may happen on web servers that close connection-based authenticated sessions (NTLM/SPNEGO) unexpectedly.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
diff --git a/src/transports/auth_negotiate.c b/src/transports/auth_negotiate.c
index e1fa803..16af4fe 100644
--- a/src/transports/auth_negotiate.c
+++ b/src/transports/auth_negotiate.c
@@ -75,6 +75,22 @@ static int negotiate_set_challenge(
return 0;
}
+static void negotiate_context_dispose(http_auth_negotiate_context *ctx)
+{
+ OM_uint32 status_minor;
+
+ if (ctx->gss_context != GSS_C_NO_CONTEXT) {
+ gss_delete_sec_context(
+ &status_minor, &ctx->gss_context, GSS_C_NO_BUFFER);
+ ctx->gss_context = GSS_C_NO_CONTEXT;
+ }
+
+ git_buf_dispose(&ctx->target);
+
+ git__free(ctx->challenge);
+ ctx->challenge = NULL;
+}
+
static int negotiate_next_token(
git_buf *buf,
git_http_auth_context *c,
@@ -128,9 +144,7 @@ static int negotiate_next_token(
input_token.length = input_buf.size;
input_token_ptr = &input_token;
} else if (ctx->gss_context != GSS_C_NO_CONTEXT) {
- /* If we're given a half-built security context, delete it so auth can continue. */
- gss_delete_sec_context(&status_minor, &ctx->gss_context, GSS_C_NO_BUFFER);
- ctx->gss_context = GSS_C_NO_CONTEXT;
+ negotiate_context_dispose(ctx);
}
mech = &negotiate_oid_spnego;
@@ -158,6 +172,7 @@ static int negotiate_next_token(
/* This message merely told us auth was complete; we do not respond. */
if (status_major == GSS_S_COMPLETE) {
+ negotiate_context_dispose(ctx);
ctx->complete = 1;
goto done;
}
@@ -193,17 +208,8 @@ static int negotiate_is_complete(git_http_auth_context *c)
static void negotiate_context_free(git_http_auth_context *c)
{
http_auth_negotiate_context *ctx = (http_auth_negotiate_context *)c;
- OM_uint32 status_minor;
- if (ctx->gss_context != GSS_C_NO_CONTEXT) {
- gss_delete_sec_context(
- &status_minor, &ctx->gss_context, GSS_C_NO_BUFFER);
- ctx->gss_context = GSS_C_NO_CONTEXT;
- }
-
- git_buf_dispose(&ctx->target);
-
- git__free(ctx->challenge);
+ negotiate_context_dispose(ctx);
ctx->configured = 0;
ctx->complete = 0;