Vulnerability: In FreeRDP less than or equal to 2.0.0, there is an out-of-bound read in ntlm_read_AuthenticateMessage. This has been fixed in 2.1.0.
Vulnerability ID: CVE-2020-11087
CWE: CWE-125
Severity score: 4.9
Project: https://github.com/FreeRDP/FreeRDP
Published: 2020-05-29
File: winpr/libwinpr/sspi/NTLM/ntlm_message.c
Commit message: Fixed oob read in ntlm_read_AuthenticateMessage
Commit author: akallabeth

Vulnerable version (before fix):
 SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu  SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer) { 	wStream* s; 	size_t length; 	UINT32 flags; 	NTLM_AV_PAIR* AvFlags; 	UINT32 PayloadBufferOffset; 	NTLM_AUTHENTICATE_MESSAGE* message; 	SSPI_CREDENTIALS* credentials = context->credentials; 	flags = 0; 	AvFlags = NULL; 	message = &context->AUTHENTICATE_MESSAGE; 	ZeroMemory(message, sizeof(NTLM_AUTHENTICATE_MESSAGE)); 	s = Stream_New((BYTE*)buffer->pvBuffer, buffer->cbBuffer); SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer 		return SEC_E_INTERNAL_ERROR;  	if (ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*)message) < 0) 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INVALID_TOKEN; 	}  	if (message->MessageType != MESSAGE_TYPE_AUTHENTICATE) 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INVALID_TOKEN; 	}  	if (ntlm_read_message_fields(s, &(message->LmChallengeResponse)) < 	    0) /* LmChallengeResponseFields (8 bytes) */ 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INVALID_TOKEN; 	}  	if (ntlm_read_message_fields(s, &(message->NtChallengeResponse)) < 	    0) /* NtChallengeResponseFields (8 bytes) */ 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INVALID_TOKEN; 	}  	if (ntlm_read_message_fields(s, &(message->DomainName)) < 0) /* DomainNameFields (8 bytes) */ 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INVALID_TOKEN; 	}  	if (ntlm_read_message_fields(s, &(message->UserName)) < 0) /* UserNameFields (8 bytes) */ 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INVALID_TOKEN; 	}  	if (ntlm_read_message_fields(s, &(message->Workstation)) < 0) /* WorkstationFields (8 bytes) */ 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INVALID_TOKEN; 	}  	if (ntlm_read_message_fields(s, &(message->EncryptedRandomSessionKey)) < 	    0) /* EncryptedRandomSessionKeyFields (8 bytes) */ 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INVALID_TOKEN; 	}  	Stream_Read_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */ 	context->NegotiateKeyExchange = 	    (message->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH) ? TRUE : FALSE;  	if ((context->NegotiateKeyExchange && !message->EncryptedRandomSessionKey.Len) || 	    (!context->NegotiateKeyExchange && message->EncryptedRandomSessionKey.Len)) 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INVALID_TOKEN; 	}  	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) 	{ 		if (ntlm_read_version_info(s, &(message->Version)) < 0) /* Version (8 bytes) */ 		{ 			Stream_Free(s, FALSE); 			return SEC_E_INVALID_TOKEN; 		} 	}  	PayloadBufferOffset = Stream_GetPosition(s);  	if (ntlm_read_message_fields_buffer(s, &(message->DomainName)) < 0) /* DomainName */ 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INTERNAL_ERROR; 	}  	if (ntlm_read_message_fields_buffer(s, &(message->UserName)) < 0) /* UserName */ 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INTERNAL_ERROR; 	}  	if (ntlm_read_message_fields_buffer(s, &(message->Workstation)) < 0) /* Workstation */ 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INTERNAL_ERROR; 	}  	if (ntlm_read_message_fields_buffer(s, &(message->LmChallengeResponse)) < 	    0) /* LmChallengeResponse */ 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INTERNAL_ERROR; 	}  	if (ntlm_read_message_fields_buffer(s, &(message->NtChallengeResponse)) < 	    0) /* NtChallengeResponse */ 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INTERNAL_ERROR; 	}  	if (message->NtChallengeResponse.Len > 0) 	{ 		size_t cbAvFlags; 		wStream* snt = 		    Stream_New(message->NtChallengeResponse.Buffer, message->NtChallengeResponse.Len);  		if (!snt) 		{ 			Stream_Free(s, FALSE); 			return SEC_E_INTERNAL_ERROR; 		}  		if (ntlm_read_ntlm_v2_response(snt, &(context->NTLMv2Response)) < 0) 		{ 			Stream_Free(s, FALSE); 			Stream_Free(snt, FALSE); 			return SEC_E_INVALID_TOKEN; 		}  		Stream_Free(snt, FALSE); 		context->NtChallengeResponse.pvBuffer = message->NtChallengeResponse.Buffer; 		context->NtChallengeResponse.cbBuffer = message->NtChallengeResponse.Len; 		sspi_SecBufferFree(&(context->ChallengeTargetInfo)); SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer  	if (ntlm_read_message_fields_buffer(s, &(message->EncryptedRandomSessionKey)) < 	    0) /* EncryptedRandomSessionKey */ 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INTERNAL_ERROR; 	}  	if (message->EncryptedRandomSessionKey.Len > 0) 	{ 		if (message->EncryptedRandomSessionKey.Len != 16) 		{ 			Stream_Free(s, FALSE); 			return SEC_E_INVALID_TOKEN; 		}  		CopyMemory(context->EncryptedRandomSessionKey, message->EncryptedRandomSessionKey.Buffer, 		           16); SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer 	length = Stream_GetPosition(s);  	if (!sspi_SecBufferAlloc(&context->AuthenticateMessage, length)) 	{ 		Stream_Free(s, FALSE); 		return SEC_E_INTERNAL_ERROR; 	}  	CopyMemory(context->AuthenticateMessage.pvBuffer, Stream_Buffer(s), length); 	buffer->cbBuffer = length; SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer 	{ 		context->MessageIntegrityCheckOffset = (UINT32)Stream_GetPosition(s);  		if (Stream_GetRemainingLength(s) < 16) 		{ 			Stream_Free(s, FALSE); 			return SEC_E_INVALID_TOKEN; 		}  		Stream_Read(s, message->MessageIntegrityCheck, 16); 	}  #ifdef WITH_DEBUG_NTLM 	WLog_DBG(TAG, "AUTHENTICATE_MESSAGE (length = %" PRIu32 ")", 	         context->AuthenticateMessage.cbBuffer); SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer 		credentials->identity.User = (UINT16*)malloc(message->UserName.Len);  		if (!credentials->identity.User) 		{ 			Stream_Free(s, FALSE); 			return SEC_E_INTERNAL_ERROR; 		}  		CopyMemory(credentials->identity.User, message->UserName.Buffer, message->UserName.Len); 		credentials->identity.UserLength = message->UserName.Len / 2; SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer 		credentials->identity.Domain = (UINT16*)malloc(message->DomainName.Len);  		if (!credentials->identity.Domain) 		{ 			Stream_Free(s, FALSE); 			return SEC_E_INTERNAL_ERROR; 		}  		CopyMemory(credentials->identity.Domain, message->DomainName.Buffer, 		           message->DomainName.Len); SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer 	/* Computations beyond this point require the NTLM hash of the password */ 	context->state = NTLM_STATE_COMPLETION; 	return SEC_I_COMPLETE_NEEDED; }  /**

Fixed version (after fix):
 SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu  SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer) { 	SECURITY_STATUS status = SEC_E_INVALID_TOKEN; 	wStream* s; 	size_t length; 	UINT32 flags = 0; 	NTLM_AV_PAIR* AvFlags = NULL; 	UINT32 PayloadBufferOffset; 	NTLM_AUTHENTICATE_MESSAGE* message; 	SSPI_CREDENTIALS* credentials = context->credentials;  	message = &context->AUTHENTICATE_MESSAGE; 	ZeroMemory(message, sizeof(NTLM_AUTHENTICATE_MESSAGE)); 	s = Stream_New((BYTE*)buffer->pvBuffer, buffer->cbBuffer); SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer 		return SEC_E_INTERNAL_ERROR;  	if (ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*)message) < 0) 		goto fail;  	if (message->MessageType != MESSAGE_TYPE_AUTHENTICATE) 		goto fail;  	if (ntlm_read_message_fields(s, &(message->LmChallengeResponse)) < 	    0) /* LmChallengeResponseFields (8 bytes) */ 		goto fail;  	if (ntlm_read_message_fields(s, &(message->NtChallengeResponse)) < 	    0) /* NtChallengeResponseFields (8 bytes) */ 		goto fail;  	if (ntlm_read_message_fields(s, &(message->DomainName)) < 0) /* DomainNameFields (8 bytes) */ 		goto fail;  	if (ntlm_read_message_fields(s, &(message->UserName)) < 0) /* UserNameFields (8 bytes) */ 		goto fail;  	if (ntlm_read_message_fields(s, &(message->Workstation)) < 0) /* WorkstationFields (8 bytes) */ 		goto fail;  	if (ntlm_read_message_fields(s, &(message->EncryptedRandomSessionKey)) < 	    0) /* EncryptedRandomSessionKeyFields (8 bytes) */ 		goto fail;  	if (Stream_GetRemainingLength(s) < 4) 		goto fail; 	Stream_Read_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */ 	context->NegotiateKeyExchange = 	    (message->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH) ? TRUE : FALSE;  	if ((context->NegotiateKeyExchange && !message->EncryptedRandomSessionKey.Len) || 	    (!context->NegotiateKeyExchange && message->EncryptedRandomSessionKey.Len)) 		goto fail;  	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) 	{ 		if (ntlm_read_version_info(s, &(message->Version)) < 0) /* Version (8 bytes) */ 			goto fail; 	}  	PayloadBufferOffset = Stream_GetPosition(s);  	status = SEC_E_INTERNAL_ERROR; 	if (ntlm_read_message_fields_buffer(s, &(message->DomainName)) < 0) /* DomainName */ 		goto fail;  	if (ntlm_read_message_fields_buffer(s, &(message->UserName)) < 0) /* UserName */ 		goto fail;  	if (ntlm_read_message_fields_buffer(s, &(message->Workstation)) < 0) /* Workstation */ 		goto fail;  	if (ntlm_read_message_fields_buffer(s, &(message->LmChallengeResponse)) < 	    0) /* LmChallengeResponse */ 		goto fail;  	if (ntlm_read_message_fields_buffer(s, &(message->NtChallengeResponse)) < 	    0) /* NtChallengeResponse */ 		goto fail;  	if (message->NtChallengeResponse.Len > 0) 	{ 		int rc; 		size_t cbAvFlags; 		wStream* snt = 		    Stream_New(message->NtChallengeResponse.Buffer, message->NtChallengeResponse.Len);  		if (!snt) 			goto fail;  		status = SEC_E_INVALID_TOKEN; 		rc = ntlm_read_ntlm_v2_response(snt, &(context->NTLMv2Response)); 		Stream_Free(snt, FALSE); 		if (rc < 0) 			goto fail; 		status = SEC_E_INTERNAL_ERROR;  		context->NtChallengeResponse.pvBuffer = message->NtChallengeResponse.Buffer; 		context->NtChallengeResponse.cbBuffer = message->NtChallengeResponse.Len; 		sspi_SecBufferFree(&(context->ChallengeTargetInfo)); SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer  	if (ntlm_read_message_fields_buffer(s, &(message->EncryptedRandomSessionKey)) < 	    0) /* EncryptedRandomSessionKey */ 		goto fail;  	if (message->EncryptedRandomSessionKey.Len > 0) 	{ 		if (message->EncryptedRandomSessionKey.Len != 16) 			goto fail;  		CopyMemory(context->EncryptedRandomSessionKey, message->EncryptedRandomSessionKey.Buffer, 		           16); SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer 	length = Stream_GetPosition(s);  	if (!sspi_SecBufferAlloc(&context->AuthenticateMessage, length)) 		goto fail;  	CopyMemory(context->AuthenticateMessage.pvBuffer, Stream_Buffer(s), length); 	buffer->cbBuffer = length; SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer 	{ 		context->MessageIntegrityCheckOffset = (UINT32)Stream_GetPosition(s);  		status = SEC_E_INVALID_TOKEN; 		if (Stream_GetRemainingLength(s) < 16) 			goto fail;  		Stream_Read(s, message->MessageIntegrityCheck, 16); 	}  	status = SEC_E_INTERNAL_ERROR;  #ifdef WITH_DEBUG_NTLM 	WLog_DBG(TAG, "AUTHENTICATE_MESSAGE (length = %" PRIu32 ")", 	         context->AuthenticateMessage.cbBuffer); SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer 		credentials->identity.User = (UINT16*)malloc(message->UserName.Len);  		if (!credentials->identity.User) 			goto fail;  		CopyMemory(credentials->identity.User, message->UserName.Buffer, message->UserName.Len); 		credentials->identity.UserLength = message->UserName.Len / 2; SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer 		credentials->identity.Domain = (UINT16*)malloc(message->DomainName.Len);  		if (!credentials->identity.Domain) 			goto fail;  		CopyMemory(credentials->identity.Domain, message->DomainName.Buffer, 		           message->DomainName.Len); SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer 	/* Computations beyond this point require the NTLM hash of the password */ 	context->state = NTLM_STATE_COMPLETION; 	return SEC_I_COMPLETE_NEEDED;  fail: 	Stream_Free(s, FALSE); 	return status; }  /**

Patch:
patch: @@ -681,15 +681,15 @@ SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer bu
 
 SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer buffer)
 {
+	SECURITY_STATUS status = SEC_E_INVALID_TOKEN;
 	wStream* s;
 	size_t length;
-	UINT32 flags;
-	NTLM_AV_PAIR* AvFlags;
+	UINT32 flags = 0;
+	NTLM_AV_PAIR* AvFlags = NULL;
 	UINT32 PayloadBufferOffset;
 	NTLM_AUTHENTICATE_MESSAGE* message;
 	SSPI_CREDENTIALS* credentials = context->credentials;
-	flags = 0;
-	AvFlags = NULL;
+
 	message = &context->AUTHENTICATE_MESSAGE;
 	ZeroMemory(message, sizeof(NTLM_AUTHENTICATE_MESSAGE));
 	s = Stream_New((BYTE*)buffer->pvBuffer, buffer->cbBuffer);
@@ -698,130 +698,85 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 		return SEC_E_INTERNAL_ERROR;
 
 	if (ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*)message) < 0)
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;
 
 	if (message->MessageType != MESSAGE_TYPE_AUTHENTICATE)
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;
 
 	if (ntlm_read_message_fields(s, &(message->LmChallengeResponse)) <
 	    0) /* LmChallengeResponseFields (8 bytes) */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;
 
 	if (ntlm_read_message_fields(s, &(message->NtChallengeResponse)) <
 	    0) /* NtChallengeResponseFields (8 bytes) */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;
 
 	if (ntlm_read_message_fields(s, &(message->DomainName)) < 0) /* DomainNameFields (8 bytes) */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;
 
 	if (ntlm_read_message_fields(s, &(message->UserName)) < 0) /* UserNameFields (8 bytes) */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;
 
 	if (ntlm_read_message_fields(s, &(message->Workstation)) < 0) /* WorkstationFields (8 bytes) */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;
 
 	if (ntlm_read_message_fields(s, &(message->EncryptedRandomSessionKey)) <
 	    0) /* EncryptedRandomSessionKeyFields (8 bytes) */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;
 
