Merge pull request #5022 from akallabeth/gw_rdg_error_mapping
Improved error mapping and tightened checks in rdg_process_packet
This commit is contained in:
commit
6c97d318ec
@ -425,7 +425,7 @@ static BOOL rdp_client_redirect_try_fqdn(rdpSettings* settings)
|
||||
{
|
||||
if (settings->RedirectionFlags & LB_TARGET_FQDN)
|
||||
{
|
||||
if (rdp_client_redirect_resolvable(settings->RedirectionTargetFQDN))
|
||||
if (settings->GatewayEnabled || rdp_client_redirect_resolvable(settings->RedirectionTargetFQDN))
|
||||
{
|
||||
free(settings->ServerHostname);
|
||||
settings->ServerHostname = _strdup(settings->RedirectionTargetFQDN);
|
||||
@ -460,7 +460,7 @@ static BOOL rdp_client_redirect_try_netbios(rdpSettings* settings)
|
||||
{
|
||||
if (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME)
|
||||
{
|
||||
if (rdp_client_redirect_resolvable(settings->RedirectionTargetNetBiosName))
|
||||
if (settings->GatewayEnabled || rdp_client_redirect_resolvable(settings->RedirectionTargetNetBiosName))
|
||||
{
|
||||
free(settings->ServerHostname);
|
||||
settings->ServerHostname = _strdup(settings->RedirectionTargetNetBiosName);
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "../proxy.h"
|
||||
#include "../rdp.h"
|
||||
#include "../../crypto/opensslcompat.h"
|
||||
#include "rpc_fault.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.rdg")
|
||||
|
||||
@ -147,6 +148,89 @@ typedef struct rdg_packet_header
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 code;
|
||||
const char* name;
|
||||
} t_err_mapping;
|
||||
|
||||
static const t_err_mapping tunnel_response_fields_present[] =
|
||||
{
|
||||
{HTTP_TUNNEL_RESPONSE_FIELD_TUNNEL_ID, "HTTP_TUNNEL_RESPONSE_FIELD_TUNNEL_ID"},
|
||||
{HTTP_TUNNEL_RESPONSE_FIELD_CAPS, "HTTP_TUNNEL_RESPONSE_FIELD_CAPS"},
|
||||
{HTTP_TUNNEL_RESPONSE_FIELD_SOH_REQ, "HTTP_TUNNEL_RESPONSE_FIELD_SOH_REQ"},
|
||||
{HTTP_TUNNEL_RESPONSE_FIELD_CONSENT_MSG, "HTTP_TUNNEL_RESPONSE_FIELD_CONSENT_MSG"}
|
||||
};
|
||||
|
||||
static const t_err_mapping channel_response_fields_present[] =
|
||||
{
|
||||
{HTTP_CHANNEL_RESPONSE_FIELD_CHANNELID, "HTTP_CHANNEL_RESPONSE_FIELD_CHANNELID"},
|
||||
{HTTP_CHANNEL_RESPONSE_OPTIONAL, "HTTP_CHANNEL_RESPONSE_OPTIONAL"},
|
||||
{HTTP_CHANNEL_RESPONSE_FIELD_UDPPORT, "HTTP_CHANNEL_RESPONSE_FIELD_UDPPORT"}
|
||||
};
|
||||
|
||||
static const t_err_mapping tunnel_authorization_response_fields_present[] =
|
||||
{
|
||||
{HTTP_TUNNEL_AUTH_RESPONSE_FIELD_REDIR_FLAGS, "HTTP_TUNNEL_AUTH_RESPONSE_FIELD_REDIR_FLAGS"},
|
||||
{HTTP_TUNNEL_AUTH_RESPONSE_FIELD_IDLE_TIMEOUT, "HTTP_TUNNEL_AUTH_RESPONSE_FIELD_IDLE_TIMEOUT"},
|
||||
{HTTP_TUNNEL_AUTH_RESPONSE_FIELD_SOH_RESPONSE, "HTTP_TUNNEL_AUTH_RESPONSE_FIELD_SOH_RESPONSE"}
|
||||
};
|
||||
|
||||
static const t_err_mapping extended_auth[] =
|
||||
{
|
||||
{HTTP_EXTENDED_AUTH_NONE, "HTTP_EXTENDED_AUTH_NONE"},
|
||||
{HTTP_EXTENDED_AUTH_SC, "HTTP_EXTENDED_AUTH_SC"},
|
||||
{HTTP_EXTENDED_AUTH_PAA, "HTTP_EXTENDED_AUTH_PAA"},
|
||||
{HTTP_EXTENDED_AUTH_SSPI_NTLM, "HTTP_EXTENDED_AUTH_SSPI_NTLM"}
|
||||
};
|
||||
|
||||
static const char* fields_present_to_string(UINT16 fieldsPresent, const t_err_mapping* map,
|
||||
size_t elements)
|
||||
{
|
||||
size_t x = 0;
|
||||
static char buffer[1024] = { 0 };
|
||||
char fields[12];
|
||||
|
||||
for (x = 0; x < elements; x++)
|
||||
{
|
||||
if (buffer[0] != '\0')
|
||||
strcat(buffer, "|");
|
||||
|
||||
if ((map[x].code & fieldsPresent) != 0)
|
||||
strcat(buffer, map[x].name);
|
||||
}
|
||||
|
||||
sprintf_s(fields, ARRAYSIZE(fields), " [%04"PRIx16"]", fieldsPresent);
|
||||
strcat(buffer, fields);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static const char* channel_response_fields_present_to_string(UINT16 fieldsPresent)
|
||||
{
|
||||
return fields_present_to_string(fieldsPresent, channel_response_fields_present,
|
||||
ARRAYSIZE(channel_response_fields_present));
|
||||
}
|
||||
|
||||
static const char* tunnel_response_fields_present_to_string(UINT16 fieldsPresent)
|
||||
{
|
||||
return fields_present_to_string(fieldsPresent, tunnel_response_fields_present,
|
||||
ARRAYSIZE(tunnel_response_fields_present));
|
||||
}
|
||||
|
||||
static const char* tunnel_authorization_response_fields_present_to_string(UINT16 fieldsPresent)
|
||||
{
|
||||
return fields_present_to_string(fieldsPresent, tunnel_authorization_response_fields_present,
|
||||
ARRAYSIZE(tunnel_authorization_response_fields_present));
|
||||
}
|
||||
|
||||
static const char* extended_auth_to_string(UINT16 auth)
|
||||
{
|
||||
if (auth == HTTP_EXTENDED_AUTH_NONE)
|
||||
return "HTTP_EXTENDED_AUTH_NONE [0x0000]";
|
||||
|
||||
return fields_present_to_string(auth, extended_auth, ARRAYSIZE(extended_auth));
|
||||
}
|
||||
|
||||
static BOOL rdg_write_packet(rdpRdg* rdg, wStream* sPacket)
|
||||
{
|
||||
size_t s;
|
||||
@ -546,6 +630,9 @@ static BOOL rdg_skip_seed_payload(rdpTls* tls, SSIZE_T lastResponseLength)
|
||||
static BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
|
||||
{
|
||||
UINT32 errorCode;
|
||||
UINT16 serverVersion, extendedAuth;
|
||||
BYTE verMajor, verMinor;
|
||||
const char* error;
|
||||
WLog_DBG(TAG, "Handshake response received");
|
||||
|
||||
if (rdg->state != RDG_CLIENT_STATE_HANDSHAKE)
|
||||
@ -553,15 +640,22 @@ static BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 12)
|
||||
if (Stream_GetRemainingLength(s) < 10)
|
||||
return FALSE;
|
||||
|
||||
Stream_Seek(s, 8);
|
||||
Stream_Read_UINT32(s, errorCode);
|
||||
Stream_Read_UINT8(s, verMajor);
|
||||
Stream_Read_UINT8(s, verMinor);
|
||||
Stream_Read_UINT16(s, serverVersion);
|
||||
Stream_Read_UINT16(s, extendedAuth);
|
||||
error = rpc_error_to_string(errorCode);
|
||||
WLog_DBG(TAG,
|
||||
"errorCode=%s, verMajor=%"PRId8", verMinor=%"PRId8", serverVersion=%"PRId16", extendedAuth=%s",
|
||||
error, verMajor, verMinor, serverVersion, extended_auth_to_string(extendedAuth));
|
||||
|
||||
if (FAILED(errorCode))
|
||||
{
|
||||
WLog_DBG(TAG, "Handshake error %"PRIx32, (HRESULT)errorCode);
|
||||
WLog_DBG(TAG, "Handshake error %s", error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -570,7 +664,9 @@ static BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
|
||||
|
||||
static BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
|
||||
{
|
||||
UINT16 serverVersion, fieldsPresent;
|
||||
UINT32 errorCode;
|
||||
const char* error;
|
||||
WLog_DBG(TAG, "Tunnel response received");
|
||||
|
||||
if (rdg->state != RDG_CLIENT_STATE_TUNNEL_CREATE)
|
||||
@ -578,15 +674,20 @@ static BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 14)
|
||||
if (Stream_GetRemainingLength(s) < 10)
|
||||
return FALSE;
|
||||
|
||||
Stream_Seek(s, 10);
|
||||
Stream_Read_UINT16(s, serverVersion);
|
||||
Stream_Read_UINT32(s, errorCode);
|
||||
Stream_Read_UINT16(s, fieldsPresent);
|
||||
Stream_Seek_UINT16(s); /* reserved */
|
||||
error = rpc_error_to_string(errorCode);
|
||||
WLog_DBG(TAG, "serverVersion=%"PRId16", errorCode=%s, fieldsPresent=%s",
|
||||
serverVersion, error, tunnel_response_fields_present_to_string(fieldsPresent));
|
||||
|
||||
if (FAILED(errorCode))
|
||||
{
|
||||
WLog_DBG(TAG, "Tunnel creation error %"PRIx32, (HRESULT)errorCode);
|
||||
WLog_DBG(TAG, "Tunnel creation error %s", error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -596,6 +697,8 @@ static BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
|
||||
static BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
|
||||
{
|
||||
UINT32 errorCode;
|
||||
UINT16 fieldsPresent;
|
||||
const char* error;
|
||||
WLog_DBG(TAG, "Tunnel authorization received");
|
||||
|
||||
if (rdg->state != RDG_CLIENT_STATE_TUNNEL_AUTHORIZE)
|
||||
@ -603,15 +706,19 @@ static BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 12)
|
||||
if (Stream_GetRemainingLength(s) < 8)
|
||||
return FALSE;
|
||||
|
||||
Stream_Seek(s, 8);
|
||||
Stream_Read_UINT32(s, errorCode);
|
||||
Stream_Read_UINT16(s, fieldsPresent);
|
||||
Stream_Seek_UINT16(s); /* reserved */
|
||||
error = rpc_error_to_string(errorCode);
|
||||
WLog_DBG(TAG, "errorCode=%s, fieldsPresent=%s",
|
||||
error, tunnel_authorization_response_fields_present_to_string(fieldsPresent));
|
||||
|
||||
if (FAILED(errorCode))
|
||||
{
|
||||
WLog_DBG(TAG, "Tunnel authorization error %"PRIx32, (HRESULT)errorCode);
|
||||
WLog_DBG(TAG, "Tunnel authorization error %s", error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -620,7 +727,9 @@ static BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
|
||||
|
||||
static BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s)
|
||||
{
|
||||
UINT16 fieldsPresent;
|
||||
UINT32 errorCode;
|
||||
const char* error;
|
||||
WLog_DBG(TAG, "Channel response received");
|
||||
|
||||
if (rdg->state != RDG_CLIENT_STATE_CHANNEL_CREATE)
|
||||
@ -628,15 +737,20 @@ static BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 12)
|
||||
if (Stream_GetRemainingLength(s) < 8)
|
||||
return FALSE;
|
||||
|
||||
Stream_Seek(s, 8);
|
||||
Stream_Read_UINT32(s, errorCode);
|
||||
Stream_Read_UINT16(s, fieldsPresent);
|
||||
Stream_Seek_UINT16(s); /* reserved */
|
||||
error = rpc_error_to_string(errorCode);
|
||||
WLog_DBG(TAG, "channel response errorCode=%s, fieldsPresent=%s",
|
||||
error, channel_response_fields_present_to_string(fieldsPresent));
|
||||
|
||||
if (FAILED(errorCode))
|
||||
{
|
||||
WLog_DBG(TAG, "Channel error %"PRIx32, (HRESULT)errorCode);
|
||||
WLog_ERR(TAG, "channel response errorCode=%s, fieldsPresent=%s",
|
||||
error, channel_response_fields_present_to_string(fieldsPresent));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -648,12 +762,18 @@ static BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
|
||||
{
|
||||
BOOL status = TRUE;
|
||||
UINT16 type;
|
||||
UINT32 packetLength;
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 2)
|
||||
if (Stream_GetRemainingLength(s) < 8)
|
||||
return FALSE;
|
||||
|
||||
Stream_Peek_UINT16(s, type);
|
||||
Stream_Read_UINT16(s, type);
|
||||
Stream_Seek_UINT16(s); /* reserved */
|
||||
Stream_Read_UINT32(s, packetLength);
|
||||
|
||||
if (Stream_GetRemainingLength(s) < packetLength)
|
||||
return FALSE;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
|
@ -446,7 +446,7 @@ static int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment)
|
||||
}
|
||||
else if (header->common.ptype == PTYPE_FAULT)
|
||||
{
|
||||
rpc_recv_fault_pdu(header);
|
||||
rpc_recv_fault_pdu(header->fault.status);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
#include "rpc_fault.h"
|
||||
|
||||
#include "rpc.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.rpc")
|
||||
|
||||
static const RPC_FAULT_CODE RPC_FAULT_CODES[] =
|
||||
@ -359,19 +361,17 @@ static UINT32 rpc_map_status_code_to_win32_error_code(UINT32 code)
|
||||
return code;
|
||||
}
|
||||
|
||||
int rpc_recv_fault_pdu(rpcconn_hdr_t* header)
|
||||
const char* rpc_error_to_string(UINT32 code)
|
||||
{
|
||||
int index;
|
||||
UINT32 code;
|
||||
WLog_ERR(TAG, "RPC Fault PDU:");
|
||||
code = rpc_map_status_code_to_win32_error_code(header->fault.status);
|
||||
size_t index;
|
||||
static char buffer[1024];
|
||||
|
||||
for (index = 0; RPC_FAULT_CODES[index].name != NULL; index++)
|
||||
{
|
||||
if (RPC_FAULT_CODES[index].code == code)
|
||||
{
|
||||
WLog_ERR(TAG, "status: %s (0x%08"PRIX32")", RPC_FAULT_CODES[index].name, code);
|
||||
return 0;
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%s [0x%08"PRIX32"]", RPC_FAULT_CODES[index].name, code);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,11 +379,20 @@ int rpc_recv_fault_pdu(rpcconn_hdr_t* header)
|
||||
{
|
||||
if (RPC_TSG_FAULT_CODES[index].code == code)
|
||||
{
|
||||
WLog_ERR(TAG, "status: %s (0x%08"PRIX32")", RPC_TSG_FAULT_CODES[index].name, code);
|
||||
return 0;
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%s [0x%08"PRIX32"]", RPC_TSG_FAULT_CODES[index].name, code);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "status: %s (0x%08"PRIX32")", "UNKNOWN", code);
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%s [0x%08"PRIX32"]", "UNKNOWN", code);
|
||||
out:
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
int rpc_recv_fault_pdu(UINT32 status)
|
||||
{
|
||||
UINT32 code = rpc_map_status_code_to_win32_error_code(status);
|
||||
WLog_ERR(TAG, "RPC Fault PDU: status=%s", rpc_error_to_string(code));
|
||||
return 0;
|
||||
}
|
||||
|
@ -20,11 +20,10 @@
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_RPC_FAULT_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_RPC_FAULT_H
|
||||
|
||||
#include "rpc.h"
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL int rpc_recv_fault_pdu(rpcconn_hdr_t* header);
|
||||
FREERDP_LOCAL int rpc_recv_fault_pdu(UINT32 status);
|
||||
FREERDP_LOCAL const char* rpc_error_to_string(UINT32 error);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_RPC_FAULT_H */
|
||||
|
Loading…
Reference in New Issue
Block a user