]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Fix error handling in gss_export_sec_context()
authorNicolas Williams <nico@twosigma.com>
Tue, 1 Sep 2015 23:42:58 +0000 (19:42 -0400)
committerGreg Hudson <ghudson@mit.edu>
Mon, 14 Sep 2015 23:46:43 +0000 (19:46 -0400)
In the mechglue gss_export_sec_context(), make sure to delete the
union context if the underlying mech context has been deleted.  This
can happen if the mech's gss_export_sec_context() returns a failure
and deletes the context (not a behavior exhibited by any of our
in-tree mechanisms, but an allowed behavior for other mechs), or if we
fail to allocate space for the wrapped token.

[ghudson@mit.edu: commit message; rename exit label to "cleanup" and
make it valid for all exit cases]

ticket: 8240 (new)
target_version: 1.13.3
tags: pullup

src/lib/gssapi/mechglue/g_exp_sec_context.c

index 03a6f2b7e7d044b47008130ec4cf0ff57896d32f..e5f95ad0eaf1b16f4814f273c6f16aca6c22aa78 100644 (file)
@@ -79,9 +79,9 @@ gss_buffer_t          interprocess_token;
 {
     OM_uint32          status;
     OM_uint32          length;
-    gss_union_ctx_id_t ctx;
+    gss_union_ctx_id_t ctx = (gss_union_ctx_id_t) *context_handle;
     gss_mechanism      mech;
-    gss_buffer_desc    token;
+    gss_buffer_desc    token = GSS_C_EMPTY_BUFFER;
     char               *buf;
 
     status = val_exp_sec_ctx_args(minor_status,
@@ -94,7 +94,6 @@ gss_buffer_t          interprocess_token;
      * call it.
      */
 
-    ctx = (gss_union_ctx_id_t) *context_handle;
     mech = gssint_get_mechanism (ctx->mech_type);
     if (!mech)
        return GSS_S_BAD_MECH;
@@ -105,15 +104,16 @@ gss_buffer_t              interprocess_token;
                                          &ctx->internal_ctx_id, &token);
     if (status != GSS_S_COMPLETE) {
        map_error(minor_status, mech);
-       return (status);
+       goto cleanup;
     }
 
     length = token.length + 4 + ctx->mech_type->length;
     interprocess_token->length = length;
     interprocess_token->value = malloc(length);
     if (interprocess_token->value == 0) {
-       (void) gss_release_buffer(minor_status, &token);
-       return (GSS_S_FAILURE);
+       *minor_status = ENOMEM;
+       status = GSS_S_FAILURE;
+       goto cleanup;
     }
     buf = interprocess_token->value;
     length = ctx->mech_type->length;
@@ -127,13 +127,17 @@ gss_buffer_t              interprocess_token;
     memcpy(buf+4, ctx->mech_type->elements, (size_t) ctx->mech_type->length);
     memcpy(buf+4+ctx->mech_type->length, token.value, token.length);
 
-    (void) gss_release_buffer(minor_status, &token);
-
-    free(ctx->mech_type->elements);
-    free(ctx->mech_type);
-    free(ctx);
-    *context_handle = 0;
+    status = GSS_S_COMPLETE;
 
-    return(GSS_S_COMPLETE);
+cleanup:
+    (void) gss_release_buffer(minor_status, &token);
+    if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) {
+       /* If the mech deleted its context, delete the union context. */
+       free(ctx->mech_type->elements);
+       free(ctx->mech_type);
+       free(ctx);
+       *context_handle = GSS_C_NO_CONTEXT;
+    }
+    return status;
 }
 #endif /*LEAN_CLIENT */