+	if (Stream_GetRemainingLength(s) < 4)
+		goto fail;
 	Stream_Read_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */
 	context->NegotiateKeyExchange =
 	    (message->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH) ? TRUE : FALSE;
 
 	if ((context->NegotiateKeyExchange && !message->EncryptedRandomSessionKey.Len) ||
 	    (!context->NegotiateKeyExchange && message->EncryptedRandomSessionKey.Len))
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INVALID_TOKEN;
-	}
+		goto fail;
 
 	if (message->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
 	{
 		if (ntlm_read_version_info(s, &(message->Version)) < 0) /* Version (8 bytes) */
-		{
-			Stream_Free(s, FALSE);
-			return SEC_E_INVALID_TOKEN;
-		}
+			goto fail;
 	}
 
 	PayloadBufferOffset = Stream_GetPosition(s);
 
+	status = SEC_E_INTERNAL_ERROR;
 	if (ntlm_read_message_fields_buffer(s, &(message->DomainName)) < 0) /* DomainName */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;
 
 	if (ntlm_read_message_fields_buffer(s, &(message->UserName)) < 0) /* UserName */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;
 
 	if (ntlm_read_message_fields_buffer(s, &(message->Workstation)) < 0) /* Workstation */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;
 
 	if (ntlm_read_message_fields_buffer(s, &(message->LmChallengeResponse)) <
 	    0) /* LmChallengeResponse */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;
 
 	if (ntlm_read_message_fields_buffer(s, &(message->NtChallengeResponse)) <
 	    0) /* NtChallengeResponse */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;
 
 	if (message->NtChallengeResponse.Len > 0)
 	{
+		int rc;
 		size_t cbAvFlags;
 		wStream* snt =
 		    Stream_New(message->NtChallengeResponse.Buffer, message->NtChallengeResponse.Len);
 
 		if (!snt)
-		{
-			Stream_Free(s, FALSE);
-			return SEC_E_INTERNAL_ERROR;
-		}
-
-		if (ntlm_read_ntlm_v2_response(snt, &(context->NTLMv2Response)) < 0)
-		{
-			Stream_Free(s, FALSE);
-			Stream_Free(snt, FALSE);
-			return SEC_E_INVALID_TOKEN;
-		}
+			goto fail;
 
+		status = SEC_E_INVALID_TOKEN;
+		rc = ntlm_read_ntlm_v2_response(snt, &(context->NTLMv2Response));
 		Stream_Free(snt, FALSE);
+		if (rc < 0)
+			goto fail;
+		status = SEC_E_INTERNAL_ERROR;
+
 		context->NtChallengeResponse.pvBuffer = message->NtChallengeResponse.Buffer;
 		context->NtChallengeResponse.cbBuffer = message->NtChallengeResponse.Len;
 		sspi_SecBufferFree(&(context->ChallengeTargetInfo));
@@ -838,18 +793,12 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 
 	if (ntlm_read_message_fields_buffer(s, &(message->EncryptedRandomSessionKey)) <
 	    0) /* EncryptedRandomSessionKey */
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;
 
 	if (message->EncryptedRandomSessionKey.Len > 0)
 	{
 		if (message->EncryptedRandomSessionKey.Len != 16)
-		{
-			Stream_Free(s, FALSE);
-			return SEC_E_INVALID_TOKEN;
-		}
+			goto fail;
 
 		CopyMemory(context->EncryptedRandomSessionKey, message->EncryptedRandomSessionKey.Buffer,
 		           16);
@@ -858,10 +807,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 	length = Stream_GetPosition(s);
 
 	if (!sspi_SecBufferAlloc(&context->AuthenticateMessage, length))
-	{
-		Stream_Free(s, FALSE);
-		return SEC_E_INTERNAL_ERROR;
-	}
+		goto fail;
 
 	CopyMemory(context->AuthenticateMessage.pvBuffer, Stream_Buffer(s), length);
 	buffer->cbBuffer = length;
@@ -871,15 +817,15 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 	{
 		context->MessageIntegrityCheckOffset = (UINT32)Stream_GetPosition(s);
 
+		status = SEC_E_INVALID_TOKEN;
 		if (Stream_GetRemainingLength(s) < 16)
-		{
-			Stream_Free(s, FALSE);
-			return SEC_E_INVALID_TOKEN;
-		}
+			goto fail;
 
 		Stream_Read(s, message->MessageIntegrityCheck, 16);
 	}
 
+	status = SEC_E_INTERNAL_ERROR;
+
 #ifdef WITH_DEBUG_NTLM
 	WLog_DBG(TAG, "AUTHENTICATE_MESSAGE (length = %" PRIu32 ")",
 	         context->AuthenticateMessage.cbBuffer);
@@ -911,10 +857,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 		credentials->identity.User = (UINT16*)malloc(message->UserName.Len);
 
 		if (!credentials->identity.User)
-		{
-			Stream_Free(s, FALSE);
-			return SEC_E_INTERNAL_ERROR;
-		}
+			goto fail;
 
 		CopyMemory(credentials->identity.User, message->UserName.Buffer, message->UserName.Len);
 		credentials->identity.UserLength = message->UserName.Len / 2;
@@ -925,10 +868,7 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 		credentials->identity.Domain = (UINT16*)malloc(message->DomainName.Len);
 
 		if (!credentials->identity.Domain)
-		{
-			Stream_Free(s, FALSE);
-			return SEC_E_INTERNAL_ERROR;
-		}
+			goto fail;
 
 		CopyMemory(credentials->identity.Domain, message->DomainName.Buffer,
 		           message->DomainName.Len);
@@ -939,6 +879,10 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer
 	/* Computations beyond this point require the NTLM hash of the password */
 	context->state = NTLM_STATE_COMPLETION;
 	return SEC_I_COMPLETE_NEEDED;
+
+fail:
+	Stream_Free(s, FALSE);
+	return status;
 }
 
 /**
path: winpr/libwinpr/sspi/NTLM/ntlm_message.c