New upstream version 2.4.1+dfsg1
This commit is contained in:
parent
68e1ca324f
commit
4e5cdbea0a
@ -85,7 +85,7 @@ if ($ENV{BUILD_NUMBER})
|
||||
endif()
|
||||
set(WITH_LIBRARY_VERSIONING "ON")
|
||||
|
||||
set(RAW_VERSION_STRING "2.4.0")
|
||||
set(RAW_VERSION_STRING "2.4.1")
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
|
||||
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
|
||||
elseif(USE_VERSION_FROM_GIT_TAG)
|
||||
|
||||
18
ChangeLog
18
ChangeLog
@ -1,3 +1,21 @@
|
||||
# 2021-10-20 Version 2.4.1
|
||||
|
||||
Noteworthy changes:
|
||||
* Refactored RPC gateway parsing code
|
||||
* OpenSSL 3.0 compatibility fixes
|
||||
* USB redirection: fixed transfer lengths
|
||||
|
||||
Fixed issues:
|
||||
* #7363: Length checks in ConvertUTF8toUTF16
|
||||
* #7349: Added checks for bitmap width and heigth values
|
||||
|
||||
Important notes:
|
||||
* CVE-2021-41159: Improper client input validation for gateway connections allows to overwrite memory
|
||||
* CVE-2021-41160: Improper region checks in all clients allow out of bound write to memory
|
||||
|
||||
For a complete and detailed change log since the last release run:
|
||||
git log 2.4.0..2.4.1
|
||||
|
||||
# 2021-07-27 Version 2.4.0
|
||||
|
||||
Noteworthy changes:
|
||||
|
||||
@ -721,9 +721,10 @@ static UINT urb_bulk_or_interrupt_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBA
|
||||
Stream_Read_UINT32(s, OutputBufferSize);
|
||||
EndpointAddress = (PipeHandle & 0x000000ff);
|
||||
/** process TS_URB_BULK_OR_INTERRUPT_TRANSFER */
|
||||
return pdev->bulk_or_interrupt_transfer(pdev, callback, MessageId, RequestId, EndpointAddress,
|
||||
TransferFlags, noAck, OutputBufferSize,
|
||||
urb_bulk_transfer_cb, 10000);
|
||||
return pdev->bulk_or_interrupt_transfer(
|
||||
pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
|
||||
OutputBufferSize, (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : NULL,
|
||||
urb_bulk_transfer_cb, 10000);
|
||||
}
|
||||
|
||||
static void urb_isoch_transfer_cb(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callback, wStream* out,
|
||||
|
||||
@ -193,8 +193,8 @@ const char* usb_interface_class_to_string(uint8_t class)
|
||||
|
||||
static ASYNC_TRANSFER_USER_DATA* async_transfer_user_data_new(IUDEVICE* idev, UINT32 MessageId,
|
||||
size_t offset, size_t BufferSize,
|
||||
size_t packetSize, BOOL NoAck,
|
||||
t_isoch_transfer_cb cb,
|
||||
const BYTE* data, size_t packetSize,
|
||||
BOOL NoAck, t_isoch_transfer_cb cb,
|
||||
URBDRC_CHANNEL_CALLBACK* callback)
|
||||
{
|
||||
ASYNC_TRANSFER_USER_DATA* user_data = calloc(1, sizeof(ASYNC_TRANSFER_USER_DATA));
|
||||
@ -210,14 +210,19 @@ static ASYNC_TRANSFER_USER_DATA* async_transfer_user_data_new(IUDEVICE* idev, UI
|
||||
free(user_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Stream_Seek(user_data->data, offset); /* Skip header offset */
|
||||
if (data)
|
||||
memcpy(Stream_Pointer(user_data->data), data, BufferSize);
|
||||
else
|
||||
user_data->OutputBufferSize = BufferSize;
|
||||
|
||||
user_data->noack = NoAck;
|
||||
user_data->cb = cb;
|
||||
user_data->callback = callback;
|
||||
user_data->idev = idev;
|
||||
user_data->MessageId = MessageId;
|
||||
user_data->OutputBufferSize = BufferSize;
|
||||
|
||||
user_data->queue = pdev->request_queue;
|
||||
|
||||
return user_data;
|
||||
@ -1197,8 +1202,8 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* c
|
||||
return -1;
|
||||
|
||||
urbdrc = pdev->urbdrc;
|
||||
user_data = async_transfer_user_data_new(idev, MessageId, 48, BufferSize, outSize + 1024, NoAck,
|
||||
cb, callback);
|
||||
user_data = async_transfer_user_data_new(idev, MessageId, 48, BufferSize, Buffer,
|
||||
outSize + 1024, NoAck, cb, callback);
|
||||
|
||||
if (!user_data)
|
||||
return -1;
|
||||
@ -1206,12 +1211,7 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* c
|
||||
user_data->ErrorCount = ErrorCount;
|
||||
user_data->StartFrame = StartFrame;
|
||||
|
||||
if (Buffer) /* We read data, prepare a bufffer */
|
||||
{
|
||||
user_data->OutputBufferSize = 0;
|
||||
memmove(Stream_Pointer(user_data->data), Buffer, BufferSize);
|
||||
}
|
||||
else
|
||||
if (!Buffer)
|
||||
Stream_Seek(user_data->data, (NumberOfPackets * 12));
|
||||
|
||||
iso_packet_size = BufferSize / NumberOfPackets;
|
||||
@ -1270,7 +1270,7 @@ static BOOL libusb_udev_control_transfer(IUDEVICE* idev, UINT32 RequestId, UINT3
|
||||
static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* callback,
|
||||
UINT32 MessageId, UINT32 RequestId,
|
||||
UINT32 EndpointAddress, UINT32 TransferFlags,
|
||||
BOOL NoAck, UINT32 BufferSize,
|
||||
BOOL NoAck, UINT32 BufferSize, const BYTE* data,
|
||||
t_isoch_transfer_cb cb, UINT32 Timeout)
|
||||
{
|
||||
UINT32 transfer_type;
|
||||
@ -1286,7 +1286,7 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, URBDRC_CHANNEL
|
||||
|
||||
urbdrc = pdev->urbdrc;
|
||||
user_data =
|
||||
async_transfer_user_data_new(idev, MessageId, 36, BufferSize, 0, NoAck, cb, callback);
|
||||
async_transfer_user_data_new(idev, MessageId, 36, BufferSize, data, 0, NoAck, cb, callback);
|
||||
|
||||
if (!user_data)
|
||||
return -1;
|
||||
|
||||
@ -134,7 +134,7 @@ struct _IUDEVICE
|
||||
int (*bulk_or_interrupt_transfer)(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* callback,
|
||||
UINT32 MessageId, UINT32 RequestId, UINT32 EndpointAddress,
|
||||
UINT32 TransferFlags, BOOL NoAck, UINT32 BufferSize,
|
||||
t_isoch_transfer_cb cb, UINT32 Timeout);
|
||||
const BYTE* data, t_isoch_transfer_cb cb, UINT32 Timeout);
|
||||
|
||||
int (*select_configuration)(IUDEVICE* idev, UINT32 bConfigurationValue);
|
||||
|
||||
|
||||
@ -1401,11 +1401,8 @@ static DWORD WINAPI xf_input_thread(LPVOID arg)
|
||||
DWORD status;
|
||||
DWORD nCount;
|
||||
HANDLE events[3];
|
||||
XEvent xevent;
|
||||
wMessage msg;
|
||||
wMessageQueue* queue;
|
||||
int pending_status = 1;
|
||||
int process_status = 1;
|
||||
freerdp* instance = (freerdp*)arg;
|
||||
xfContext* xfc = (xfContext*)instance->context;
|
||||
queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
|
||||
@ -1434,26 +1431,7 @@ static DWORD WINAPI xf_input_thread(LPVOID arg)
|
||||
|
||||
if (WaitForSingleObject(events[1], 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
do
|
||||
{
|
||||
xf_lock_x11(xfc);
|
||||
pending_status = XPending(xfc->display);
|
||||
xf_unlock_x11(xfc);
|
||||
|
||||
if (pending_status)
|
||||
{
|
||||
xf_lock_x11(xfc);
|
||||
ZeroMemory(&xevent, sizeof(xevent));
|
||||
XNextEvent(xfc->display, &xevent);
|
||||
process_status = xf_event_process(instance, &xevent);
|
||||
xf_unlock_x11(xfc);
|
||||
|
||||
if (!process_status)
|
||||
break;
|
||||
}
|
||||
} while (pending_status);
|
||||
|
||||
if (!process_status)
|
||||
if (!xf_process_x_events(xfc->context.instance))
|
||||
{
|
||||
running = FALSE;
|
||||
break;
|
||||
@ -1472,6 +1450,7 @@ static DWORD WINAPI xf_input_thread(LPVOID arg)
|
||||
}
|
||||
|
||||
MessageQueue_PostQuit(queue, 0);
|
||||
freerdp_abort_connect(xfc->context.instance);
|
||||
ExitThread(0);
|
||||
return 0;
|
||||
}
|
||||
@ -1533,6 +1512,84 @@ static DWORD WINAPI xf_client_thread(LPVOID param)
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED)
|
||||
exit_code = XF_EXIT_NEGO_FAILURE;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_LOGON_FAILURE)
|
||||
exit_code = XF_EXIT_LOGON_FAILURE;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT)
|
||||
exit_code = XF_EXIT_ACCOUNT_LOCKED_OUT;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_PRE_CONNECT_FAILED)
|
||||
exit_code = XF_EXIT_PRE_CONNECT_FAILED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_UNDEFINED)
|
||||
exit_code = XF_EXIT_CONNECT_UNDEFINED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_POST_CONNECT_FAILED)
|
||||
exit_code = XF_EXIT_POST_CONNECT_FAILED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_DNS_ERROR)
|
||||
exit_code = XF_EXIT_DNS_ERROR;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_DNS_NAME_NOT_FOUND)
|
||||
exit_code = XF_EXIT_DNS_NAME_NOT_FOUND;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_FAILED)
|
||||
exit_code = XF_EXIT_CONNECT_FAILED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR)
|
||||
exit_code = XF_EXIT_MCS_CONNECT_INITIAL_ERROR;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_TLS_CONNECT_FAILED)
|
||||
exit_code = XF_EXIT_TLS_CONNECT_FAILED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_INSUFFICIENT_PRIVILEGES)
|
||||
exit_code = XF_EXIT_INSUFFICIENT_PRIVILEGES;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_CANCELLED)
|
||||
exit_code = XF_EXIT_CONNECT_CANCELLED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED)
|
||||
exit_code = XF_EXIT_SECURITY_NEGO_CONNECT_FAILED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_TRANSPORT_FAILED)
|
||||
exit_code = XF_EXIT_CONNECT_TRANSPORT_FAILED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED)
|
||||
exit_code = XF_EXIT_CONNECT_PASSWORD_EXPIRED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE)
|
||||
exit_code = XF_EXIT_CONNECT_PASSWORD_MUST_CHANGE;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_KDC_UNREACHABLE)
|
||||
exit_code = XF_EXIT_CONNECT_KDC_UNREACHABLE;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED)
|
||||
exit_code = XF_EXIT_CONNECT_ACCOUNT_DISABLED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED)
|
||||
exit_code = XF_EXIT_CONNECT_PASSWORD_CERTAINLY_EXPIRED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_CLIENT_REVOKED)
|
||||
exit_code = XF_EXIT_CONNECT_CLIENT_REVOKED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_WRONG_PASSWORD)
|
||||
exit_code = XF_EXIT_CONNECT_WRONG_PASSWORD;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_ACCESS_DENIED)
|
||||
exit_code = XF_EXIT_CONNECT_ACCESS_DENIED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION)
|
||||
exit_code = XF_EXIT_CONNECT_ACCOUNT_RESTRICTION;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED)
|
||||
exit_code = XF_EXIT_CONNECT_ACCOUNT_EXPIRED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED)
|
||||
exit_code = XF_EXIT_CONNECT_LOGON_TYPE_NOT_GRANTED;
|
||||
else if (freerdp_get_last_error(instance->context) ==
|
||||
FREERDP_ERROR_CONNECT_NO_OR_MISSING_CREDENTIALS)
|
||||
exit_code = XF_EXIT_CONNECT_NO_OR_MISSING_CREDENTIALS;
|
||||
else
|
||||
exit_code = XF_EXIT_CONN_FAILED;
|
||||
}
|
||||
@ -1697,7 +1754,7 @@ end:
|
||||
|
||||
DWORD xf_exit_code_from_disconnect_reason(DWORD reason)
|
||||
{
|
||||
if (reason == 0 || (reason >= XF_EXIT_PARSE_ARGUMENTS && reason <= XF_EXIT_NEGO_FAILURE))
|
||||
if (reason == 0 || (reason >= XF_EXIT_PARSE_ARGUMENTS && reason <= XF_EXIT_CONNECT_NO_OR_MISSING_CREDENTIALS))
|
||||
return reason;
|
||||
/* License error set */
|
||||
else if (reason >= 0x100 && reason <= 0x10A)
|
||||
|
||||
@ -318,7 +318,32 @@ enum XF_EXIT_CODE
|
||||
XF_EXIT_CONN_FAILED = 131,
|
||||
XF_EXIT_AUTH_FAILURE = 132,
|
||||
XF_EXIT_NEGO_FAILURE = 133,
|
||||
|
||||
XF_EXIT_LOGON_FAILURE = 134,
|
||||
XF_EXIT_ACCOUNT_LOCKED_OUT = 135,
|
||||
XF_EXIT_PRE_CONNECT_FAILED = 136,
|
||||
XF_EXIT_CONNECT_UNDEFINED = 137,
|
||||
XF_EXIT_POST_CONNECT_FAILED = 138,
|
||||
XF_EXIT_DNS_ERROR = 139,
|
||||
XF_EXIT_DNS_NAME_NOT_FOUND = 140,
|
||||
XF_EXIT_CONNECT_FAILED = 141,
|
||||
XF_EXIT_MCS_CONNECT_INITIAL_ERROR = 142,
|
||||
XF_EXIT_TLS_CONNECT_FAILED = 143,
|
||||
XF_EXIT_INSUFFICIENT_PRIVILEGES = 144,
|
||||
XF_EXIT_CONNECT_CANCELLED = 145,
|
||||
XF_EXIT_SECURITY_NEGO_CONNECT_FAILED = 146,
|
||||
XF_EXIT_CONNECT_TRANSPORT_FAILED = 147,
|
||||
XF_EXIT_CONNECT_PASSWORD_EXPIRED = 148,
|
||||
XF_EXIT_CONNECT_PASSWORD_MUST_CHANGE = 149,
|
||||
XF_EXIT_CONNECT_KDC_UNREACHABLE = 150,
|
||||
XF_EXIT_CONNECT_ACCOUNT_DISABLED = 151,
|
||||
XF_EXIT_CONNECT_PASSWORD_CERTAINLY_EXPIRED = 152,
|
||||
XF_EXIT_CONNECT_CLIENT_REVOKED = 153,
|
||||
XF_EXIT_CONNECT_WRONG_PASSWORD = 154,
|
||||
XF_EXIT_CONNECT_ACCESS_DENIED = 155,
|
||||
XF_EXIT_CONNECT_ACCOUNT_RESTRICTION = 156,
|
||||
XF_EXIT_CONNECT_ACCOUNT_EXPIRED = 157,
|
||||
XF_EXIT_CONNECT_LOGON_TYPE_NOT_GRANTED = 158,
|
||||
XF_EXIT_CONNECT_NO_OR_MISSING_CREDENTIALS = 159,
|
||||
XF_EXIT_UNKNOWN = 255,
|
||||
};
|
||||
|
||||
|
||||
@ -1606,7 +1606,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
#if !defined(DEFINE_NO_DEPRECATED)
|
||||
if (compatibility)
|
||||
{
|
||||
WLog_WARN(TAG, "----------------------------------------");
|
||||
WLog_WARN(TAG, "Using deprecated command-line interface!");
|
||||
WLog_WARN(TAG, "This will be removed with FreeRDP 3!");
|
||||
WLog_WARN(TAG, "----------------------------------------");
|
||||
return freerdp_client_parse_old_command_line_arguments(argc, argv, settings);
|
||||
}
|
||||
else
|
||||
|
||||
@ -105,7 +105,7 @@ BOOL rpc_ncacn_http_send_in_channel_request(RpcChannel* inChannel)
|
||||
BOOL rpc_ncacn_http_recv_in_channel_response(RpcChannel* inChannel, HttpResponse* response)
|
||||
{
|
||||
const char* token64 = NULL;
|
||||
int ntlmTokenLength = 0;
|
||||
size_t ntlmTokenLength = 0;
|
||||
BYTE* ntlmTokenData = NULL;
|
||||
rdpNtlm* ntlm;
|
||||
|
||||
@ -121,6 +121,7 @@ BOOL rpc_ncacn_http_recv_in_channel_response(RpcChannel* inChannel, HttpResponse
|
||||
if (ntlmTokenData && ntlmTokenLength)
|
||||
return ntlm_client_set_input_buffer(ntlm, FALSE, ntlmTokenData, ntlmTokenLength);
|
||||
|
||||
free(ntlmTokenData);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -258,7 +259,7 @@ BOOL rpc_ncacn_http_send_out_channel_request(RpcChannel* outChannel, BOOL replac
|
||||
BOOL rpc_ncacn_http_recv_out_channel_response(RpcChannel* outChannel, HttpResponse* response)
|
||||
{
|
||||
const char* token64 = NULL;
|
||||
int ntlmTokenLength = 0;
|
||||
size_t ntlmTokenLength = 0;
|
||||
BYTE* ntlmTokenData = NULL;
|
||||
rdpNtlm* ntlm;
|
||||
|
||||
@ -274,5 +275,6 @@ BOOL rpc_ncacn_http_recv_out_channel_response(RpcChannel* outChannel, HttpRespon
|
||||
if (ntlmTokenData && ntlmTokenLength)
|
||||
return ntlm_client_set_input_buffer(ntlm, FALSE, ntlmTokenData, ntlmTokenLength);
|
||||
|
||||
free(ntlmTokenData);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -139,6 +139,7 @@ typedef struct
|
||||
WEBSOCKET_STATE state;
|
||||
wStream* responseStreamBuffer;
|
||||
} rdg_http_websocket_context;
|
||||
|
||||
typedef enum _CHUNK_STATE
|
||||
{
|
||||
ChunkStateLenghHeader,
|
||||
@ -358,12 +359,15 @@ static BOOL rdg_write_chunked(BIO* bio, wStream* sPacket)
|
||||
len = Stream_Length(sChunk);
|
||||
|
||||
if (len > INT_MAX)
|
||||
{
|
||||
Stream_Free(sChunk, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = BIO_write(bio, Stream_Buffer(sChunk), (int)len);
|
||||
Stream_Free(sChunk, TRUE);
|
||||
|
||||
if (status != len)
|
||||
if (status != (SSIZE_T)len)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
@ -437,7 +441,7 @@ static BOOL rdg_write_websocket(BIO* bio, wStream* sPacket, WEBSOCKET_OPCODE opc
|
||||
status = BIO_write(bio, Stream_Buffer(sWS), Stream_Length(sWS));
|
||||
Stream_Free(sWS, TRUE);
|
||||
|
||||
if (status != fullLen)
|
||||
if (status != (SSIZE_T)fullLen)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
@ -559,11 +563,13 @@ static BOOL rdg_websocket_reply_close(BIO* bio, wStream* s)
|
||||
{
|
||||
uint16_t data;
|
||||
Stream_Read_UINT16(s, data);
|
||||
Stream_Write_UINT16(s, data ^ maskingKey1);
|
||||
Stream_Write_UINT16(closeFrame, data ^ maskingKey1);
|
||||
}
|
||||
Stream_SealLength(closeFrame);
|
||||
|
||||
status = BIO_write(bio, Stream_Buffer(closeFrame), Stream_Length(closeFrame));
|
||||
Stream_Free(closeFrame, TRUE);
|
||||
|
||||
/* server MUST close socket now. The server is not allowed anymore to
|
||||
* send frames but if he does, nothing bad would happen */
|
||||
if (status < 0)
|
||||
@ -742,7 +748,6 @@ static int rdg_websocket_read(BIO* bio, BYTE* pBuffer, size_t size,
|
||||
TAG, "Websocket Server sends data with masking key. This is against RFC 6455.");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case WebSocketStatePayload:
|
||||
{
|
||||
status = rdg_websocket_handle_payload(bio, pBuffer, size, encodingContext);
|
||||
@ -761,6 +766,7 @@ static int rdg_websocket_read(BIO* bio, BYTE* pBuffer, size_t size,
|
||||
/* should be unreachable */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int rdg_chuncked_read(BIO* bio, BYTE* pBuffer, size_t size,
|
||||
rdg_http_encoding_chunked_context* encodingContext)
|
||||
{
|
||||
@ -832,9 +838,7 @@ static int rdg_chuncked_read(BIO* bio, BYTE* pBuffer, size_t size,
|
||||
else
|
||||
return (effectiveDataLen > 0 ? effectiveDataLen : status);
|
||||
}
|
||||
|
||||
*dst = '\0';
|
||||
|
||||
/* strtoul is tricky, error are reported via errno, we also need
|
||||
* to ensure the result does not overflow */
|
||||
errno = 0;
|
||||
@ -868,10 +872,12 @@ static int rdg_socket_read(BIO* bio, BYTE* pBuffer, size_t size,
|
||||
rdg_http_encoding_context* encodingContext)
|
||||
{
|
||||
assert(encodingContext != NULL);
|
||||
|
||||
if (encodingContext->isWebsocketTransport)
|
||||
{
|
||||
return rdg_websocket_read(bio, pBuffer, size, &encodingContext->context.websocket);
|
||||
}
|
||||
|
||||
switch (encodingContext->httpTransferEncoding)
|
||||
{
|
||||
case TransferEncodingIdentity:
|
||||
@ -881,7 +887,6 @@ static int rdg_socket_read(BIO* bio, BYTE* pBuffer, size_t size,
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return -1; /* should not be reached */
|
||||
}
|
||||
|
||||
static BOOL rdg_read_all(rdpTls* tls, BYTE* buffer, size_t size,
|
||||
@ -893,7 +898,6 @@ static BOOL rdg_read_all(rdpTls* tls, BYTE* buffer, size_t size,
|
||||
while (readCount < size)
|
||||
{
|
||||
int status = rdg_socket_read(tls->bio, pBuffer, size - readCount, transferEncoding);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
if (!BIO_should_retry(tls->bio))
|
||||
@ -1169,7 +1173,7 @@ static wStream* rdg_build_http_request(rdpRdg* rdg, const char* method,
|
||||
goto out;
|
||||
}
|
||||
|
||||
http_request_set_transfer_encoding(request, transferEncoding);
|
||||
http_request_set_transfer_encoding(request, transferEncoding);
|
||||
|
||||
s = http_request_write(rdg->http, request);
|
||||
out:
|
||||
@ -1186,7 +1190,7 @@ static BOOL rdg_handle_ntlm_challenge(rdpNtlm* ntlm, HttpResponse* response)
|
||||
BOOL continueNeeded = FALSE;
|
||||
size_t len;
|
||||
const char* token64 = NULL;
|
||||
int ntlmTokenLength = 0;
|
||||
size_t ntlmTokenLength = 0;
|
||||
BYTE* ntlmTokenData = NULL;
|
||||
long StatusCode;
|
||||
|
||||
@ -1852,7 +1856,6 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
|
||||
rdg->transferEncoding.context.websocket.responseStreamBuffer = NULL;
|
||||
|
||||
return TRUE;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
@ -1899,6 +1902,9 @@ static BOOL rdg_tunnel_connect(rdpRdg* rdg)
|
||||
|
||||
if (!status)
|
||||
{
|
||||
assert(rdg);
|
||||
assert(rdg->context);
|
||||
assert(rdg->context->rdp);
|
||||
rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED;
|
||||
return FALSE;
|
||||
}
|
||||
@ -1937,6 +1943,9 @@ BOOL rdg_connect(rdpRdg* rdg, DWORD timeout, BOOL* rpcFallback)
|
||||
|
||||
if (!status)
|
||||
{
|
||||
assert(rdg);
|
||||
assert(rdg->context);
|
||||
assert(rdg->context->rdp);
|
||||
rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED;
|
||||
return FALSE;
|
||||
}
|
||||
@ -2013,7 +2022,7 @@ static int rdg_write_websocket_data_packet(rdpRdg* rdg, const BYTE* buf, int isi
|
||||
/* mask as much as possible with 32bit access */
|
||||
for (streamPos = 0; streamPos + 4 <= isize; streamPos += 4)
|
||||
{
|
||||
uint32_t masked = *((uint32_t*)((BYTE*)buf + streamPos)) ^ maskingKey;
|
||||
uint32_t masked = *((const uint32_t*)((const BYTE*)buf + streamPos)) ^ maskingKey;
|
||||
Stream_Write_UINT32(sWS, masked);
|
||||
}
|
||||
|
||||
@ -2021,7 +2030,7 @@ static int rdg_write_websocket_data_packet(rdpRdg* rdg, const BYTE* buf, int isi
|
||||
for (; streamPos < isize; streamPos++)
|
||||
{
|
||||
BYTE* partialMask = (BYTE*)(&maskingKey) + streamPos % 4;
|
||||
BYTE masked = *((BYTE*)((BYTE*)buf + streamPos)) ^ *partialMask;
|
||||
BYTE masked = *((const BYTE*)((const BYTE*)buf + streamPos)) ^ *partialMask;
|
||||
Stream_Write_UINT8(sWS, masked);
|
||||
}
|
||||
|
||||
@ -2068,7 +2077,10 @@ static int rdg_write_chunked_data_packet(rdpRdg* rdg, const BYTE* buf, int isize
|
||||
len = Stream_Length(sChunk);
|
||||
|
||||
if (len > INT_MAX)
|
||||
{
|
||||
Stream_Free(sChunk, TRUE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), (int)len);
|
||||
Stream_Free(sChunk, TRUE);
|
||||
@ -2089,8 +2101,6 @@ static int rdg_write_data_packet(rdpRdg* rdg, const BYTE* buf, int isize)
|
||||
}
|
||||
else
|
||||
return rdg_write_chunked_data_packet(rdg, buf, isize);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static BOOL rdg_process_close_packet(rdpRdg* rdg, wStream* s)
|
||||
@ -2402,10 +2412,10 @@ static int rdg_bio_gets(BIO* bio, char* str, int size)
|
||||
return -2;
|
||||
}
|
||||
|
||||
static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
static long rdg_bio_ctrl(BIO* in_bio, int cmd, long arg1, void* arg2)
|
||||
{
|
||||
long status = -1;
|
||||
rdpRdg* rdg = (rdpRdg*)BIO_get_data(bio);
|
||||
rdpRdg* rdg = (rdpRdg*)BIO_get_data(in_bio);
|
||||
rdpTls* tlsOut = rdg->tlsOut;
|
||||
rdpTls* tlsIn = rdg->tlsIn;
|
||||
|
||||
@ -2422,42 +2432,42 @@ static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
}
|
||||
else if (cmd == BIO_C_READ_BLOCKED)
|
||||
{
|
||||
BIO* bio = tlsOut->bio;
|
||||
status = BIO_read_blocked(bio);
|
||||
BIO* cbio = tlsOut->bio;
|
||||
status = BIO_read_blocked(cbio);
|
||||
}
|
||||
else if (cmd == BIO_C_WRITE_BLOCKED)
|
||||
{
|
||||
BIO* bio = tlsIn->bio;
|
||||
BIO* cbio = tlsIn->bio;
|
||||
|
||||
if (rdg->transferEncoding.isWebsocketTransport)
|
||||
bio = tlsOut->bio;
|
||||
cbio = tlsOut->bio;
|
||||
|
||||
status = BIO_write_blocked(bio);
|
||||
status = BIO_write_blocked(cbio);
|
||||
}
|
||||
else if (cmd == BIO_C_WAIT_READ)
|
||||
{
|
||||
int timeout = (int)arg1;
|
||||
BIO* bio = tlsOut->bio;
|
||||
BIO* cbio = tlsOut->bio;
|
||||
|
||||
if (BIO_read_blocked(bio))
|
||||
return BIO_wait_read(bio, timeout);
|
||||
else if (BIO_write_blocked(bio))
|
||||
return BIO_wait_write(bio, timeout);
|
||||
if (BIO_read_blocked(cbio))
|
||||
return BIO_wait_read(cbio, timeout);
|
||||
else if (BIO_write_blocked(cbio))
|
||||
return BIO_wait_write(cbio, timeout);
|
||||
else
|
||||
status = 1;
|
||||
}
|
||||
else if (cmd == BIO_C_WAIT_WRITE)
|
||||
{
|
||||
int timeout = (int)arg1;
|
||||
BIO* bio = tlsIn->bio;
|
||||
BIO* cbio = tlsIn->bio;
|
||||
|
||||
if (rdg->transferEncoding.isWebsocketTransport)
|
||||
bio = tlsOut->bio;
|
||||
cbio = tlsOut->bio;
|
||||
|
||||
if (BIO_write_blocked(bio))
|
||||
status = BIO_wait_write(bio, timeout);
|
||||
else if (BIO_read_blocked(bio))
|
||||
status = BIO_wait_read(bio, timeout);
|
||||
if (BIO_write_blocked(cbio))
|
||||
status = BIO_wait_write(cbio, timeout);
|
||||
else if (BIO_read_blocked(cbio))
|
||||
status = BIO_wait_read(cbio, timeout);
|
||||
else
|
||||
status = 1;
|
||||
}
|
||||
@ -2619,6 +2629,7 @@ void rdg_free(rdpRdg* rdg)
|
||||
BIO_free_all(rdg->frontBio);
|
||||
|
||||
DeleteCriticalSection(&rdg->writeSection);
|
||||
|
||||
if (rdg->transferEncoding.isWebsocketTransport)
|
||||
{
|
||||
if (rdg->transferEncoding.context.websocket.responseStreamBuffer != NULL)
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <assert.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/dsparse.h>
|
||||
@ -46,6 +47,7 @@
|
||||
#include "rpc_client.h"
|
||||
|
||||
#include "rpc.h"
|
||||
#include "rts.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.rpc")
|
||||
|
||||
@ -88,8 +90,10 @@ static const char* PTYPE_STRINGS[] = { "PTYPE_REQUEST", "PTYPE_PING",
|
||||
*
|
||||
*/
|
||||
|
||||
void rpc_pdu_header_print(rpcconn_hdr_t* header)
|
||||
void rpc_pdu_header_print(const rpcconn_hdr_t* header)
|
||||
{
|
||||
assert(header);
|
||||
|
||||
WLog_INFO(TAG, "rpc_vers: %" PRIu8 "", header->common.rpc_vers);
|
||||
WLog_INFO(TAG, "rpc_vers_minor: %" PRIu8 "", header->common.rpc_vers_minor);
|
||||
|
||||
@ -139,26 +143,30 @@ void rpc_pdu_header_print(rpcconn_hdr_t* header)
|
||||
}
|
||||
}
|
||||
|
||||
void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_common_hdr_t* header)
|
||||
rpcconn_common_hdr_t rpc_pdu_header_init(const rdpRpc* rpc)
|
||||
{
|
||||
header->rpc_vers = rpc->rpc_vers;
|
||||
header->rpc_vers_minor = rpc->rpc_vers_minor;
|
||||
header->packed_drep[0] = rpc->packed_drep[0];
|
||||
header->packed_drep[1] = rpc->packed_drep[1];
|
||||
header->packed_drep[2] = rpc->packed_drep[2];
|
||||
header->packed_drep[3] = rpc->packed_drep[3];
|
||||
rpcconn_common_hdr_t header = { 0 };
|
||||
assert(rpc);
|
||||
|
||||
header.rpc_vers = rpc->rpc_vers;
|
||||
header.rpc_vers_minor = rpc->rpc_vers_minor;
|
||||
header.packed_drep[0] = rpc->packed_drep[0];
|
||||
header.packed_drep[1] = rpc->packed_drep[1];
|
||||
header.packed_drep[2] = rpc->packed_drep[2];
|
||||
header.packed_drep[3] = rpc->packed_drep[3];
|
||||
return header;
|
||||
}
|
||||
|
||||
UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment)
|
||||
size_t rpc_offset_align(size_t* offset, size_t alignment)
|
||||
{
|
||||
UINT32 pad;
|
||||
size_t pad;
|
||||
pad = *offset;
|
||||
*offset = (*offset + alignment - 1) & ~(alignment - 1);
|
||||
pad = *offset - pad;
|
||||
return pad;
|
||||
}
|
||||
|
||||
UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad)
|
||||
size_t rpc_offset_pad(size_t* offset, size_t pad)
|
||||
{
|
||||
*offset += pad;
|
||||
return pad;
|
||||
@ -239,64 +247,67 @@ UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad)
|
||||
*
|
||||
*/
|
||||
|
||||
BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* length)
|
||||
BOOL rpc_get_stub_data_info(const rpcconn_hdr_t* header, size_t* poffset, size_t* length)
|
||||
{
|
||||
UINT32 alloc_hint = 0;
|
||||
rpcconn_hdr_t* header;
|
||||
size_t used = 0;
|
||||
size_t offset = 0;
|
||||
BOOL rc = FALSE;
|
||||
UINT32 frag_length;
|
||||
UINT32 auth_length;
|
||||
UINT32 auth_pad_length;
|
||||
UINT32 auth_pad_length = 0;
|
||||
UINT32 sec_trailer_offset;
|
||||
rpc_sec_trailer* sec_trailer;
|
||||
*offset = RPC_COMMON_FIELDS_LENGTH;
|
||||
header = ((rpcconn_hdr_t*)buffer);
|
||||
const rpc_sec_trailer* sec_trailer = NULL;
|
||||
|
||||
assert(header);
|
||||
assert(poffset);
|
||||
assert(length);
|
||||
|
||||
offset = RPC_COMMON_FIELDS_LENGTH;
|
||||
|
||||
switch (header->common.ptype)
|
||||
{
|
||||
case PTYPE_RESPONSE:
|
||||
*offset += 8;
|
||||
rpc_offset_align(offset, 8);
|
||||
alloc_hint = header->response.alloc_hint;
|
||||
offset += 8;
|
||||
rpc_offset_align(&offset, 8);
|
||||
sec_trailer = &header->response.auth_verifier;
|
||||
break;
|
||||
|
||||
case PTYPE_REQUEST:
|
||||
*offset += 4;
|
||||
rpc_offset_align(offset, 8);
|
||||
alloc_hint = header->request.alloc_hint;
|
||||
offset += 4;
|
||||
rpc_offset_align(&offset, 8);
|
||||
sec_trailer = &header->request.auth_verifier;
|
||||
break;
|
||||
|
||||
case PTYPE_RTS:
|
||||
*offset += 4;
|
||||
offset += 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Unknown PTYPE: 0x%02" PRIX8 "", header->common.ptype);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!length)
|
||||
return TRUE;
|
||||
|
||||
if (header->common.ptype == PTYPE_REQUEST)
|
||||
{
|
||||
UINT32 sec_trailer_offset;
|
||||
sec_trailer_offset = header->common.frag_length - header->common.auth_length - 8;
|
||||
*length = sec_trailer_offset - *offset;
|
||||
return TRUE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
frag_length = header->common.frag_length;
|
||||
auth_length = header->common.auth_length;
|
||||
|
||||
if (poffset)
|
||||
*poffset = offset;
|
||||
|
||||
/* The fragment must be larger than the authentication trailer */
|
||||
used = offset + auth_length + 8ull;
|
||||
if (sec_trailer)
|
||||
{
|
||||
auth_pad_length = sec_trailer->auth_pad_length;
|
||||
used += sec_trailer->auth_pad_length;
|
||||
}
|
||||
|
||||
if (frag_length < used)
|
||||
goto fail;
|
||||
|
||||
if (!length)
|
||||
return TRUE;
|
||||
|
||||
sec_trailer_offset = frag_length - auth_length - 8;
|
||||
sec_trailer = (rpc_sec_trailer*)&buffer[sec_trailer_offset];
|
||||
auth_pad_length = sec_trailer->auth_pad_length;
|
||||
#if 0
|
||||
WLog_DBG(TAG,
|
||||
"sec_trailer: type: %"PRIu8" level: %"PRIu8" pad_length: %"PRIu8" reserved: %"PRIu8" context_id: %"PRIu32"",
|
||||
sec_trailer->auth_type, sec_trailer->auth_level,
|
||||
sec_trailer->auth_pad_length, sec_trailer->auth_reserved,
|
||||
sec_trailer->auth_context_id);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* According to [MS-RPCE], auth_pad_length is the number of padding
|
||||
@ -310,18 +321,21 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l
|
||||
auth_length, (frag_length - (sec_trailer_offset + 8)));
|
||||
}
|
||||
|
||||
*length = frag_length - auth_length - 24 - 8 - auth_pad_length;
|
||||
return TRUE;
|
||||
*length = sec_trailer_offset - auth_pad_length - offset;
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
SSIZE_T rpc_channel_read(RpcChannel* channel, wStream* s, size_t length)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!channel)
|
||||
if (!channel || (length > INT32_MAX))
|
||||
return -1;
|
||||
|
||||
status = BIO_read(channel->tls->bio, Stream_Pointer(s), length);
|
||||
status = BIO_read(channel->tls->bio, Stream_Pointer(s), (INT32)length);
|
||||
|
||||
if (status > 0)
|
||||
{
|
||||
@ -340,10 +354,10 @@ SSIZE_T rpc_channel_write(RpcChannel* channel, const BYTE* data, size_t length)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!channel)
|
||||
if (!channel || (length > INT32_MAX))
|
||||
return -1;
|
||||
|
||||
status = tls_write_all(channel->tls, data, length);
|
||||
status = tls_write_all(channel->tls, data, (INT32)length);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -629,7 +643,7 @@ static void rpc_virtual_connection_free(RpcVirtualConnection* connection)
|
||||
free(connection);
|
||||
}
|
||||
|
||||
static BOOL rpc_channel_tls_connect(RpcChannel* channel, int timeout)
|
||||
static BOOL rpc_channel_tls_connect(RpcChannel* channel, UINT32 timeout)
|
||||
{
|
||||
int sockfd;
|
||||
rdpTls* tls;
|
||||
@ -719,7 +733,7 @@ static BOOL rpc_channel_tls_connect(RpcChannel* channel, int timeout)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int rpc_in_channel_connect(RpcInChannel* inChannel, int timeout)
|
||||
static int rpc_in_channel_connect(RpcInChannel* inChannel, UINT32 timeout)
|
||||
{
|
||||
rdpContext* context;
|
||||
|
||||
@ -814,7 +828,7 @@ int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel, int timeout)
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL rpc_connect(rdpRpc* rpc, int timeout)
|
||||
BOOL rpc_connect(rdpRpc* rpc, UINT32 timeout)
|
||||
{
|
||||
RpcInChannel* inChannel;
|
||||
RpcOutChannel* outChannel;
|
||||
@ -840,7 +854,15 @@ BOOL rpc_connect(rdpRpc* rpc, int timeout)
|
||||
|
||||
rdpRpc* rpc_new(rdpTransport* transport)
|
||||
{
|
||||
rdpRpc* rpc = (rdpRpc*)calloc(1, sizeof(rdpRpc));
|
||||
rdpContext* context;
|
||||
rdpRpc* rpc;
|
||||
|
||||
assert(transport);
|
||||
|
||||
context = transport->context;
|
||||
assert(context);
|
||||
|
||||
rpc = (rdpRpc*)calloc(1, sizeof(rdpRpc));
|
||||
|
||||
if (!rpc)
|
||||
return NULL;
|
||||
@ -848,7 +870,7 @@ rdpRpc* rpc_new(rdpTransport* transport)
|
||||
rpc->State = RPC_CLIENT_STATE_INITIAL;
|
||||
rpc->transport = transport;
|
||||
rpc->settings = transport->settings;
|
||||
rpc->context = transport->context;
|
||||
rpc->context = context;
|
||||
rpc->SendSeqNum = 0;
|
||||
rpc->ntlm = ntlm_new();
|
||||
|
||||
@ -873,7 +895,7 @@ rdpRpc* rpc_new(rdpTransport* transport)
|
||||
rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
|
||||
rpc->CurrentKeepAliveTime = 0;
|
||||
rpc->CallId = 2;
|
||||
rpc->client = rpc_client_new(rpc->context, rpc->max_recv_frag);
|
||||
rpc->client = rpc_client_new(context, rpc->max_recv_frag);
|
||||
|
||||
if (!rpc->client)
|
||||
goto out_free;
|
||||
|
||||
@ -73,7 +73,6 @@ typedef struct _RPC_PDU
|
||||
#include "../tcp.h"
|
||||
#include "../transport.h"
|
||||
|
||||
#include "rts.h"
|
||||
#include "http.h"
|
||||
#include "ntlm.h"
|
||||
|
||||
@ -525,7 +524,8 @@ typedef struct
|
||||
rpcconn_common_hdr_t header;
|
||||
} rpcconn_shutdown_hdr_t;
|
||||
|
||||
typedef union {
|
||||
typedef union
|
||||
{
|
||||
rpcconn_common_hdr_t common;
|
||||
rpcconn_alter_context_hdr_t alter_context;
|
||||
rpcconn_alter_context_response_hdr_t alter_context_response;
|
||||
@ -767,14 +767,14 @@ struct rdp_rpc
|
||||
RpcVirtualConnection* VirtualConnection;
|
||||
};
|
||||
|
||||
FREERDP_LOCAL void rpc_pdu_header_print(rpcconn_hdr_t* header);
|
||||
FREERDP_LOCAL void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_common_hdr_t* header);
|
||||
FREERDP_LOCAL void rpc_pdu_header_print(const rpcconn_hdr_t* header);
|
||||
FREERDP_LOCAL rpcconn_common_hdr_t rpc_pdu_header_init(const rdpRpc* rpc);
|
||||
|
||||
FREERDP_LOCAL UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment);
|
||||
FREERDP_LOCAL UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad);
|
||||
FREERDP_LOCAL size_t rpc_offset_align(size_t* offset, size_t alignment);
|
||||
FREERDP_LOCAL size_t rpc_offset_pad(size_t* offset, size_t pad);
|
||||
|
||||
FREERDP_LOCAL BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* header, UINT32* offset,
|
||||
UINT32* length);
|
||||
FREERDP_LOCAL BOOL rpc_get_stub_data_info(const rpcconn_hdr_t* header, size_t* offset,
|
||||
size_t* length);
|
||||
|
||||
FREERDP_LOCAL SSIZE_T rpc_channel_write(RpcChannel* channel, const BYTE* data, size_t length);
|
||||
|
||||
@ -794,7 +794,7 @@ FREERDP_LOCAL BOOL rpc_virtual_connection_transition_to_state(rdpRpc* rpc,
|
||||
RpcVirtualConnection* connection,
|
||||
VIRTUAL_CONNECTION_STATE state);
|
||||
|
||||
FREERDP_LOCAL BOOL rpc_connect(rdpRpc* rpc, int timeout);
|
||||
FREERDP_LOCAL BOOL rpc_connect(rdpRpc* rpc, UINT32 timeout);
|
||||
|
||||
FREERDP_LOCAL rdpRpc* rpc_new(rdpTransport* transport);
|
||||
FREERDP_LOCAL void rpc_free(rdpRpc* rpc);
|
||||
|
||||
@ -22,11 +22,14 @@
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "rpc_client.h"
|
||||
|
||||
#include "rts.h"
|
||||
|
||||
#include "rpc_bind.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.rpc")
|
||||
@ -106,18 +109,32 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
|
||||
{
|
||||
BOOL continueNeeded = FALSE;
|
||||
int status = -1;
|
||||
BYTE* buffer = NULL;
|
||||
wStream* buffer = NULL;
|
||||
UINT32 offset;
|
||||
UINT32 length;
|
||||
RpcClientCall* clientCall;
|
||||
p_cont_elem_t* p_cont_elem;
|
||||
rpcconn_bind_hdr_t* bind_pdu = NULL;
|
||||
rpcconn_bind_hdr_t bind_pdu = { 0 };
|
||||
BOOL promptPassword = FALSE;
|
||||
rdpSettings* settings = rpc->settings;
|
||||
freerdp* instance = (freerdp*)settings->instance;
|
||||
RpcVirtualConnection* connection = rpc->VirtualConnection;
|
||||
RpcInChannel* inChannel = connection->DefaultInChannel;
|
||||
rdpSettings* settings;
|
||||
freerdp* instance;
|
||||
RpcVirtualConnection* connection;
|
||||
RpcInChannel* inChannel;
|
||||
const SecBuffer* sbuffer = NULL;
|
||||
|
||||
assert(rpc);
|
||||
|
||||
settings = rpc->settings;
|
||||
assert(settings);
|
||||
|
||||
instance = (freerdp*)settings->instance;
|
||||
assert(instance);
|
||||
|
||||
connection = rpc->VirtualConnection;
|
||||
|
||||
assert(connection);
|
||||
|
||||
inChannel = connection->DefaultInChannel;
|
||||
|
||||
WLog_DBG(TAG, "Sending Bind PDU");
|
||||
ntlm_free(rpc->ntlm);
|
||||
rpc->ntlm = ntlm_new();
|
||||
@ -180,36 +197,31 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
|
||||
if (!continueNeeded)
|
||||
goto fail;
|
||||
|
||||
bind_pdu = (rpcconn_bind_hdr_t*)calloc(1, sizeof(rpcconn_bind_hdr_t));
|
||||
|
||||
if (!bind_pdu)
|
||||
goto fail;
|
||||
|
||||
sbuffer = ntlm_client_get_output_buffer(rpc->ntlm);
|
||||
|
||||
if (!sbuffer)
|
||||
goto fail;
|
||||
|
||||
rpc_pdu_header_init(rpc, &bind_pdu->header);
|
||||
bind_pdu->header.auth_length = (UINT16)sbuffer->cbBuffer;
|
||||
bind_pdu->auth_verifier.auth_value = sbuffer->pvBuffer;
|
||||
bind_pdu->header.ptype = PTYPE_BIND;
|
||||
bind_pdu->header.pfc_flags =
|
||||
bind_pdu.header = rpc_pdu_header_init(rpc);
|
||||
bind_pdu.header.auth_length = (UINT16)sbuffer->cbBuffer;
|
||||
bind_pdu.auth_verifier.auth_value = sbuffer->pvBuffer;
|
||||
bind_pdu.header.ptype = PTYPE_BIND;
|
||||
bind_pdu.header.pfc_flags =
|
||||
PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_SUPPORT_HEADER_SIGN | PFC_CONC_MPX;
|
||||
bind_pdu->header.call_id = 2;
|
||||
bind_pdu->max_xmit_frag = rpc->max_xmit_frag;
|
||||
bind_pdu->max_recv_frag = rpc->max_recv_frag;
|
||||
bind_pdu->assoc_group_id = 0;
|
||||
bind_pdu->p_context_elem.n_context_elem = 2;
|
||||
bind_pdu->p_context_elem.reserved = 0;
|
||||
bind_pdu->p_context_elem.reserved2 = 0;
|
||||
bind_pdu->p_context_elem.p_cont_elem =
|
||||
calloc(bind_pdu->p_context_elem.n_context_elem, sizeof(p_cont_elem_t));
|
||||
bind_pdu.header.call_id = 2;
|
||||
bind_pdu.max_xmit_frag = rpc->max_xmit_frag;
|
||||
bind_pdu.max_recv_frag = rpc->max_recv_frag;
|
||||
bind_pdu.assoc_group_id = 0;
|
||||
bind_pdu.p_context_elem.n_context_elem = 2;
|
||||
bind_pdu.p_context_elem.reserved = 0;
|
||||
bind_pdu.p_context_elem.reserved2 = 0;
|
||||
bind_pdu.p_context_elem.p_cont_elem =
|
||||
calloc(bind_pdu.p_context_elem.n_context_elem, sizeof(p_cont_elem_t));
|
||||
|
||||
if (!bind_pdu->p_context_elem.p_cont_elem)
|
||||
if (!bind_pdu.p_context_elem.p_cont_elem)
|
||||
goto fail;
|
||||
|
||||
p_cont_elem = &bind_pdu->p_context_elem.p_cont_elem[0];
|
||||
p_cont_elem = &bind_pdu.p_context_elem.p_cont_elem[0];
|
||||
p_cont_elem->p_cont_id = 0;
|
||||
p_cont_elem->n_transfer_syn = 1;
|
||||
p_cont_elem->reserved = 0;
|
||||
@ -222,7 +234,7 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
|
||||
|
||||
CopyMemory(&(p_cont_elem->transfer_syntaxes[0].if_uuid), &NDR_UUID, sizeof(p_uuid_t));
|
||||
p_cont_elem->transfer_syntaxes[0].if_version = NDR_SYNTAX_IF_VERSION;
|
||||
p_cont_elem = &bind_pdu->p_context_elem.p_cont_elem[1];
|
||||
p_cont_elem = &bind_pdu.p_context_elem.p_cont_elem[1];
|
||||
p_cont_elem->p_cont_id = 1;
|
||||
p_cont_elem->n_transfer_syn = 1;
|
||||
p_cont_elem->reserved = 0;
|
||||
@ -236,32 +248,23 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
|
||||
CopyMemory(&(p_cont_elem->transfer_syntaxes[0].if_uuid), &BTFN_UUID, sizeof(p_uuid_t));
|
||||
p_cont_elem->transfer_syntaxes[0].if_version = BTFN_SYNTAX_IF_VERSION;
|
||||
offset = 116;
|
||||
bind_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4);
|
||||
bind_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT;
|
||||
bind_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
|
||||
bind_pdu->auth_verifier.auth_reserved = 0x00;
|
||||
bind_pdu->auth_verifier.auth_context_id = 0x00000000;
|
||||
offset += (8 + bind_pdu->header.auth_length);
|
||||
bind_pdu->header.frag_length = offset;
|
||||
buffer = (BYTE*)malloc(bind_pdu->header.frag_length);
|
||||
|
||||
bind_pdu.auth_verifier.auth_type = RPC_C_AUTHN_WINNT;
|
||||
bind_pdu.auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
|
||||
bind_pdu.auth_verifier.auth_reserved = 0x00;
|
||||
bind_pdu.auth_verifier.auth_context_id = 0x00000000;
|
||||
offset += (8 + bind_pdu.header.auth_length);
|
||||
bind_pdu.header.frag_length = offset;
|
||||
|
||||
buffer = Stream_New(NULL, bind_pdu.header.frag_length);
|
||||
|
||||
if (!buffer)
|
||||
goto fail;
|
||||
|
||||
CopyMemory(buffer, bind_pdu, 24);
|
||||
CopyMemory(&buffer[24], &bind_pdu->p_context_elem, 4);
|
||||
CopyMemory(&buffer[28], &bind_pdu->p_context_elem.p_cont_elem[0], 24);
|
||||
CopyMemory(&buffer[52], bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes, 20);
|
||||
CopyMemory(&buffer[72], &bind_pdu->p_context_elem.p_cont_elem[1], 24);
|
||||
CopyMemory(&buffer[96], bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes, 20);
|
||||
offset = 116;
|
||||
rpc_offset_pad(&offset, bind_pdu->auth_verifier.auth_pad_length);
|
||||
CopyMemory(&buffer[offset], &bind_pdu->auth_verifier.auth_type, 8);
|
||||
CopyMemory(&buffer[offset + 8], bind_pdu->auth_verifier.auth_value,
|
||||
bind_pdu->header.auth_length);
|
||||
offset += (8 + bind_pdu->header.auth_length);
|
||||
length = bind_pdu->header.frag_length;
|
||||
clientCall = rpc_client_call_new(bind_pdu->header.call_id, 0);
|
||||
if (!rts_write_pdu_bind(buffer, &bind_pdu))
|
||||
goto fail;
|
||||
|
||||
clientCall = rpc_client_call_new(bind_pdu.header.call_id, 0);
|
||||
|
||||
if (!clientCall)
|
||||
goto fail;
|
||||
@ -272,22 +275,19 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
status = rpc_in_channel_send_pdu(inChannel, buffer, length);
|
||||
Stream_SealLength(buffer);
|
||||
status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer));
|
||||
fail:
|
||||
|
||||
if (bind_pdu)
|
||||
if (bind_pdu.p_context_elem.p_cont_elem)
|
||||
{
|
||||
if (bind_pdu->p_context_elem.p_cont_elem)
|
||||
{
|
||||
free(bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes);
|
||||
free(bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes);
|
||||
}
|
||||
|
||||
free(bind_pdu->p_context_elem.p_cont_elem);
|
||||
free(bind_pdu.p_context_elem.p_cont_elem[0].transfer_syntaxes);
|
||||
free(bind_pdu.p_context_elem.p_cont_elem[1].transfer_syntaxes);
|
||||
}
|
||||
|
||||
free(bind_pdu);
|
||||
free(buffer);
|
||||
free(bind_pdu.p_context_elem.p_cont_elem);
|
||||
|
||||
Stream_Free(buffer, TRUE);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
@ -317,31 +317,47 @@ fail:
|
||||
* example.
|
||||
*/
|
||||
|
||||
int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
BOOL rpc_recv_bind_ack_pdu(rdpRpc* rpc, wStream* s)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
BOOL continueNeeded = FALSE;
|
||||
BYTE* auth_data;
|
||||
rpcconn_hdr_t* header;
|
||||
header = (rpcconn_hdr_t*)buffer;
|
||||
const BYTE* auth_data;
|
||||
size_t pos, end;
|
||||
rpcconn_hdr_t header = { 0 };
|
||||
|
||||
assert(rpc);
|
||||
assert(rpc->ntlm);
|
||||
assert(s);
|
||||
|
||||
pos = Stream_GetPosition(s);
|
||||
if (!rts_read_pdu_header(s, &header))
|
||||
goto fail;
|
||||
|
||||
WLog_DBG(TAG, "Receiving BindAck PDU");
|
||||
|
||||
if (!rpc || !rpc->ntlm)
|
||||
return -1;
|
||||
rpc->max_recv_frag = header.bind_ack.max_xmit_frag;
|
||||
rpc->max_xmit_frag = header.bind_ack.max_recv_frag;
|
||||
|
||||
rpc->max_recv_frag = header->bind_ack.max_xmit_frag;
|
||||
rpc->max_xmit_frag = header->bind_ack.max_recv_frag;
|
||||
auth_data = buffer + (header->common.frag_length - header->common.auth_length);
|
||||
/* Get the correct offset in the input data and pass that on as input buffer.
|
||||
* rts_read_pdu_header did already do consistency checks */
|
||||
end = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, pos + header.common.frag_length - header.common.auth_length);
|
||||
auth_data = Stream_Pointer(s);
|
||||
Stream_SetPosition(s, end);
|
||||
|
||||
if (!ntlm_client_set_input_buffer(rpc->ntlm, TRUE, auth_data, header->common.auth_length))
|
||||
return -1;
|
||||
if (!ntlm_client_set_input_buffer(rpc->ntlm, TRUE, auth_data, header.common.auth_length))
|
||||
goto fail;
|
||||
|
||||
if (!ntlm_authenticate(rpc->ntlm, &continueNeeded))
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
if (continueNeeded)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
return (int)length;
|
||||
rc = TRUE;
|
||||
fail:
|
||||
rts_free_pdu_header(&header, FALSE);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -354,68 +370,63 @@ int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
|
||||
{
|
||||
int status = -1;
|
||||
BYTE* buffer;
|
||||
UINT32 offset;
|
||||
UINT32 length;
|
||||
wStream* buffer;
|
||||
size_t offset;
|
||||
const SecBuffer* sbuffer;
|
||||
RpcClientCall* clientCall;
|
||||
rpcconn_rpc_auth_3_hdr_t* auth_3_pdu;
|
||||
RpcVirtualConnection* connection = rpc->VirtualConnection;
|
||||
RpcInChannel* inChannel = connection->DefaultInChannel;
|
||||
WLog_DBG(TAG, "Sending RpcAuth3 PDU");
|
||||
auth_3_pdu = (rpcconn_rpc_auth_3_hdr_t*)calloc(1, sizeof(rpcconn_rpc_auth_3_hdr_t));
|
||||
rpcconn_rpc_auth_3_hdr_t auth_3_pdu = { 0 };
|
||||
RpcVirtualConnection* connection;
|
||||
RpcInChannel* inChannel;
|
||||
|
||||
if (!auth_3_pdu)
|
||||
return -1;
|
||||
assert(rpc);
|
||||
|
||||
connection = rpc->VirtualConnection;
|
||||
assert(connection);
|
||||
|
||||
inChannel = connection->DefaultInChannel;
|
||||
assert(inChannel);
|
||||
|
||||
WLog_DBG(TAG, "Sending RpcAuth3 PDU");
|
||||
|
||||
sbuffer = ntlm_client_get_output_buffer(rpc->ntlm);
|
||||
|
||||
if (!sbuffer)
|
||||
{
|
||||
free(auth_3_pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rpc_pdu_header_init(rpc, &auth_3_pdu->header);
|
||||
auth_3_pdu->header.auth_length = (UINT16)sbuffer->cbBuffer;
|
||||
auth_3_pdu->auth_verifier.auth_value = sbuffer->pvBuffer;
|
||||
auth_3_pdu->header.ptype = PTYPE_RPC_AUTH_3;
|
||||
auth_3_pdu->header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX;
|
||||
auth_3_pdu->header.call_id = 2;
|
||||
auth_3_pdu->max_xmit_frag = rpc->max_xmit_frag;
|
||||
auth_3_pdu->max_recv_frag = rpc->max_recv_frag;
|
||||
auth_3_pdu.header = rpc_pdu_header_init(rpc);
|
||||
auth_3_pdu.header.auth_length = (UINT16)sbuffer->cbBuffer;
|
||||
auth_3_pdu.auth_verifier.auth_value = sbuffer->pvBuffer;
|
||||
auth_3_pdu.header.ptype = PTYPE_RPC_AUTH_3;
|
||||
auth_3_pdu.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX;
|
||||
auth_3_pdu.header.call_id = 2;
|
||||
auth_3_pdu.max_xmit_frag = rpc->max_xmit_frag;
|
||||
auth_3_pdu.max_recv_frag = rpc->max_recv_frag;
|
||||
offset = 20;
|
||||
auth_3_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4);
|
||||
auth_3_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT;
|
||||
auth_3_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
|
||||
auth_3_pdu->auth_verifier.auth_reserved = 0x00;
|
||||
auth_3_pdu->auth_verifier.auth_context_id = 0x00000000;
|
||||
offset += (8 + auth_3_pdu->header.auth_length);
|
||||
auth_3_pdu->header.frag_length = offset;
|
||||
buffer = (BYTE*)malloc(auth_3_pdu->header.frag_length);
|
||||
auth_3_pdu.auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4);
|
||||
auth_3_pdu.auth_verifier.auth_type = RPC_C_AUTHN_WINNT;
|
||||
auth_3_pdu.auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
|
||||
auth_3_pdu.auth_verifier.auth_reserved = 0x00;
|
||||
auth_3_pdu.auth_verifier.auth_context_id = 0x00000000;
|
||||
offset += (8 + auth_3_pdu.header.auth_length);
|
||||
auth_3_pdu.header.frag_length = offset;
|
||||
|
||||
buffer = Stream_New(NULL, auth_3_pdu.header.frag_length);
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
free(auth_3_pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
CopyMemory(buffer, auth_3_pdu, 20);
|
||||
offset = 20;
|
||||
rpc_offset_pad(&offset, auth_3_pdu->auth_verifier.auth_pad_length);
|
||||
CopyMemory(&buffer[offset], &auth_3_pdu->auth_verifier.auth_type, 8);
|
||||
CopyMemory(&buffer[offset + 8], auth_3_pdu->auth_verifier.auth_value,
|
||||
auth_3_pdu->header.auth_length);
|
||||
offset += (8 + auth_3_pdu->header.auth_length);
|
||||
length = auth_3_pdu->header.frag_length;
|
||||
clientCall = rpc_client_call_new(auth_3_pdu->header.call_id, 0);
|
||||
if (!rts_write_pdu_auth3(buffer, &auth_3_pdu))
|
||||
goto fail;
|
||||
|
||||
clientCall = rpc_client_call_new(auth_3_pdu.header.call_id, 0);
|
||||
|
||||
if (ArrayList_Add(rpc->client->ClientCallList, clientCall) >= 0)
|
||||
{
|
||||
status = rpc_in_channel_send_pdu(inChannel, buffer, length);
|
||||
Stream_SealLength(buffer);
|
||||
status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer));
|
||||
}
|
||||
|
||||
free(auth_3_pdu);
|
||||
free(buffer);
|
||||
fail:
|
||||
Stream_Free(buffer, TRUE);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ FREERDP_LOCAL extern const p_uuid_t BTFN_UUID;
|
||||
#define BTFN_SYNTAX_IF_VERSION 0x00000001
|
||||
|
||||
FREERDP_LOCAL int rpc_send_bind_pdu(rdpRpc* rpc);
|
||||
FREERDP_LOCAL int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length);
|
||||
FREERDP_LOCAL BOOL rpc_recv_bind_ack_pdu(rdpRpc* rpc, wStream* s);
|
||||
FREERDP_LOCAL int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_RPC_BIND_H */
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <assert.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/thread.h>
|
||||
@ -35,6 +36,8 @@
|
||||
#include "rpc_bind.h"
|
||||
#include "rpc_fault.h"
|
||||
#include "rpc_client.h"
|
||||
#include "rts_signature.h"
|
||||
|
||||
#include "../rdp.h"
|
||||
#include "../proxy.h"
|
||||
|
||||
@ -99,7 +102,7 @@ static int rpc_client_receive_pipe_write(RpcClient* client, const BYTE* buffer,
|
||||
int rpc_client_receive_pipe_read(RpcClient* client, BYTE* buffer, size_t length)
|
||||
{
|
||||
int index = 0;
|
||||
int status = 0;
|
||||
size_t status = 0;
|
||||
int nchunks = 0;
|
||||
DataChunk chunks[2];
|
||||
|
||||
@ -122,7 +125,10 @@ int rpc_client_receive_pipe_read(RpcClient* client, BYTE* buffer, size_t length)
|
||||
ResetEvent(client->PipeEvent);
|
||||
|
||||
LeaveCriticalSection(&(client->PipeLock));
|
||||
return status;
|
||||
|
||||
if (status > INT_MAX)
|
||||
return -1;
|
||||
return (int)status;
|
||||
}
|
||||
|
||||
static int rpc_client_transition_to_state(rdpRpc* rpc, RPC_CLIENT_STATE state)
|
||||
@ -173,8 +179,15 @@ static int rpc_client_transition_to_state(rdpRpc* rpc, RPC_CLIENT_STATE state)
|
||||
static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
|
||||
{
|
||||
int status = -1;
|
||||
rpcconn_rts_hdr_t* rts;
|
||||
rdpTsg* tsg = rpc->transport->tsg;
|
||||
rdpTsg* tsg;
|
||||
|
||||
assert(rpc);
|
||||
assert(pdu);
|
||||
|
||||
Stream_SealLength(pdu->s);
|
||||
Stream_SetPosition(pdu->s, 0);
|
||||
|
||||
tsg = rpc->transport->tsg;
|
||||
|
||||
if (rpc->VirtualConnection->State < VIRTUAL_CONNECTION_STATE_OPENED)
|
||||
{
|
||||
@ -187,17 +200,13 @@ static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
|
||||
break;
|
||||
|
||||
case VIRTUAL_CONNECTION_STATE_WAIT_A3W:
|
||||
rts = (rpcconn_rts_hdr_t*)Stream_Buffer(pdu->s);
|
||||
|
||||
if (!rts_match_pdu_signature(&RTS_PDU_CONN_A3_SIGNATURE, rts))
|
||||
if (!rts_match_pdu_signature(&RTS_PDU_CONN_A3_SIGNATURE, pdu->s, NULL))
|
||||
{
|
||||
WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/A3");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = rts_recv_CONN_A3_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s));
|
||||
|
||||
if (status < 0)
|
||||
if (!rts_recv_CONN_A3_pdu(rpc, pdu->s))
|
||||
{
|
||||
WLog_ERR(TAG, "rts_recv_CONN_A3_pdu failure");
|
||||
return -1;
|
||||
@ -209,17 +218,13 @@ static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
|
||||
break;
|
||||
|
||||
case VIRTUAL_CONNECTION_STATE_WAIT_C2:
|
||||
rts = (rpcconn_rts_hdr_t*)Stream_Buffer(pdu->s);
|
||||
|
||||
if (!rts_match_pdu_signature(&RTS_PDU_CONN_C2_SIGNATURE, rts))
|
||||
if (!rts_match_pdu_signature(&RTS_PDU_CONN_C2_SIGNATURE, pdu->s, NULL))
|
||||
{
|
||||
WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/C2");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = rts_recv_CONN_C2_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s));
|
||||
|
||||
if (status < 0)
|
||||
if (!rts_recv_CONN_C2_pdu(rpc, pdu->s))
|
||||
{
|
||||
WLog_ERR(TAG, "rts_recv_CONN_C2_pdu failure");
|
||||
return -1;
|
||||
@ -252,7 +257,7 @@ static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
|
||||
{
|
||||
if (pdu->Type == PTYPE_BIND_ACK)
|
||||
{
|
||||
if (rpc_recv_bind_ack_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s)) <= 0)
|
||||
if (!rpc_recv_bind_ack_pdu(rpc, pdu->s))
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_recv_bind_ack_pdu failure");
|
||||
return -1;
|
||||
@ -301,90 +306,117 @@ static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
|
||||
|
||||
static int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment)
|
||||
{
|
||||
BYTE* buffer;
|
||||
int rc = -1;
|
||||
RPC_PDU* pdu;
|
||||
UINT32 StubOffset;
|
||||
UINT32 StubLength;
|
||||
size_t StubOffset;
|
||||
size_t StubLength;
|
||||
RpcClientCall* call;
|
||||
rpcconn_hdr_t* header;
|
||||
pdu = rpc->client->pdu;
|
||||
buffer = (BYTE*)Stream_Buffer(fragment);
|
||||
header = (rpcconn_hdr_t*)Stream_Buffer(fragment);
|
||||
rpcconn_hdr_t header = { 0 };
|
||||
|
||||
if (header->common.ptype == PTYPE_RESPONSE)
|
||||
assert(rpc);
|
||||
assert(rpc->client);
|
||||
assert(fragment);
|
||||
|
||||
pdu = rpc->client->pdu;
|
||||
assert(pdu);
|
||||
|
||||
Stream_SealLength(fragment);
|
||||
Stream_SetPosition(fragment, 0);
|
||||
|
||||
if (!rts_read_pdu_header(fragment, &header))
|
||||
goto fail;
|
||||
|
||||
if (header.common.ptype == PTYPE_RESPONSE)
|
||||
{
|
||||
rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header->common.frag_length;
|
||||
rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header.common.frag_length;
|
||||
rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -=
|
||||
header->common.frag_length;
|
||||
header.common.frag_length;
|
||||
|
||||
if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow <
|
||||
(rpc->ReceiveWindow / 2))
|
||||
{
|
||||
if (rts_send_flow_control_ack_pdu(rpc) < 0)
|
||||
return -1;
|
||||
if (!rts_send_flow_control_ack_pdu(rpc))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!rpc_get_stub_data_info(rpc, buffer, &StubOffset, &StubLength))
|
||||
if (!rpc_get_stub_data_info(&header, &StubOffset, &StubLength))
|
||||
{
|
||||
WLog_ERR(TAG, "expected stub");
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (StubLength == 4)
|
||||
{
|
||||
if ((header->common.call_id == rpc->PipeCallId) &&
|
||||
(header->common.pfc_flags & PFC_LAST_FRAG))
|
||||
if ((header.common.call_id == rpc->PipeCallId) &&
|
||||
(header.common.pfc_flags & PFC_LAST_FRAG))
|
||||
{
|
||||
/* End of TsProxySetupReceivePipe */
|
||||
TerminateEventArgs e;
|
||||
rpc->result = *((UINT32*)&buffer[StubOffset]);
|
||||
freerdp_abort_connect(rpc->context->instance);
|
||||
tsg_set_state(rpc->transport->tsg, TSG_STATE_TUNNEL_CLOSE_PENDING);
|
||||
rdpContext* context = rpc->transport->context;
|
||||
rdpTsg* tsg = rpc->transport->tsg;
|
||||
|
||||
assert(context);
|
||||
|
||||
if (Stream_Length(fragment) < StubOffset + 4)
|
||||
goto fail;
|
||||
Stream_SetPosition(fragment, StubOffset);
|
||||
Stream_Read_UINT32(fragment, rpc->result);
|
||||
|
||||
freerdp_abort_connect(context->instance);
|
||||
tsg_set_state(tsg, TSG_STATE_TUNNEL_CLOSE_PENDING);
|
||||
EventArgsInit(&e, "freerdp");
|
||||
e.code = 0;
|
||||
PubSub_OnTerminate(rpc->context->pubSub, rpc->context, &e);
|
||||
return 0;
|
||||
PubSub_OnTerminate(context->pubSub, context, &e);
|
||||
rc = 0;
|
||||
goto success;
|
||||
}
|
||||
|
||||
if (header->common.call_id != rpc->PipeCallId)
|
||||
if (header.common.call_id != rpc->PipeCallId)
|
||||
{
|
||||
/* Ignoring non-TsProxySetupReceivePipe Response */
|
||||
return 0;
|
||||
rc = 0;
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
|
||||
if (rpc->StubFragCount == 0)
|
||||
rpc->StubCallId = header->common.call_id;
|
||||
rpc->StubCallId = header.common.call_id;
|
||||
|
||||
if (rpc->StubCallId != header->common.call_id)
|
||||
if (rpc->StubCallId != header.common.call_id)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"invalid call_id: actual: %" PRIu32 ", expected: %" PRIu32
|
||||
", frag_count: %" PRIu32 "",
|
||||
rpc->StubCallId, header->common.call_id, rpc->StubFragCount);
|
||||
rpc->StubCallId, header.common.call_id, rpc->StubFragCount);
|
||||
}
|
||||
|
||||
call = rpc_client_call_find_by_id(rpc->client, rpc->StubCallId);
|
||||
|
||||
if (!call)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
if (call->OpNum != TsProxySetupReceivePipeOpnum)
|
||||
{
|
||||
if (!Stream_EnsureCapacity(pdu->s, header->response.alloc_hint))
|
||||
return -1;
|
||||
const rpcconn_response_hdr_t* response =
|
||||
(const rpcconn_response_hdr_t*)&header.response;
|
||||
if (!Stream_EnsureCapacity(pdu->s, response->alloc_hint))
|
||||
goto fail;
|
||||
|
||||
Stream_Write(pdu->s, &buffer[StubOffset], StubLength);
|
||||
if (Stream_Length(fragment) < StubOffset + StubLength)
|
||||
goto fail;
|
||||
|
||||
Stream_SetPosition(fragment, StubOffset);
|
||||
Stream_Write(pdu->s, Stream_Pointer(fragment), StubLength);
|
||||
rpc->StubFragCount++;
|
||||
|
||||
if (header->response.alloc_hint == StubLength)
|
||||
if (response->alloc_hint == StubLength)
|
||||
{
|
||||
pdu->Flags = RPC_PDU_FLAG_STUB;
|
||||
pdu->Type = PTYPE_RESPONSE;
|
||||
pdu->CallId = rpc->StubCallId;
|
||||
Stream_SealLength(pdu->s);
|
||||
|
||||
if (rpc_client_recv_pdu(rpc, pdu) < 0)
|
||||
return -1;
|
||||
goto fail;
|
||||
rpc_pdu_reset(pdu);
|
||||
rpc->StubFragCount = 0;
|
||||
rpc->StubCallId = 0;
|
||||
@ -392,75 +424,84 @@ static int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment)
|
||||
}
|
||||
else
|
||||
{
|
||||
rpc_client_receive_pipe_write(rpc->client, &buffer[StubOffset], (size_t)StubLength);
|
||||
const rpcconn_response_hdr_t* response = &header.response;
|
||||
if (Stream_Length(fragment) < StubOffset + StubLength)
|
||||
goto fail;
|
||||
Stream_SetPosition(fragment, StubOffset);
|
||||
rpc_client_receive_pipe_write(rpc->client, Stream_Pointer(fragment),
|
||||
(size_t)StubLength);
|
||||
rpc->StubFragCount++;
|
||||
|
||||
if (header->response.alloc_hint == StubLength)
|
||||
if (response->alloc_hint == StubLength)
|
||||
{
|
||||
rpc->StubFragCount = 0;
|
||||
rpc->StubCallId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
goto success;
|
||||
}
|
||||
else if (header->common.ptype == PTYPE_RTS)
|
||||
else if (header.common.ptype == PTYPE_RTS)
|
||||
{
|
||||
if (rpc->State < RPC_CLIENT_STATE_CONTEXT_NEGOTIATED)
|
||||
{
|
||||
pdu->Flags = 0;
|
||||
pdu->Type = header->common.ptype;
|
||||
pdu->CallId = header->common.call_id;
|
||||
pdu->Type = header.common.ptype;
|
||||
pdu->CallId = header.common.call_id;
|
||||
|
||||
if (!Stream_EnsureCapacity(pdu->s, Stream_Length(fragment)))
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
Stream_Write(pdu->s, buffer, Stream_Length(fragment));
|
||||
Stream_SealLength(pdu->s);
|
||||
Stream_Write(pdu->s, Stream_Buffer(fragment), Stream_Length(fragment));
|
||||
|
||||
if (rpc_client_recv_pdu(rpc, pdu) < 0)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
rpc_pdu_reset(pdu);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rts_recv_out_of_sequence_pdu(rpc, buffer, header->common.frag_length) < 0)
|
||||
return -1;
|
||||
if (!rts_recv_out_of_sequence_pdu(rpc, fragment, &header))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 1;
|
||||
goto success;
|
||||
}
|
||||
else if (header->common.ptype == PTYPE_BIND_ACK)
|
||||
else if (header.common.ptype == PTYPE_BIND_ACK)
|
||||
{
|
||||
pdu->Flags = 0;
|
||||
pdu->Type = header->common.ptype;
|
||||
pdu->CallId = header->common.call_id;
|
||||
pdu->Type = header.common.ptype;
|
||||
pdu->CallId = header.common.call_id;
|
||||
|
||||
if (!Stream_EnsureCapacity(pdu->s, Stream_Length(fragment)))
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
Stream_Write(pdu->s, buffer, Stream_Length(fragment));
|
||||
Stream_SealLength(pdu->s);
|
||||
Stream_Write(pdu->s, Stream_Buffer(fragment), Stream_Length(fragment));
|
||||
|
||||
if (rpc_client_recv_pdu(rpc, pdu) < 0)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
rpc_pdu_reset(pdu);
|
||||
return 1;
|
||||
goto success;
|
||||
}
|
||||
else if (header->common.ptype == PTYPE_FAULT)
|
||||
else if (header.common.ptype == PTYPE_FAULT)
|
||||
{
|
||||
rpc_recv_fault_pdu(header->fault.status);
|
||||
return -1;
|
||||
const rpcconn_fault_hdr_t* fault = (const rpcconn_fault_hdr_t*)&header.fault;
|
||||
rpc_recv_fault_pdu(fault->status);
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "unexpected RPC PDU type 0x%02" PRIX8 "", header->common.ptype);
|
||||
return -1;
|
||||
WLog_ERR(TAG, "unexpected RPC PDU type 0x%02" PRIX8 "", header.common.ptype);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 1;
|
||||
success:
|
||||
rc = (rc < 0) ? 1 : 0; /* In case of default error return change to 1, otherwise we already set
|
||||
the return code */
|
||||
fail:
|
||||
rts_free_pdu_header(&header, FALSE);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
@ -510,7 +551,7 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
|
||||
/* Send CONN/A1 PDU over OUT channel */
|
||||
|
||||
if (rts_send_CONN_A1_pdu(rpc) < 0)
|
||||
if (!rts_send_CONN_A1_pdu(rpc))
|
||||
{
|
||||
http_response_free(response);
|
||||
WLog_ERR(TAG, "rpc_send_CONN_A1_pdu error!");
|
||||
@ -550,7 +591,8 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
|
||||
if (statusCode == HTTP_STATUS_DENIED)
|
||||
{
|
||||
freerdp_set_last_error_if_not(rpc->context, FREERDP_ERROR_AUTHENTICATION_FAILED);
|
||||
rdpContext* context = rpc->context;
|
||||
freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
|
||||
}
|
||||
|
||||
http_response_free(response);
|
||||
@ -564,12 +606,13 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
}
|
||||
else
|
||||
{
|
||||
wStream* fragment;
|
||||
rpcconn_common_hdr_t* header;
|
||||
fragment = rpc->client->ReceiveFragment;
|
||||
wStream* fragment = rpc->client->ReceiveFragment;
|
||||
|
||||
while (1)
|
||||
{
|
||||
size_t pos;
|
||||
rpcconn_common_hdr_t header = { 0 };
|
||||
|
||||
while (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH)
|
||||
{
|
||||
status = rpc_channel_read(&outChannel->common, fragment,
|
||||
@ -582,22 +625,27 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
header = (rpcconn_common_hdr_t*)Stream_Buffer(fragment);
|
||||
pos = Stream_GetPosition(fragment);
|
||||
Stream_SetPosition(fragment, 0);
|
||||
|
||||
if (header->frag_length > rpc->max_recv_frag)
|
||||
/* Ignore errors, the PDU might not be complete. */
|
||||
rts_read_common_pdu_header(fragment, &header);
|
||||
Stream_SetPosition(fragment, pos);
|
||||
|
||||
if (header.frag_length > rpc->max_recv_frag)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"rpc_client_recv: invalid fragment size: %" PRIu16 " (max: %" PRIu16 ")",
|
||||
header->frag_length, rpc->max_recv_frag);
|
||||
header.frag_length, rpc->max_recv_frag);
|
||||
winpr_HexDump(TAG, WLOG_ERROR, Stream_Buffer(fragment),
|
||||
Stream_GetPosition(fragment));
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (Stream_GetPosition(fragment) < header->frag_length)
|
||||
while (Stream_GetPosition(fragment) < header.frag_length)
|
||||
{
|
||||
status = rpc_channel_read(&outChannel->common, fragment,
|
||||
header->frag_length - Stream_GetPosition(fragment));
|
||||
header.frag_length - Stream_GetPosition(fragment));
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
@ -605,14 +653,12 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (Stream_GetPosition(fragment) < header->frag_length)
|
||||
if (Stream_GetPosition(fragment) < header.frag_length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
/* complete fragment received */
|
||||
Stream_SealLength(fragment);
|
||||
Stream_SetPosition(fragment, 0);
|
||||
status = rpc_client_recv_fragment(rpc, fragment);
|
||||
|
||||
if (status < 0)
|
||||
@ -664,10 +710,10 @@ static int rpc_client_nondefault_out_channel_recv(rdpRpc* rpc)
|
||||
if (rpc_ncacn_http_send_out_channel_request(&nextOutChannel->common, TRUE))
|
||||
{
|
||||
rpc_ncacn_http_ntlm_uninit(&nextOutChannel->common);
|
||||
status = rts_send_OUT_R1_A3_pdu(rpc);
|
||||
|
||||
if (status >= 0)
|
||||
if (rts_send_OUT_R1_A3_pdu(rpc))
|
||||
{
|
||||
status = 1;
|
||||
rpc_out_channel_transition_to_state(
|
||||
nextOutChannel, CLIENT_OUT_CHANNEL_STATE_OPENED_A6W);
|
||||
}
|
||||
@ -688,11 +734,14 @@ static int rpc_client_nondefault_out_channel_recv(rdpRpc* rpc)
|
||||
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_INITIAL:
|
||||
case CLIENT_OUT_CHANNEL_STATE_CONNECTED:
|
||||
case CLIENT_OUT_CHANNEL_STATE_NEGOTIATED:
|
||||
default:
|
||||
WLog_ERR(TAG,
|
||||
"rpc_client_nondefault_out_channel_recv: Unexpected message %08" PRIx32,
|
||||
nextOutChannel->State);
|
||||
return -1;
|
||||
status = -1;
|
||||
}
|
||||
|
||||
http_response_free(response);
|
||||
@ -770,7 +819,7 @@ int rpc_client_in_channel_recv(rdpRpc* rpc)
|
||||
|
||||
/* Send CONN/B1 PDU over IN channel */
|
||||
|
||||
if (rts_send_CONN_B1_pdu(rpc) < 0)
|
||||
if (!rts_send_CONN_B1_pdu(rpc))
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_send_CONN_B1_pdu error!");
|
||||
http_response_free(response);
|
||||
@ -811,8 +860,8 @@ int rpc_client_in_channel_recv(rdpRpc* rpc)
|
||||
|
||||
RpcClientCall* rpc_client_call_find_by_id(RpcClient* client, UINT32 CallId)
|
||||
{
|
||||
int index;
|
||||
int count;
|
||||
size_t index;
|
||||
size_t count;
|
||||
RpcClientCall* clientCall = NULL;
|
||||
|
||||
if (!client)
|
||||
@ -857,18 +906,23 @@ static void rpc_array_client_call_free(void* call)
|
||||
rpc_client_call_free((RpcClientCall*)call);
|
||||
}
|
||||
|
||||
int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer, UINT32 length)
|
||||
int rpc_in_channel_send_pdu(RpcInChannel* inChannel, const BYTE* buffer, size_t length)
|
||||
{
|
||||
int status;
|
||||
SSIZE_T status;
|
||||
RpcClientCall* clientCall;
|
||||
rpcconn_common_hdr_t* header;
|
||||
wStream s;
|
||||
rpcconn_common_hdr_t header = { 0 };
|
||||
|
||||
status = rpc_channel_write(&inChannel->common, buffer, length);
|
||||
|
||||
if (status <= 0)
|
||||
return -1;
|
||||
|
||||
header = (rpcconn_common_hdr_t*)buffer;
|
||||
clientCall = rpc_client_call_find_by_id(inChannel->common.client, header->call_id);
|
||||
Stream_StaticInit(&s, buffer, length);
|
||||
if (!rts_read_common_pdu_header(&s, &header))
|
||||
return -1;
|
||||
|
||||
clientCall = rpc_client_call_find_by_id(inChannel->common.client, header.call_id);
|
||||
clientCall->State = RPC_CLIENT_CALL_STATE_DISPATCHED;
|
||||
|
||||
/*
|
||||
@ -878,7 +932,7 @@ int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer, UINT32 length
|
||||
* variables specified by this abstract data model.
|
||||
*/
|
||||
|
||||
if (header->ptype == PTYPE_REQUEST)
|
||||
if (header.ptype == PTYPE_REQUEST)
|
||||
{
|
||||
inChannel->BytesSent += status;
|
||||
inChannel->SenderAvailableWindow -= status;
|
||||
@ -889,7 +943,7 @@ int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer, UINT32 length
|
||||
|
||||
BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum)
|
||||
{
|
||||
UINT32 offset;
|
||||
size_t offset;
|
||||
BYTE* buffer = NULL;
|
||||
UINT32 stub_data_pad;
|
||||
SecBuffer Buffers[2] = { 0 };
|
||||
@ -937,7 +991,7 @@ BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum)
|
||||
if (size < 0)
|
||||
goto fail;
|
||||
|
||||
rpc_pdu_header_init(rpc, &request_pdu.header);
|
||||
request_pdu.header = rpc_pdu_header_init(rpc);
|
||||
request_pdu.header.ptype = PTYPE_REQUEST;
|
||||
request_pdu.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
|
||||
request_pdu.header.auth_length = (UINT16)size;
|
||||
@ -1026,7 +1080,7 @@ static BOOL rpc_client_resolve_gateway(rdpSettings* settings, char** host, UINT1
|
||||
const char* peerHostname = freerdp_settings_get_string(settings, FreeRDP_GatewayHostname);
|
||||
const char* proxyUsername = freerdp_settings_get_string(settings, FreeRDP_GatewayUsername);
|
||||
const char* proxyPassword = freerdp_settings_get_string(settings, FreeRDP_GatewayPassword);
|
||||
*port = freerdp_settings_get_uint32(settings, FreeRDP_GatewayPort);
|
||||
*port = (UINT16)freerdp_settings_get_uint32(settings, FreeRDP_GatewayPort);
|
||||
*isProxy = proxy_prepare(settings, &peerHostname, port, &proxyUsername, &proxyPassword);
|
||||
result = freerdp_tcp_resolve_host(peerHostname, *port, 0);
|
||||
|
||||
@ -1084,9 +1138,6 @@ RpcClient* rpc_client_new(rdpContext* context, UINT32 max_recv_frag)
|
||||
goto fail;
|
||||
|
||||
obj = ArrayList_Object(client->ClientCallList);
|
||||
if (!obj)
|
||||
goto fail;
|
||||
|
||||
obj->fnObjectFree = rpc_array_client_call_free;
|
||||
return client;
|
||||
fail:
|
||||
|
||||
@ -31,7 +31,8 @@ FREERDP_LOCAL RpcClientCall* rpc_client_call_find_by_id(RpcClient* client, UINT3
|
||||
FREERDP_LOCAL RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum);
|
||||
FREERDP_LOCAL void rpc_client_call_free(RpcClientCall* client_call);
|
||||
|
||||
FREERDP_LOCAL int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer, UINT32 length);
|
||||
FREERDP_LOCAL int rpc_in_channel_send_pdu(RpcInChannel* inChannel, const BYTE* buffer,
|
||||
size_t length);
|
||||
|
||||
FREERDP_LOCAL int rpc_client_in_channel_recv(rdpRpc* rpc);
|
||||
FREERDP_LOCAL int rpc_client_out_channel_recv(rdpRpc* rpc);
|
||||
|
||||
@ -154,8 +154,7 @@ static const RPC_FAULT_CODE RPC_FAULT_CODES[] = {
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_COOKIE_AUTH_FAILED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_GROUP_MEMBER_NOT_FOUND, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(EPT_S_CANT_CREATE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_OBJECT, CAT_GATEWAY),
|
||||
{ 0, NULL, NULL }
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_OBJECT, CAT_GATEWAY)
|
||||
};
|
||||
|
||||
static const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[] = {
|
||||
@ -207,8 +206,7 @@ static const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[] = {
|
||||
{ HRESULT_CODE(E_PROXY_REAUTH_NAP_FAILED), "E_PROXY_REAUTH_NAP_FAILED", CAT_GATEWAY },
|
||||
{ HRESULT_CODE(E_PROXY_CONNECTIONABORTED), "E_PROXY_CONNECTIONABORTED", CAT_GATEWAY },
|
||||
{ HRESULT_CODE(E_PROXY_NOCERTAVAILABLE), "E_PROXY_NOCERTAVAILABLE", CAT_GATEWAY },
|
||||
{ HRESULT_CODE(RPC_S_CALL_CANCELLED), "RPC_S_CALL_CANCELLED", CAT_GATEWAY },
|
||||
{ 0, NULL, NULL }
|
||||
{ HRESULT_CODE(RPC_S_CALL_CANCELLED), "RPC_S_CALL_CANCELLED", CAT_GATEWAY }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -361,29 +359,32 @@ const char* rpc_error_to_string(UINT32 code)
|
||||
size_t index;
|
||||
static char buffer[1024];
|
||||
|
||||
for (index = 0; RPC_FAULT_CODES[index].name != NULL; index++)
|
||||
for (index = 0; index < ARRAYSIZE(RPC_FAULT_CODES); index++)
|
||||
{
|
||||
if (RPC_FAULT_CODES[index].code == code)
|
||||
const RPC_FAULT_CODE* const current = &RPC_FAULT_CODES[index];
|
||||
if (current->code == code)
|
||||
{
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%s", RPC_FAULT_CODES[index].name);
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%s", current->name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
for (index = 0; RPC_TSG_FAULT_CODES[index].name != NULL; index++)
|
||||
for (index = 0; index < ARRAYSIZE(RPC_TSG_FAULT_CODES); index++)
|
||||
{
|
||||
if (RPC_TSG_FAULT_CODES[index].code == code)
|
||||
const RPC_FAULT_CODE* const current = &RPC_TSG_FAULT_CODES[index];
|
||||
if (current->code == code)
|
||||
{
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%s", RPC_TSG_FAULT_CODES[index].name);
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%s", current->name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
for (index = 0; RPC_TSG_FAULT_CODES[index].name != NULL; index++)
|
||||
for (index = 0; index < ARRAYSIZE(RPC_TSG_FAULT_CODES); index++)
|
||||
{
|
||||
if (RPC_TSG_FAULT_CODES[index].code == HRESULT_CODE(code))
|
||||
const RPC_FAULT_CODE* const current = &RPC_TSG_FAULT_CODES[index];
|
||||
if (current->code == HRESULT_CODE(code))
|
||||
{
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%s", RPC_TSG_FAULT_CODES[index].name);
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%s", current->name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -397,22 +398,25 @@ const char* rpc_error_to_category(UINT32 code)
|
||||
{
|
||||
size_t index;
|
||||
|
||||
for (index = 0; RPC_FAULT_CODES[index].category != NULL; index++)
|
||||
for (index = 0; index < ARRAYSIZE(RPC_FAULT_CODES); index++)
|
||||
{
|
||||
if (RPC_FAULT_CODES[index].code == code)
|
||||
return RPC_FAULT_CODES[index].category;
|
||||
const RPC_FAULT_CODE* const current = &RPC_FAULT_CODES[index];
|
||||
if (current->code == code)
|
||||
return current->category;
|
||||
}
|
||||
|
||||
for (index = 0; RPC_TSG_FAULT_CODES[index].category != NULL; index++)
|
||||
for (index = 0; index < ARRAYSIZE(RPC_TSG_FAULT_CODES); index++)
|
||||
{
|
||||
if (RPC_TSG_FAULT_CODES[index].code == code)
|
||||
return RPC_TSG_FAULT_CODES[index].category;
|
||||
const RPC_FAULT_CODE* const current = &RPC_TSG_FAULT_CODES[index];
|
||||
if (current->code == code)
|
||||
return current->category;
|
||||
}
|
||||
|
||||
for (index = 0; RPC_TSG_FAULT_CODES[index].category != NULL; index++)
|
||||
for (index = 0; index < ARRAYSIZE(RPC_TSG_FAULT_CODES); index++)
|
||||
{
|
||||
if (RPC_TSG_FAULT_CODES[index].code == HRESULT_CODE(code))
|
||||
return RPC_TSG_FAULT_CODES[index].category;
|
||||
const RPC_FAULT_CODE* const current = &RPC_TSG_FAULT_CODES[index];
|
||||
if (current->code == HRESULT_CODE(code))
|
||||
return current->category;
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -24,12 +24,14 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "rpc.h"
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "rpc.h"
|
||||
|
||||
#define RTS_FLAG_NONE 0x0000
|
||||
#define RTS_FLAG_PING 0x0001
|
||||
#define RTS_FLAG_OTHER_CMD 0x0002
|
||||
@ -79,21 +81,28 @@
|
||||
|
||||
FREERDP_LOCAL void rts_generate_cookie(BYTE* cookie);
|
||||
|
||||
FREERDP_LOCAL SSIZE_T rts_command_length(UINT32 CommandType, const BYTE* buffer, size_t length);
|
||||
FREERDP_LOCAL BOOL rts_write_pdu_auth3(wStream* s, const rpcconn_rpc_auth_3_hdr_t* auth);
|
||||
FREERDP_LOCAL BOOL rts_write_pdu_bind(wStream* s, const rpcconn_bind_hdr_t* bind);
|
||||
|
||||
FREERDP_LOCAL int rts_send_CONN_A1_pdu(rdpRpc* rpc);
|
||||
FREERDP_LOCAL int rts_recv_CONN_A3_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length);
|
||||
FREERDP_LOCAL BOOL rts_read_pdu_header(wStream* s, rpcconn_hdr_t* header);
|
||||
FREERDP_LOCAL void rts_free_pdu_header(rpcconn_hdr_t* header, BOOL allocated);
|
||||
|
||||
FREERDP_LOCAL int rts_send_CONN_B1_pdu(rdpRpc* rpc);
|
||||
FREERDP_LOCAL BOOL rts_read_common_pdu_header(wStream* s, rpcconn_common_hdr_t* header);
|
||||
|
||||
FREERDP_LOCAL int rts_recv_CONN_C2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length);
|
||||
FREERDP_LOCAL BOOL rts_command_length(UINT32 CommandType, wStream* s, size_t* length);
|
||||
|
||||
FREERDP_LOCAL int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc);
|
||||
FREERDP_LOCAL BOOL rts_send_CONN_A1_pdu(rdpRpc* rpc);
|
||||
FREERDP_LOCAL BOOL rts_recv_CONN_A3_pdu(rdpRpc* rpc, wStream* buffer);
|
||||
|
||||
FREERDP_LOCAL int rts_send_flow_control_ack_pdu(rdpRpc* rpc);
|
||||
FREERDP_LOCAL BOOL rts_send_CONN_B1_pdu(rdpRpc* rpc);
|
||||
|
||||
FREERDP_LOCAL int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length);
|
||||
FREERDP_LOCAL BOOL rts_recv_CONN_C2_pdu(rdpRpc* rpc, wStream* buffer);
|
||||
|
||||
#include "rts_signature.h"
|
||||
FREERDP_LOCAL BOOL rts_send_OUT_R1_A3_pdu(rdpRpc* rpc);
|
||||
|
||||
FREERDP_LOCAL BOOL rts_send_flow_control_ack_pdu(rdpRpc* rpc);
|
||||
|
||||
FREERDP_LOCAL BOOL rts_recv_out_of_sequence_pdu(rdpRpc* rpc, wStream* buffer,
|
||||
const rpcconn_hdr_t* header);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_RTS_H */
|
||||
|
||||
@ -17,6 +17,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "rts_signature.h"
|
||||
@ -276,90 +279,74 @@ static const RTS_PDU_SIGNATURE_ENTRY RTS_PDU_SIGNATURE_TABLE[] = {
|
||||
{ RTS_PDU_PING, TRUE, &RTS_PDU_PING_SIGNATURE, "Ping" },
|
||||
{ RTS_PDU_FLOW_CONTROL_ACK, TRUE, &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE, "FlowControlAck" },
|
||||
{ RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION, TRUE,
|
||||
&RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE, "FlowControlAckWithDestination" },
|
||||
|
||||
{ 0, FALSE, NULL, NULL }
|
||||
&RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE, "FlowControlAckWithDestination" }
|
||||
};
|
||||
|
||||
BOOL rts_match_pdu_signature(const RtsPduSignature* signature, const rpcconn_rts_hdr_t* rts)
|
||||
BOOL rts_match_pdu_signature(const RtsPduSignature* signature, wStream* src,
|
||||
const rpcconn_hdr_t* header)
|
||||
{
|
||||
UINT16 i;
|
||||
int status;
|
||||
const BYTE* buffer;
|
||||
UINT32 length;
|
||||
UINT32 offset;
|
||||
UINT32 CommandType;
|
||||
UINT32 CommandLength;
|
||||
RtsPduSignature extracted = { 0 };
|
||||
|
||||
if (!signature || !rts)
|
||||
assert(signature);
|
||||
assert(src);
|
||||
|
||||
if (!rts_extract_pdu_signature(&extracted, src, header))
|
||||
return FALSE;
|
||||
|
||||
if (rts->Flags != signature->Flags)
|
||||
return FALSE;
|
||||
|
||||
if (rts->NumberOfCommands != signature->NumberOfCommands)
|
||||
return FALSE;
|
||||
|
||||
buffer = (const BYTE*)rts;
|
||||
offset = RTS_PDU_HEADER_LENGTH;
|
||||
length = rts->header.frag_length - offset;
|
||||
|
||||
for (i = 0; i < rts->NumberOfCommands; i++)
|
||||
{
|
||||
CommandType = *((UINT32*)&buffer[offset]); /* CommandType (4 bytes) */
|
||||
offset += 4;
|
||||
|
||||
if (CommandType != signature->CommandTypes[i])
|
||||
return FALSE;
|
||||
|
||||
status = rts_command_length(CommandType, &buffer[offset], length);
|
||||
|
||||
if (status < 0)
|
||||
return FALSE;
|
||||
|
||||
CommandLength = (UINT32)status;
|
||||
offset += CommandLength;
|
||||
length = rts->header.frag_length - offset;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return memcmp(signature, &extracted, sizeof(extracted)) == 0;
|
||||
}
|
||||
|
||||
BOOL rts_extract_pdu_signature(RtsPduSignature* signature, const rpcconn_rts_hdr_t* rts)
|
||||
BOOL rts_extract_pdu_signature(RtsPduSignature* signature, wStream* src,
|
||||
const rpcconn_hdr_t* header)
|
||||
{
|
||||
int i;
|
||||
int status;
|
||||
BYTE* buffer;
|
||||
UINT32 length;
|
||||
UINT32 offset;
|
||||
UINT32 CommandType;
|
||||
UINT32 CommandLength;
|
||||
BOOL rc = FALSE;
|
||||
UINT16 i;
|
||||
wStream tmp;
|
||||
rpcconn_hdr_t rheader = { 0 };
|
||||
const rpcconn_rts_hdr_t* rts;
|
||||
|
||||
if (!signature || !rts)
|
||||
return FALSE;
|
||||
assert(signature);
|
||||
assert(src);
|
||||
|
||||
Stream_StaticInit(&tmp, Stream_Pointer(src), Stream_GetRemainingLength(src));
|
||||
if (!header)
|
||||
{
|
||||
if (!rts_read_pdu_header(&tmp, &rheader))
|
||||
goto fail;
|
||||
header = &rheader;
|
||||
}
|
||||
rts = &header->rts;
|
||||
if (rts->header.frag_length < sizeof(rpcconn_rts_hdr_t))
|
||||
goto fail;
|
||||
|
||||
signature->Flags = rts->Flags;
|
||||
signature->NumberOfCommands = rts->NumberOfCommands;
|
||||
buffer = (BYTE*)rts;
|
||||
offset = RTS_PDU_HEADER_LENGTH;
|
||||
length = rts->header.frag_length - offset;
|
||||
|
||||
for (i = 0; i < rts->NumberOfCommands; i++)
|
||||
{
|
||||
CommandType = *((UINT32*)&buffer[offset]); /* CommandType (4 bytes) */
|
||||
offset += 4;
|
||||
signature->CommandTypes[i] = CommandType;
|
||||
status = rts_command_length(CommandType, &buffer[offset], length);
|
||||
UINT32 CommandType;
|
||||
size_t CommandLength;
|
||||
|
||||
if (status < 0)
|
||||
return FALSE;
|
||||
if (Stream_GetRemainingLength(&tmp) < 4)
|
||||
goto fail;
|
||||
|
||||
CommandLength = (UINT32)status;
|
||||
offset += CommandLength;
|
||||
length = rts->header.frag_length - offset;
|
||||
Stream_Read_UINT32(&tmp, CommandType); /* CommandType (4 bytes) */
|
||||
|
||||
/* We only need this for comparison against known command types */
|
||||
if (i < ARRAYSIZE(signature->CommandTypes))
|
||||
signature->CommandTypes[i] = CommandType;
|
||||
|
||||
if (!rts_command_length(CommandType, &tmp, &CommandLength))
|
||||
goto fail;
|
||||
if (!Stream_SafeSeek(&tmp, CommandLength))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
rc = TRUE;
|
||||
fail:
|
||||
rts_free_pdu_header(&rheader, FALSE);
|
||||
Stream_Free(&tmp, FALSE);
|
||||
return rc;
|
||||
}
|
||||
|
||||
UINT32 rts_identify_pdu_signature(const RtsPduSignature* signature,
|
||||
@ -367,11 +354,15 @@ UINT32 rts_identify_pdu_signature(const RtsPduSignature* signature,
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; RTS_PDU_SIGNATURE_TABLE[i].SignatureId != 0; i++)
|
||||
{
|
||||
const RtsPduSignature* pSignature = RTS_PDU_SIGNATURE_TABLE[i].Signature;
|
||||
if (entry)
|
||||
*entry = NULL;
|
||||
|
||||
if (!RTS_PDU_SIGNATURE_TABLE[i].SignatureClient)
|
||||
for (i = 0; i < ARRAYSIZE(RTS_PDU_SIGNATURE_TABLE); i++)
|
||||
{
|
||||
const RTS_PDU_SIGNATURE_ENTRY* current = &RTS_PDU_SIGNATURE_TABLE[i];
|
||||
const RtsPduSignature* pSignature = current->Signature;
|
||||
|
||||
if (!current->SignatureClient)
|
||||
continue;
|
||||
|
||||
if (signature->Flags != pSignature->Flags)
|
||||
@ -387,9 +378,9 @@ UINT32 rts_identify_pdu_signature(const RtsPduSignature* signature,
|
||||
}
|
||||
|
||||
if (entry)
|
||||
*entry = &RTS_PDU_SIGNATURE_TABLE[i];
|
||||
*entry = current;
|
||||
|
||||
return RTS_PDU_SIGNATURE_TABLE[i].SignatureId;
|
||||
return current->SignatureId;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -178,10 +178,10 @@ FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_PING_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL BOOL rts_match_pdu_signature(const RtsPduSignature* signature,
|
||||
const rpcconn_rts_hdr_t* rts);
|
||||
FREERDP_LOCAL BOOL rts_extract_pdu_signature(RtsPduSignature* signature,
|
||||
const rpcconn_rts_hdr_t* rts);
|
||||
FREERDP_LOCAL BOOL rts_match_pdu_signature(const RtsPduSignature* signature, wStream* s,
|
||||
const rpcconn_hdr_t* header);
|
||||
FREERDP_LOCAL BOOL rts_extract_pdu_signature(RtsPduSignature* signature, wStream* s,
|
||||
const rpcconn_hdr_t* header);
|
||||
FREERDP_LOCAL UINT32 rts_identify_pdu_signature(const RtsPduSignature* signature,
|
||||
const RTS_PDU_SIGNATURE_ENTRY** entry);
|
||||
FREERDP_LOCAL BOOL rts_print_pdu_signature(const RtsPduSignature* signature);
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/ndr.h>
|
||||
#include <winpr/error.h>
|
||||
@ -39,13 +40,14 @@
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.tsg")
|
||||
|
||||
#define TSG_CAPABILITY_TYPE_NAP 0x00000001
|
||||
|
||||
#define TSG_PACKET_TYPE_HEADER 0x00004844
|
||||
#define TSG_PACKET_TYPE_VERSIONCAPS 0x00005643
|
||||
#define TSG_PACKET_TYPE_QUARCONFIGREQUEST 0x00005143
|
||||
#define TSG_PACKET_TYPE_QUARREQUEST 0x00005152
|
||||
#define TSG_PACKET_TYPE_RESPONSE 0x00005052
|
||||
#define TSG_PACKET_TYPE_QUARENC_RESPONSE 0x00004552
|
||||
#define TSG_CAPABILITY_TYPE_NAP 0x00000001
|
||||
#define TSG_PACKET_TYPE_CAPS_RESPONSE 0x00004350
|
||||
#define TSG_PACKET_TYPE_MSGREQUEST_PACKET 0x00004752
|
||||
#define TSG_PACKET_TYPE_MESSAGE_PACKET 0x00004750
|
||||
@ -222,7 +224,6 @@ struct rdp_tsg
|
||||
UINT32 TunnelId;
|
||||
UINT32 ChannelId;
|
||||
BOOL reauthSequence;
|
||||
rdpSettings* settings;
|
||||
rdpTransport* transport;
|
||||
UINT64 ReauthTunnelContext;
|
||||
CONTEXT_HANDLE TunnelContext;
|
||||
@ -311,16 +312,35 @@ static BOOL tsg_print(char** buffer, size_t* len, const char* fmt, ...)
|
||||
static BOOL tsg_packet_header_to_string(char** buffer, size_t* length,
|
||||
const TSG_PACKET_HEADER* header)
|
||||
{
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(header);
|
||||
|
||||
return tsg_print(buffer, length,
|
||||
"header { ComponentId=0x%04" PRIx16 ", PacketId=0x%04" PRIx16 " }",
|
||||
header->ComponentId, header->PacketId);
|
||||
}
|
||||
|
||||
static BOOL tsg_type_capability_nap_to_string(char** buffer, size_t* length,
|
||||
const TSG_CAPABILITY_NAP* cur)
|
||||
{
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(cur);
|
||||
|
||||
return tsg_print(buffer, length, "%s { capabilities=0x%08" PRIx32 " }",
|
||||
tsg_packet_id_to_string(TSG_CAPABILITY_TYPE_NAP), cur->capabilities);
|
||||
}
|
||||
|
||||
static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length,
|
||||
const TSG_PACKET_CAPABILITIES* caps, UINT32 numCaps)
|
||||
{
|
||||
UINT32 x;
|
||||
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(caps);
|
||||
|
||||
if (!tsg_print(buffer, length, "capabilities { "))
|
||||
return FALSE;
|
||||
|
||||
@ -330,9 +350,7 @@ static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length,
|
||||
switch (cur->capabilityType)
|
||||
{
|
||||
case TSG_CAPABILITY_TYPE_NAP:
|
||||
if (!tsg_print(buffer, length, "%s { capabilities=0x%08" PRIx32 " }",
|
||||
tsg_packet_id_to_string(cur->capabilityType),
|
||||
cur->tsgPacket.tsgCapNap.capabilities))
|
||||
if (!tsg_type_capability_nap_to_string(buffer, length, &cur->tsgPacket.tsgCapNap))
|
||||
return FALSE;
|
||||
break;
|
||||
default:
|
||||
@ -347,6 +365,10 @@ static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length,
|
||||
static BOOL tsg_packet_versioncaps_to_string(char** buffer, size_t* length,
|
||||
const TSG_PACKET_VERSIONCAPS* caps)
|
||||
{
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(caps);
|
||||
|
||||
if (!tsg_print(buffer, length, "versioncaps { "))
|
||||
return FALSE;
|
||||
if (!tsg_packet_header_to_string(buffer, length, &caps->tsgHeader))
|
||||
@ -368,6 +390,281 @@ static BOOL tsg_packet_versioncaps_to_string(char** buffer, size_t* length,
|
||||
return tsg_print(buffer, length, " }");
|
||||
}
|
||||
|
||||
static BOOL tsg_packet_quarconfigrequest_to_string(char** buffer, size_t* length,
|
||||
const TSG_PACKET_QUARCONFIGREQUEST* caps)
|
||||
{
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(caps);
|
||||
|
||||
if (!tsg_print(buffer, length, "quarconfigrequest { "))
|
||||
return FALSE;
|
||||
|
||||
if (!tsg_print(buffer, length, " "))
|
||||
return FALSE;
|
||||
|
||||
if (!tsg_print(buffer, length, " flags=0x%08" PRIx32, caps->flags))
|
||||
return FALSE;
|
||||
|
||||
return tsg_print(buffer, length, " }");
|
||||
}
|
||||
|
||||
static BOOL tsg_packet_quarrequest_to_string(char** buffer, size_t* length,
|
||||
const TSG_PACKET_QUARREQUEST* caps)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
char* name = NULL;
|
||||
char* strdata = NULL;
|
||||
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(caps);
|
||||
|
||||
if (!tsg_print(buffer, length, "quarrequest { "))
|
||||
return FALSE;
|
||||
|
||||
if (!tsg_print(buffer, length, " "))
|
||||
return FALSE;
|
||||
|
||||
if (caps->nameLength > 0)
|
||||
{
|
||||
if (caps->nameLength > INT_MAX)
|
||||
return FALSE;
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, caps->machineName, (int)caps->nameLength, &name, 0, NULL,
|
||||
NULL) < 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
strdata = winpr_BinToHexString(caps->data, caps->dataLen, TRUE);
|
||||
if (strdata || (caps->dataLen == 0))
|
||||
rc = tsg_print(buffer, length,
|
||||
" flags=0x%08" PRIx32 ", machineName=%s [%" PRIu32 "], data[%" PRIu32 "]=%s",
|
||||
caps->flags, name, caps->nameLength, caps->dataLen, strdata);
|
||||
free(name);
|
||||
free(strdata);
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
|
||||
return tsg_print(buffer, length, " }");
|
||||
}
|
||||
|
||||
static const char* tsg_bool_to_string(BOOL val)
|
||||
{
|
||||
if (val)
|
||||
return "true";
|
||||
return "false";
|
||||
}
|
||||
|
||||
static const char* tsg_redirection_flags_to_string(char* buffer, size_t size,
|
||||
const TSG_REDIRECTION_FLAGS* flags)
|
||||
{
|
||||
assert(buffer || (size == 0));
|
||||
assert(flags);
|
||||
|
||||
_snprintf(buffer, size,
|
||||
"enableAllRedirections=%s, disableAllRedirections=%s, driveRedirectionDisabled=%s, "
|
||||
"printerRedirectionDisabled=%s, portRedirectionDisabled=%s, reserved=%s, "
|
||||
"clipboardRedirectionDisabled=%s, pnpRedirectionDisabled=%s",
|
||||
tsg_bool_to_string(flags->enableAllRedirections),
|
||||
tsg_bool_to_string(flags->disableAllRedirections),
|
||||
tsg_bool_to_string(flags->driveRedirectionDisabled),
|
||||
tsg_bool_to_string(flags->printerRedirectionDisabled),
|
||||
tsg_bool_to_string(flags->portRedirectionDisabled),
|
||||
tsg_bool_to_string(flags->reserved),
|
||||
tsg_bool_to_string(flags->clipboardRedirectionDisabled),
|
||||
tsg_bool_to_string(flags->pnpRedirectionDisabled));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static BOOL tsg_packet_response_to_string(char** buffer, size_t* length,
|
||||
const TSG_PACKET_RESPONSE* caps)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
char* strdata = NULL;
|
||||
char tbuffer[8192] = { 0 };
|
||||
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(caps);
|
||||
|
||||
if (!tsg_print(buffer, length, "response { "))
|
||||
return FALSE;
|
||||
|
||||
if (!tsg_print(buffer, length, " "))
|
||||
return FALSE;
|
||||
|
||||
strdata = winpr_BinToHexString(caps->responseData, caps->responseDataLen, TRUE);
|
||||
if (strdata || (caps->responseDataLen == 0))
|
||||
rc = tsg_print(
|
||||
buffer, length,
|
||||
" flags=0x%08" PRIx32 ", reserved=0x%08" PRIx32 ", responseData[%" PRIu32
|
||||
"]=%s, redirectionFlags={ %s }",
|
||||
caps->flags, caps->reserved, caps->responseDataLen, strdata,
|
||||
tsg_redirection_flags_to_string(tbuffer, ARRAYSIZE(tbuffer), &caps->redirectionFlags));
|
||||
free(strdata);
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
|
||||
return tsg_print(buffer, length, " }");
|
||||
}
|
||||
|
||||
static BOOL tsg_packet_quarenc_response_to_string(char** buffer, size_t* length,
|
||||
const TSG_PACKET_QUARENC_RESPONSE* caps)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
char* strdata = NULL;
|
||||
RPC_CSTR uuid;
|
||||
char tbuffer[8192] = { 0 };
|
||||
size_t size = ARRAYSIZE(tbuffer);
|
||||
char* ptbuffer = tbuffer;
|
||||
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(caps);
|
||||
|
||||
if (!tsg_print(buffer, length, "quarenc_response { "))
|
||||
return FALSE;
|
||||
|
||||
if (!tsg_print(buffer, length, " "))
|
||||
return FALSE;
|
||||
|
||||
if (caps->certChainLen > 0)
|
||||
{
|
||||
if (caps->certChainLen > INT_MAX)
|
||||
return FALSE;
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, caps->certChainData, (int)caps->certChainLen, &strdata,
|
||||
0, NULL, NULL) <= 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tsg_packet_versioncaps_to_string(&ptbuffer, &size, caps->versionCaps);
|
||||
UuidToStringA(&caps->nonce, &uuid);
|
||||
if (strdata || (caps->certChainLen == 0))
|
||||
rc =
|
||||
tsg_print(buffer, length,
|
||||
" flags=0x%08" PRIx32 ", certChain[%" PRIu32 "]=%s, nonce=%s, versionCaps=%s",
|
||||
caps->flags, caps->certChainLen, strdata, uuid, tbuffer);
|
||||
free(strdata);
|
||||
free(uuid);
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
|
||||
return tsg_print(buffer, length, " }");
|
||||
}
|
||||
|
||||
static BOOL tsg_packet_message_response_to_string(char** buffer, size_t* length,
|
||||
const TSG_PACKET_MSG_RESPONSE* caps)
|
||||
{
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(caps);
|
||||
|
||||
if (!tsg_print(buffer, length, "msg_response { "))
|
||||
return FALSE;
|
||||
|
||||
if (!tsg_print(buffer, length,
|
||||
" msgID=0x%08" PRIx32 ", msgType=0x%08" PRIx32 ", isMsgPresent=%" PRId32,
|
||||
caps->msgID, caps->msgType, caps->isMsgPresent))
|
||||
return FALSE;
|
||||
|
||||
return tsg_print(buffer, length, " }");
|
||||
}
|
||||
|
||||
static BOOL tsg_packet_caps_response_to_string(char** buffer, size_t* length,
|
||||
const TSG_PACKET_CAPS_RESPONSE* caps)
|
||||
{
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(caps);
|
||||
|
||||
if (!tsg_print(buffer, length, "caps_response { "))
|
||||
return FALSE;
|
||||
|
||||
if (!tsg_packet_quarenc_response_to_string(buffer, length, &caps->pktQuarEncResponse))
|
||||
return FALSE;
|
||||
|
||||
if (!tsg_packet_message_response_to_string(buffer, length, &caps->pktConsentMessage))
|
||||
return FALSE;
|
||||
|
||||
return tsg_print(buffer, length, " }");
|
||||
}
|
||||
|
||||
static BOOL tsg_packet_message_request_to_string(char** buffer, size_t* length,
|
||||
const TSG_PACKET_MSG_REQUEST* caps)
|
||||
{
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(caps);
|
||||
|
||||
if (!tsg_print(buffer, length, "caps_message_request { "))
|
||||
return FALSE;
|
||||
|
||||
if (!tsg_print(buffer, length, " maxMessagesPerBatch=%" PRIu32, caps->maxMessagesPerBatch))
|
||||
return FALSE;
|
||||
|
||||
return tsg_print(buffer, length, " }");
|
||||
}
|
||||
|
||||
static BOOL tsg_packet_auth_to_string(char** buffer, size_t* length, const TSG_PACKET_AUTH* caps)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
char* strdata = NULL;
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(caps);
|
||||
|
||||
if (!tsg_print(buffer, length, "caps_message_request { "))
|
||||
return FALSE;
|
||||
|
||||
if (!tsg_packet_versioncaps_to_string(buffer, length, &caps->tsgVersionCaps))
|
||||
return FALSE;
|
||||
|
||||
strdata = winpr_BinToHexString(caps->cookie, caps->cookieLen, TRUE);
|
||||
if (strdata || (caps->cookieLen == 0))
|
||||
rc = tsg_print(buffer, length, " cookie[%" PRIu32 "]=%s", caps->cookieLen, strdata);
|
||||
free(strdata);
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
|
||||
return tsg_print(buffer, length, " }");
|
||||
}
|
||||
|
||||
static BOOL tsg_packet_reauth_to_string(char** buffer, size_t* length,
|
||||
const TSG_PACKET_REAUTH* caps)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
assert(buffer);
|
||||
assert(length);
|
||||
assert(caps);
|
||||
|
||||
if (!tsg_print(buffer, length, "caps_message_request { "))
|
||||
return FALSE;
|
||||
|
||||
if (!tsg_print(buffer, length, " tunnelContext=0x%016" PRIx64 ", packetId=%s [0x%08" PRIx32 "]",
|
||||
caps->tunnelContext, tsg_packet_id_to_string(caps->packetId), caps->packetId))
|
||||
return FALSE;
|
||||
|
||||
switch (caps->packetId)
|
||||
{
|
||||
case TSG_PACKET_TYPE_VERSIONCAPS:
|
||||
rc = tsg_packet_versioncaps_to_string(buffer, length,
|
||||
caps->tsgInitialPacket.packetVersionCaps);
|
||||
break;
|
||||
case TSG_PACKET_TYPE_AUTH:
|
||||
rc = tsg_packet_auth_to_string(buffer, length, caps->tsgInitialPacket.packetAuth);
|
||||
break;
|
||||
default:
|
||||
rc = tsg_print(buffer, length, "TODO: Unhandled packet type %s [0x%08" PRIx32 "]",
|
||||
tsg_packet_id_to_string(caps->packetId), caps->packetId);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
|
||||
return tsg_print(buffer, length, " }");
|
||||
}
|
||||
|
||||
static const char* tsg_packet_to_string(const TSG_PACKET* packet)
|
||||
{
|
||||
size_t len = 8192;
|
||||
@ -390,43 +687,45 @@ static const char* tsg_packet_to_string(const TSG_PACKET* packet)
|
||||
goto fail;
|
||||
break;
|
||||
case TSG_PACKET_TYPE_QUARCONFIGREQUEST:
|
||||
if (!tsg_print(&buffer, &len, "TODO"))
|
||||
if (!tsg_packet_quarconfigrequest_to_string(&buffer, &len,
|
||||
packet->tsgPacket.packetQuarConfigRequest))
|
||||
goto fail;
|
||||
break;
|
||||
case TSG_PACKET_TYPE_QUARREQUEST:
|
||||
if (!tsg_print(&buffer, &len, "TODO"))
|
||||
if (!tsg_packet_quarrequest_to_string(&buffer, &len,
|
||||
packet->tsgPacket.packetQuarRequest))
|
||||
goto fail;
|
||||
break;
|
||||
case TSG_PACKET_TYPE_RESPONSE:
|
||||
if (!tsg_print(&buffer, &len, "TODO"))
|
||||
if (!tsg_packet_response_to_string(&buffer, &len, packet->tsgPacket.packetResponse))
|
||||
goto fail;
|
||||
break;
|
||||
case TSG_PACKET_TYPE_QUARENC_RESPONSE:
|
||||
if (!tsg_print(&buffer, &len, "TODO"))
|
||||
goto fail;
|
||||
break;
|
||||
case TSG_CAPABILITY_TYPE_NAP:
|
||||
if (!tsg_print(&buffer, &len, "TODO"))
|
||||
if (!tsg_packet_quarenc_response_to_string(&buffer, &len,
|
||||
packet->tsgPacket.packetQuarEncResponse))
|
||||
goto fail;
|
||||
break;
|
||||
case TSG_PACKET_TYPE_CAPS_RESPONSE:
|
||||
if (!tsg_print(&buffer, &len, "TODO"))
|
||||
if (!tsg_packet_caps_response_to_string(&buffer, &len,
|
||||
packet->tsgPacket.packetCapsResponse))
|
||||
goto fail;
|
||||
break;
|
||||
case TSG_PACKET_TYPE_MSGREQUEST_PACKET:
|
||||
if (!tsg_print(&buffer, &len, "TODO"))
|
||||
if (!tsg_packet_message_request_to_string(&buffer, &len,
|
||||
packet->tsgPacket.packetMsgRequest))
|
||||
goto fail;
|
||||
break;
|
||||
case TSG_PACKET_TYPE_MESSAGE_PACKET:
|
||||
if (!tsg_print(&buffer, &len, "TODO"))
|
||||
if (!tsg_packet_message_response_to_string(&buffer, &len,
|
||||
packet->tsgPacket.packetMsgResponse))
|
||||
goto fail;
|
||||
break;
|
||||
case TSG_PACKET_TYPE_AUTH:
|
||||
if (!tsg_print(&buffer, &len, "TODO"))
|
||||
if (!tsg_packet_auth_to_string(&buffer, &len, packet->tsgPacket.packetAuth))
|
||||
goto fail;
|
||||
break;
|
||||
case TSG_PACKET_TYPE_REAUTH:
|
||||
if (!tsg_print(&buffer, &len, "TODO"))
|
||||
if (!tsg_packet_reauth_to_string(&buffer, &len, packet->tsgPacket.packetReauth))
|
||||
goto fail;
|
||||
break;
|
||||
default:
|
||||
@ -500,7 +799,7 @@ static int TsProxySendToServer(handle_t IDL_handle, const byte pRpcMessage[], UI
|
||||
{
|
||||
wStream* s;
|
||||
rdpTsg* tsg;
|
||||
int length;
|
||||
size_t length;
|
||||
const byte* buffer1 = NULL;
|
||||
const byte* buffer2 = NULL;
|
||||
const byte* buffer3 = NULL;
|
||||
@ -536,7 +835,9 @@ static int TsProxySendToServer(handle_t IDL_handle, const byte pRpcMessage[], UI
|
||||
totalDataBytes += lengths[2] + 4;
|
||||
}
|
||||
|
||||
length = 28 + totalDataBytes;
|
||||
length = 28ull + totalDataBytes;
|
||||
if (length > INT_MAX)
|
||||
return -1;
|
||||
s = Stream_New(NULL, length);
|
||||
|
||||
if (!s)
|
||||
@ -572,7 +873,7 @@ static int TsProxySendToServer(handle_t IDL_handle, const byte pRpcMessage[], UI
|
||||
if (!rpc_client_write_call(tsg->rpc, s, TsProxySendToServerOpnum))
|
||||
return -1;
|
||||
|
||||
return length;
|
||||
return (int)length;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -725,12 +1026,19 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu,
|
||||
UINT32 SwitchValue;
|
||||
UINT32 MessageSwitchValue = 0;
|
||||
UINT32 IsMessagePresent;
|
||||
rdpContext* context;
|
||||
PTSG_PACKET_CAPABILITIES tsgCaps = NULL;
|
||||
PTSG_PACKET_VERSIONCAPS versionCaps = NULL;
|
||||
TSG_PACKET_STRING_MESSAGE packetStringMessage;
|
||||
PTSG_PACKET_CAPS_RESPONSE packetCapsResponse = NULL;
|
||||
PTSG_PACKET_QUARENC_RESPONSE packetQuarEncResponse = NULL;
|
||||
|
||||
assert(tsg);
|
||||
assert(tsg->rpc);
|
||||
|
||||
context = tsg->rpc->context;
|
||||
assert(context);
|
||||
|
||||
if (!pdu)
|
||||
return FALSE;
|
||||
|
||||
@ -877,8 +1185,8 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu,
|
||||
if (Stream_GetRemainingLength(pdu->s) < 16)
|
||||
goto fail;
|
||||
|
||||
Stream_Read_UINT32(pdu->s, packetStringMessage.isDisplayMandatory);
|
||||
Stream_Read_UINT32(pdu->s, packetStringMessage.isConsentMandatory);
|
||||
Stream_Read_INT32(pdu->s, packetStringMessage.isDisplayMandatory);
|
||||
Stream_Read_INT32(pdu->s, packetStringMessage.isConsentMandatory);
|
||||
Stream_Read_UINT32(pdu->s, packetStringMessage.msgBytes);
|
||||
Stream_Read_UINT32(pdu->s, Pointer);
|
||||
|
||||
@ -907,16 +1215,15 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (tsg->rpc && tsg->rpc->context && tsg->rpc->context->instance)
|
||||
if (context->instance)
|
||||
{
|
||||
rc = IFCALLRESULT(TRUE, tsg->rpc->context->instance->PresentGatewayMessage,
|
||||
tsg->rpc->context->instance,
|
||||
TSG_ASYNC_MESSAGE_CONSENT_MESSAGE
|
||||
? GATEWAY_MESSAGE_CONSENT
|
||||
: TSG_ASYNC_MESSAGE_SERVICE_MESSAGE,
|
||||
packetStringMessage.isDisplayMandatory != 0,
|
||||
packetStringMessage.isConsentMandatory != 0,
|
||||
packetStringMessage.msgBytes, packetStringMessage.msgBuffer);
|
||||
rc = IFCALLRESULT(
|
||||
TRUE, context->instance->PresentGatewayMessage, context->instance,
|
||||
TSG_ASYNC_MESSAGE_CONSENT_MESSAGE ? GATEWAY_MESSAGE_CONSENT
|
||||
: TSG_ASYNC_MESSAGE_SERVICE_MESSAGE,
|
||||
packetStringMessage.isDisplayMandatory != 0,
|
||||
packetStringMessage.isConsentMandatory != 0, packetStringMessage.msgBytes,
|
||||
packetStringMessage.msgBuffer);
|
||||
if (!rc)
|
||||
goto fail;
|
||||
}
|
||||
@ -1079,16 +1386,19 @@ fail:
|
||||
|
||||
static BOOL TsProxyAuthorizeTunnelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunnelContext)
|
||||
{
|
||||
UINT32 pad;
|
||||
size_t pad;
|
||||
wStream* s;
|
||||
size_t count;
|
||||
UINT32 offset;
|
||||
size_t offset;
|
||||
rdpRpc* rpc;
|
||||
|
||||
if (!tsg || !tsg->rpc || !tunnelContext || !tsg->MachineName)
|
||||
return FALSE;
|
||||
|
||||
count = _wcslen(tsg->MachineName) + 1;
|
||||
if (count > UINT32_MAX)
|
||||
return FALSE;
|
||||
|
||||
rpc = tsg->rpc;
|
||||
WLog_DBG(TAG, "TsProxyAuthorizeTunnelWriteRequest");
|
||||
s = Stream_New(NULL, 1024 + count * 2);
|
||||
@ -1105,13 +1415,13 @@ static BOOL TsProxyAuthorizeTunnelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunn
|
||||
Stream_Write_UINT32(s, 0x00020000); /* PacketQuarRequestPtr (4 bytes) */
|
||||
Stream_Write_UINT32(s, 0x00000000); /* Flags (4 bytes) */
|
||||
Stream_Write_UINT32(s, 0x00020004); /* MachineNamePtr (4 bytes) */
|
||||
Stream_Write_UINT32(s, count); /* NameLength (4 bytes) */
|
||||
Stream_Write_UINT32(s, (UINT32)count); /* NameLength (4 bytes) */
|
||||
Stream_Write_UINT32(s, 0x00020008); /* DataPtr (4 bytes) */
|
||||
Stream_Write_UINT32(s, 0); /* DataLength (4 bytes) */
|
||||
/* MachineName */
|
||||
Stream_Write_UINT32(s, count); /* MaxCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, (UINT32)count); /* MaxCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, 0); /* Offset (4 bytes) */
|
||||
Stream_Write_UINT32(s, count); /* ActualCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, (UINT32)count); /* ActualCount (4 bytes) */
|
||||
Stream_Write_UTF16_String(s, tsg->MachineName, count); /* Array */
|
||||
/* 4-byte alignment */
|
||||
offset = Stream_GetPosition(s);
|
||||
@ -1122,7 +1432,7 @@ static BOOL TsProxyAuthorizeTunnelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunn
|
||||
return rpc_client_write_call(rpc, s, TsProxyAuthorizeTunnelOpnum);
|
||||
}
|
||||
|
||||
static BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu)
|
||||
static BOOL TsProxyAuthorizeTunnelReadResponse(RPC_PDU* pdu)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
UINT32 Pointer;
|
||||
@ -1184,25 +1494,24 @@ static BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu)
|
||||
Stream_Seek_UINT32(pdu->s); /* Reserved (4 bytes) */
|
||||
Stream_Read_UINT32(pdu->s, Pointer); /* ResponseDataPtr (4 bytes) */
|
||||
Stream_Read_UINT32(pdu->s, packetResponse->responseDataLen); /* ResponseDataLength (4 bytes) */
|
||||
Stream_Read_UINT32(pdu->s, packetResponse->redirectionFlags
|
||||
.enableAllRedirections); /* EnableAllRedirections (4 bytes) */
|
||||
Stream_Read_UINT32(pdu->s, packetResponse->redirectionFlags
|
||||
.disableAllRedirections); /* DisableAllRedirections (4 bytes) */
|
||||
Stream_Read_UINT32(pdu->s,
|
||||
packetResponse->redirectionFlags
|
||||
.driveRedirectionDisabled); /* DriveRedirectionDisabled (4 bytes) */
|
||||
Stream_Read_UINT32(pdu->s,
|
||||
packetResponse->redirectionFlags
|
||||
.printerRedirectionDisabled); /* PrinterRedirectionDisabled (4 bytes) */
|
||||
Stream_Read_UINT32(pdu->s,
|
||||
packetResponse->redirectionFlags
|
||||
.portRedirectionDisabled); /* PortRedirectionDisabled (4 bytes) */
|
||||
Stream_Read_UINT32(pdu->s, packetResponse->redirectionFlags.reserved); /* Reserved (4 bytes) */
|
||||
Stream_Read_UINT32(
|
||||
Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags
|
||||
.enableAllRedirections); /* EnableAllRedirections (4 bytes) */
|
||||
Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags
|
||||
.disableAllRedirections); /* DisableAllRedirections (4 bytes) */
|
||||
Stream_Read_INT32(pdu->s,
|
||||
packetResponse->redirectionFlags
|
||||
.driveRedirectionDisabled); /* DriveRedirectionDisabled (4 bytes) */
|
||||
Stream_Read_INT32(pdu->s,
|
||||
packetResponse->redirectionFlags
|
||||
.printerRedirectionDisabled); /* PrinterRedirectionDisabled (4 bytes) */
|
||||
Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags
|
||||
.portRedirectionDisabled); /* PortRedirectionDisabled (4 bytes) */
|
||||
Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags.reserved); /* Reserved (4 bytes) */
|
||||
Stream_Read_INT32(
|
||||
pdu->s, packetResponse->redirectionFlags
|
||||
.clipboardRedirectionDisabled); /* ClipboardRedirectionDisabled (4 bytes) */
|
||||
Stream_Read_UINT32(pdu->s, packetResponse->redirectionFlags
|
||||
.pnpRedirectionDisabled); /* PnpRedirectionDisabled (4 bytes) */
|
||||
Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags
|
||||
.pnpRedirectionDisabled); /* PnpRedirectionDisabled (4 bytes) */
|
||||
Stream_Read_UINT32(pdu->s, SizeValue); /* (4 bytes) */
|
||||
|
||||
if (SizeValue != packetResponse->responseDataLen)
|
||||
@ -1302,11 +1611,18 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu)
|
||||
UINT32 Pointer;
|
||||
UINT32 SwitchValue;
|
||||
TSG_PACKET packet;
|
||||
rdpContext* context;
|
||||
char* messageText = NULL;
|
||||
TSG_PACKET_MSG_RESPONSE packetMsgResponse = { 0 };
|
||||
TSG_PACKET_STRING_MESSAGE packetStringMessage = { 0 };
|
||||
TSG_PACKET_REAUTH_MESSAGE packetReauthMessage = { 0 };
|
||||
|
||||
assert(tsg);
|
||||
assert(tsg->rpc);
|
||||
|
||||
context = tsg->rpc->context;
|
||||
assert(context);
|
||||
|
||||
/* This is an asynchronous response */
|
||||
|
||||
if (!pdu)
|
||||
@ -1356,10 +1672,10 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu)
|
||||
WLog_INFO(TAG, "Consent Message: %s", messageText);
|
||||
free(messageText);
|
||||
|
||||
if (tsg->rpc && tsg->rpc->context && tsg->rpc->context->instance)
|
||||
if (context->instance)
|
||||
{
|
||||
rc = IFCALLRESULT(TRUE, tsg->rpc->context->instance->PresentGatewayMessage,
|
||||
tsg->rpc->context->instance, GATEWAY_MESSAGE_CONSENT,
|
||||
rc = IFCALLRESULT(TRUE, context->instance->PresentGatewayMessage, context->instance,
|
||||
GATEWAY_MESSAGE_CONSENT,
|
||||
packetStringMessage.isDisplayMandatory != 0,
|
||||
packetStringMessage.isConsentMandatory != 0,
|
||||
packetStringMessage.msgBytes, packetStringMessage.msgBuffer);
|
||||
@ -1377,10 +1693,10 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu)
|
||||
WLog_INFO(TAG, "Service Message: %s", messageText);
|
||||
free(messageText);
|
||||
|
||||
if (tsg->rpc && tsg->rpc->context && tsg->rpc->context->instance)
|
||||
if (context->instance)
|
||||
{
|
||||
rc = IFCALLRESULT(TRUE, tsg->rpc->context->instance->PresentGatewayMessage,
|
||||
tsg->rpc->context->instance, GATEWAY_MESSAGE_SERVICE,
|
||||
rc = IFCALLRESULT(TRUE, context->instance->PresentGatewayMessage, context->instance,
|
||||
GATEWAY_MESSAGE_SERVICE,
|
||||
packetStringMessage.isDisplayMandatory != 0,
|
||||
packetStringMessage.isConsentMandatory != 0,
|
||||
packetStringMessage.msgBytes, packetStringMessage.msgBuffer);
|
||||
@ -1432,6 +1748,8 @@ static BOOL TsProxyCreateChannelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunnel
|
||||
|
||||
rpc = tsg->rpc;
|
||||
count = _wcslen(tsg->Hostname) + 1;
|
||||
if (count > UINT32_MAX)
|
||||
return FALSE;
|
||||
s = Stream_New(NULL, 60 + count * 2);
|
||||
|
||||
if (!s)
|
||||
@ -1451,15 +1769,15 @@ static BOOL TsProxyCreateChannelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunnel
|
||||
Stream_Write_UINT16(s, tsg->Port); /* PortNumber (0xD3D = 3389) (2 bytes) */
|
||||
Stream_Write_UINT32(s, 0x00000001); /* NumResourceNames (4 bytes) */
|
||||
Stream_Write_UINT32(s, 0x00020004); /* ResourceNamePtr (4 bytes) */
|
||||
Stream_Write_UINT32(s, count); /* MaxCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, (UINT32)count); /* MaxCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, 0); /* Offset (4 bytes) */
|
||||
Stream_Write_UINT32(s, count); /* ActualCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, (UINT32)count); /* ActualCount (4 bytes) */
|
||||
Stream_Write_UTF16_String(s, tsg->Hostname, count); /* Array */
|
||||
return rpc_client_write_call(rpc, s, TsProxyCreateChannelOpnum);
|
||||
}
|
||||
|
||||
static BOOL TsProxyCreateChannelReadResponse(rdpTsg* tsg, RPC_PDU* pdu,
|
||||
CONTEXT_HANDLE* channelContext, UINT32* channelId)
|
||||
static BOOL TsProxyCreateChannelReadResponse(RPC_PDU* pdu, CONTEXT_HANDLE* channelContext,
|
||||
UINT32* channelId)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
WLog_DBG(TAG, "TsProxyCreateChannelReadResponse");
|
||||
@ -1507,7 +1825,7 @@ static BOOL TsProxyCloseChannelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* context
|
||||
return rpc_client_write_call(rpc, s, TsProxyCloseChannelOpnum);
|
||||
}
|
||||
|
||||
static BOOL TsProxyCloseChannelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, CONTEXT_HANDLE* context)
|
||||
static BOOL TsProxyCloseChannelReadResponse(RPC_PDU* pdu, CONTEXT_HANDLE* context)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
WLog_DBG(TAG, "TsProxyCloseChannelReadResponse");
|
||||
@ -1554,7 +1872,7 @@ static BOOL TsProxyCloseTunnelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* context)
|
||||
return rpc_client_write_call(rpc, s, TsProxyCloseTunnelOpnum);
|
||||
}
|
||||
|
||||
static BOOL TsProxyCloseTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, CONTEXT_HANDLE* context)
|
||||
static BOOL TsProxyCloseTunnelReadResponse(RPC_PDU* pdu, CONTEXT_HANDLE* context)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
WLog_DBG(TAG, "TsProxyCloseTunnelReadResponse");
|
||||
@ -1705,8 +2023,6 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu)
|
||||
return FALSE;
|
||||
|
||||
rpc = tsg->rpc;
|
||||
Stream_SealLength(pdu->s);
|
||||
Stream_SetPosition(pdu->s, 0);
|
||||
|
||||
if (!(pdu->Flags & RPC_PDU_FLAG_STUB))
|
||||
{
|
||||
@ -1745,7 +2061,7 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu)
|
||||
CONTEXT_HANDLE* TunnelContext;
|
||||
TunnelContext = (tsg->reauthSequence) ? &tsg->NewTunnelContext : &tsg->TunnelContext;
|
||||
|
||||
if (!TsProxyAuthorizeTunnelReadResponse(tsg, pdu))
|
||||
if (!TsProxyAuthorizeTunnelReadResponse(pdu))
|
||||
{
|
||||
WLog_ERR(TAG, "TsProxyAuthorizeTunnelReadResponse failure");
|
||||
return FALSE;
|
||||
@ -1794,7 +2110,7 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu)
|
||||
{
|
||||
CONTEXT_HANDLE ChannelContext;
|
||||
|
||||
if (!TsProxyCreateChannelReadResponse(tsg, pdu, &ChannelContext, &tsg->ChannelId))
|
||||
if (!TsProxyCreateChannelReadResponse(pdu, &ChannelContext, &tsg->ChannelId))
|
||||
{
|
||||
WLog_ERR(TAG, "TsProxyCreateChannelReadResponse failure");
|
||||
return FALSE;
|
||||
@ -1867,7 +2183,7 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu)
|
||||
{
|
||||
CONTEXT_HANDLE ChannelContext;
|
||||
|
||||
if (!TsProxyCloseChannelReadResponse(tsg, pdu, &ChannelContext))
|
||||
if (!TsProxyCloseChannelReadResponse(pdu, &ChannelContext))
|
||||
{
|
||||
WLog_ERR(TAG, "TsProxyCloseChannelReadResponse failure");
|
||||
return FALSE;
|
||||
@ -1879,7 +2195,7 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu)
|
||||
{
|
||||
CONTEXT_HANDLE TunnelContext;
|
||||
|
||||
if (!TsProxyCloseTunnelReadResponse(tsg, pdu, &TunnelContext))
|
||||
if (!TsProxyCloseTunnelReadResponse(pdu, &TunnelContext))
|
||||
{
|
||||
WLog_ERR(TAG, "TsProxyCloseTunnelReadResponse failure");
|
||||
return FALSE;
|
||||
@ -1894,7 +2210,7 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu)
|
||||
{
|
||||
CONTEXT_HANDLE ChannelContext;
|
||||
|
||||
if (!TsProxyCloseChannelReadResponse(tsg, pdu, &ChannelContext))
|
||||
if (!TsProxyCloseChannelReadResponse(pdu, &ChannelContext))
|
||||
{
|
||||
WLog_ERR(TAG, "TsProxyCloseChannelReadResponse failure");
|
||||
return FALSE;
|
||||
@ -1924,7 +2240,7 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu)
|
||||
{
|
||||
CONTEXT_HANDLE TunnelContext;
|
||||
|
||||
if (!TsProxyCloseTunnelReadResponse(tsg, pdu, &TunnelContext))
|
||||
if (!TsProxyCloseTunnelReadResponse(pdu, &TunnelContext))
|
||||
{
|
||||
WLog_ERR(TAG, "TsProxyCloseTunnelReadResponse failure");
|
||||
return FALSE;
|
||||
@ -2033,10 +2349,25 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, DWORD timeout)
|
||||
{
|
||||
UINT64 looptimeout = timeout * 1000ULL;
|
||||
DWORD nCount;
|
||||
HANDLE events[64];
|
||||
rdpRpc* rpc = tsg->rpc;
|
||||
rdpSettings* settings = rpc->settings;
|
||||
rdpTransport* transport = rpc->transport;
|
||||
HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 };
|
||||
rdpRpc* rpc;
|
||||
rdpContext* context;
|
||||
rdpSettings* settings;
|
||||
rdpTransport* transport;
|
||||
|
||||
assert(tsg);
|
||||
|
||||
rpc = tsg->rpc;
|
||||
assert(rpc);
|
||||
|
||||
transport = rpc->transport;
|
||||
assert(transport);
|
||||
|
||||
context = tsg->rpc->context;
|
||||
assert(context);
|
||||
|
||||
settings = context->settings;
|
||||
|
||||
tsg->Port = port;
|
||||
tsg->transport = transport;
|
||||
|
||||
@ -2055,7 +2386,7 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, DWORD timeout)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nCount = tsg_get_event_handles(tsg, events, 64);
|
||||
nCount = tsg_get_event_handles(tsg, events, ARRAYSIZE(events));
|
||||
|
||||
if (nCount == 0)
|
||||
return FALSE;
|
||||
@ -2138,7 +2469,7 @@ BOOL tsg_disconnect(rdpTsg* tsg)
|
||||
* @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 bytes to read
|
||||
*/
|
||||
|
||||
static int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length)
|
||||
static int tsg_read(rdpTsg* tsg, BYTE* data, size_t length)
|
||||
{
|
||||
rdpRpc* rpc;
|
||||
int status = 0;
|
||||
@ -2156,7 +2487,7 @@ static int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length)
|
||||
|
||||
do
|
||||
{
|
||||
status = rpc_client_receive_pipe_read(rpc->client, data, (size_t)length);
|
||||
status = rpc_client_receive_pipe_read(rpc->client, data, length);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
@ -2206,7 +2537,7 @@ static int tsg_write(rdpTsg* tsg, const BYTE* data, UINT32 length)
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
return length;
|
||||
return (int)length;
|
||||
}
|
||||
|
||||
rdpTsg* tsg_new(rdpTransport* transport)
|
||||
@ -2218,7 +2549,6 @@ rdpTsg* tsg_new(rdpTransport* transport)
|
||||
return NULL;
|
||||
|
||||
tsg->transport = transport;
|
||||
tsg->settings = transport->settings;
|
||||
tsg->rpc = rpc_new(tsg->transport);
|
||||
|
||||
if (!tsg->rpc)
|
||||
@ -2246,7 +2576,10 @@ static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
|
||||
int status;
|
||||
rdpTsg* tsg = (rdpTsg*)BIO_get_data(bio);
|
||||
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||
status = tsg_write(tsg, (BYTE*)buf, num);
|
||||
|
||||
if (num < 0)
|
||||
return -1;
|
||||
status = tsg_write(tsg, (const BYTE*)buf, (UINT32)num);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
@ -2278,7 +2611,7 @@ static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
|
||||
}
|
||||
|
||||
BIO_clear_flags(bio, BIO_FLAGS_READ);
|
||||
status = tsg_read(tsg, (BYTE*)buf, size);
|
||||
status = tsg_read(tsg, (BYTE*)buf, (size_t)size);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
@ -2300,17 +2633,22 @@ static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
|
||||
|
||||
static int transport_bio_tsg_puts(BIO* bio, const char* str)
|
||||
{
|
||||
WINPR_UNUSED(bio);
|
||||
WINPR_UNUSED(str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_gets(BIO* bio, char* str, int size)
|
||||
{
|
||||
WINPR_UNUSED(bio);
|
||||
WINPR_UNUSED(str);
|
||||
WINPR_UNUSED(size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
{
|
||||
int status = -1;
|
||||
long status = -1;
|
||||
rdpTsg* tsg = (rdpTsg*)BIO_get_data(bio);
|
||||
RpcVirtualConnection* connection = tsg->rpc->VirtualConnection;
|
||||
RpcInChannel* inChannel = connection->DefaultInChannel;
|
||||
@ -2339,27 +2677,27 @@ static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
|
||||
case BIO_C_READ_BLOCKED:
|
||||
{
|
||||
BIO* bio = outChannel->common.bio;
|
||||
status = BIO_read_blocked(bio);
|
||||
BIO* cbio = outChannel->common.bio;
|
||||
status = BIO_read_blocked(cbio);
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_C_WRITE_BLOCKED:
|
||||
{
|
||||
BIO* bio = inChannel->common.bio;
|
||||
status = BIO_write_blocked(bio);
|
||||
BIO* cbio = inChannel->common.bio;
|
||||
status = BIO_write_blocked(cbio);
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_C_WAIT_READ:
|
||||
{
|
||||
int timeout = (int)arg1;
|
||||
BIO* bio = outChannel->common.bio;
|
||||
BIO* cbio = outChannel->common.bio;
|
||||
|
||||
if (BIO_read_blocked(bio))
|
||||
return BIO_wait_read(bio, timeout);
|
||||
else if (BIO_write_blocked(bio))
|
||||
return BIO_wait_write(bio, timeout);
|
||||
if (BIO_read_blocked(cbio))
|
||||
return BIO_wait_read(cbio, timeout);
|
||||
else if (BIO_write_blocked(cbio))
|
||||
return BIO_wait_write(cbio, timeout);
|
||||
else
|
||||
status = 1;
|
||||
}
|
||||
@ -2368,12 +2706,12 @@ static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
case BIO_C_WAIT_WRITE:
|
||||
{
|
||||
int timeout = (int)arg1;
|
||||
BIO* bio = inChannel->common.bio;
|
||||
BIO* cbio = inChannel->common.bio;
|
||||
|
||||
if (BIO_write_blocked(bio))
|
||||
status = BIO_wait_write(bio, timeout);
|
||||
else if (BIO_read_blocked(bio))
|
||||
status = BIO_wait_read(bio, timeout);
|
||||
if (BIO_write_blocked(cbio))
|
||||
status = BIO_wait_write(cbio, timeout);
|
||||
else if (BIO_read_blocked(cbio))
|
||||
status = BIO_wait_read(cbio, timeout);
|
||||
else
|
||||
status = 1;
|
||||
}
|
||||
@ -2388,6 +2726,7 @@ static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
|
||||
static int transport_bio_tsg_new(BIO* bio)
|
||||
{
|
||||
assert(bio);
|
||||
BIO_set_init(bio, 1);
|
||||
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
return 1;
|
||||
@ -2395,6 +2734,8 @@ static int transport_bio_tsg_new(BIO* bio)
|
||||
|
||||
static int transport_bio_tsg_free(BIO* bio)
|
||||
{
|
||||
assert(bio);
|
||||
WINPR_UNUSED(bio);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -1881,6 +1881,13 @@ static BOOL update_read_fast_glyph_order(wStream* s, const ORDER_INFO* orderInfo
|
||||
!update_read_2byte_unsigned(&sub, &glyph->cy))
|
||||
return FALSE;
|
||||
|
||||
if ((glyph->cx == 0) || (glyph->cy == 0))
|
||||
{
|
||||
WLog_ERR(TAG, "GLYPH_DATA_V2::cx=%" PRIu32 ", GLYPH_DATA_V2::cy=%" PRIu32,
|
||||
glyph->cx, glyph->cy);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
glyph->cb = Stream_GetRemainingLength(&sub);
|
||||
if (glyph->cb > 0)
|
||||
{
|
||||
@ -2867,6 +2874,13 @@ update_read_create_offscreen_bitmap_order(wStream* s,
|
||||
Stream_Read_UINT16(s, create_offscreen_bitmap->cy); /* cy (2 bytes) */
|
||||
deleteList = &(create_offscreen_bitmap->deleteList);
|
||||
|
||||
if ((create_offscreen_bitmap->cx == 0) || (create_offscreen_bitmap->cy == 0))
|
||||
{
|
||||
WLog_ERR(TAG, "Invalid OFFSCREEN_DELETE_LIST: cx=%" PRIu16 ", cy=%" PRIu16,
|
||||
create_offscreen_bitmap->cx, create_offscreen_bitmap->cy);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (deleteListPresent)
|
||||
{
|
||||
UINT32 i;
|
||||
|
||||
@ -21,6 +21,8 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <freerdp/utils/pcap.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
@ -62,6 +64,13 @@ static BOOL update_recv_surfcmd_bitmap_ex(wStream* s, TS_BITMAP_DATA_EX* bmp)
|
||||
Stream_Read_UINT16(s, bmp->height);
|
||||
Stream_Read_UINT32(s, bmp->bitmapDataLength);
|
||||
|
||||
if ((bmp->width == 0) || (bmp->height == 0))
|
||||
{
|
||||
WLog_ERR(TAG, "invalid size value width=%" PRIu16 ", height=%" PRIu16, bmp->width,
|
||||
bmp->height);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((bmp->bpp < 1) || (bmp->bpp > 32))
|
||||
{
|
||||
WLog_ERR(TAG, "invalid bpp value %" PRIu32 "", bmp->bpp);
|
||||
@ -85,6 +94,39 @@ static BOOL update_recv_surfcmd_bitmap_ex(wStream* s, TS_BITMAP_DATA_EX* bmp)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL update_recv_surfcmd_is_rect_valid(const rdpContext* context,
|
||||
const SURFACE_BITS_COMMAND* cmd)
|
||||
{
|
||||
assert(context);
|
||||
assert(context->settings);
|
||||
assert(cmd);
|
||||
|
||||
/* We need a rectangle with left/top being smaller than right/bottom.
|
||||
* Also do not allow empty rectangles. */
|
||||
if ((cmd->destTop >= cmd->destBottom) || (cmd->destLeft >= cmd->destRight))
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"Empty surface bits command rectangle: %" PRIu16 "x%" PRIu16 "-%" PRIu16
|
||||
"x%" PRIu16,
|
||||
cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* The rectangle needs to fit into our session size */
|
||||
if ((cmd->destRight > context->settings->DesktopWidth) ||
|
||||
(cmd->destBottom > context->settings->DesktopHeight))
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"Invalid surface bits command rectangle: %" PRIu16 "x%" PRIu16 "-%" PRIu16
|
||||
"x%" PRIu16 " does not fit %" PRIu32 "x%" PRIu32,
|
||||
cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom,
|
||||
context->settings->DesktopWidth, context->settings->DesktopHeight);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT16 cmdType)
|
||||
{
|
||||
SURFACE_BITS_COMMAND cmd = { 0 };
|
||||
@ -98,6 +140,9 @@ static BOOL update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT
|
||||
Stream_Read_UINT16(s, cmd.destRight);
|
||||
Stream_Read_UINT16(s, cmd.destBottom);
|
||||
|
||||
if (!update_recv_surfcmd_is_rect_valid(update->context, &cmd))
|
||||
goto fail;
|
||||
|
||||
if (!update_recv_surfcmd_bitmap_ex(s, &cmd.bmp))
|
||||
goto fail;
|
||||
|
||||
|
||||
@ -99,6 +99,13 @@ static BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA*
|
||||
Stream_Read_UINT16(s, bitmapData->flags);
|
||||
Stream_Read_UINT16(s, bitmapData->bitmapLength);
|
||||
|
||||
if ((bitmapData->width == 0) || (bitmapData->height == 0))
|
||||
{
|
||||
WLog_ERR(TAG, "Invalid BITMAP_DATA: width=%" PRIu16 ", height=%" PRIu16, bitmapData->width,
|
||||
bitmapData->height);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (bitmapData->flags & BITMAP_COMPRESSION)
|
||||
{
|
||||
if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
|
||||
|
||||
@ -51,7 +51,7 @@ if (NOT WIN32)
|
||||
endif()
|
||||
|
||||
# Soname versioning
|
||||
set(RAW_VERSION_STRING "2.4.0")
|
||||
set(RAW_VERSION_STRING "2.4.1")
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
|
||||
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
|
||||
elseif(USE_VERSION_FROM_GIT_TAG)
|
||||
|
||||
@ -414,8 +414,8 @@ static BOOL test_ConvertToUnicode_wrapper(void)
|
||||
/* Test static string buffers of differing sizes */
|
||||
{
|
||||
char name[] = "someteststring";
|
||||
const WCHAR cmp[] = { L's', L'o', L'm', L'e', L't', L'e', L's', L't',
|
||||
L's', L't', L'r', L'i', L'n', L'g', 0 };
|
||||
const BYTE cmp[] = { 's', 0, 'o', 0, 'm', 0, 'e', 0, 't', 0, 'e', 0, 's', 0, 't', 0,
|
||||
's', 0, 't', 0, 'r', 0, 'i', 0, 'n', 0, 'g', 0, 0, 0 };
|
||||
WCHAR xname[128] = { 0 };
|
||||
LPWSTR aname = NULL;
|
||||
LPWSTR wname = &xname[0];
|
||||
|
||||
@ -29,6 +29,9 @@
|
||||
#include <openssl/rc4.h>
|
||||
#include <openssl/des.h>
|
||||
#include <openssl/evp.h>
|
||||
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
|
||||
#include <openssl/provider.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MBEDTLS
|
||||
@ -55,6 +58,14 @@ static WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOO
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
|
||||
if (keylen > INT_MAX)
|
||||
return NULL;
|
||||
|
||||
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
|
||||
if (OSSL_PROVIDER_load(NULL, "legacy") == NULL)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
if (!(ctx = (WINPR_RC4_CTX*)EVP_CIPHER_CTX_new()))
|
||||
return NULL;
|
||||
|
||||
@ -64,7 +75,12 @@ static WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOO
|
||||
return NULL;
|
||||
|
||||
EVP_CIPHER_CTX_init((EVP_CIPHER_CTX*)ctx);
|
||||
EVP_EncryptInit_ex((EVP_CIPHER_CTX*)ctx, evp, NULL, NULL, NULL);
|
||||
if (EVP_EncryptInit_ex((EVP_CIPHER_CTX*)ctx, evp, NULL, NULL, NULL) != 1)
|
||||
{
|
||||
EVP_CIPHER_CTX_free ((EVP_CIPHER_CTX*)ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* EVP_CIPH_FLAG_NON_FIPS_ALLOW does not exist before openssl 1.0.1 */
|
||||
#if !(OPENSSL_VERSION_NUMBER < 0x10001000L)
|
||||
|
||||
@ -72,8 +88,12 @@ static WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOO
|
||||
EVP_CIPHER_CTX_set_flags((EVP_CIPHER_CTX*)ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW);
|
||||
|
||||
#endif
|
||||
EVP_CIPHER_CTX_set_key_length((EVP_CIPHER_CTX*)ctx, keylen);
|
||||
EVP_EncryptInit_ex((EVP_CIPHER_CTX*)ctx, NULL, NULL, key, NULL);
|
||||
EVP_CIPHER_CTX_set_key_length((EVP_CIPHER_CTX*)ctx, (int)keylen);
|
||||
if (EVP_EncryptInit_ex((EVP_CIPHER_CTX*)ctx, NULL, NULL, key, NULL) != 1)
|
||||
{
|
||||
EVP_CIPHER_CTX_free ((EVP_CIPHER_CTX*)ctx);
|
||||
return NULL;
|
||||
}
|
||||
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
|
||||
|
||||
if (!(ctx = (WINPR_RC4_CTX*)calloc(1, sizeof(mbedtls_arc4_context))))
|
||||
|
||||
@ -539,15 +539,80 @@ DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char* append(char* buffer, size_t size, const char* append)
|
||||
{
|
||||
const size_t len = strnlen(buffer, size);
|
||||
if (len == 0)
|
||||
_snprintf(buffer, size, "%s", append);
|
||||
else
|
||||
{
|
||||
strcat(buffer, "|");
|
||||
strcat(buffer, append);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static const char* flagsToStr(char* buffer, size_t size, DWORD flags)
|
||||
{
|
||||
char strflags[32] = { 0 };
|
||||
if (flags & FILE_ATTRIBUTE_READONLY)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_READONLY");
|
||||
if (flags & FILE_ATTRIBUTE_HIDDEN)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_HIDDEN");
|
||||
if (flags & FILE_ATTRIBUTE_SYSTEM)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_SYSTEM");
|
||||
if (flags & FILE_ATTRIBUTE_DIRECTORY)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_DIRECTORY");
|
||||
if (flags & FILE_ATTRIBUTE_ARCHIVE)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_ARCHIVE");
|
||||
if (flags & FILE_ATTRIBUTE_DEVICE)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_DEVICE");
|
||||
if (flags & FILE_ATTRIBUTE_NORMAL)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_NORMAL");
|
||||
if (flags & FILE_ATTRIBUTE_TEMPORARY)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_TEMPORARY");
|
||||
if (flags & FILE_ATTRIBUTE_SPARSE_FILE)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_SPARSE_FILE");
|
||||
if (flags & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_REPARSE_POINT");
|
||||
if (flags & FILE_ATTRIBUTE_COMPRESSED)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_COMPRESSED");
|
||||
if (flags & FILE_ATTRIBUTE_OFFLINE)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_OFFLINE");
|
||||
if (flags & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_NOT_CONTENT_INDEXED");
|
||||
if (flags & FILE_ATTRIBUTE_ENCRYPTED)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_ENCRYPTED");
|
||||
if (flags & FILE_ATTRIBUTE_VIRTUAL)
|
||||
append(buffer, size, "FILE_ATTRIBUTE_VIRTUAL");
|
||||
|
||||
_snprintf(strflags, sizeof(strflags), " [0x%08" PRIx32 "]", flags);
|
||||
strcat(buffer, strflags);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
|
||||
{
|
||||
struct stat st;
|
||||
int fd;
|
||||
BOOL rc = FALSE;
|
||||
|
||||
if (stat(lpFileName, &st) != 0)
|
||||
if (dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)
|
||||
{
|
||||
return FALSE;
|
||||
char buffer[8192] = { 0 };
|
||||
const char* flags =
|
||||
flagsToStr(buffer, sizeof(buffer), dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
|
||||
WLog_WARN(TAG, "[%s] Unsupported flags %s, ignoring!", __FUNCTION__, flags);
|
||||
}
|
||||
|
||||
fd = open(lpFileName, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return FALSE;
|
||||
|
||||
if (fstat(fd, &st) != 0)
|
||||
goto fail;
|
||||
|
||||
if (dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
||||
{
|
||||
st.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
|
||||
@ -557,12 +622,13 @@ BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
|
||||
st.st_mode |= S_IWUSR;
|
||||
}
|
||||
|
||||
if (chmod(lpFileName, st.st_mode) != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (fchmod(fd, st.st_mode) != 0)
|
||||
goto fail;
|
||||
|
||||
return TRUE;
|
||||
rc = TRUE;
|
||||
fail:
|
||||
close(fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
|
||||
@ -570,6 +636,14 @@ BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
|
||||
BOOL ret;
|
||||
LPSTR lpCFileName;
|
||||
|
||||
if (dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)
|
||||
{
|
||||
char buffer[8192] = { 0 };
|
||||
const char* flags =
|
||||
flagsToStr(buffer, sizeof(buffer), dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
|
||||
WLog_WARN(TAG, "[%s] Unsupported flags %s, ignoring!", __FUNCTION__, flags);
|
||||
}
|
||||
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpCFileName, 0, NULL, NULL) <= 0)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
|
||||
@ -1,54 +1,58 @@
|
||||
|
||||
set(MODULE_NAME "TestFile")
|
||||
set(MODULE_PREFIX "TEST_FILE")
|
||||
if (NOT WIN32)
|
||||
set(MODULE_NAME "TestFile")
|
||||
set(MODULE_PREFIX "TEST_FILE")
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS
|
||||
TestFileCreateFile.c
|
||||
TestFileDeleteFile.c
|
||||
TestFileReadFile.c
|
||||
TestFileWriteFile.c
|
||||
TestFilePatternMatch.c
|
||||
TestFileFindFirstFile.c
|
||||
TestFileFindFirstFileEx.c
|
||||
TestFileFindNextFile.c
|
||||
TestFileGetStdHandle.c
|
||||
)
|
||||
set(${MODULE_PREFIX}_TESTS
|
||||
TestFileCreateFile.c
|
||||
TestFileDeleteFile.c
|
||||
TestFileReadFile.c
|
||||
TestSetFileAttributes.c
|
||||
TestFileWriteFile.c
|
||||
TestFilePatternMatch.c
|
||||
TestFileFindFirstFile.c
|
||||
TestFileFindFirstFileEx.c
|
||||
TestFileFindNextFile.c
|
||||
TestFileGetStdHandle.c
|
||||
)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||
${${MODULE_PREFIX}_DRIVER}
|
||||
${${MODULE_PREFIX}_TESTS})
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||
${${MODULE_PREFIX}_DRIVER}
|
||||
${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} winpr)
|
||||
target_link_libraries(${MODULE_NAME} winpr)
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||
|
||||
if(NOT MSVC)
|
||||
set(TEST_AREA "${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME}Area")
|
||||
else()
|
||||
set(TEST_AREA "${TESTING_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}/${MODULE_NAME}Area")
|
||||
endif()
|
||||
|
||||
file(MAKE_DIRECTORY "${TEST_AREA}")
|
||||
file(WRITE "${TEST_AREA}/TestFile1" "TestFile1")
|
||||
file(WRITE "${TEST_AREA}/TestFile2" "TestFile2")
|
||||
file(WRITE "${TEST_AREA}/TestFile3" "TestFile3")
|
||||
file(MAKE_DIRECTORY "${TEST_AREA}/TestDirectory1")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory1/TestDirectory1File1" "TestDirectory1File1")
|
||||
file(MAKE_DIRECTORY "${TEST_AREA}/TestDirectory2")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory2/TestDirectory2File1" "TestDirectory2File1")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory2/TestDirectory2File2" "TestDirectory2File2")
|
||||
file(MAKE_DIRECTORY "${TEST_AREA}/TestDirectory3")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory3/TestDirectory3File1" "TestDirectory3File1")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory3/TestDirectory3File2" "TestDirectory3File2")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory3/TestDirectory3File3" "TestDirectory3File3")
|
||||
|
||||
foreach(test ${${MODULE_PREFIX}_TESTS})
|
||||
get_filename_component(TestName ${test} NAME_WE)
|
||||
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName} ${TEST_AREA})
|
||||
endforeach()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")
|
||||
|
||||
if(NOT MSVC)
|
||||
set(TEST_AREA "${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME}Area")
|
||||
else()
|
||||
set(TEST_AREA "${TESTING_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}/${MODULE_NAME}Area")
|
||||
endif()
|
||||
|
||||
file(MAKE_DIRECTORY "${TEST_AREA}")
|
||||
file(WRITE "${TEST_AREA}/TestFile1" "TestFile1")
|
||||
file(WRITE "${TEST_AREA}/TestFile2" "TestFile2")
|
||||
file(WRITE "${TEST_AREA}/TestFile3" "TestFile3")
|
||||
file(MAKE_DIRECTORY "${TEST_AREA}/TestDirectory1")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory1/TestDirectory1File1" "TestDirectory1File1")
|
||||
file(MAKE_DIRECTORY "${TEST_AREA}/TestDirectory2")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory2/TestDirectory2File1" "TestDirectory2File1")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory2/TestDirectory2File2" "TestDirectory2File2")
|
||||
file(MAKE_DIRECTORY "${TEST_AREA}/TestDirectory3")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory3/TestDirectory3File1" "TestDirectory3File1")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory3/TestDirectory3File2" "TestDirectory3File2")
|
||||
file(WRITE "${TEST_AREA}/TestDirectory3/TestDirectory3File3" "TestDirectory3File3")
|
||||
|
||||
foreach(test ${${MODULE_PREFIX}_TESTS})
|
||||
get_filename_component(TestName ${test} NAME_WE)
|
||||
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName} ${TEST_AREA})
|
||||
endforeach()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")
|
||||
|
||||
149
winpr/libwinpr/file/test/TestSetFileAttributes.c
Normal file
149
winpr/libwinpr/file/test/TestSetFileAttributes.c
Normal file
@ -0,0 +1,149 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/handle.h>
|
||||
#include <winpr/windows.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
static const DWORD allflags[] = {
|
||||
0,
|
||||
FILE_ATTRIBUTE_READONLY,
|
||||
FILE_ATTRIBUTE_HIDDEN,
|
||||
FILE_ATTRIBUTE_SYSTEM,
|
||||
FILE_ATTRIBUTE_DIRECTORY,
|
||||
FILE_ATTRIBUTE_ARCHIVE,
|
||||
FILE_ATTRIBUTE_DEVICE,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
FILE_ATTRIBUTE_TEMPORARY,
|
||||
FILE_ATTRIBUTE_SPARSE_FILE,
|
||||
FILE_ATTRIBUTE_REPARSE_POINT,
|
||||
FILE_ATTRIBUTE_COMPRESSED,
|
||||
FILE_ATTRIBUTE_OFFLINE,
|
||||
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
|
||||
FILE_ATTRIBUTE_ENCRYPTED,
|
||||
FILE_ATTRIBUTE_VIRTUAL,
|
||||
FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,
|
||||
FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DEVICE |
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_SPARSE_FILE | FILE_ATTRIBUTE_REPARSE_POINT |
|
||||
FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_OFFLINE,
|
||||
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_VIRTUAL
|
||||
};
|
||||
|
||||
static BOOL test_SetFileAttributesA(void)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
HANDLE handle;
|
||||
DWORD x;
|
||||
const DWORD flags[] = { 0, FILE_ATTRIBUTE_READONLY };
|
||||
char* name = GetKnownSubPath(KNOWN_PATH_TEMP, "afsklhjwe4oq5iu432oijrlkejadlkhjaklhfdkahfd");
|
||||
if (!name)
|
||||
goto fail;
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(allflags); x++)
|
||||
{
|
||||
const DWORD flag = allflags[x];
|
||||
rc = SetFileAttributesA(NULL, flag);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
rc = SetFileAttributesA(name, flag);
|
||||
if (rc)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
handle = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
goto fail;
|
||||
CloseHandle(handle);
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(flags); x++)
|
||||
{
|
||||
DWORD attr;
|
||||
const DWORD flag = flags[x];
|
||||
rc = SetFileAttributesA(name, flag);
|
||||
if (!rc)
|
||||
goto fail;
|
||||
|
||||
attr = GetFileAttributesA(name);
|
||||
if (flag != 0)
|
||||
{
|
||||
if ((attr & flag) == 0)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
DeleteFileA(name);
|
||||
free(name);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL test_SetFileAttributesW(void)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
WCHAR* name = NULL;
|
||||
HANDLE handle;
|
||||
DWORD x;
|
||||
const DWORD flags[] = { 0, FILE_ATTRIBUTE_READONLY };
|
||||
char* base = GetKnownSubPath(KNOWN_PATH_TEMP, "afsklhjwe4oq5iu432oijrlkejadlkhjaklhfdkahfd");
|
||||
if (!base)
|
||||
goto fail;
|
||||
|
||||
ConvertToUnicode(CP_UTF8, 0, base, -1, &name, 0);
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(allflags); x++)
|
||||
{
|
||||
const DWORD flag = allflags[x];
|
||||
rc = SetFileAttributesW(NULL, flag);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
rc = SetFileAttributesW(name, flag);
|
||||
if (rc)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
handle = CreateFileW(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
goto fail;
|
||||
CloseHandle(handle);
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(flags); x++)
|
||||
{
|
||||
DWORD attr;
|
||||
const DWORD flag = flags[x];
|
||||
rc = SetFileAttributesW(name, flag);
|
||||
if (!rc)
|
||||
goto fail;
|
||||
|
||||
attr = GetFileAttributesW(name);
|
||||
if (flag != 0)
|
||||
{
|
||||
if ((attr & flag) == 0)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
DeleteFileW(name);
|
||||
free(name);
|
||||
free(base);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestSetFileAttributes(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
if (!test_SetFileAttributesA())
|
||||
return -1;
|
||||
if (!test_SetFileAttributesW())
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
@ -244,9 +244,17 @@ static BOOL winpr_enable_fips(DWORD flags)
|
||||
#else
|
||||
WLog_DBG(TAG, "Ensuring openssl fips mode is ENabled");
|
||||
|
||||
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
|
||||
if (!EVP_default_properties_is_fips_enabled(NULL))
|
||||
#else
|
||||
if (FIPS_mode() != 1)
|
||||
#endif
|
||||
{
|
||||
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
|
||||
if (EVP_set_default_properties(NULL, "fips=yes"))
|
||||
#else
|
||||
if (FIPS_mode_set(1))
|
||||
#endif
|
||||
WLog_INFO(TAG, "Openssl fips mode ENabled!");
|
||||
else
|
||||
{
|
||||
@ -356,6 +364,8 @@ BOOL winpr_FIPSMode(void)
|
||||
{
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10001000L) || defined(LIBRESSL_VERSION_NUMBER)
|
||||
return FALSE;
|
||||
#elif defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
|
||||
return (EVP_default_properties_is_fips_enabled(NULL) == 1);
|
||||
#else
|
||||
return (FIPS_mode() == 1);
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user