Commit d3a25bea authored by Mike Gabriel's avatar Mike Gabriel

debian/patches: Backport CredSSP v3 support and RDP proto v6 support. Patchset...

debian/patches: Backport CredSSP v3 support and RDP proto v6 support. Patchset still incomplete, dysfunctional (committed + pushed for sharing and getting review).
parent 9341b2b7
......@@ -15,7 +15,7 @@ Build-Depends:
libcups2-dev,
libpcsclite-dev,
libpulse-dev,
libssl1.0-dev,
libssl-dev,
libx11-dev,
libxcursor-dev,
libxdamage-dev,
......
--- a/libfreerdp/core/nla.c
+++ b/libfreerdp/core/nla.c
@@ -3,6 +3,7 @@
* Network Level Authentication (NLA)
*
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2016 Martin Fleisz <martin.fleisz@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,7 +44,8 @@
* version [0] INTEGER,
* negoTokens [1] NegoData OPTIONAL,
* authInfo [2] OCTET STRING OPTIONAL,
- * pubKeyAuth [3] OCTET STRING OPTIONAL
+ * pubKeyAuth [3] OCTET STRING OPTIONAL,
+ * errorCode [4] INTEGER OPTIONAL
* }
*
* NegoData ::= SEQUENCE OF NegoDataItem
@@ -560,8 +562,28 @@
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED))
{
+ /* Special handling of these specific error codes as HRESULT_FROM_WIN32
+ unfortunately does not map directly to the corresponding NTSTATUS values
+ */
+ switch (GetLastError())
+ {
+ case ERROR_PASSWORD_MUST_CHANGE:
+ credssp->errorCode = STATUS_PASSWORD_MUST_CHANGE;
+ break;
+ case ERROR_PASSWORD_EXPIRED:
+ credssp->errorCode = STATUS_PASSWORD_EXPIRED;
+ break;
+ case ERROR_ACCOUNT_DISABLED:
+ credssp->errorCode = STATUS_ACCOUNT_DISABLED;
+ break;
+ default:
+ credssp->errorCode = HRESULT_FROM_WIN32(GetLastError());
+ break;
+ }
+
fprintf(stderr, "AcceptSecurityContext status: 0x%08X\n", status);
- return -1;
+ credssp_send(credssp);
+ return -1; /* Access Denied */
}
/* send authentication token */
@@ -1057,15 +1079,24 @@
wStream* s;
int length;
int ts_request_length;
- int nego_tokens_length;
- int pub_key_auth_length;
- int auth_info_length;
-
- nego_tokens_length = (credssp->negoToken.cbBuffer > 0) ? credssp_sizeof_nego_tokens(credssp->negoToken.cbBuffer) : 0;
- pub_key_auth_length = (credssp->pubKeyAuth.cbBuffer > 0) ? credssp_sizeof_pub_key_auth(credssp->pubKeyAuth.cbBuffer) : 0;
- auth_info_length = (credssp->authInfo.cbBuffer > 0) ? credssp_sizeof_auth_info(credssp->authInfo.cbBuffer) : 0;
-
- length = nego_tokens_length + pub_key_auth_length + auth_info_length;
+ int nego_tokens_length = 0;
+ int pub_key_auth_length = 0;
+ int auth_info_length = 0;
+ int error_code_context_length = 0;
+ int error_code_length = 0;
+
+ if (credssp->version < 3 || credssp->errorCode == 0)
+ {
+ nego_tokens_length = (credssp->negoToken.cbBuffer > 0) ? credssp_sizeof_nego_tokens(credssp->negoToken.cbBuffer) : 0;
+ pub_key_auth_length = (credssp->pubKeyAuth.cbBuffer > 0) ? credssp_sizeof_pub_key_auth(credssp->pubKeyAuth.cbBuffer) : 0;
+ auth_info_length = (credssp->authInfo.cbBuffer > 0) ? credssp_sizeof_auth_info(credssp->authInfo.cbBuffer) : 0;
+ }
+ else
+ {
+ error_code_length = ber_sizeof_integer(credssp->errorCode);
+ error_code_context_length = ber_sizeof_contextual_tag(error_code_length);
+ }
+ length = nego_tokens_length + pub_key_auth_length + auth_info_length + error_code_context_length + error_code_length;
ts_request_length = credssp_sizeof_ts_request(length);
@@ -1076,7 +1107,7 @@
/* [0] version */
ber_write_contextual_tag(s, 0, 3, TRUE);
- ber_write_integer(s, 2); /* INTEGER */
+ ber_write_integer(s, credssp->version); /* INTEGER */
/* [1] negoTokens (NegoData) */
if (nego_tokens_length > 0)
@@ -1109,6 +1140,13 @@
// assert length == 0
}
+ /* [4] errorCode (INTEGER) */
+ if (error_code_length > 0)
+ {
+ ber_write_contextual_tag(s, 4, error_code_length, TRUE);
+ ber_write_integer(s, credssp->errorCode);
+ }
+
Stream_SealLength(s);
transport_write(credssp->transport, s);
@@ -1127,7 +1165,6 @@
wStream* s;
int length;
int status;
- UINT32 version;
s = Stream_New(NULL, 4096);
@@ -1144,8 +1181,11 @@
/* TSRequest */
if(!ber_read_sequence_tag(s, &length) ||
!ber_read_contextual_tag(s, 0, &length, TRUE) ||
- !ber_read_integer(s, &version))
+ !ber_read_integer(s, &credssp->version))
+ {
+ Stream_Free(s, TRUE);
return -1;
+ }
/* [1] negoTokens (NegoData) */
if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE)
@@ -1155,7 +1195,10 @@
!ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */
!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
Stream_GetRemainingLength(s) < length)
+ {
+ Stream_Free(s, TRUE);
return -1;
+ }
sspi_SecBufferAlloc(&credssp->negoToken, length);
Stream_Read(s, credssp->negoToken.pvBuffer, length);
credssp->negoToken.cbBuffer = length;
@@ -1166,7 +1209,10 @@
{
if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
Stream_GetRemainingLength(s) < length)
+ {
+ Stream_Free(s, TRUE);
return -1;
+ }
sspi_SecBufferAlloc(&credssp->authInfo, length);
Stream_Read(s, credssp->authInfo.pvBuffer, length);
credssp->authInfo.cbBuffer = length;
@@ -1177,11 +1223,26 @@
{
if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
Stream_GetRemainingLength(s) < length)
+ {
+ Stream_Free(s, TRUE);
return -1;
+ }
sspi_SecBufferAlloc(&credssp->pubKeyAuth, length);
Stream_Read(s, credssp->pubKeyAuth.pvBuffer, length);
credssp->pubKeyAuth.cbBuffer = length;
}
+ /* [4] errorCode (INTEGER) */
+ if (credssp->version >= 3)
+ {
+ if (ber_read_contextual_tag(s, 4, &length, TRUE) != FALSE)
+ {
+ if (!ber_read_integer(s, &credssp->errorCode))
+ {
+ Stream_Free(s, TRUE);
+ return -1;
+ }
+ }
+ }
Stream_Free(s, TRUE);
@@ -1242,6 +1303,8 @@
credssp->transport = transport;
credssp->send_seq_num = 0;
credssp->recv_seq_num = 0;
+ credssp->version = 3;
+
ZeroMemory(&credssp->negoToken, sizeof(SecBuffer));
ZeroMemory(&credssp->pubKeyAuth, sizeof(SecBuffer));
ZeroMemory(&credssp->authInfo, sizeof(SecBuffer));
--- a/libfreerdp/core/nla.h
+++ b/libfreerdp/core/nla.h
@@ -45,6 +45,8 @@
LPTSTR SspiModule;
rdpSettings* settings;
rdpTransport* transport;
+ UINT32 version;
+ UINT32 errorCode;
SecBuffer negoToken;
SecBuffer pubKeyAuth;
SecBuffer authInfo;
--- a/libfreerdp/crypto/ber.c
+++ b/libfreerdp/crypto/ber.c
@@ -448,6 +448,14 @@
Stream_Write_UINT32_BE(s, value);
return 6;
}
+ else
+ {
+ /* treat as signed integer i.e. NT/HRESULT error codes */
+ ber_write_universal_tag(s, BER_TAG_INTEGER, FALSE);
+ ber_write_length(s, 4);
+ Stream_Write_UINT32_BE(s, value);
+ return 6;
+ }
return 0;
}
@@ -470,6 +478,11 @@
{
return 6;
}
+ else
+ {
+ /* treat as signed integer i.e. NT/HRESULT error codes */
+ return 6;
+ }
return 0;
}
This diff is collapsed.
From e7ae3f6babc881d893411a5ada9156abe8525b2f Mon Sep 17 00:00:00 2001
From: Bernhard Miklautz <bernhard.miklautz@thincast.com>
Date: Wed, 14 Mar 2018 13:39:23 +0100
Subject: [PATCH] fix nla: don't use server version
FreeRDP currently only supports CredSSP protocol version 3. However the
current implementation always sent back the version received by the
server indicating that this version was supported.
With recent windows updates applied the protocol changed and this approach
doesn't work anymore (see
https://msdn.microsoft.com/en-us/library/mt752485.aspx for protocol changes).
With this fix FreeRDP always sends version 3 as supported version.
Credit goes to @mfleisz.
Fixes #4449
---
libfreerdp/core/nla.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/libfreerdp/core/nla.c
+++ b/libfreerdp/core/nla.c
@@ -1364,6 +1364,7 @@
wStream* s;
int length;
int status;
+ UNIT32 version;
s = Stream_New(NULL, 4096);
@@ -1380,12 +1381,15 @@
/* TSRequest */
if(!ber_read_sequence_tag(s, &length) ||
!ber_read_contextual_tag(s, 0, &length, TRUE) ||
- !ber_read_integer(s, &credssp->version))
+ !ber_read_integer(s, &version))
{
Stream_Free(s, TRUE);
return -1;
}
+ if (version < credssp->version)
+ credssp->version = version;
+
/* [1] negoTokens (NegoData) */
if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE)
{
--- a/libfreerdp/core/nla.c
+++ b/libfreerdp/core/nla.c
@@ -3,6 +3,7 @@
* Network Level Authentication (NLA)
*
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2016 Martin Fleisz <martin.fleisz@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,7 +44,8 @@
* version [0] INTEGER,
* negoTokens [1] NegoData OPTIONAL,
* authInfo [2] OCTET STRING OPTIONAL,
- * pubKeyAuth [3] OCTET STRING OPTIONAL
+ * pubKeyAuth [3] OCTET STRING OPTIONAL,
+ * errorCode [4] INTEGER OPTIONAL
* }
*
* NegoData ::= SEQUENCE OF NegoDataItem
@@ -560,8 +562,28 @@
if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED))
{
+ /* Special handling of these specific error codes as HRESULT_FROM_WIN32
+ unfortunately does not map directly to the corresponding NTSTATUS values
+ */
+ switch (GetLastError())
+ {
+ case ERROR_PASSWORD_MUST_CHANGE:
+ credssp->errorCode = STATUS_PASSWORD_MUST_CHANGE;
+ break;
+ case ERROR_PASSWORD_EXPIRED:
+ credssp->errorCode = STATUS_PASSWORD_EXPIRED;
+ break;
+ case ERROR_ACCOUNT_DISABLED:
+ credssp->errorCode = STATUS_ACCOUNT_DISABLED;
+ break;
+ default:
+ credssp->errorCode = HRESULT_FROM_WIN32(GetLastError());
+ break;
+ }
+
fprintf(stderr, "AcceptSecurityContext status: 0x%08X\n", status);
- return -1;
+ credssp_send(credssp);
+ return -1; /* Access Denied */
}
/* send authentication token */
@@ -1057,15 +1079,24 @@
wStream* s;
int length;
int ts_request_length;
- int nego_tokens_length;
- int pub_key_auth_length;
- int auth_info_length;
-
- nego_tokens_length = (credssp->negoToken.cbBuffer > 0) ? credssp_sizeof_nego_tokens(credssp->negoToken.cbBuffer) : 0;
- pub_key_auth_length = (credssp->pubKeyAuth.cbBuffer > 0) ? credssp_sizeof_pub_key_auth(credssp->pubKeyAuth.cbBuffer) : 0;
- auth_info_length = (credssp->authInfo.cbBuffer > 0) ? credssp_sizeof_auth_info(credssp->authInfo.cbBuffer) : 0;
-
- length = nego_tokens_length + pub_key_auth_length + auth_info_length;
+ int nego_tokens_length = 0;
+ int pub_key_auth_length = 0;
+ int auth_info_length = 0;
+ int error_code_context_length = 0;
+ int error_code_length = 0;
+
+ if (credssp->version < 3 || credssp->errorCode == 0)
+ {
+ nego_tokens_length = (credssp->negoToken.cbBuffer > 0) ? credssp_sizeof_nego_tokens(credssp->negoToken.cbBuffer) : 0;
+ pub_key_auth_length = (credssp->pubKeyAuth.cbBuffer > 0) ? credssp_sizeof_pub_key_auth(credssp->pubKeyAuth.cbBuffer) : 0;
+ auth_info_length = (credssp->authInfo.cbBuffer > 0) ? credssp_sizeof_auth_info(credssp->authInfo.cbBuffer) : 0;
+ }
+ else
+ {
+ error_code_length = ber_sizeof_integer(nla->errorCode);
+ error_code_context_length = ber_sizeof_contextual_tag(error_code_length);
+ }
+ length = nego_tokens_length + pub_key_auth_length + auth_info_length + error_code_context_length + error_code_length;
ts_request_length = credssp_sizeof_ts_request(length);
@@ -1076,7 +1107,7 @@
/* [0] version */
ber_write_contextual_tag(s, 0, 3, TRUE);
- ber_write_integer(s, 2); /* INTEGER */
+ ber_write_integer(s, credssp->version); /* INTEGER */
/* [1] negoTokens (NegoData) */
if (nego_tokens_length > 0)
@@ -1109,6 +1140,13 @@
// assert length == 0
}
+ /* [4] errorCode (INTEGER) */
+ if (error_code_length > 0)
+ {
+ ber_write_contextual_tag(s, 4, error_code_length, TRUE);
+ ber_write_integer(s, nla->errorCode);
+ }
+
Stream_SealLength(s);
transport_write(credssp->transport, s);
@@ -1127,7 +1165,6 @@
wStream* s;
int length;
int status;
- UINT32 version;
s = Stream_New(NULL, 4096);
@@ -1144,8 +1181,11 @@
/* TSRequest */
if(!ber_read_sequence_tag(s, &length) ||
!ber_read_contextual_tag(s, 0, &length, TRUE) ||
- !ber_read_integer(s, &version))
+ !ber_read_integer(s, &credssp->version))
+ {
+ Stream_Free(s, TRUE);
return -1;
+ }
/* [1] negoTokens (NegoData) */
if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE)
@@ -1155,7 +1195,10 @@
!ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */
!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
Stream_GetRemainingLength(s) < length)
+ {
+ Stream_Free(s, TRUE);
return -1;
+ }
sspi_SecBufferAlloc(&credssp->negoToken, length);
Stream_Read(s, credssp->negoToken.pvBuffer, length);
credssp->negoToken.cbBuffer = length;
@@ -1166,7 +1209,10 @@
{
if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
Stream_GetRemainingLength(s) < length)
+ {
+ Stream_Free(s, TRUE);
return -1;
+ }
sspi_SecBufferAlloc(&credssp->authInfo, length);
Stream_Read(s, credssp->authInfo.pvBuffer, length);
credssp->authInfo.cbBuffer = length;
@@ -1177,11 +1223,26 @@
{
if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
Stream_GetRemainingLength(s) < length)
+ {
+ Stream_Free(s, TRUE);
return -1;
+ }
sspi_SecBufferAlloc(&credssp->pubKeyAuth, length);
Stream_Read(s, credssp->pubKeyAuth.pvBuffer, length);
credssp->pubKeyAuth.cbBuffer = length;
}
+ /* [4] errorCode (INTEGER) */
+ if (credssp->version >= 3)
+ {
+ if (ber_read_contextual_tag(s, 4, &length, TRUE) != FALSE)
+ {
+ if (!ber_read_integer(s, &credssp->errorCode))
+ {
+ Stream_Free(s, TRUE);
+ return -1;
+ }
+ }
+ }
Stream_Free(s, TRUE);
@@ -1242,6 +1303,8 @@
credssp->transport = transport;
credssp->send_seq_num = 0;
credssp->recv_seq_num = 0;
+ credssp->version = 3;
+
ZeroMemory(&credssp->negoToken, sizeof(SecBuffer));
ZeroMemory(&credssp->pubKeyAuth, sizeof(SecBuffer));
ZeroMemory(&credssp->authInfo, sizeof(SecBuffer));
--- a/libfreerdp/core/nla.h
+++ b/libfreerdp/core/nla.h
@@ -45,6 +45,8 @@
LPTSTR SspiModule;
rdpSettings* settings;
rdpTransport* transport;
+ UINT32 version;
+ UINT32 errorCode;
SecBuffer negoToken;
SecBuffer pubKeyAuth;
SecBuffer authInfo;
--- a/libfreerdp/crypto/ber.c
+++ b/libfreerdp/crypto/ber.c
@@ -448,6 +448,14 @@
Stream_Write_UINT32_BE(s, value);
return 6;
}
+ else
+ {
+ /* treat as signed integer i.e. NT/HRESULT error codes */
+ ber_write_universal_tag(s, BER_TAG_INTEGER, FALSE);
+ ber_write_length(s, 4);
+ Stream_Write_UINT32_BE(s, value);
+ return 6;
+ }
return 0;
}
@@ -470,6 +478,11 @@
{
return 6;
}
+ else
+ {
+ /* treat as signed integer i.e. NT/HRESULT error codes */
+ return 6;
+ }
return 0;
}
......@@ -25,3 +25,6 @@ CVE-2018-8786.patch
CVE-2018-8787.patch
CVE-2018-8788.patch
CVE-2018-8789.patch
0010_add-support-for-credssp-version-3.patch
0011_add-support-for-proto-version-6.patch
0012-fix-nla-don-t-use-server-version.patch
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment