From: Viktor Szakats Date: Tue, 14 Oct 2025 15:43:48 +0000 (+0200) Subject: krb5: fix `output_token` allocators in the GSS debug stub (Windows) X-Git-Tag: rc-8_17_0-3~135 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=87b72b81829f8ef8fc0a243667cb7aea9d0c1c6e;p=thirdparty%2Fcurl.git krb5: fix `output_token` allocators in the GSS debug stub (Windows) Before this patch system `malloc()`/`free()` were used to allocate the buffer returned in the `output_token` object from the debug stub of `gss_init_sec_context()` when enabled via `CURL_STUB_GSS_CREDS` in debug-enabled libcurl builds. This object is later released via stock `gss_release_buffer()`, which, in the Windows builds of MIT Kerberos, doesn't use the system `free()`, but the Win32 `HeapFree()`. Fix it by using the GSS alloc/free macros: `gssalloc_malloc()` and `gssalloc_free()` from `gssapi_alloc.h`. To make this work without MIT Kerberos feature detection, use a canary macro to detect a version which installs `gssapi_alloc.h` for Windows. For <1.15 (2016-11-30) releases, that do not install it, disable the GSS debug stub in libcurl. Strictly speaking, non-Windows builds would also need to use GSS allocators, but, detecting support for `gssapi_alloc.h` is impossible without build-level logic. Built-level logic is complex and overkill, and MIT Kerberos, as of 1.22.1, uses standard malloc/free on non-Windows platforms anyway. (except in GSS debug builds.) Follow-up to 73840836a51c443e6b5d385014ce1c8f5be3e02b #17752 Closes #19064 --- diff --git a/lib/curl_gssapi.c b/lib/curl_gssapi.c index 42ccaa3e29..74128559c1 100644 --- a/lib/curl_gssapi.c +++ b/lib/curl_gssapi.c @@ -29,6 +29,28 @@ #include "curl_gssapi.h" #include "sendf.h" +#ifdef DEBUGBUILD +#if defined(HAVE_GSSGNU) || !defined(_WIN32) +/* To avoid memdebug macro replacement, wrap the name in parentheses to call + the original version. It is freed via the GSS API gss_release_buffer(). */ +#define Curl_gss_alloc (malloc) +#define Curl_gss_free (free) +#define CURL_GSS_STUB +/* For correctness this would be required for all platforms, not only Windows, + but, as of v1.22.1, MIT Kerberos uses a special allocator only for Windows, + and the availability of 'gssapi/gssapi_alloc.h' is difficult to detect, + because GSS headers are not versioned, and there is also no other macro to + indicate 1.18+ vs. previous versions. On Windows we can use 'GSS_S_BAD_MIC'. + */ +#elif defined(_WIN32) && defined(GSS_S_BAD_MIC) /* MIT Kerberos 1.15+ */ +/* MIT Kerberos 1.10+ (Windows), 1.18+ (all platforms), missing from GNU GSS */ +#include +#define Curl_gss_alloc gssalloc_malloc +#define Curl_gss_free gssalloc_free +#define CURL_GSS_STUB +#endif +#endif /* DEBUGBUILD */ + /* The last 2 #include files should be in this order */ #include "curl_memory.h" #include "memdebug.h" @@ -51,7 +73,7 @@ gss_OID_desc Curl_krb5_mech_oid CURL_ALIGN8 = { 9, CURL_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") }; -#ifdef DEBUGBUILD +#ifdef CURL_GSS_STUB enum min_err_code { STUB_GSS_OK = 0, STUB_GSS_NO_MEMORY, @@ -212,9 +234,7 @@ stub_gss_init_sec_context(OM_uint32 *min, ctx->flags = req_flags; } - /* To avoid memdebug macro replacement, wrap the name in parentheses to call - the original version. It is freed via the GSS API gss_release_buffer(). */ - token = (malloc)(length); + token = Curl_gss_alloc(length); if(!token) { free(ctx); *min = STUB_GSS_NO_MEMORY; @@ -229,14 +249,14 @@ stub_gss_init_sec_context(OM_uint32 *min, major_status = gss_display_name(&minor_status, target_name, &target_desc, &name_type); if(GSS_ERROR(major_status)) { - (free)(token); + Curl_gss_free(token); free(ctx); *min = STUB_GSS_NO_MEMORY; return GSS_S_FAILURE; } if(strlen(creds) + target_desc.length + 5 >= sizeof(ctx->creds)) { - (free)(token); + Curl_gss_free(token); free(ctx); *min = STUB_GSS_NO_MEMORY; return GSS_S_FAILURE; @@ -252,7 +272,7 @@ stub_gss_init_sec_context(OM_uint32 *min, } if(used >= length) { - (free)(token); + Curl_gss_free(token); free(ctx); *min = STUB_GSS_NO_MEMORY; return GSS_S_FAILURE; @@ -294,7 +314,7 @@ stub_gss_delete_sec_context(OM_uint32 *min, return GSS_S_COMPLETE; } -#endif /* DEBUGBUILD */ +#endif /* CURL_GSS_STUB */ OM_uint32 Curl_gss_init_sec_context(struct Curl_easy *data, OM_uint32 *minor_status, @@ -324,7 +344,7 @@ OM_uint32 Curl_gss_init_sec_context(struct Curl_easy *data, if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG) req_flags |= GSS_C_DELEG_FLAG; -#ifdef DEBUGBUILD +#ifdef CURL_GSS_STUB if(getenv("CURL_STUB_GSS_CREDS")) return stub_gss_init_sec_context(minor_status, GSS_C_NO_CREDENTIAL, /* cred_handle */ @@ -339,7 +359,7 @@ OM_uint32 Curl_gss_init_sec_context(struct Curl_easy *data, output_token, ret_flags, NULL /* time_rec */); -#endif /* DEBUGBUILD */ +#endif /* CURL_GSS_STUB */ return gss_init_sec_context(minor_status, GSS_C_NO_CREDENTIAL, /* cred_handle */ @@ -360,12 +380,12 @@ OM_uint32 Curl_gss_delete_sec_context(OM_uint32 *min, gss_ctx_id_t *context, gss_buffer_t output_token) { -#ifdef DEBUGBUILD +#ifdef CURL_GSS_STUB if(getenv("CURL_STUB_GSS_CREDS")) return stub_gss_delete_sec_context(min, (struct stub_gss_ctx_id_t_desc **)context, output_token); -#endif /* DEBUGBUILD */ +#endif /* CURL_GSS_STUB */ return gss_delete_sec_context(min, context, output_token); }