CVE-2013-4119: NULL Pointer Dereference (CWE-476)
value: FreeRDP before 1.1.0-beta+2013071101 allows remote attackers to cause a denial of service (NULL pointer dereference and application crash) by disconnecting before authentication has finished.
CWE description: The product dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 7.5
Published: 2016-10-03T21:59Z
Repository: https://github.com/FreeRDP/FreeRDP
Language: C
Files changed: libfreerdp/core/nla.c, libfreerdp/core/peer.c, libfreerdp/core/transport.c, winpr/libwinpr/sspi/sspi.c
Commit date: 2013-07-01 19:24:19 +0200
Commit message: nla: invalidate sec handle after creation

If sec pointer isn't invalidated after creation it is not possible
to check if the upper and lower pointers are valid.

This fixes a segfault in the server part if the client disconnects before
the authentication was finished.

Diff: diff --git a/libfreerdp/core/nla.c b/libfreerdp/core/nla.c
index 2b4b71992..875c0ae73 100644
--- a/libfreerdp/core/nla.c
+++ b/libfreerdp/core/nla.c
@@ -1243,10 +1243,11 @@ rdpCredssp* credssp_new(freerdp* instance, rdpTransport* transport, rdpSettings*
 		credssp->send_seq_num = 0;
 		credssp->recv_seq_num = 0;
 		ZeroMemory(&credssp->negoToken, sizeof(SecBuffer));
 		ZeroMemory(&credssp->pubKeyAuth, sizeof(SecBuffer));
 		ZeroMemory(&credssp->authInfo, sizeof(SecBuffer));
+		SecInvalidateHandle(&credssp->context);
 
 		if (credssp->server)
 		{
 			status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"),
 					0, KEY_READ | KEY_WOW64_64KEY, &hKey);
diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c
index 3806a736e..eb4ad60ea 100644
--- a/libfreerdp/core/peer.c
+++ b/libfreerdp/core/peer.c
@@ -270,10 +270,11 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
 			if (rdp->nego->selected_protocol & PROTOCOL_NLA)
 			{
 				sspi_CopyAuthIdentity(&client->identity, &(rdp->nego->transport->credssp->identity));
 				IFCALLRET(client->Logon, client->authenticated, client, &client->identity, TRUE);
 				credssp_free(rdp->nego->transport->credssp);
+				rdp->nego->transport->credssp = NULL;
 			}
 			else
 			{
 				IFCALLRET(client->Logon, client->authenticated, client, &client->identity, FALSE);
 			}
diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c
index a9a710511..4afec5a12 100644
--- a/libfreerdp/core/transport.c
+++ b/libfreerdp/core/transport.c
@@ -157,10 +157,11 @@ BOOL transport_connect_nla(rdpTransport* transport)
 
 		fprintf(stderr, "Authentication failure, check credentials.\n"
 			"If credentials are valid, the NTLMSSP implementation may be to blame.\n");
 
 		credssp_free(transport->credssp);
+		transport->credssp = NULL;
 		return FALSE;
 	}
 
 	credssp_free(transport->credssp);
 
@@ -290,10 +291,11 @@ BOOL transport_accept_nla(rdpTransport* transport)
 
 	if (credssp_authenticate(transport->credssp) < 0)
 	{
 		fprintf(stderr, "client authentication failure\n");
 		credssp_free(transport->credssp);
+		transport->credssp = NULL;
 		return FALSE;
 	}
 
 	/* don't free credssp module yet, we need to copy the credentials from it first */
 
diff --git a/winpr/libwinpr/sspi/sspi.c b/winpr/libwinpr/sspi/sspi.c
index 8747e3f01..96c959995 100644
--- a/winpr/libwinpr/sspi/sspi.c
+++ b/winpr/libwinpr/sspi/sspi.c
@@ -246,11 +246,11 @@ void sspi_SecureHandleInvalidate(SecHandle* handle)
 
 void* sspi_SecureHandleGetLowerPointer(SecHandle* handle)
 {
 	void* pointer;
 
-	if (!handle)
+	if (!handle || !SecIsValidHandle(handle))
 		return NULL;
 
 	pointer = (void*) ~((size_t) handle->dwLower);
 
 	return pointer;
@@ -266,11 +266,11 @@ void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer)
 
 void* sspi_SecureHandleGetUpperPointer(SecHandle* handle)
 {
 	void* pointer;
 
-	if (!handle)
+	if (!handle || !SecIsValidHandle(handle))
 		return NULL;
 
 	pointer = (void*) ~((size_t) handle->dwUpper);
 
 	return pointer;
@@ -837,11 +837,11 @@ SECURITY_STATUS SEC_ENTRY CompleteAuthToken(PCtxtHandle phContext, PSecBufferDes
 	return SEC_E_OK;
 }
 
 SECURITY_STATUS SEC_ENTRY DeleteSecurityContext(PCtxtHandle phContext)
 {
-	char* Name;
+	char* Name = NULL;
 	SECURITY_STATUS status;
 	SecurityFunctionTableA* table;
 
 	Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
 

Vulnerable code: 	if (!handle)
	if (!handle)
	char* Name;
Fixed code: 		SecInvalidateHandle(&credssp->context);
				rdp->nego->transport->credssp = NULL;
		transport->credssp = NULL;
		transport->credssp = NULL;
	if (!handle || !SecIsValidHandle(handle))
	if (!handle || !SecIsValidHandle(handle))
	char* Name = NULL;