sspi: free libcurl allocated memory with curlx_free

DecryptMessage() decrypts the buffer in place, overwriting the original
contents. It does not allocate any new buffer so the single original
buffer should be freed using the same memory "system" that allocated it.

Reported-by: Trail of Bits
Closes #21990
This commit is contained in:
Daniel Stenberg 2026-06-12 14:37:55 +02:00
parent bb837dda23
commit 8d3c4fe344
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
2 changed files with 16 additions and 21 deletions

View file

@ -421,8 +421,7 @@ static CURLcode socks5_sspi_encrypt(struct Curl_cfilter *cf,
if(result || (actualread != us_length)) {
failf(data, "Failed to receive SSPI encryption type.");
curlx_free(sspi_w_token[0].pvBuffer);
return result ? result : CURLE_COULDNT_CONNECT;
goto fail;
}
if(!data->set.socks5_gssapi_nec) {
@ -432,34 +431,26 @@ static CURLcode socks5_sspi_encrypt(struct Curl_cfilter *cf,
sspi_w_token[1].cbBuffer = 0;
sspi_w_token[1].pvBuffer = NULL;
status = Curl_pSecFn->DecryptMessage(sspi_context, &wrap_desc,
0, &qop);
/* At least one of the descriptors must be of type SECBUFFER_DATA. The
message is decrypted in place so the SECBUFFER_DATA receives a pointer
to the message in SECBUFFER_STREAM. */
status = Curl_pSecFn->DecryptMessage(sspi_context, &wrap_desc, 0, &qop);
if(check_sspi_err(data, status, "DecryptMessage")) {
if(sspi_w_token[1].pvBuffer)
Curl_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
curlx_free(sspi_w_token[0].pvBuffer);
return CURLE_COULDNT_CONNECT;
}
if(check_sspi_err(data, status, "DecryptMessage"))
goto fail;
if(sspi_w_token[1].cbBuffer != 1) {
failf(data, "Invalid SSPI encryption response length (%lu).",
(unsigned long)sspi_w_token[1].cbBuffer);
if(sspi_w_token[1].pvBuffer)
Curl_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
curlx_free(sspi_w_token[0].pvBuffer);
return CURLE_COULDNT_CONNECT;
}
memcpy(socksreq, sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
Curl_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
}
else {
if(sspi_w_token[0].cbBuffer != 1) {
failf(data, "Invalid SSPI encryption response length (%lu).",
(unsigned long)sspi_w_token[0].cbBuffer);
curlx_free(sspi_w_token[0].pvBuffer);
return CURLE_COULDNT_CONNECT;
goto fail;
}
memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer);
}
@ -471,6 +462,10 @@ static CURLcode socks5_sspi_encrypt(struct Curl_cfilter *cf,
" GSS-API confidentiality"));
return CURLE_OK;
fail:
curlx_free(sspi_w_token[0].pvBuffer);
return CURLE_COULDNT_CONNECT;
}
CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,

View file

@ -291,7 +291,10 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
input_buf[1].pvBuffer = NULL;
input_buf[1].cbBuffer = 0;
/* Decrypt the inbound challenge and obtain the qop */
/* Decrypt the inbound challenge and obtain the qop. The encrypted message
is decrypted in place, overwriting the original contents of its buffer.
The SECBUFFER_DATA receives a pointer to the message in
SECBUFFER_STREAM. */
status = Curl_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop);
if(status != SEC_E_OK) {
infof(data, "GSSAPI handshake failure (empty security message)");
@ -310,9 +313,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
max_size = ((unsigned long)indata[1] << 16) |
((unsigned long)indata[2] << 8) | indata[3];
/* Free the challenge as it is not required anymore */
Curl_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer);
/* Process the security layer */
if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) {
infof(data, "GSSAPI handshake failure (invalid security layer)");