Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
170
third_party/FreeRDP/libfreerdp/core/CMakeLists.txt
vendored
Normal file
170
third_party/FreeRDP/libfreerdp/core/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# libfreerdp-core cmake build script
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(MODULE_NAME "freerdp-core")
|
||||
set(MODULE_PREFIX "FREERDP_CORE")
|
||||
|
||||
# We use some fields that are only defined in linux 5.11+
|
||||
check_symbol_exists(VMADDR_FLAG_TO_HOST "ctype.h;sys/socket.h;linux/vm_sockets.h" HAVE_AF_VSOCK_H)
|
||||
|
||||
freerdp_definition_add(EXT_PATH="${FREERDP_EXTENSION_PATH}")
|
||||
|
||||
freerdp_include_directory_add(${OPENSSL_INCLUDE_DIR})
|
||||
|
||||
set(${MODULE_PREFIX}_GATEWAY_DIR "gateway")
|
||||
|
||||
set(${MODULE_PREFIX}_GATEWAY_SRCS
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/tsg.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/tsg.h
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rdg.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rdg.h
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rpc.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rpc.h
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rpc_bind.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rpc_bind.h
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rpc_client.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rpc_client.h
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rpc_fault.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rpc_fault.h
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rts.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rts.h
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rts_signature.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/rts_signature.h
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/http.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/http.h
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/websocket.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/websocket.h
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/wst.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/wst.h
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/arm.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/arm.h
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/ncacn_http.c
|
||||
${${MODULE_PREFIX}_GATEWAY_DIR}/ncacn_http.h
|
||||
)
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
simd.h
|
||||
state.h
|
||||
state.c
|
||||
utils.c
|
||||
utils.h
|
||||
streamdump.c
|
||||
activation.c
|
||||
activation.h
|
||||
gcc.c
|
||||
gcc.h
|
||||
mcs.c
|
||||
mcs.h
|
||||
nla.c
|
||||
nla.h
|
||||
smartcardlogon.c
|
||||
nego.c
|
||||
nego.h
|
||||
info.c
|
||||
info.h
|
||||
input.c
|
||||
input.h
|
||||
license.c
|
||||
license.h
|
||||
errinfo.c
|
||||
errbase.c
|
||||
errconnect.c
|
||||
errinfo.h
|
||||
security.c
|
||||
security.h
|
||||
settings.c
|
||||
settings.h
|
||||
orders.c
|
||||
orders.h
|
||||
freerdp.c
|
||||
graphics.c
|
||||
client.c
|
||||
client.h
|
||||
server.c
|
||||
server.h
|
||||
codecs.c
|
||||
metrics.c
|
||||
capabilities.c
|
||||
capabilities.h
|
||||
connection.c
|
||||
connection.h
|
||||
redirection.c
|
||||
redirection.h
|
||||
autodetect.c
|
||||
autodetect.h
|
||||
heartbeat.c
|
||||
heartbeat.h
|
||||
multitransport.c
|
||||
multitransport.h
|
||||
timezone.c
|
||||
timezone.h
|
||||
childsession.c
|
||||
rdp.c
|
||||
rdp.h
|
||||
tcp.c
|
||||
tcp.h
|
||||
proxy.c
|
||||
proxy.h
|
||||
tpdu.c
|
||||
tpdu.h
|
||||
tpkt.c
|
||||
tpkt.h
|
||||
fastpath.c
|
||||
fastpath.h
|
||||
surface.c
|
||||
surface.h
|
||||
transport.c
|
||||
transport.h
|
||||
update.c
|
||||
update.h
|
||||
message.c
|
||||
message.h
|
||||
channels.c
|
||||
channels.h
|
||||
window.c
|
||||
window.h
|
||||
listener.c
|
||||
listener.h
|
||||
peer.c
|
||||
peer.h
|
||||
display.c
|
||||
display.h
|
||||
credssp_auth.c
|
||||
credssp_auth.h
|
||||
rdstls.c
|
||||
rdstls.h
|
||||
aad.c
|
||||
aad.h
|
||||
timer.c
|
||||
timer.h
|
||||
)
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${${MODULE_PREFIX}_GATEWAY_SRCS})
|
||||
|
||||
freerdp_module_add(${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
if(WIN32)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ws2_32)
|
||||
freerdp_library_add(ws2_32)
|
||||
endif()
|
||||
|
||||
freerdp_library_add(${OPENSSL_LIBRARIES})
|
||||
freerdp_pc_add_requires_private("libssl")
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
1051
third_party/FreeRDP/libfreerdp/core/aad.c
vendored
Normal file
1051
third_party/FreeRDP/libfreerdp/core/aad.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
53
third_party/FreeRDP/libfreerdp/core/aad.h
vendored
Normal file
53
third_party/FreeRDP/libfreerdp/core/aad.h
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Network Level Authentication (NLA)
|
||||
*
|
||||
* Copyright 2023 Isaac Klein <fifthdegree@protonmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_AAD_H
|
||||
#define FREERDP_LIB_CORE_AAD_H
|
||||
|
||||
typedef struct rdp_aad rdpAad;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AAD_STATE_INITIAL,
|
||||
AAD_STATE_AUTH,
|
||||
AAD_STATE_FINAL
|
||||
} AAD_STATE;
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL aad_is_supported(void);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int aad_client_begin(rdpAad* aad);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int aad_recv(rdpAad* aad, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL AAD_STATE aad_get_state(rdpAad* aad);
|
||||
|
||||
FREERDP_LOCAL void aad_free(rdpAad* aad);
|
||||
|
||||
WINPR_ATTR_MALLOC(aad_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpAad* aad_new(rdpContext* context);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_AAD_H */
|
||||
834
third_party/FreeRDP/libfreerdp/core/activation.c
vendored
Normal file
834
third_party/FreeRDP/libfreerdp/core/activation.c
vendored
Normal file
@@ -0,0 +1,834 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Activation Sequence
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
|
||||
#include "activation.h"
|
||||
#include "display.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.activation")
|
||||
|
||||
static BOOL rdp_recv_client_font_list_pdu(wStream* s);
|
||||
static BOOL rdp_recv_client_persistent_key_list_pdu(wStream* s);
|
||||
static BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp);
|
||||
|
||||
static BOOL rdp_write_synchronize_pdu(wStream* s, const rdpSettings* settings)
|
||||
{
|
||||
const UINT32 PduSource = freerdp_settings_get_uint32(settings, FreeRDP_PduSource);
|
||||
|
||||
if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 4))
|
||||
return FALSE;
|
||||
Stream_Write_UINT16(s, SYNCMSGTYPE_SYNC); /* messageType (2 bytes) */
|
||||
Stream_Write_UINT16(s,
|
||||
WINPR_ASSERTING_INT_CAST(uint16_t, PduSource)); /* targetUser (2 bytes) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL rdp_recv_sync_pdu(rdpRdp* rdp, wStream* s, const char* what)
|
||||
{
|
||||
UINT16 msgType = 0;
|
||||
UINT16 targetUser = 0;
|
||||
|
||||
WINPR_UNUSED(rdp);
|
||||
if (!Stream_CheckAndLogRequiredLengthEx(TAG, WLOG_WARN, s, 4, 1, "%s(%s:%" PRIuz ") %s",
|
||||
__func__, __FILE__, (size_t)__LINE__, what))
|
||||
return FALSE;
|
||||
Stream_Read_UINT16(s, msgType);
|
||||
if (msgType != SYNCMSGTYPE_SYNC)
|
||||
{
|
||||
WLog_WARN(TAG, "%s: Invalid messageType=0x%04" PRIx16 ", expected 0x%04" PRIx16, what,
|
||||
msgType, WINPR_CXX_COMPAT_CAST(uint16_t, SYNCMSGTYPE_SYNC));
|
||||
return FALSE;
|
||||
}
|
||||
Stream_Read_UINT16(s, targetUser);
|
||||
WLog_VRB(TAG, "%s: targetUser=0x%04" PRIx16, what, targetUser);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
if (!rdp_recv_sync_pdu(rdp, s, "[MS-RDPBCGR] 2.2.1.19 Server Synchronize PDU"))
|
||||
return FALSE;
|
||||
return rdp_finalize_set_flag(rdp, FINALIZE_SC_SYNCHRONIZE_PDU);
|
||||
}
|
||||
|
||||
BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp)
|
||||
{
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
WINPR_ASSERT(rdp);
|
||||
if (!rdp_write_synchronize_pdu(s, rdp->settings))
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(rdp->mcs);
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId, sec_flags);
|
||||
}
|
||||
|
||||
BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
if (!rdp_recv_sync_pdu(rdp, s, "[MS-RDPBCGR] 2.2.1.14 Client Synchronize PDU"))
|
||||
return FALSE;
|
||||
return rdp_finalize_set_flag(rdp, FINALIZE_CS_SYNCHRONIZE_PDU);
|
||||
}
|
||||
|
||||
BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp)
|
||||
{
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
WINPR_ASSERT(rdp);
|
||||
if (!rdp_write_synchronize_pdu(s, rdp->settings))
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(rdp->mcs);
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId, sec_flags);
|
||||
}
|
||||
|
||||
static BOOL rdp_recv_control_pdu(wStream* s, UINT16* action, UINT16* grantId, UINT32* controlId)
|
||||
{
|
||||
WINPR_ASSERT(s);
|
||||
WINPR_ASSERT(action);
|
||||
WINPR_ASSERT(grantId);
|
||||
WINPR_ASSERT(controlId);
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT16(s, *action); /* action (2 bytes) */
|
||||
Stream_Read_UINT16(s, *grantId); /* grantId (2 bytes) */
|
||||
Stream_Read_UINT32(s, *controlId); /* controlId (4 bytes) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL rdp_write_client_control_pdu(wStream* s, UINT16 action, UINT16 grantId,
|
||||
UINT32 controlId)
|
||||
{
|
||||
WINPR_ASSERT(s);
|
||||
if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
|
||||
return FALSE;
|
||||
Stream_Write_UINT16(s, action); /* action (2 bytes) */
|
||||
Stream_Write_UINT16(s, grantId); /* grantId (2 bytes) */
|
||||
Stream_Write_UINT32(s, controlId); /* controlId (4 bytes) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_recv_server_control_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
UINT16 action = 0;
|
||||
UINT16 grantId = 0;
|
||||
UINT32 controlId = 0;
|
||||
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
if (!rdp_recv_control_pdu(s, &action, &grantId, &controlId))
|
||||
return FALSE;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case CTRLACTION_COOPERATE:
|
||||
return rdp_finalize_set_flag(rdp, FINALIZE_SC_CONTROL_COOPERATE_PDU);
|
||||
|
||||
case CTRLACTION_GRANTED_CONTROL:
|
||||
rdp->resendFocus = TRUE;
|
||||
return rdp_finalize_set_flag(rdp, FINALIZE_SC_CONTROL_GRANTED_PDU);
|
||||
default:
|
||||
{
|
||||
char buffer[128] = WINPR_C_ARRAY_INIT;
|
||||
WLog_WARN(TAG, "Unexpected control PDU %s",
|
||||
rdp_ctrlaction_string(action, buffer, sizeof(buffer)));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp)
|
||||
{
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
Stream_Write_UINT16(s, CTRLACTION_COOPERATE); /* action (2 bytes) */
|
||||
Stream_Write_UINT16(s, 0); /* grantId (2 bytes) */
|
||||
Stream_Write_UINT32(s, 0); /* controlId (4 bytes) */
|
||||
|
||||
WINPR_ASSERT(rdp->mcs);
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId, sec_flags);
|
||||
}
|
||||
|
||||
BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp)
|
||||
{
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(rdp->mcs);
|
||||
Stream_Write_UINT16(s, CTRLACTION_GRANTED_CONTROL); /* action (2 bytes) */
|
||||
Stream_Write_UINT16(s, rdp->mcs->userId); /* grantId (2 bytes) */
|
||||
Stream_Write_UINT32(s, 0x03EA); /* controlId (4 bytes) */
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId, sec_flags);
|
||||
}
|
||||
|
||||
BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action)
|
||||
{
|
||||
UINT16 GrantId = 0;
|
||||
UINT16 ControlId = 0;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case CTRLACTION_COOPERATE:
|
||||
case CTRLACTION_REQUEST_CONTROL:
|
||||
break;
|
||||
default:
|
||||
WLog_WARN(TAG,
|
||||
"Invalid client control PDU::action 0x%04" PRIx16 ", not allowed by client",
|
||||
action);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
if (!rdp_write_client_control_pdu(s, action, GrantId, ControlId))
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(rdp->mcs);
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId, sec_flags);
|
||||
}
|
||||
|
||||
static BOOL rdp_write_client_persistent_key_list_pdu(wStream* s,
|
||||
const RDP_BITMAP_PERSISTENT_INFO* info)
|
||||
{
|
||||
WINPR_ASSERT(s);
|
||||
WINPR_ASSERT(info);
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, 24))
|
||||
return FALSE;
|
||||
|
||||
Stream_Write_UINT16(s, info->numEntriesCache0); /* numEntriesCache0 (2 bytes) */
|
||||
Stream_Write_UINT16(s, info->numEntriesCache1); /* numEntriesCache1 (2 bytes) */
|
||||
Stream_Write_UINT16(s, info->numEntriesCache2); /* numEntriesCache2 (2 bytes) */
|
||||
Stream_Write_UINT16(s, info->numEntriesCache3); /* numEntriesCache3 (2 bytes) */
|
||||
Stream_Write_UINT16(s, info->numEntriesCache4); /* numEntriesCache4 (2 bytes) */
|
||||
Stream_Write_UINT16(s, info->totalEntriesCache0); /* totalEntriesCache0 (2 bytes) */
|
||||
Stream_Write_UINT16(s, info->totalEntriesCache1); /* totalEntriesCache1 (2 bytes) */
|
||||
Stream_Write_UINT16(s, info->totalEntriesCache2); /* totalEntriesCache2 (2 bytes) */
|
||||
Stream_Write_UINT16(s, info->totalEntriesCache3); /* totalEntriesCache3 (2 bytes) */
|
||||
Stream_Write_UINT16(s, info->totalEntriesCache4); /* totalEntriesCache4 (2 bytes) */
|
||||
Stream_Write_UINT8(s, PERSIST_FIRST_PDU | PERSIST_LAST_PDU); /* bBitMask (1 byte) */
|
||||
Stream_Write_UINT8(s, 0); /* pad1 (1 byte) */
|
||||
Stream_Write_UINT16(s, 0); /* pad3 (2 bytes) */
|
||||
/* entries */
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, info->keyCount * 8ull))
|
||||
return FALSE;
|
||||
|
||||
for (UINT32 index = 0; index < info->keyCount; index++)
|
||||
{
|
||||
const UINT64 val = info->keyList[index];
|
||||
Stream_Write_UINT64(s, val);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static UINT16 rdp_load_persistent_key_list(rdpRdp* rdp, UINT64** pKeyList)
|
||||
{
|
||||
UINT16 keyCount = 0;
|
||||
UINT64* keyList = nullptr;
|
||||
rdpPersistentCache* persistent = nullptr;
|
||||
rdpSettings* settings = rdp->settings;
|
||||
|
||||
*pKeyList = nullptr;
|
||||
|
||||
if (!freerdp_settings_get_bool(settings, FreeRDP_BitmapCachePersistEnabled))
|
||||
return 0;
|
||||
|
||||
if (!settings->BitmapCachePersistFile)
|
||||
return 0;
|
||||
|
||||
persistent = persistent_cache_new();
|
||||
|
||||
if (!persistent)
|
||||
return 0;
|
||||
|
||||
const int status =
|
||||
persistent_cache_open(persistent, settings->BitmapCachePersistFile, FALSE, 0);
|
||||
|
||||
if (status < 1)
|
||||
goto error;
|
||||
|
||||
{
|
||||
const int count = persistent_cache_get_count(persistent);
|
||||
if ((count < 0) || (count > UINT16_MAX))
|
||||
goto error;
|
||||
|
||||
keyCount = (UINT16)count;
|
||||
keyList = (UINT64*)calloc(keyCount, sizeof(UINT64));
|
||||
|
||||
if (!keyList)
|
||||
goto error;
|
||||
|
||||
for (int index = 0; index < count; index++)
|
||||
{
|
||||
PERSISTENT_CACHE_ENTRY cacheEntry = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (persistent_cache_read_entry(persistent, &cacheEntry) < 1)
|
||||
continue;
|
||||
|
||||
keyList[index] = cacheEntry.key64;
|
||||
}
|
||||
}
|
||||
|
||||
*pKeyList = keyList;
|
||||
|
||||
persistent_cache_free(persistent);
|
||||
return keyCount;
|
||||
error:
|
||||
persistent_cache_free(persistent);
|
||||
free(keyList);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp)
|
||||
{
|
||||
UINT16 keyMaxFrag = 2042;
|
||||
UINT64* keyList = nullptr;
|
||||
RDP_BITMAP_PERSISTENT_INFO info = WINPR_C_ARRAY_INIT;
|
||||
WINPR_ASSERT(rdp);
|
||||
rdpSettings* settings = rdp->settings;
|
||||
UINT16 keyCount = rdp_load_persistent_key_list(rdp, &keyList);
|
||||
|
||||
WLog_DBG(TAG, "Persistent Key List: TotalKeyCount: %" PRIu16 " MaxKeyFrag: %" PRIu16, keyCount,
|
||||
keyMaxFrag);
|
||||
|
||||
// MS-RDPBCGR recommends sending no more than 169 entries at once.
|
||||
// In practice, sending more than 2042 entries at once triggers an error.
|
||||
// It should be possible to advertise the entire client bitmap cache
|
||||
// by sending multiple persistent key list PDUs, but the current code
|
||||
// only bothers sending a single, smaller list of entries instead.
|
||||
|
||||
if (keyCount > keyMaxFrag)
|
||||
keyCount = keyMaxFrag;
|
||||
|
||||
WINPR_ASSERT(settings->BitmapCacheV2CellInfo[0].numEntries <= UINT16_MAX);
|
||||
info.totalEntriesCache0 = (UINT16)settings->BitmapCacheV2CellInfo[0].numEntries;
|
||||
|
||||
WINPR_ASSERT(settings->BitmapCacheV2CellInfo[1].numEntries <= UINT16_MAX);
|
||||
info.totalEntriesCache1 = (UINT16)settings->BitmapCacheV2CellInfo[1].numEntries;
|
||||
|
||||
WINPR_ASSERT(settings->BitmapCacheV2CellInfo[2].numEntries <= UINT16_MAX);
|
||||
info.totalEntriesCache2 = (UINT16)settings->BitmapCacheV2CellInfo[2].numEntries;
|
||||
|
||||
WINPR_ASSERT(settings->BitmapCacheV2CellInfo[3].numEntries <= UINT16_MAX);
|
||||
info.totalEntriesCache3 = (UINT16)settings->BitmapCacheV2CellInfo[3].numEntries;
|
||||
|
||||
WINPR_ASSERT(settings->BitmapCacheV2CellInfo[4].numEntries <= UINT16_MAX);
|
||||
info.totalEntriesCache4 = (UINT16)settings->BitmapCacheV2CellInfo[4].numEntries;
|
||||
|
||||
info.numEntriesCache0 = MIN(keyCount, info.totalEntriesCache0);
|
||||
keyCount -= info.numEntriesCache0;
|
||||
info.numEntriesCache1 = MIN(keyCount, info.totalEntriesCache1);
|
||||
keyCount -= info.numEntriesCache1;
|
||||
info.numEntriesCache2 = MIN(keyCount, info.totalEntriesCache2);
|
||||
keyCount -= info.numEntriesCache2;
|
||||
info.numEntriesCache3 = MIN(keyCount, info.totalEntriesCache3);
|
||||
keyCount -= info.numEntriesCache3;
|
||||
info.numEntriesCache4 = MIN(keyCount, info.totalEntriesCache4);
|
||||
|
||||
info.totalEntriesCache0 = info.numEntriesCache0;
|
||||
info.totalEntriesCache1 = info.numEntriesCache1;
|
||||
info.totalEntriesCache2 = info.numEntriesCache2;
|
||||
info.totalEntriesCache3 = info.numEntriesCache3;
|
||||
info.totalEntriesCache4 = info.numEntriesCache4;
|
||||
|
||||
keyCount = info.totalEntriesCache0 + info.totalEntriesCache1 + info.totalEntriesCache2 +
|
||||
info.totalEntriesCache3 + info.totalEntriesCache4;
|
||||
|
||||
info.keyCount = keyCount;
|
||||
info.keyList = keyList;
|
||||
|
||||
WLog_DBG(TAG, "persistentKeyList count: %" PRIu32, info.keyCount);
|
||||
|
||||
WLog_DBG(TAG,
|
||||
"numEntriesCache: [0]: %" PRIu16 " [1]: %" PRIu16 " [2]: %" PRIu16 " [3]: %" PRIu16
|
||||
" [4]: %" PRIu16,
|
||||
info.numEntriesCache0, info.numEntriesCache1, info.numEntriesCache2,
|
||||
info.numEntriesCache3, info.numEntriesCache4);
|
||||
|
||||
WLog_DBG(TAG,
|
||||
"totalEntriesCache: [0]: %" PRIu16 " [1]: %" PRIu16 " [2]: %" PRIu16 " [3]: %" PRIu16
|
||||
" [4]: %" PRIu16,
|
||||
info.totalEntriesCache0, info.totalEntriesCache1, info.totalEntriesCache2,
|
||||
info.totalEntriesCache3, info.totalEntriesCache4);
|
||||
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
free(keyList);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!rdp_write_client_persistent_key_list_pdu(s, &info))
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
free(keyList);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(rdp->mcs);
|
||||
free(keyList);
|
||||
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->userId,
|
||||
sec_flags);
|
||||
}
|
||||
|
||||
BOOL rdp_recv_client_font_list_pdu(wStream* s)
|
||||
{
|
||||
WINPR_ASSERT(s);
|
||||
/* 2.2.1.18 Client Font List PDU */
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
|
||||
return FALSE;
|
||||
|
||||
return Stream_SafeSeek(s, 8);
|
||||
}
|
||||
|
||||
BOOL rdp_recv_client_persistent_key_list_pdu(wStream* s)
|
||||
{
|
||||
BYTE flags = 0;
|
||||
size_t count = 0;
|
||||
size_t total = 0;
|
||||
UINT16 cache = 0;
|
||||
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
/* 2.2.1.17.1 Persistent Key List PDU Data (TS_BITMAPCACHE_PERSISTENT_LIST_PDU) */
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 21))
|
||||
{
|
||||
WLog_ERR(TAG, "short TS_BITMAPCACHE_PERSISTENT_LIST_PDU, need 21 bytes, got %" PRIuz,
|
||||
Stream_GetRemainingLength(s));
|
||||
return FALSE;
|
||||
}
|
||||
/* Read numEntriesCacheX for variable length data in PDU */
|
||||
for (size_t x = 0; x < 5; x++)
|
||||
{
|
||||
Stream_Read_UINT16(s, cache);
|
||||
count += cache;
|
||||
}
|
||||
|
||||
/* Skip totalEntriesCacheX */
|
||||
for (size_t x = 0; x < 5; x++)
|
||||
{
|
||||
UINT16 tmp = 0;
|
||||
Stream_Read_UINT16(s, tmp);
|
||||
total += tmp;
|
||||
}
|
||||
|
||||
if (total > 262144)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"TS_BITMAPCACHE_PERSISTENT_LIST_PDU::totalEntriesCacheX exceeds 262144 entries");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Read_UINT8(s, flags);
|
||||
if ((flags & ~(PERSIST_LAST_PDU | PERSIST_FIRST_PDU)) != 0)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"TS_BITMAPCACHE_PERSISTENT_LIST_PDU::bBitMask has an invalid value of 0x%02" PRIx8,
|
||||
flags);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Skip padding */
|
||||
if (!Stream_SafeSeek(s, 3))
|
||||
{
|
||||
WLog_ERR(TAG, "short TS_BITMAPCACHE_PERSISTENT_LIST_PDU, need 3 bytes, got %" PRIuz,
|
||||
Stream_GetRemainingLength(s));
|
||||
return FALSE;
|
||||
}
|
||||
/* Skip actual entries sent by client */
|
||||
if (!Stream_SafeSeek(s, count * sizeof(UINT64)))
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"short TS_BITMAPCACHE_PERSISTENT_LIST_PDU, need %" PRIuz " bytes, got %" PRIuz,
|
||||
count * sizeof(UINT64), Stream_GetRemainingLength(s));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL rdp_write_client_font_list_pdu(wStream* s, UINT16 flags)
|
||||
{
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
|
||||
return FALSE;
|
||||
Stream_Write_UINT16(s, 0); /* numberFonts (2 bytes) */
|
||||
Stream_Write_UINT16(s, 0); /* totalNumFonts (2 bytes) */
|
||||
Stream_Write_UINT16(s, flags); /* listFlags (2 bytes) */
|
||||
Stream_Write_UINT16(s, 50); /* entrySize (2 bytes) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags)
|
||||
{
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
if (!rdp_write_client_font_list_pdu(s, flags))
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(rdp->mcs);
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->userId, sec_flags);
|
||||
}
|
||||
|
||||
BOOL rdp_recv_font_map_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
UINT16 numberEntries = 0;
|
||||
UINT16 totalNumEntries = 0;
|
||||
UINT16 mapFlags = 0;
|
||||
UINT16 entrySize = 0;
|
||||
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(rdp->settings);
|
||||
WINPR_ASSERT(s);
|
||||
WINPR_ASSERT(!freerdp_settings_get_bool(rdp->settings, FreeRDP_ServerMode));
|
||||
|
||||
/* Do not fail here, see https://github.com/FreeRDP/FreeRDP/issues/925 */
|
||||
if (Stream_CheckAndLogRequiredLength(TAG, s, 8))
|
||||
{
|
||||
Stream_Read_UINT16(s, numberEntries); /* numberEntries (2 bytes) */
|
||||
if (numberEntries != 0)
|
||||
WLog_WARN(
|
||||
TAG,
|
||||
"[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::numberEntries != 0 "
|
||||
"[%" PRIu16 "]",
|
||||
numberEntries);
|
||||
Stream_Read_UINT16(s, totalNumEntries); /* totalNumEntries (2 bytes) */
|
||||
if (totalNumEntries != 0)
|
||||
WLog_WARN(
|
||||
TAG,
|
||||
"[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::totalNumEntries != "
|
||||
"0 [%" PRIu16 "]",
|
||||
totalNumEntries);
|
||||
Stream_Read_UINT16(s, mapFlags); /* mapFlags (2 bytes) */
|
||||
if (mapFlags != (FONTLIST_FIRST | FONTLIST_LAST))
|
||||
WLog_WARN(
|
||||
TAG,
|
||||
"[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::mapFlags != 0x0003 "
|
||||
"(FONTLIST_FIRST | FONTLIST_LAST) "
|
||||
"[0x%04" PRIx16 "]",
|
||||
mapFlags);
|
||||
Stream_Read_UINT16(s, entrySize); /* entrySize (2 bytes) */
|
||||
if (entrySize != 4)
|
||||
WLog_WARN(TAG,
|
||||
"[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::entrySize != 4 "
|
||||
"[%" PRIu16 "]",
|
||||
entrySize);
|
||||
}
|
||||
else
|
||||
WLog_WARN(TAG,
|
||||
"[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU) paylaod size is "
|
||||
"0 instead of 8");
|
||||
|
||||
return rdp_finalize_set_flag(rdp, FINALIZE_SC_FONT_MAP_PDU);
|
||||
}
|
||||
|
||||
BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp)
|
||||
{
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
Stream_Write_UINT16(s, 0); /* numberEntries (2 bytes) */
|
||||
Stream_Write_UINT16(s, 0); /* totalNumEntries (2 bytes) */
|
||||
Stream_Write_UINT16(s, FONTLIST_FIRST | FONTLIST_LAST); /* mapFlags (2 bytes) */
|
||||
Stream_Write_UINT16(s, 4); /* entrySize (2 bytes) */
|
||||
|
||||
WINPR_ASSERT(rdp->mcs);
|
||||
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_MAP, rdp->mcs->userId, sec_flags);
|
||||
}
|
||||
|
||||
BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
UINT16 lengthSourceDescriptor = 0;
|
||||
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
if (rdp_get_state(rdp) == CONNECTION_STATE_ACTIVE)
|
||||
{
|
||||
if (!rdp_finalize_set_flag(rdp, FINALIZE_DEACTIVATE_REACTIVATE))
|
||||
return FALSE;
|
||||
|
||||
rdp->was_deactivated = TRUE;
|
||||
rdp->deactivated_height = freerdp_settings_get_uint32(rdp->settings, FreeRDP_DesktopHeight);
|
||||
rdp->deactivated_width = freerdp_settings_get_uint32(rdp->settings, FreeRDP_DesktopWidth);
|
||||
}
|
||||
|
||||
/*
|
||||
* Windows XP can send short DEACTIVATE_ALL PDU that doesn't contain
|
||||
* the following fields.
|
||||
*/
|
||||
|
||||
WINPR_ASSERT(rdp->settings);
|
||||
if (Stream_GetRemainingLength(s) > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
UINT32 ShareId = 0;
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
|
||||
break;
|
||||
|
||||
Stream_Read_UINT32(s, ShareId); /* shareId (4 bytes) */
|
||||
if (!freerdp_settings_set_uint32(rdp->settings, FreeRDP_ShareId, ShareId))
|
||||
return FALSE;
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
|
||||
break;
|
||||
|
||||
Stream_Read_UINT16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, lengthSourceDescriptor))
|
||||
break;
|
||||
|
||||
Stream_Seek(s, lengthSourceDescriptor); /* sourceDescriptor (should be 0x00) */
|
||||
} while (0);
|
||||
}
|
||||
|
||||
return rdp_client_transition_to_state(rdp,
|
||||
CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
|
||||
}
|
||||
|
||||
BOOL rdp_send_deactivate_all(rdpRdp* rdp)
|
||||
{
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(rdp->mcs);
|
||||
|
||||
if (rdp->mcs->userId == 0)
|
||||
{
|
||||
WLog_Print(rdp->log, WLOG_WARN,
|
||||
"rdpMcs::userId == 0, skip sending PDU_TYPE_DEACTIVATE_ALL");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_send_stream_pdu_init(rdp, &sec_flags);
|
||||
BOOL status = FALSE;
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!Stream_CheckAndLogRequiredCapacityWLog(rdp->log, (s), 7))
|
||||
goto fail;
|
||||
|
||||
WINPR_ASSERT(rdp->settings);
|
||||
{
|
||||
const UINT32 ShareId = freerdp_settings_get_uint32(rdp->settings, FreeRDP_ShareId);
|
||||
Stream_Write_UINT32(s, ShareId); /* shareId (4 bytes) */
|
||||
}
|
||||
Stream_Write_UINT16(s, 1); /* lengthSourceDescriptor (2 bytes) */
|
||||
Stream_Write_UINT8(s, 0); /* sourceDescriptor (should be 0x00) */
|
||||
|
||||
WINPR_ASSERT(rdp->mcs);
|
||||
status = rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->userId, sec_flags);
|
||||
fail:
|
||||
Stream_Release(s);
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
UINT16 action = 0;
|
||||
UINT16 GrantId = 0;
|
||||
UINT32 ControlId = 0;
|
||||
const CONNECTION_STATE state = rdp_get_state(rdp);
|
||||
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
if (!rdp_recv_control_pdu(s, &action, &GrantId, &ControlId))
|
||||
return FALSE;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
|
||||
case CTRLACTION_REQUEST_CONTROL:
|
||||
if (!rdp_finalize_is_flag_set(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU))
|
||||
{
|
||||
char abuffer[128] = WINPR_C_ARRAY_INIT;
|
||||
char buffer[1024] = WINPR_C_ARRAY_INIT;
|
||||
WLog_WARN(TAG,
|
||||
"Received action=%s with GrantId=0x%04" PRIx16 ", ControlId=0x%08" PRIx32
|
||||
" in unexpected state %s [missing %s]",
|
||||
rdp_ctrlaction_string(action, abuffer, sizeof(abuffer)), GrantId,
|
||||
ControlId, rdp_state_string(state),
|
||||
rdp_finalize_flags_to_str(FINALIZE_CS_CONTROL_COOPERATE_PDU, buffer,
|
||||
sizeof(buffer)));
|
||||
return FALSE;
|
||||
}
|
||||
if ((GrantId != 0) || (ControlId != 0))
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"Received CTRLACTION_COOPERATE with GrantId=0x%04" PRIx16
|
||||
" != 0x00, ControlId=0x%08" PRIx32 " != 0x00",
|
||||
GrantId, ControlId);
|
||||
return FALSE;
|
||||
}
|
||||
return rdp_finalize_set_flag(rdp, FINALIZE_CS_CONTROL_REQUEST_PDU);
|
||||
case CTRLACTION_COOPERATE:
|
||||
if (!rdp_finalize_is_flag_set(rdp, FINALIZE_CS_SYNCHRONIZE_PDU))
|
||||
{
|
||||
char abuffer[128] = WINPR_C_ARRAY_INIT;
|
||||
char buffer[1024] = WINPR_C_ARRAY_INIT;
|
||||
WLog_WARN(
|
||||
TAG,
|
||||
"Received action=%s with GrantId=0x%04" PRIx16 ", ControlId=0x%08" PRIx32
|
||||
" in unexpected state %s [missing %s]",
|
||||
rdp_ctrlaction_string(action, abuffer, sizeof(abuffer)), GrantId, ControlId,
|
||||
rdp_state_string(state),
|
||||
rdp_finalize_flags_to_str(FINALIZE_CS_SYNCHRONIZE_PDU, buffer, sizeof(buffer)));
|
||||
return FALSE;
|
||||
}
|
||||
if ((GrantId != 0) || (ControlId != 0))
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"Received CTRLACTION_COOPERATE with GrantId=0x%04" PRIx16
|
||||
" != 0x00, ControlId=0x%08" PRIx32 " != 0x00",
|
||||
GrantId, ControlId);
|
||||
return FALSE;
|
||||
}
|
||||
return rdp_finalize_set_flag(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU);
|
||||
default:
|
||||
{
|
||||
char abuffer[128] = WINPR_C_ARRAY_INIT;
|
||||
WLog_WARN(TAG,
|
||||
"Received unexpected action=%s with GrantId=0x%04" PRIx16
|
||||
", ControlId=0x%08" PRIx32,
|
||||
rdp_ctrlaction_string(action, abuffer, sizeof(abuffer)), GrantId, ControlId);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
if (!rdp_recv_client_font_list_pdu(s))
|
||||
return FALSE;
|
||||
rdp_finalize_set_flag(rdp, FINALIZE_CS_FONT_LIST_PDU);
|
||||
|
||||
if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP))
|
||||
return FALSE;
|
||||
|
||||
if (!rdp_send_server_font_map_pdu(rdp))
|
||||
return FALSE;
|
||||
|
||||
if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_ACTIVE))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_server_accept_client_persistent_key_list_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
if (!rdp_recv_client_persistent_key_list_pdu(s))
|
||||
return FALSE;
|
||||
|
||||
rdp_finalize_set_flag(rdp, FINALIZE_CS_PERSISTENT_KEY_LIST_PDU);
|
||||
// TODO: Actually do something with this
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const char* rdp_ctrlaction_string(UINT16 action, char* buffer, size_t size)
|
||||
{
|
||||
const char* actstr = nullptr;
|
||||
switch (action)
|
||||
{
|
||||
case CTRLACTION_COOPERATE:
|
||||
actstr = "CTRLACTION_COOPERATE";
|
||||
break;
|
||||
case CTRLACTION_DETACH:
|
||||
actstr = "CTRLACTION_DETACH";
|
||||
break;
|
||||
case CTRLACTION_GRANTED_CONTROL:
|
||||
actstr = "CTRLACTION_GRANTED_CONTROL";
|
||||
break;
|
||||
case CTRLACTION_REQUEST_CONTROL:
|
||||
actstr = "CTRLACTION_REQUEST_CONTROL";
|
||||
break;
|
||||
default:
|
||||
actstr = "CTRLACTION_UNKNOWN";
|
||||
break;
|
||||
}
|
||||
|
||||
(void)_snprintf(buffer, size, "%s [0x%04" PRIx16 "]", actstr, action);
|
||||
return buffer;
|
||||
}
|
||||
112
third_party/FreeRDP/libfreerdp/core/activation.h
vendored
Normal file
112
third_party/FreeRDP/libfreerdp/core/activation.h
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Activation Sequence
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_ACTIVATION_H
|
||||
#define FREERDP_LIB_CORE_ACTIVATION_H
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/cache/persistent.h>
|
||||
|
||||
#define SYNCMSGTYPE_SYNC 0x0001
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CTRLACTION_REQUEST_CONTROL = 0x0001,
|
||||
CTRLACTION_GRANTED_CONTROL = 0x0002,
|
||||
CTRLACTION_DETACH = 0x0003,
|
||||
CTRLACTION_COOPERATE = 0x0004
|
||||
} CTRLACTION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 numEntriesCache0;
|
||||
UINT16 numEntriesCache1;
|
||||
UINT16 numEntriesCache2;
|
||||
UINT16 numEntriesCache3;
|
||||
UINT16 numEntriesCache4;
|
||||
UINT16 totalEntriesCache0;
|
||||
UINT16 totalEntriesCache1;
|
||||
UINT16 totalEntriesCache2;
|
||||
UINT16 totalEntriesCache3;
|
||||
UINT16 totalEntriesCache4;
|
||||
UINT32 keyCount;
|
||||
UINT64* keyList;
|
||||
} RDP_BITMAP_PERSISTENT_INFO;
|
||||
|
||||
#define PERSIST_FIRST_PDU 0x01
|
||||
#define PERSIST_LAST_PDU 0x02
|
||||
|
||||
#define FONTLIST_FIRST 0x0001
|
||||
#define FONTLIST_LAST 0x0002
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* rdp_ctrlaction_string(UINT16 action, char* buffer, size_t size);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_deactivate_all(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_recv_server_control_pdu(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_recv_font_map_pdu(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_server_accept_client_persistent_key_list_pdu(rdpRdp* rdp, wStream* s);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_ACTIVATION_H */
|
||||
1100
third_party/FreeRDP/libfreerdp/core/autodetect.c
vendored
Normal file
1100
third_party/FreeRDP/libfreerdp/core/autodetect.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
58
third_party/FreeRDP/libfreerdp/core/autodetect.h
vendored
Normal file
58
third_party/FreeRDP/libfreerdp/core/autodetect.h
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Auto-Detect PDUs
|
||||
*
|
||||
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_AUTODETECT_H
|
||||
#define FREERDP_LIB_CORE_AUTODETECT_H
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/autodetect.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include "state.h"
|
||||
|
||||
FREERDP_LOCAL void autodetect_free(rdpAutoDetect* autodetect);
|
||||
|
||||
WINPR_ATTR_MALLOC(autodetect_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpAutoDetect* autodetect_new(rdpContext* context);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t autodetect_recv_request_packet(rdpAutoDetect* autodetect,
|
||||
RDP_TRANSPORT_TYPE transport, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t autodetect_recv_response_packet(rdpAutoDetect* autodetect,
|
||||
RDP_TRANSPORT_TYPE transport, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL FREERDP_AUTODETECT_STATE autodetect_get_state(rdpAutoDetect* autodetect);
|
||||
|
||||
FREERDP_LOCAL void autodetect_register_server_callbacks(rdpAutoDetect* autodetect);
|
||||
FREERDP_LOCAL void autodetect_on_connect_time_auto_detect_begin(rdpAutoDetect* autodetect);
|
||||
FREERDP_LOCAL void autodetect_on_connect_time_auto_detect_progress(rdpAutoDetect* autodetect);
|
||||
|
||||
#define AUTODETECT_TAG FREERDP_TAG("core.autodetect")
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_AUTODETECT_H */
|
||||
4991
third_party/FreeRDP/libfreerdp/core/capabilities.c
vendored
Normal file
4991
third_party/FreeRDP/libfreerdp/core/capabilities.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
179
third_party/FreeRDP/libfreerdp/core/capabilities.h
vendored
Normal file
179
third_party/FreeRDP/libfreerdp/core/capabilities.h
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Capability Sets
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_CAPABILITIES_H
|
||||
#define FREERDP_LIB_CORE_CAPABILITIES_H
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
/* Capability Set Types */
|
||||
#define CAPSET_TYPE_GENERAL 0x0001
|
||||
#define CAPSET_TYPE_BITMAP 0x0002
|
||||
#define CAPSET_TYPE_ORDER 0x0003
|
||||
#define CAPSET_TYPE_BITMAP_CACHE 0x0004
|
||||
#define CAPSET_TYPE_CONTROL 0x0005
|
||||
#define CAPSET_TYPE_BITMAP_CACHE_V3_CODEC_ID 0x0006
|
||||
#define CAPSET_TYPE_ACTIVATION 0x0007
|
||||
#define CAPSET_TYPE_POINTER 0x0008
|
||||
#define CAPSET_TYPE_SHARE 0x0009
|
||||
#define CAPSET_TYPE_COLOR_CACHE 0x000A
|
||||
#define CAPSET_TYPE_SOUND 0x000C
|
||||
#define CAPSET_TYPE_INPUT 0x000D
|
||||
#define CAPSET_TYPE_FONT 0x000E
|
||||
#define CAPSET_TYPE_BRUSH 0x000F
|
||||
#define CAPSET_TYPE_GLYPH_CACHE 0x0010
|
||||
#define CAPSET_TYPE_OFFSCREEN_CACHE 0x0011
|
||||
#define CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT 0x0012
|
||||
#define CAPSET_TYPE_BITMAP_CACHE_V2 0x0013
|
||||
#define CAPSET_TYPE_VIRTUAL_CHANNEL 0x0014
|
||||
#define CAPSET_TYPE_DRAW_NINE_GRID_CACHE 0x0015
|
||||
#define CAPSET_TYPE_DRAW_GDI_PLUS 0x0016
|
||||
#define CAPSET_TYPE_RAIL 0x0017
|
||||
#define CAPSET_TYPE_WINDOW 0x0018
|
||||
#define CAPSET_TYPE_COMP_DESK 0x0019
|
||||
#define CAPSET_TYPE_MULTI_FRAGMENT_UPDATE 0x001A
|
||||
#define CAPSET_TYPE_LARGE_POINTER 0x001B
|
||||
#define CAPSET_TYPE_SURFACE_COMMANDS 0x001C
|
||||
#define CAPSET_TYPE_BITMAP_CODECS 0x001D
|
||||
#define CAPSET_TYPE_FRAME_ACKNOWLEDGE 0x001E
|
||||
|
||||
#define CAPSET_HEADER_LENGTH 4
|
||||
|
||||
#define SOURCE_DESCRIPTOR "FREERDP"
|
||||
|
||||
/* Capabilities Protocol Version */
|
||||
#define CAPS_PROTOCOL_VERSION 0x0200
|
||||
|
||||
/* General Capability Flags */
|
||||
#define FASTPATH_OUTPUT_SUPPORTED 0x0001
|
||||
#define NO_BITMAP_COMPRESSION_HDR 0x0400
|
||||
#define LONG_CREDENTIALS_SUPPORTED 0x0004
|
||||
#define AUTORECONNECT_SUPPORTED 0x0008
|
||||
#define ENC_SALTED_CHECKSUM 0x0010
|
||||
|
||||
/* Drawing Flags */
|
||||
#define DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY 0x02
|
||||
#define DRAW_ALLOW_COLOR_SUBSAMPLING 0x04
|
||||
#define DRAW_ALLOW_SKIP_ALPHA 0x08
|
||||
|
||||
/* Order Flags */
|
||||
#define NEGOTIATE_ORDER_SUPPORT 0x0002
|
||||
#define ZERO_BOUNDS_DELTA_SUPPORT 0x0008
|
||||
#define COLOR_INDEX_SUPPORT 0x0020
|
||||
#define SOLID_PATTERN_BRUSH_ONLY 0x0040
|
||||
#define ORDER_FLAGS_EXTRA_SUPPORT 0x0080
|
||||
|
||||
/* Extended Order Flags */
|
||||
#define CACHE_BITMAP_V3_SUPPORT 0x0002
|
||||
#define ALTSEC_FRAME_MARKER_SUPPORT 0x0004
|
||||
|
||||
/* Sound Flags */
|
||||
#define SOUND_BEEPS_FLAG 0x0001
|
||||
|
||||
/* Input Flags */
|
||||
#define INPUT_FLAG_SCANCODES 0x0001
|
||||
#define INPUT_FLAG_MOUSEX 0x0004
|
||||
#define INPUT_FLAG_FASTPATH_INPUT 0x0008
|
||||
#define INPUT_FLAG_UNICODE 0x0010
|
||||
#define INPUT_FLAG_FASTPATH_INPUT2 0x0020
|
||||
#define INPUT_FLAG_UNUSED1 0x0040
|
||||
#define INPUT_FLAG_MOUSE_RELATIVE 0x0080
|
||||
#define TS_INPUT_FLAG_MOUSE_HWHEEL 0x0100
|
||||
#define TS_INPUT_FLAG_QOE_TIMESTAMPS 0x0200
|
||||
|
||||
/* Font Support Flags */
|
||||
#define FONTSUPPORT_FONTLIST 0x0001
|
||||
|
||||
/* Brush Support Level */
|
||||
#define BRUSH_DEFAULT 0x00000000
|
||||
#define BRUSH_COLOR_8x8 0x00000001
|
||||
#define BRUSH_COLOR_FULL 0x00000002
|
||||
|
||||
/* Bitmap Cache Version */
|
||||
#define BITMAP_CACHE_V2 0x01
|
||||
|
||||
/* Bitmap Cache V2 Flags */
|
||||
#define PERSISTENT_KEYS_EXPECTED_FLAG 0x0001
|
||||
#define ALLOW_CACHE_WAITING_LIST_FLAG 0x0002
|
||||
|
||||
/* Draw Nine Grid Support Level */
|
||||
#define DRAW_NINEGRID_NO_SUPPORT 0x00000000
|
||||
#define DRAW_NINEGRID_SUPPORTED 0x00000001
|
||||
#define DRAW_NINEGRID_SUPPORTED_V2 0x00000002
|
||||
|
||||
/* Draw GDI+ Support Level */
|
||||
#define DRAW_GDIPLUS_DEFAULT 0x00000000
|
||||
#define DRAW_GDIPLUS_SUPPORTED 0x00000001
|
||||
|
||||
/* Draw GDI+ Cache Level */
|
||||
#define DRAW_GDIPLUS_CACHE_LEVEL_DEFAULT 0x00000000
|
||||
#define DRAW_GDIPLUS_CACHE_LEVEL_ONE 0x00000001
|
||||
|
||||
/* Window Support Level */
|
||||
#define WINDOW_LEVEL_NOT_SUPPORTED 0x00000000
|
||||
#define WINDOW_LEVEL_SUPPORTED 0x00000001
|
||||
#define WINDOW_LEVEL_SUPPORTED_EX 0x00000002
|
||||
|
||||
/* Desktop Composition Support Level */
|
||||
#define COMPDESK_NOT_SUPPORTED 0x0000
|
||||
#define COMPDESK_SUPPORTED 0x0001
|
||||
|
||||
/* Bitmap Codec Constants */
|
||||
#define CARDP_CAPS_CAPTURE_NON_CAC 0x00000001
|
||||
#define CBY_CAPS 0xCBC0
|
||||
#define CBY_CAPSET 0xCBC1
|
||||
#define CLY_CAPSET 0xCFC0
|
||||
#define CLW_VERSION_1_0 0x0100
|
||||
#define CT_TILE_64x64 0x0040
|
||||
#define CLW_COL_CONV_ICT 0x1
|
||||
#define CLW_XFORM_DWT_53_A 0x1
|
||||
#define CLW_ENTROPY_RLGR1 0x01
|
||||
#define CLW_ENTROPY_RLGR3 0x04
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId,
|
||||
UINT16* length);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_recv_demand_active(rdpRdp* rdp, wStream* s, UINT16 pduSource, UINT16 length);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_demand_active(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_recv_confirm_active(rdpRdp* rdp, wStream* s, UINT16 pduLength);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_confirm_active(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_read_capability_set(wLog* log, wStream* sub, UINT16 type,
|
||||
rdpSettings* settings, BOOL isServer);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* rdp_input_flag_string(UINT16 flags, char* buffer, size_t len);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_CAPABILITIES_H */
|
||||
321
third_party/FreeRDP/libfreerdp/core/channels.c
vendored
Normal file
321
third_party/FreeRDP/libfreerdp/core/channels.c
vendored
Normal file
@@ -0,0 +1,321 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Virtual Channels
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
* Copyright 2015 Copyright 2015 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/wtsapi.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/constants.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/svc.h>
|
||||
#include <freerdp/peer.h>
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include <freerdp/client/channels.h>
|
||||
#include <freerdp/client/drdynvc.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
|
||||
#include "rdp.h"
|
||||
#include "client.h"
|
||||
#include "server.h"
|
||||
#include "channels.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.channels")
|
||||
|
||||
BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, const BYTE* data, size_t size)
|
||||
{
|
||||
size_t left = 0;
|
||||
UINT32 flags = 0;
|
||||
size_t chunkSize = 0;
|
||||
rdpMcs* mcs = nullptr;
|
||||
const rdpMcsChannel* channel = nullptr;
|
||||
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(data || (size == 0));
|
||||
|
||||
mcs = rdp->mcs;
|
||||
WINPR_ASSERT(mcs);
|
||||
for (UINT32 i = 0; i < mcs->channelCount; i++)
|
||||
{
|
||||
const rdpMcsChannel* cur = &mcs->channels[i];
|
||||
if (cur->ChannelId == channelId)
|
||||
{
|
||||
channel = cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!channel)
|
||||
{
|
||||
WLog_ERR(TAG, "freerdp_channel_send: unknown channelId %" PRIu16 "", channelId);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
flags = CHANNEL_FLAG_FIRST;
|
||||
left = size;
|
||||
|
||||
while (left > 0)
|
||||
{
|
||||
if (left > rdp->settings->VCChunkSize)
|
||||
{
|
||||
chunkSize = rdp->settings->VCChunkSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
chunkSize = left;
|
||||
flags |= CHANNEL_FLAG_LAST;
|
||||
}
|
||||
|
||||
if (!rdp->settings->ServerMode && (channel->options & CHANNEL_OPTION_SHOW_PROTOCOL))
|
||||
{
|
||||
flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
|
||||
}
|
||||
|
||||
if (!freerdp_channel_send_packet(rdp, channelId, size, flags, data, chunkSize))
|
||||
return FALSE;
|
||||
|
||||
data += chunkSize;
|
||||
left -= chunkSize;
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channelId, size_t packetLength)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
UINT32 length = 0;
|
||||
UINT32 flags = 0;
|
||||
size_t chunkLength = 0;
|
||||
|
||||
WINPR_ASSERT(instance);
|
||||
|
||||
if (packetLength < 8)
|
||||
{
|
||||
WLog_ERR(TAG, "Header length %" PRIuz " bytes promised, none available", packetLength);
|
||||
return FALSE;
|
||||
}
|
||||
packetLength -= 8;
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
|
||||
return FALSE;
|
||||
|
||||
/* [MS-RDPBCGR] 3.1.5.2.2 Processing of Virtual Channel PDU
|
||||
* chunked data. Length is the total size of the combined data,
|
||||
* chunkLength is the actual data received.
|
||||
* check chunkLength against packetLength, which is the TPKT header size.
|
||||
*/
|
||||
Stream_Read_UINT32(s, length);
|
||||
Stream_Read_UINT32(s, flags);
|
||||
chunkLength = Stream_GetRemainingLength(s);
|
||||
if (packetLength != chunkLength)
|
||||
{
|
||||
WLog_ERR(TAG, "Header length %" PRIuz " != actual length %" PRIuz, packetLength,
|
||||
chunkLength);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
IFCALLRET(instance->ReceiveChannelData, rc, instance, channelId, Stream_Pointer(s), chunkLength,
|
||||
flags, length);
|
||||
if (!rc)
|
||||
{
|
||||
WLog_WARN(TAG, "ReceiveChannelData returned %d", rc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return Stream_SafeSeek(s, chunkLength);
|
||||
}
|
||||
|
||||
BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channelId)
|
||||
{
|
||||
UINT32 length = 0;
|
||||
UINT32 flags = 0;
|
||||
|
||||
WINPR_ASSERT(client);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT32(s, length);
|
||||
Stream_Read_UINT32(s, flags);
|
||||
const size_t chunkLength = Stream_GetRemainingLength(s);
|
||||
if (chunkLength > UINT32_MAX)
|
||||
return FALSE;
|
||||
|
||||
if (client->VirtualChannelRead)
|
||||
{
|
||||
int rc = 0;
|
||||
BOOL found = FALSE;
|
||||
HANDLE hChannel = nullptr;
|
||||
rdpContext* context = client->context;
|
||||
rdpMcs* mcs = context->rdp->mcs;
|
||||
|
||||
for (UINT32 index = 0; index < mcs->channelCount; index++)
|
||||
{
|
||||
const rdpMcsChannel* mcsChannel = &(mcs->channels[index]);
|
||||
|
||||
if (mcsChannel->ChannelId == channelId)
|
||||
{
|
||||
hChannel = (HANDLE)mcsChannel->handle;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return FALSE;
|
||||
|
||||
rc = client->VirtualChannelRead(client, hChannel, Stream_Pointer(s), (UINT32)chunkLength);
|
||||
if (rc < 0)
|
||||
return FALSE;
|
||||
}
|
||||
else if (client->ReceiveChannelData)
|
||||
{
|
||||
BOOL rc = client->ReceiveChannelData(client, channelId, Stream_Pointer(s),
|
||||
(UINT32)chunkLength, flags, length);
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
}
|
||||
if (!Stream_SafeSeek(s, chunkLength))
|
||||
{
|
||||
WLog_WARN(TAG, "Short PDU, need %" PRIuz " bytes, got %" PRIuz, chunkLength,
|
||||
Stream_GetRemainingLength(s));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const WtsApiFunctionTable FreeRDP_WtsApiFunctionTable = {
|
||||
0, /* dwVersion */
|
||||
0, /* dwFlags */
|
||||
|
||||
FreeRDP_WTSStopRemoteControlSession, /* StopRemoteControlSession */
|
||||
FreeRDP_WTSStartRemoteControlSessionW, /* StartRemoteControlSessionW */
|
||||
FreeRDP_WTSStartRemoteControlSessionA, /* StartRemoteControlSessionA */
|
||||
FreeRDP_WTSConnectSessionW, /* ConnectSessionW */
|
||||
FreeRDP_WTSConnectSessionA, /* ConnectSessionA */
|
||||
FreeRDP_WTSEnumerateServersW, /* EnumerateServersW */
|
||||
FreeRDP_WTSEnumerateServersA, /* EnumerateServersA */
|
||||
FreeRDP_WTSOpenServerW, /* OpenServerW */
|
||||
FreeRDP_WTSOpenServerA, /* OpenServerA */
|
||||
FreeRDP_WTSOpenServerExW, /* OpenServerExW */
|
||||
FreeRDP_WTSOpenServerExA, /* OpenServerExA */
|
||||
FreeRDP_WTSCloseServer, /* CloseServer */
|
||||
FreeRDP_WTSEnumerateSessionsW, /* EnumerateSessionsW */
|
||||
FreeRDP_WTSEnumerateSessionsA, /* EnumerateSessionsA */
|
||||
FreeRDP_WTSEnumerateSessionsExW, /* EnumerateSessionsExW */
|
||||
FreeRDP_WTSEnumerateSessionsExA, /* EnumerateSessionsExA */
|
||||
FreeRDP_WTSEnumerateProcessesW, /* EnumerateProcessesW */
|
||||
FreeRDP_WTSEnumerateProcessesA, /* EnumerateProcessesA */
|
||||
FreeRDP_WTSTerminateProcess, /* TerminateProcess */
|
||||
FreeRDP_WTSQuerySessionInformationW, /* QuerySessionInformationW */
|
||||
FreeRDP_WTSQuerySessionInformationA, /* QuerySessionInformationA */
|
||||
FreeRDP_WTSQueryUserConfigW, /* QueryUserConfigW */
|
||||
FreeRDP_WTSQueryUserConfigA, /* QueryUserConfigA */
|
||||
FreeRDP_WTSSetUserConfigW, /* SetUserConfigW */
|
||||
FreeRDP_WTSSetUserConfigA, /* SetUserConfigA */
|
||||
FreeRDP_WTSSendMessageW, /* SendMessageW */
|
||||
FreeRDP_WTSSendMessageA, /* SendMessageA */
|
||||
FreeRDP_WTSDisconnectSession, /* DisconnectSession */
|
||||
FreeRDP_WTSLogoffSession, /* LogoffSession */
|
||||
FreeRDP_WTSShutdownSystem, /* ShutdownSystem */
|
||||
FreeRDP_WTSWaitSystemEvent, /* WaitSystemEvent */
|
||||
FreeRDP_WTSVirtualChannelOpen, /* VirtualChannelOpen */
|
||||
FreeRDP_WTSVirtualChannelOpenEx, /* VirtualChannelOpenEx */
|
||||
FreeRDP_WTSVirtualChannelClose, /* VirtualChannelClose */
|
||||
FreeRDP_WTSVirtualChannelRead, /* VirtualChannelRead */
|
||||
FreeRDP_WTSVirtualChannelWrite, /* VirtualChannelWrite */
|
||||
FreeRDP_WTSVirtualChannelPurgeInput, /* VirtualChannelPurgeInput */
|
||||
FreeRDP_WTSVirtualChannelPurgeOutput, /* VirtualChannelPurgeOutput */
|
||||
FreeRDP_WTSVirtualChannelQuery, /* VirtualChannelQuery */
|
||||
FreeRDP_WTSFreeMemory, /* FreeMemory */
|
||||
FreeRDP_WTSRegisterSessionNotification, /* RegisterSessionNotification */
|
||||
FreeRDP_WTSUnRegisterSessionNotification, /* UnRegisterSessionNotification */
|
||||
FreeRDP_WTSRegisterSessionNotificationEx, /* RegisterSessionNotificationEx */
|
||||
FreeRDP_WTSUnRegisterSessionNotificationEx, /* UnRegisterSessionNotificationEx */
|
||||
FreeRDP_WTSQueryUserToken, /* QueryUserToken */
|
||||
FreeRDP_WTSFreeMemoryExW, /* FreeMemoryExW */
|
||||
FreeRDP_WTSFreeMemoryExA, /* FreeMemoryExA */
|
||||
FreeRDP_WTSEnumerateProcessesExW, /* EnumerateProcessesExW */
|
||||
FreeRDP_WTSEnumerateProcessesExA, /* EnumerateProcessesExA */
|
||||
FreeRDP_WTSEnumerateListenersW, /* EnumerateListenersW */
|
||||
FreeRDP_WTSEnumerateListenersA, /* EnumerateListenersA */
|
||||
FreeRDP_WTSQueryListenerConfigW, /* QueryListenerConfigW */
|
||||
FreeRDP_WTSQueryListenerConfigA, /* QueryListenerConfigA */
|
||||
FreeRDP_WTSCreateListenerW, /* CreateListenerW */
|
||||
FreeRDP_WTSCreateListenerA, /* CreateListenerA */
|
||||
FreeRDP_WTSSetListenerSecurityW, /* SetListenerSecurityW */
|
||||
FreeRDP_WTSSetListenerSecurityA, /* SetListenerSecurityA */
|
||||
FreeRDP_WTSGetListenerSecurityW, /* GetListenerSecurityW */
|
||||
FreeRDP_WTSGetListenerSecurityA, /* GetListenerSecurityA */
|
||||
FreeRDP_WTSEnableChildSessions, /* EnableChildSessions */
|
||||
FreeRDP_WTSIsChildSessionsEnabled, /* IsChildSessionsEnabled */
|
||||
FreeRDP_WTSGetChildSessionId, /* GetChildSessionId */
|
||||
FreeRDP_WTSGetActiveConsoleSessionId, /* GetActiveConsoleSessionId */
|
||||
FreeRDP_WTSLogonUser,
|
||||
FreeRDP_WTSLogoffUser,
|
||||
FreeRDP_WTSStartRemoteControlSessionExW,
|
||||
FreeRDP_WTSStartRemoteControlSessionExA
|
||||
};
|
||||
|
||||
const WtsApiFunctionTable* FreeRDP_InitWtsApi(void)
|
||||
{
|
||||
return &FreeRDP_WtsApiFunctionTable;
|
||||
}
|
||||
|
||||
BOOL freerdp_channel_send_packet(rdpRdp* rdp, UINT16 channelId, size_t totalSize, UINT32 flags,
|
||||
const BYTE* data, size_t chunkSize)
|
||||
{
|
||||
if (totalSize > UINT32_MAX)
|
||||
return FALSE;
|
||||
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_send_stream_init(rdp, &sec_flags);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, chunkSize + 8))
|
||||
{
|
||||
Stream_Release(s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(s, (UINT32)totalSize);
|
||||
Stream_Write_UINT32(s, flags);
|
||||
|
||||
Stream_Write(s, data, chunkSize);
|
||||
|
||||
/* WLog_DBG(TAG, "sending data (flags=0x%x size=%d)", flags, size); */
|
||||
return rdp_send(rdp, s, channelId, sec_flags);
|
||||
}
|
||||
41
third_party/FreeRDP/libfreerdp/core/channels.h
vendored
Normal file
41
third_party/FreeRDP/libfreerdp/core/channels.h
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Virtual Channels
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_CHANNELS_H
|
||||
#define FREERDP_LIB_CORE_CHANNELS_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include "client.h"
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, const BYTE* data,
|
||||
size_t size);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_channel_send_packet(rdpRdp* rdp, UINT16 channelId, size_t totalSize,
|
||||
UINT32 flags, const BYTE* data, size_t chunkSize);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channelId,
|
||||
size_t packetLength);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channelId);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_CHANNELS_H */
|
||||
572
third_party/FreeRDP/libfreerdp/core/childsession.c
vendored
Normal file
572
third_party/FreeRDP/libfreerdp/core/childsession.c
vendored
Normal file
@@ -0,0 +1,572 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Named pipe transport
|
||||
*
|
||||
* Copyright 2023-2024 David Fort <contact@hardening-consulting.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "tcp.h"
|
||||
|
||||
#include <winpr/library.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/utils/ringbuffer.h>
|
||||
|
||||
#include "childsession.h"
|
||||
|
||||
#define TAG FREERDP_TAG("childsession")
|
||||
|
||||
typedef struct
|
||||
{
|
||||
OVERLAPPED readOverlapped;
|
||||
HANDLE hFile;
|
||||
BOOL opInProgress;
|
||||
BOOL lastOpClosed;
|
||||
RingBuffer readBuffer;
|
||||
BOOL blocking;
|
||||
BYTE tmpReadBuffer[4096];
|
||||
|
||||
HANDLE readEvent;
|
||||
} WINPR_BIO_NAMED;
|
||||
|
||||
static int transport_bio_named_uninit(BIO* bio);
|
||||
|
||||
static int transport_bio_named_write(BIO* bio, const char* buf, int size)
|
||||
{
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(buf);
|
||||
|
||||
WINPR_BIO_NAMED* ptr = (WINPR_BIO_NAMED*)BIO_get_data(bio);
|
||||
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||
DWORD written = 0;
|
||||
|
||||
const UINT64 start = GetTickCount64();
|
||||
BOOL ret =
|
||||
WriteFile(ptr->hFile, buf, WINPR_ASSERTING_INT_CAST(uint32_t, size), &written, nullptr);
|
||||
// winpr_HexDump(TAG, WLOG_DEBUG, buf, size);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
WLog_VRB(TAG, "error or deferred");
|
||||
return 0;
|
||||
}
|
||||
|
||||
WLog_VRB(TAG, "(%d)=%d written=%" PRIu32 " duration=%" PRIu64, size, ret, written,
|
||||
GetTickCount64() - start);
|
||||
|
||||
if (written == 0)
|
||||
{
|
||||
WLog_VRB(TAG, "closed on write");
|
||||
return 0;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(written <= INT32_MAX);
|
||||
return (int)written;
|
||||
}
|
||||
|
||||
static BOOL treatReadResult(WINPR_BIO_NAMED* ptr, DWORD readBytes)
|
||||
{
|
||||
WLog_VRB(TAG, "treatReadResult(readBytes=%" PRIu32 ")", readBytes);
|
||||
ptr->opInProgress = FALSE;
|
||||
if (readBytes == 0)
|
||||
{
|
||||
WLog_VRB(TAG, "readBytes == 0");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!ringbuffer_write(&ptr->readBuffer, ptr->tmpReadBuffer, readBytes))
|
||||
{
|
||||
WLog_VRB(TAG, "ringbuffer_write()");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return SetEvent(ptr->readEvent);
|
||||
}
|
||||
|
||||
static BOOL doReadOp(WINPR_BIO_NAMED* ptr)
|
||||
{
|
||||
DWORD readBytes = 0;
|
||||
|
||||
if (!ResetEvent(ptr->readEvent))
|
||||
return FALSE;
|
||||
|
||||
ptr->opInProgress = TRUE;
|
||||
if (!ReadFile(ptr->hFile, ptr->tmpReadBuffer, sizeof(ptr->tmpReadBuffer), &readBytes,
|
||||
&ptr->readOverlapped))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
switch (error)
|
||||
{
|
||||
case ERROR_NO_DATA:
|
||||
WLog_VRB(TAG, "No Data, unexpected");
|
||||
return TRUE;
|
||||
case ERROR_IO_PENDING:
|
||||
WLog_VRB(TAG, "ERROR_IO_PENDING");
|
||||
return TRUE;
|
||||
case ERROR_BROKEN_PIPE:
|
||||
WLog_VRB(TAG, "broken pipe");
|
||||
ptr->lastOpClosed = TRUE;
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return treatReadResult(ptr, readBytes);
|
||||
}
|
||||
|
||||
static int transport_bio_named_read(BIO* bio, char* buf, int size)
|
||||
{
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(buf);
|
||||
|
||||
WINPR_BIO_NAMED* ptr = (WINPR_BIO_NAMED*)BIO_get_data(bio);
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_READ);
|
||||
|
||||
if (ptr->blocking)
|
||||
{
|
||||
while (!ringbuffer_used(&ptr->readBuffer))
|
||||
{
|
||||
if (ptr->lastOpClosed)
|
||||
return 0;
|
||||
|
||||
if (ptr->opInProgress)
|
||||
{
|
||||
DWORD status = WaitForSingleObjectEx(ptr->readEvent, 500, TRUE);
|
||||
switch (status)
|
||||
{
|
||||
case WAIT_TIMEOUT:
|
||||
case WAIT_IO_COMPLETION:
|
||||
continue;
|
||||
case WAIT_OBJECT_0:
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
DWORD readBytes = 0;
|
||||
if (!GetOverlappedResult(ptr->hFile, &ptr->readOverlapped, &readBytes, FALSE))
|
||||
{
|
||||
WLog_ERR(TAG, "GetOverlappedResult blocking(lastError=%" PRIu32 ")",
|
||||
GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!treatReadResult(ptr, readBytes))
|
||||
{
|
||||
WLog_ERR(TAG, "treatReadResult blocking");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ptr->opInProgress)
|
||||
{
|
||||
DWORD status = WaitForSingleObject(ptr->readEvent, 0);
|
||||
switch (status)
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
BIO_set_flags(bio, (BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_READ));
|
||||
return -1;
|
||||
default:
|
||||
WLog_ERR(TAG, "error WaitForSingleObject(readEvent)=0x%" PRIx32 "", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DWORD readBytes = 0;
|
||||
if (!GetOverlappedResult(ptr->hFile, &ptr->readOverlapped, &readBytes, FALSE))
|
||||
{
|
||||
WLog_ERR(TAG, "GetOverlappedResult non blocking(lastError=%" PRIu32 ")",
|
||||
GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!treatReadResult(ptr, readBytes))
|
||||
{
|
||||
WLog_ERR(TAG, "error treatReadResult non blocking");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SSIZE_T ret = -1;
|
||||
if (size >= 0)
|
||||
{
|
||||
size_t rsize = ringbuffer_used(&ptr->readBuffer);
|
||||
if (rsize <= SSIZE_MAX)
|
||||
ret = MIN(size, (SSIZE_T)rsize);
|
||||
}
|
||||
if ((size >= 0) && ret)
|
||||
{
|
||||
DataChunk chunks[2] = WINPR_C_ARRAY_INIT;
|
||||
const int nchunks =
|
||||
ringbuffer_peek(&ptr->readBuffer, chunks, WINPR_ASSERTING_INT_CAST(size_t, ret));
|
||||
for (int i = 0; i < nchunks; i++)
|
||||
{
|
||||
memcpy(buf, chunks[i].data, chunks[i].size);
|
||||
buf += chunks[i].size;
|
||||
}
|
||||
|
||||
ringbuffer_commit_read_bytes(&ptr->readBuffer, WINPR_ASSERTING_INT_CAST(size_t, ret));
|
||||
|
||||
WLog_VRB(TAG, "(%d)=%" PRIdz " nchunks=%d", size, ret, nchunks);
|
||||
}
|
||||
|
||||
if (!ringbuffer_used(&ptr->readBuffer))
|
||||
{
|
||||
if (!ptr->opInProgress && !doReadOp(ptr))
|
||||
{
|
||||
WLog_ERR(TAG, "error rearming read");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret <= 0)
|
||||
BIO_set_flags(bio, (BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_READ));
|
||||
|
||||
WINPR_ASSERT(ret <= INT32_MAX);
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
static int transport_bio_named_puts(BIO* bio, const char* str)
|
||||
{
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(str);
|
||||
|
||||
const size_t max = (INT_MAX > SIZE_MAX) ? SIZE_MAX : INT_MAX;
|
||||
const size_t len = strnlen(str, max);
|
||||
if (len >= max)
|
||||
return -1;
|
||||
return transport_bio_named_write(bio, str, WINPR_ASSERTING_INT_CAST(int, len));
|
||||
}
|
||||
|
||||
static int transport_bio_named_gets(BIO* bio, char* str, int size)
|
||||
{
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(str);
|
||||
|
||||
return transport_bio_named_read(bio, str, size);
|
||||
}
|
||||
|
||||
static long transport_bio_named_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
{
|
||||
WINPR_ASSERT(bio);
|
||||
|
||||
int status = -1;
|
||||
WINPR_BIO_NAMED* ptr = (WINPR_BIO_NAMED*)BIO_get_data(bio);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case BIO_C_SET_SOCKET:
|
||||
case BIO_C_GET_SOCKET:
|
||||
return -1;
|
||||
case BIO_C_GET_EVENT:
|
||||
if (!BIO_get_init(bio) || !arg2)
|
||||
return 0;
|
||||
|
||||
*((HANDLE*)arg2) = ptr->readEvent;
|
||||
return 1;
|
||||
case BIO_C_SET_HANDLE:
|
||||
BIO_set_init(bio, 1);
|
||||
if (!BIO_get_init(bio) || !arg2)
|
||||
return 0;
|
||||
|
||||
ptr->hFile = (HANDLE)arg2;
|
||||
ptr->blocking = TRUE;
|
||||
if (!doReadOp(ptr))
|
||||
return -1;
|
||||
return 1;
|
||||
case BIO_C_SET_NONBLOCK:
|
||||
{
|
||||
WLog_DBG(TAG, "BIO_C_SET_NONBLOCK");
|
||||
ptr->blocking = FALSE;
|
||||
return 1;
|
||||
}
|
||||
case BIO_C_WAIT_READ:
|
||||
{
|
||||
WLog_DBG(TAG, "BIO_C_WAIT_READ");
|
||||
return 1;
|
||||
}
|
||||
|
||||
case BIO_C_WAIT_WRITE:
|
||||
{
|
||||
WLog_DBG(TAG, "BIO_C_WAIT_WRITE");
|
||||
return 1;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
status = BIO_get_shutdown(bio);
|
||||
break;
|
||||
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
BIO_set_shutdown(bio, (int)arg1);
|
||||
status = 1;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_DUP:
|
||||
status = 1;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_FLUSH:
|
||||
status = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void BIO_NAMED_free(WINPR_BIO_NAMED* ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
if (ptr->hFile)
|
||||
{
|
||||
(void)CloseHandle(ptr->hFile);
|
||||
ptr->hFile = nullptr;
|
||||
}
|
||||
|
||||
if (ptr->readEvent)
|
||||
{
|
||||
(void)CloseHandle(ptr->readEvent);
|
||||
ptr->readEvent = nullptr;
|
||||
}
|
||||
|
||||
ringbuffer_destroy(&ptr->readBuffer);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static int transport_bio_named_uninit(BIO* bio)
|
||||
{
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_BIO_NAMED* ptr = (WINPR_BIO_NAMED*)BIO_get_data(bio);
|
||||
|
||||
BIO_NAMED_free(ptr);
|
||||
|
||||
BIO_set_init(bio, 0);
|
||||
BIO_set_flags(bio, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_named_new(BIO* bio)
|
||||
{
|
||||
WINPR_ASSERT(bio);
|
||||
|
||||
WINPR_BIO_NAMED* ptr = (WINPR_BIO_NAMED*)calloc(1, sizeof(WINPR_BIO_NAMED));
|
||||
if (!ptr)
|
||||
return 0;
|
||||
|
||||
if (!ringbuffer_init(&ptr->readBuffer, 0xfffff))
|
||||
goto error;
|
||||
|
||||
ptr->readEvent = CreateEventA(nullptr, TRUE, FALSE, nullptr);
|
||||
if (!ptr->readEvent || ptr->readEvent == INVALID_HANDLE_VALUE)
|
||||
goto error;
|
||||
|
||||
ptr->readOverlapped.hEvent = ptr->readEvent;
|
||||
|
||||
BIO_set_data(bio, ptr);
|
||||
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
return 1;
|
||||
|
||||
error:
|
||||
BIO_NAMED_free(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transport_bio_named_free(BIO* bio)
|
||||
{
|
||||
WINPR_BIO_NAMED* ptr = nullptr;
|
||||
|
||||
if (!bio)
|
||||
return 0;
|
||||
|
||||
transport_bio_named_uninit(bio);
|
||||
|
||||
ptr = (WINPR_BIO_NAMED*)BIO_get_data(bio);
|
||||
if (ptr)
|
||||
BIO_set_data(bio, nullptr);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BIO_METHOD* BIO_s_namedpipe(void)
|
||||
{
|
||||
static BIO_METHOD* bio_methods = nullptr;
|
||||
|
||||
if (bio_methods == nullptr)
|
||||
{
|
||||
if (!(bio_methods = BIO_meth_new(BIO_TYPE_NAMEDPIPE, "NamedPipe")))
|
||||
return nullptr;
|
||||
|
||||
BIO_meth_set_write(bio_methods, transport_bio_named_write);
|
||||
BIO_meth_set_read(bio_methods, transport_bio_named_read);
|
||||
BIO_meth_set_puts(bio_methods, transport_bio_named_puts);
|
||||
BIO_meth_set_gets(bio_methods, transport_bio_named_gets);
|
||||
BIO_meth_set_ctrl(bio_methods, transport_bio_named_ctrl);
|
||||
BIO_meth_set_create(bio_methods, transport_bio_named_new);
|
||||
BIO_meth_set_destroy(bio_methods, transport_bio_named_free);
|
||||
}
|
||||
|
||||
return bio_methods;
|
||||
}
|
||||
|
||||
typedef NTSTATUS (*WinStationCreateChildSessionTransportFn)(WCHAR* path, DWORD len);
|
||||
static BOOL createChildSessionTransport(HANDLE* pFile)
|
||||
{
|
||||
WINPR_ASSERT(pFile);
|
||||
|
||||
HANDLE hModule = nullptr;
|
||||
BOOL ret = FALSE;
|
||||
*pFile = INVALID_HANDLE_VALUE;
|
||||
|
||||
BOOL childEnabled = 0;
|
||||
if (!WTSIsChildSessionsEnabled(&childEnabled))
|
||||
{
|
||||
WLog_ERR(TAG, "error when calling WTSIsChildSessionsEnabled");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!childEnabled)
|
||||
{
|
||||
WLog_INFO(TAG, "child sessions aren't enabled");
|
||||
if (!WTSEnableChildSessions(TRUE))
|
||||
{
|
||||
WLog_ERR(TAG, "error when calling WTSEnableChildSessions");
|
||||
goto out;
|
||||
}
|
||||
WLog_INFO(TAG, "successfully enabled child sessions");
|
||||
}
|
||||
|
||||
hModule = LoadLibraryA("winsta.dll");
|
||||
if (!hModule)
|
||||
return FALSE;
|
||||
|
||||
{
|
||||
WCHAR pipePath[0x80] = WINPR_C_ARRAY_INIT;
|
||||
char pipePathA[0x80] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
{
|
||||
WinStationCreateChildSessionTransportFn createChildSessionFn =
|
||||
GetProcAddressAs(hModule, "WinStationCreateChildSessionTransport",
|
||||
WinStationCreateChildSessionTransportFn);
|
||||
if (!createChildSessionFn)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to retrieve WinStationCreateChildSessionTransport function");
|
||||
goto out;
|
||||
}
|
||||
|
||||
{
|
||||
HRESULT hStatus = createChildSessionFn(pipePath, 0x80);
|
||||
if (!SUCCEEDED(hStatus))
|
||||
{
|
||||
WLog_ERR(TAG, "error 0x%08x when creating childSessionTransport",
|
||||
WINPR_CXX_COMPAT_CAST(unsigned, hStatus));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const BYTE startOfPath[] = { '\\', 0, '\\', 0, '.', 0, '\\', 0 };
|
||||
if (_wcsncmp(pipePath, (const WCHAR*)startOfPath, 4))
|
||||
{
|
||||
/* when compiled under 32 bits, the path may miss "\\.\" at the beginning of the
|
||||
* string so add it if it's not there
|
||||
*/
|
||||
size_t len = _wcslen(pipePath);
|
||||
if (len > 0x80 - (4 + 1))
|
||||
{
|
||||
WLog_ERR(TAG, "pipePath is too long to be adjusted");
|
||||
goto out;
|
||||
}
|
||||
|
||||
memmove(pipePath + 4, pipePath, (len + 1) * sizeof(WCHAR));
|
||||
memcpy(pipePath, startOfPath, 8);
|
||||
}
|
||||
}
|
||||
|
||||
(void)ConvertWCharNToUtf8(pipePath, 0x80, pipePathA, sizeof(pipePathA));
|
||||
WLog_DBG(TAG, "child session is at '%s'", pipePathA);
|
||||
|
||||
{
|
||||
HANDLE f = CreateFileW(pipePath, GENERIC_READ | GENERIC_WRITE, 0, nullptr,
|
||||
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
|
||||
if (f == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WLog_ERR(TAG, "error when connecting to local named pipe");
|
||||
goto out;
|
||||
}
|
||||
|
||||
*pFile = f;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
FreeLibrary(hModule);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIO* createChildSessionBio(void)
|
||||
{
|
||||
HANDLE f = INVALID_HANDLE_VALUE;
|
||||
if (!createChildSessionTransport(&f))
|
||||
return nullptr;
|
||||
|
||||
BIO* lowLevelBio = BIO_new(BIO_s_namedpipe());
|
||||
if (!lowLevelBio)
|
||||
{
|
||||
(void)CloseHandle(f);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BIO_set_handle(lowLevelBio, f);
|
||||
BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
|
||||
|
||||
if (!bufferedBio)
|
||||
{
|
||||
BIO_free_all(lowLevelBio);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bufferedBio = BIO_push(bufferedBio, lowLevelBio);
|
||||
|
||||
return bufferedBio;
|
||||
}
|
||||
31
third_party/FreeRDP/libfreerdp/core/childsession.h
vendored
Normal file
31
third_party/FreeRDP/libfreerdp/core/childsession.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Connecting to windows child session
|
||||
*
|
||||
* Copyright 2023 David Fort <contact@hardening-consulting.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_CHILDSESSION_H
|
||||
#define FREERDP_LIB_CORE_CHILDSESSION_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BIO* createChildSessionBio(void);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_CHILDSESSION_H */
|
||||
1528
third_party/FreeRDP/libfreerdp/core/client.c
vendored
Normal file
1528
third_party/FreeRDP/libfreerdp/core/client.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
138
third_party/FreeRDP/libfreerdp/core/client.h
vendored
Normal file
138
third_party/FreeRDP/libfreerdp/core/client.h
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Client Channels
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_CLIENT_H
|
||||
#define FREERDP_LIB_CORE_CLIENT_H
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/wtsapi.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/constants.h>
|
||||
|
||||
#include <freerdp/svc.h>
|
||||
#include <freerdp/peer.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <freerdp/client/channels.h>
|
||||
#include <freerdp/client/drdynvc.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
|
||||
#ifndef CHANNEL_MAX_COUNT
|
||||
#define CHANNEL_MAX_COUNT 30
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WINPR_ATTR_NODISCARD PVIRTUALCHANNELENTRY entry;
|
||||
WINPR_ATTR_NODISCARD PVIRTUALCHANNELENTRYEX entryEx;
|
||||
PCHANNEL_INIT_EVENT_FN pChannelInitEventProc;
|
||||
PCHANNEL_INIT_EVENT_EX_FN pChannelInitEventProcEx;
|
||||
void* pInitHandle;
|
||||
void* lpUserParam;
|
||||
} CHANNEL_CLIENT_DATA;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[CHANNEL_NAME_LEN + 1];
|
||||
uint32_t OpenHandle;
|
||||
ULONG options;
|
||||
int flags;
|
||||
void* pInterface;
|
||||
rdpChannels* channels;
|
||||
void* lpUserParam;
|
||||
PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc;
|
||||
PCHANNEL_OPEN_EVENT_EX_FN pChannelOpenEventProcEx;
|
||||
} CHANNEL_OPEN_DATA;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* Data;
|
||||
UINT32 DataLength;
|
||||
void* UserData;
|
||||
CHANNEL_OPEN_DATA* pChannelOpenData;
|
||||
} CHANNEL_OPEN_EVENT;
|
||||
|
||||
/**
|
||||
* pInitHandle: handle that identifies the client connection
|
||||
* Obtained by the client with VirtualChannelInit
|
||||
* Used by the client with VirtualChannelOpen
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rdpChannels* channels;
|
||||
void* pInterface;
|
||||
} CHANNEL_INIT_DATA;
|
||||
|
||||
struct rdp_channels
|
||||
{
|
||||
int clientDataCount;
|
||||
CHANNEL_CLIENT_DATA clientDataList[CHANNEL_MAX_COUNT];
|
||||
|
||||
int openDataCount;
|
||||
CHANNEL_OPEN_DATA openDataList[CHANNEL_MAX_COUNT];
|
||||
|
||||
int initDataCount;
|
||||
CHANNEL_INIT_DATA initDataList[CHANNEL_MAX_COUNT];
|
||||
|
||||
/* control for entry into MyVirtualChannelInit */
|
||||
int can_call_init;
|
||||
|
||||
/* true once freerdp_channels_post_connect is called */
|
||||
BOOL connected;
|
||||
|
||||
/* used for locating the channels for a given instance */
|
||||
freerdp* instance;
|
||||
|
||||
wMessageQueue* queue;
|
||||
|
||||
DrdynvcClientContext* drdynvc;
|
||||
CRITICAL_SECTION channelsLock;
|
||||
|
||||
wHashTable* channelEvents;
|
||||
};
|
||||
|
||||
FREERDP_LOCAL void freerdp_channels_free(rdpChannels* channels);
|
||||
|
||||
WINPR_ATTR_MALLOC(freerdp_channels_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpChannels* freerdp_channels_new(freerdp* instance);
|
||||
|
||||
FREERDP_LOCAL UINT freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance);
|
||||
|
||||
FREERDP_LOCAL void freerdp_channels_close(rdpChannels* channels, freerdp* instance);
|
||||
|
||||
FREERDP_LOCAL void freerdp_channels_register_instance(rdpChannels* channels, freerdp* instance);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL UINT freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL UINT freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance);
|
||||
|
||||
/** @since version 3.9.0 */
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL SSIZE_T freerdp_client_channel_get_registered_event_handles(rdpChannels* channels,
|
||||
HANDLE* events,
|
||||
DWORD count);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_CLIENT_H */
|
||||
296
third_party/FreeRDP/libfreerdp/core/codecs.c
vendored
Normal file
296
third_party/FreeRDP/libfreerdp/core/codecs.c
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Codecs
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
#include <freerdp/codecs.h>
|
||||
|
||||
#define TAG FREERDP_TAG("core.codecs")
|
||||
|
||||
static void codecs_free_int(rdpCodecs* codecs, UINT32 flags)
|
||||
{
|
||||
WINPR_ASSERT(codecs);
|
||||
|
||||
if (flags & FREERDP_CODEC_REMOTEFX)
|
||||
{
|
||||
if (codecs->rfx)
|
||||
{
|
||||
rfx_context_free(codecs->rfx);
|
||||
codecs->rfx = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_NSCODEC)
|
||||
{
|
||||
if (codecs->nsc)
|
||||
{
|
||||
nsc_context_free(codecs->nsc);
|
||||
codecs->nsc = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_GFX_H264
|
||||
if (flags & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444))
|
||||
{
|
||||
if (codecs->h264)
|
||||
{
|
||||
h264_context_free(codecs->h264);
|
||||
codecs->h264 = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (flags & FREERDP_CODEC_CLEARCODEC)
|
||||
{
|
||||
if (codecs->clear)
|
||||
{
|
||||
clear_context_free(codecs->clear);
|
||||
codecs->clear = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_PROGRESSIVE)
|
||||
{
|
||||
if (codecs->progressive)
|
||||
{
|
||||
progressive_context_free(codecs->progressive);
|
||||
codecs->progressive = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_PLANAR)
|
||||
{
|
||||
if (codecs->planar)
|
||||
{
|
||||
freerdp_bitmap_planar_context_free(codecs->planar);
|
||||
codecs->planar = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_INTERLEAVED)
|
||||
{
|
||||
if (codecs->interleaved)
|
||||
{
|
||||
bitmap_interleaved_context_free(codecs->interleaved);
|
||||
codecs->interleaved = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOL freerdp_client_codecs_prepare(rdpCodecs* codecs, UINT32 flags, UINT32 width, UINT32 height)
|
||||
{
|
||||
codecs_free_int(codecs, flags);
|
||||
if ((flags & FREERDP_CODEC_INTERLEAVED))
|
||||
{
|
||||
if (!(codecs->interleaved = bitmap_interleaved_context_new(FALSE)))
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to create interleaved codec context");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & FREERDP_CODEC_PLANAR))
|
||||
{
|
||||
if (!(codecs->planar = freerdp_bitmap_planar_context_new(0, 64, 64)))
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to create planar bitmap codec context");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & FREERDP_CODEC_NSCODEC))
|
||||
{
|
||||
if (!(codecs->nsc = nsc_context_new()))
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to create nsc codec context");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & FREERDP_CODEC_REMOTEFX))
|
||||
{
|
||||
if (!(codecs->rfx = rfx_context_new_ex(FALSE, codecs->ThreadingFlags)))
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to create rfx codec context");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & FREERDP_CODEC_CLEARCODEC))
|
||||
{
|
||||
if (!(codecs->clear = clear_context_new(FALSE)))
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to create clear codec context");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_ALPHACODEC)
|
||||
{
|
||||
}
|
||||
|
||||
if ((flags & FREERDP_CODEC_PROGRESSIVE))
|
||||
{
|
||||
if (!(codecs->progressive = progressive_context_new_ex(FALSE, codecs->ThreadingFlags)))
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to create progressive codec context");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_GFX_H264
|
||||
if ((flags & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444)))
|
||||
{
|
||||
if (!(codecs->h264 = h264_context_new(FALSE)))
|
||||
{
|
||||
WLog_WARN(TAG, "Failed to create h264 codec context");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return freerdp_client_codecs_reset(codecs, flags, width, height);
|
||||
}
|
||||
|
||||
BOOL freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags, UINT32 width, UINT32 height)
|
||||
{
|
||||
BOOL rc = TRUE;
|
||||
|
||||
if (flags & FREERDP_CODEC_INTERLEAVED)
|
||||
{
|
||||
if (codecs->interleaved)
|
||||
{
|
||||
rc &= bitmap_interleaved_context_reset(codecs->interleaved);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_PLANAR)
|
||||
{
|
||||
if (codecs->planar)
|
||||
{
|
||||
rc &= freerdp_bitmap_planar_context_reset(codecs->planar, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_NSCODEC)
|
||||
{
|
||||
if (codecs->nsc)
|
||||
{
|
||||
rc &= nsc_context_reset(codecs->nsc, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_REMOTEFX)
|
||||
{
|
||||
if (codecs->rfx)
|
||||
{
|
||||
rc &= rfx_context_reset(codecs->rfx, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_CLEARCODEC)
|
||||
{
|
||||
if (codecs->clear)
|
||||
{
|
||||
rc &= clear_context_reset(codecs->clear);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_ALPHACODEC)
|
||||
{
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_PROGRESSIVE)
|
||||
{
|
||||
if (codecs->progressive)
|
||||
{
|
||||
rc &= progressive_context_reset(codecs->progressive);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_GFX_H264
|
||||
if (flags & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444))
|
||||
{
|
||||
if (codecs->h264)
|
||||
{
|
||||
rc &= h264_context_reset(codecs->h264, width, height);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
rdpCodecs* codecs_new(rdpContext* context)
|
||||
{
|
||||
if (!context || !context->settings)
|
||||
return nullptr;
|
||||
|
||||
const UINT32 flags = freerdp_settings_get_uint32(context->settings, FreeRDP_ThreadingFlags);
|
||||
return freerdp_client_codecs_new(flags);
|
||||
}
|
||||
|
||||
void codecs_free(rdpCodecs* codecs)
|
||||
{
|
||||
freerdp_client_codecs_free(codecs);
|
||||
}
|
||||
#endif
|
||||
|
||||
rdpCodecs* freerdp_client_codecs_new(UINT32 ThreadingFlags)
|
||||
{
|
||||
rdpCodecs* codecs = (rdpCodecs*)calloc(1, sizeof(rdpCodecs));
|
||||
|
||||
if (!codecs)
|
||||
return nullptr;
|
||||
|
||||
codecs->ThreadingFlags = ThreadingFlags;
|
||||
|
||||
return codecs;
|
||||
}
|
||||
|
||||
void freerdp_client_codecs_free(rdpCodecs* codecs)
|
||||
{
|
||||
if (!codecs)
|
||||
return;
|
||||
|
||||
codecs_free_int(codecs, FREERDP_CODEC_ALL);
|
||||
|
||||
free(codecs);
|
||||
}
|
||||
|
||||
const char* freerdp_codec_id_to_str(UINT32 id)
|
||||
{
|
||||
#define ENTRY(x) \
|
||||
case x: \
|
||||
return #x
|
||||
switch (id)
|
||||
{
|
||||
ENTRY(RDP_CODEC_ID_NONE);
|
||||
ENTRY(RDP_CODEC_ID_NSCODEC);
|
||||
ENTRY(RDP_CODEC_ID_JPEG);
|
||||
ENTRY(RDP_CODEC_ID_REMOTEFX);
|
||||
ENTRY(RDP_CODEC_ID_IMAGE_REMOTEFX);
|
||||
default:
|
||||
return "RDP_CODEC_ID_UNKNOWN";
|
||||
}
|
||||
#undef ENTRY
|
||||
}
|
||||
2229
third_party/FreeRDP/libfreerdp/core/connection.c
vendored
Normal file
2229
third_party/FreeRDP/libfreerdp/core/connection.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
133
third_party/FreeRDP/libfreerdp/core/connection.h
vendored
Normal file
133
third_party/FreeRDP/libfreerdp/core/connection.h
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Connection Sequence
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_CONNECTION_H
|
||||
#define FREERDP_LIB_CORE_CONNECTION_H
|
||||
|
||||
#include "rdp.h"
|
||||
#include "tpkt.h"
|
||||
#include "tpdu.h"
|
||||
#include "nego.h"
|
||||
#include "mcs.h"
|
||||
#include "activation.h"
|
||||
#include "state.h"
|
||||
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
enum CLIENT_CONNECTION_STATE
|
||||
{
|
||||
CLIENT_STATE_INITIAL,
|
||||
CLIENT_STATE_PRECONNECT_PASSED,
|
||||
CLIENT_STATE_POSTCONNECT_PASSED
|
||||
};
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_client_connect(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_client_disconnect(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_client_disconnect_and_clear(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_client_reconnect(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_client_redirect(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_client_skip_mcs_channel_join(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s, DWORD logLevel);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t rdp_client_connect_license(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t rdp_client_connect_confirm_active(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t rdp_client_connect_finalize(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_client_transition_to_state(rdpRdp* rdp, CONNECTION_STATE state);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL CONNECTION_STATE rdp_get_state(const rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* rdp_state_string(CONNECTION_STATE state);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_is_active_state(const rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_server_accept_mcs_erect_domain_request(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_server_accept_mcs_attach_user_request(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_server_accept_confirm_active(rdpRdp* rdp, wStream* s, UINT16 pduLength);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_server_reactivate(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_server_transition_to_state(rdpRdp* rdp, CONNECTION_STATE state);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* rdp_get_state_string(const rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* rdp_client_connection_state_string(UINT state);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_channels_from_mcs(rdpSettings* settings, const rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t rdp_handle_message_channel(rdpRdp* rdp, wStream* s, UINT16 channelId,
|
||||
UINT16 length);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_handle_optional_rdp_decryption(rdpRdp* rdp, wStream* s, UINT16* length,
|
||||
UINT16* pSecurityFlags);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_CONNECTION_H */
|
||||
1140
third_party/FreeRDP/libfreerdp/core/credssp_auth.c
vendored
Normal file
1140
third_party/FreeRDP/libfreerdp/core/credssp_auth.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
102
third_party/FreeRDP/libfreerdp/core/credssp_auth.h
vendored
Normal file
102
third_party/FreeRDP/libfreerdp/core/credssp_auth.h
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
*
|
||||
* Copyright 2022 Isaac Klein <fifthdegree@protonmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_CREDSSP_AUTH_H
|
||||
#define FREERDP_LIB_CORE_CREDSSP_AUTH_H
|
||||
|
||||
#define CREDSSP_AUTH_PKG_SPNEGO "Negotiate"
|
||||
#define CREDSSP_AUTH_PKG_NTLM "NTLM"
|
||||
#define CREDSSP_AUTH_PKG_KERBEROS "Kerberos"
|
||||
#define CREDSSP_AUTH_PKG_SCHANNEL "Schannel"
|
||||
|
||||
typedef struct rdp_credssp_auth rdpCredsspAuth;
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/secapi.h>
|
||||
|
||||
FREERDP_LOCAL void credssp_auth_free(rdpCredsspAuth* auth);
|
||||
|
||||
WINPR_ATTR_MALLOC(credssp_auth_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpCredsspAuth* credssp_auth_new(const rdpContext* context);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL credssp_auth_init(rdpCredsspAuth* auth, TCHAR* pkg_name,
|
||||
SecPkgContext_Bindings* bindings);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL credssp_auth_setup_client(rdpCredsspAuth* auth, const char* target_service,
|
||||
const char* target_hostname,
|
||||
const SEC_WINNT_AUTH_IDENTITY* identity,
|
||||
const char* pkinit);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL credssp_auth_setup_server(rdpCredsspAuth* auth);
|
||||
|
||||
FREERDP_LOCAL void credssp_auth_set_flags(rdpCredsspAuth* auth, ULONG flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int credssp_auth_authenticate(rdpCredsspAuth* auth);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL credssp_auth_encrypt(rdpCredsspAuth* auth, const SecBuffer* plaintext,
|
||||
SecBuffer* ciphertext, size_t* signature_length,
|
||||
ULONG sequence);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL credssp_auth_decrypt(rdpCredsspAuth* auth, const SecBuffer* ciphertext,
|
||||
SecBuffer* plaintext, ULONG sequence);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL credssp_auth_impersonate(rdpCredsspAuth* auth);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL credssp_auth_revert_to_self(rdpCredsspAuth* auth);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL credssp_auth_set_spn(rdpCredsspAuth* auth, const char* service,
|
||||
const char* hostname);
|
||||
|
||||
FREERDP_LOCAL void credssp_auth_take_input_buffer(rdpCredsspAuth* auth, SecBuffer* buffer);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const SecBuffer* credssp_auth_get_output_buffer(const rdpCredsspAuth* auth);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL credssp_auth_have_output_token(rdpCredsspAuth* auth);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL credssp_auth_is_complete(const rdpCredsspAuth* auth);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* credssp_auth_pkg_name(const rdpCredsspAuth* auth);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t credssp_auth_trailer_size(const rdpCredsspAuth* auth);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL INT32 credssp_auth_sspi_error(const rdpCredsspAuth* auth);
|
||||
|
||||
FREERDP_LOCAL void credssp_auth_tableAndContext(rdpCredsspAuth* auth,
|
||||
SecurityFunctionTable** ptable,
|
||||
CtxtHandle* pcontext);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_CREDSSP_AUTH_H */
|
||||
91
third_party/FreeRDP/libfreerdp/core/display.c
vendored
Normal file
91
third_party/FreeRDP/libfreerdp/core/display.c
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Display update notifications
|
||||
*
|
||||
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "display.h"
|
||||
|
||||
static BOOL display_write_monitor_layout_pdu(wStream* s, UINT32 monitorCount,
|
||||
const MONITOR_DEF* monitorDefArray)
|
||||
{
|
||||
if (!Stream_EnsureRemainingCapacity(s, 4 + (monitorCount * 20)))
|
||||
return FALSE;
|
||||
|
||||
Stream_Write_UINT32(s, monitorCount); /* monitorCount (4 bytes) */
|
||||
|
||||
for (UINT32 index = 0; index < monitorCount; index++)
|
||||
{
|
||||
const MONITOR_DEF* monitor = &monitorDefArray[index];
|
||||
|
||||
Stream_Write_INT32(s, monitor->left); /* left (4 bytes) */
|
||||
Stream_Write_INT32(s, monitor->top); /* top (4 bytes) */
|
||||
Stream_Write_INT32(s, monitor->right); /* right (4 bytes) */
|
||||
Stream_Write_INT32(s, monitor->bottom); /* bottom (4 bytes) */
|
||||
Stream_Write_UINT32(s, monitor->flags); /* flags (4 bytes) */
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL display_convert_rdp_monitor_to_monitor_def(UINT32 monitorCount,
|
||||
const rdpMonitor* monitorDefArray,
|
||||
MONITOR_DEF** result)
|
||||
{
|
||||
MONITOR_DEF* mdef = nullptr;
|
||||
|
||||
if (!monitorDefArray || !result || (*result))
|
||||
return FALSE;
|
||||
|
||||
mdef = (MONITOR_DEF*)calloc(monitorCount, sizeof(MONITOR_DEF));
|
||||
|
||||
if (!mdef)
|
||||
return FALSE;
|
||||
|
||||
for (UINT32 index = 0; index < monitorCount; index++)
|
||||
{
|
||||
const rdpMonitor* monitor = &monitorDefArray[index];
|
||||
MONITOR_DEF* current = &mdef[index];
|
||||
|
||||
current->left = monitor->x; /* left (4 bytes) */
|
||||
current->top = monitor->y; /* top (4 bytes) */
|
||||
current->right = monitor->x + monitor->width - 1; /* right (4 bytes) */
|
||||
current->bottom = monitor->y + monitor->height - 1; /* bottom (4 bytes) */
|
||||
current->flags = monitor->is_primary ? MONITOR_PRIMARY : 0x0; /* flags (4 bytes) */
|
||||
}
|
||||
|
||||
*result = mdef;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL freerdp_display_send_monitor_layout(rdpContext* context, UINT32 monitorCount,
|
||||
const MONITOR_DEF* monitorDefArray)
|
||||
{
|
||||
rdpRdp* rdp = context->rdp;
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* st = rdp_data_pdu_init(rdp, &sec_flags);
|
||||
|
||||
if (!st)
|
||||
return FALSE;
|
||||
|
||||
if (!display_write_monitor_layout_pdu(st, monitorCount, monitorDefArray))
|
||||
{
|
||||
Stream_Release(st);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return rdp_send_data_pdu(rdp, st, DATA_PDU_TYPE_MONITOR_LAYOUT, 0, sec_flags);
|
||||
}
|
||||
31
third_party/FreeRDP/libfreerdp/core/display.h
vendored
Normal file
31
third_party/FreeRDP/libfreerdp/core/display.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Display update notifications
|
||||
*
|
||||
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_DISPLAY_H
|
||||
#define FREERDP_LIB_CORE_DISPLAY_H
|
||||
|
||||
#include <freerdp/display.h>
|
||||
#include "rdp.h"
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL display_convert_rdp_monitor_to_monitor_def(UINT32 monitorCount,
|
||||
const rdpMonitor* monitorDefArray,
|
||||
MONITOR_DEF** result);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_DISPLAY_H */
|
||||
85
third_party/FreeRDP/libfreerdp/core/errbase.c
vendored
Normal file
85
third_party/FreeRDP/libfreerdp/core/errbase.c
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Error Base
|
||||
*
|
||||
* Copyright 2015 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "errinfo.h"
|
||||
|
||||
#define ERRBASE_DEFINE(_code) \
|
||||
{ \
|
||||
ERRBASE_##_code, "ERRBASE_" #_code, ERRBASE_##_code##_STRING, "" \
|
||||
}
|
||||
|
||||
/* Protocol-independent codes */
|
||||
|
||||
/* Special codes */
|
||||
#define ERRBASE_SUCCESS_STRING "Success."
|
||||
#define ERRBASE_NONE_STRING ""
|
||||
|
||||
static const ERRINFO ERRBASE_CODES[] = { ERRBASE_DEFINE(SUCCESS),
|
||||
|
||||
ERRBASE_DEFINE(NONE) };
|
||||
|
||||
const char* freerdp_get_error_base_string(UINT32 code)
|
||||
{
|
||||
for (size_t x = 0; x < ARRAYSIZE(ERRBASE_CODES); x++)
|
||||
{
|
||||
const ERRINFO* errInfo = &ERRBASE_CODES[x];
|
||||
|
||||
if (code == errInfo->code)
|
||||
{
|
||||
return errInfo->info;
|
||||
}
|
||||
}
|
||||
|
||||
return "ERRBASE_UNKNOWN";
|
||||
}
|
||||
|
||||
const char* freerdp_get_error_base_category(UINT32 code)
|
||||
{
|
||||
for (size_t x = 0; x < ARRAYSIZE(ERRBASE_CODES); x++)
|
||||
{
|
||||
const ERRINFO* errInfo = &ERRBASE_CODES[x];
|
||||
if (code == errInfo->code)
|
||||
{
|
||||
return errInfo->category;
|
||||
}
|
||||
}
|
||||
|
||||
return "ERRBASE_UNKNOWN";
|
||||
}
|
||||
|
||||
const char* freerdp_get_error_base_name(UINT32 code)
|
||||
{
|
||||
for (size_t x = 0; x < ARRAYSIZE(ERRBASE_CODES); x++)
|
||||
{
|
||||
const ERRINFO* errInfo = &ERRBASE_CODES[x];
|
||||
if (code == errInfo->code)
|
||||
{
|
||||
return errInfo->name;
|
||||
}
|
||||
}
|
||||
|
||||
return "ERRBASE_UNKNOWN";
|
||||
}
|
||||
191
third_party/FreeRDP/libfreerdp/core/errconnect.c
vendored
Normal file
191
third_party/FreeRDP/libfreerdp/core/errconnect.c
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Error Connect
|
||||
*
|
||||
* Copyright 2015 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "errinfo.h"
|
||||
|
||||
#define ERRCONNECT_DEFINE(_code, category) \
|
||||
{ \
|
||||
ERRCONNECT_##_code, "ERRCONNECT_" #_code, ERRCONNECT_##_code##_STRING, category \
|
||||
}
|
||||
|
||||
/* Protocol-independent codes */
|
||||
|
||||
#define ERRCONNECT_PRE_CONNECT_FAILED_STRING \
|
||||
"A configuration error prevented a connection to be established."
|
||||
|
||||
#define ERRCONNECT_CONNECT_UNDEFINED_STRING "A undefined connection error occurred."
|
||||
|
||||
#define ERRCONNECT_POST_CONNECT_FAILED_STRING \
|
||||
"The connection attempt was aborted due to post connect configuration errors."
|
||||
|
||||
#define ERRCONNECT_DNS_ERROR_STRING "The DNS entry could not be resolved."
|
||||
|
||||
#define ERRCONNECT_DNS_NAME_NOT_FOUND_STRING "The DNS host name was not found."
|
||||
|
||||
#define ERRCONNECT_CONNECT_FAILED_STRING "The connection failed."
|
||||
|
||||
#define ERRCONNECT_MCS_CONNECT_INITIAL_ERROR_STRING "The connection failed at initial MCS connect"
|
||||
|
||||
#define ERRCONNECT_TLS_CONNECT_FAILED_STRING "The connection failed at TLS connect."
|
||||
|
||||
#define ERRCONNECT_AUTHENTICATION_FAILED_STRING "An authentication failure aborted the connection."
|
||||
|
||||
#define ERRCONNECT_INSUFFICIENT_PRIVILEGES_STRING \
|
||||
"Insufficient privileges to establish a connection."
|
||||
|
||||
#define ERRCONNECT_CONNECT_CANCELLED_STRING "The connection was cancelled."
|
||||
|
||||
#define ERRCONNECT_SECURITY_NEGO_CONNECT_FAILED_STRING \
|
||||
"The connection failed at negotiating security settings."
|
||||
|
||||
#define ERRCONNECT_CONNECT_TRANSPORT_FAILED_STRING "The connection transport layer failed."
|
||||
|
||||
#define ERRCONNECT_PASSWORD_EXPIRED_STRING "The password has expired and must be changed."
|
||||
|
||||
#define ERRCONNECT_PASSWORD_CERTAINLY_EXPIRED_STRING \
|
||||
"The password has certainly expired and must be changed."
|
||||
|
||||
#define ERRCONNECT_CLIENT_REVOKED_STRING "The client has been revoked."
|
||||
|
||||
#define ERRCONNECT_KDC_UNREACHABLE_STRING "The KDC is unreachable."
|
||||
|
||||
#define ERRCONNECT_ACCOUNT_DISABLED_STRING "The account is disabled."
|
||||
|
||||
#define ERRCONNECT_PASSWORD_MUST_CHANGE_STRING "The password must be changed."
|
||||
|
||||
#define ERRCONNECT_LOGON_FAILURE_STRING "Logon failed."
|
||||
|
||||
#define ERRCONNECT_WRONG_PASSWORD_STRING "Wrong password supplied."
|
||||
|
||||
#define ERRCONNECT_ACCESS_DENIED_STRING "Access denied."
|
||||
|
||||
#define ERRCONNECT_ACCOUNT_RESTRICTION_STRING "Account restriction."
|
||||
|
||||
#define ERRCONNECT_ACCOUNT_LOCKED_OUT_STRING "Account locked out."
|
||||
|
||||
#define ERRCONNECT_ACCOUNT_EXPIRED_STRING "Account expired."
|
||||
|
||||
#define ERRCONNECT_LOGON_TYPE_NOT_GRANTED_STRING "Logon type not granted."
|
||||
|
||||
#define ERRCONNECT_NO_OR_MISSING_CREDENTIALS_STRING "Credentials invalid or missing."
|
||||
|
||||
#define ERRCONNECT_ACTIVATION_TIMEOUT_STRING "Timeout waiting for activation."
|
||||
|
||||
#define ERRCONNECT_TARGET_BOOTING_STRING "Starting your VM. It may take up to 5 minutes."
|
||||
|
||||
/* Special codes */
|
||||
#define ERRCONNECT_SUCCESS_STRING "Success."
|
||||
#define ERRCONNECT_NONE_STRING ""
|
||||
|
||||
static const ERRINFO ERRCONNECT_CODES[] = {
|
||||
ERRCONNECT_DEFINE(SUCCESS, CAT_NONE),
|
||||
|
||||
ERRCONNECT_DEFINE(PRE_CONNECT_FAILED, CAT_CONFIG),
|
||||
ERRCONNECT_DEFINE(CONNECT_UNDEFINED, CAT_USE),
|
||||
ERRCONNECT_DEFINE(POST_CONNECT_FAILED, CAT_CONFIG),
|
||||
ERRCONNECT_DEFINE(DNS_ERROR, CAT_USE),
|
||||
ERRCONNECT_DEFINE(DNS_NAME_NOT_FOUND, CAT_CONFIG),
|
||||
ERRCONNECT_DEFINE(CONNECT_FAILED, CAT_USE),
|
||||
ERRCONNECT_DEFINE(MCS_CONNECT_INITIAL_ERROR, CAT_PROTOCOL),
|
||||
ERRCONNECT_DEFINE(TLS_CONNECT_FAILED, CAT_USE),
|
||||
ERRCONNECT_DEFINE(AUTHENTICATION_FAILED, CAT_USE),
|
||||
ERRCONNECT_DEFINE(INSUFFICIENT_PRIVILEGES, CAT_ADMIN),
|
||||
ERRCONNECT_DEFINE(CONNECT_CANCELLED, CAT_USE),
|
||||
ERRCONNECT_DEFINE(SECURITY_NEGO_CONNECT_FAILED, CAT_USE),
|
||||
ERRCONNECT_DEFINE(CONNECT_TRANSPORT_FAILED, CAT_USE),
|
||||
ERRCONNECT_DEFINE(PASSWORD_EXPIRED, CAT_ADMIN),
|
||||
ERRCONNECT_DEFINE(PASSWORD_CERTAINLY_EXPIRED, CAT_ADMIN),
|
||||
ERRCONNECT_DEFINE(CLIENT_REVOKED, CAT_ADMIN),
|
||||
ERRCONNECT_DEFINE(KDC_UNREACHABLE, CAT_ADMIN),
|
||||
ERRCONNECT_DEFINE(ACCOUNT_DISABLED, CAT_ADMIN),
|
||||
ERRCONNECT_DEFINE(PASSWORD_MUST_CHANGE, CAT_ADMIN),
|
||||
ERRCONNECT_DEFINE(LOGON_FAILURE, CAT_USE),
|
||||
ERRCONNECT_DEFINE(WRONG_PASSWORD, CAT_USE),
|
||||
ERRCONNECT_DEFINE(ACCESS_DENIED, CAT_ADMIN),
|
||||
ERRCONNECT_DEFINE(ACCOUNT_RESTRICTION, CAT_ADMIN),
|
||||
ERRCONNECT_DEFINE(ACCOUNT_LOCKED_OUT, CAT_ADMIN),
|
||||
ERRCONNECT_DEFINE(ACCOUNT_EXPIRED, CAT_ADMIN),
|
||||
ERRCONNECT_DEFINE(LOGON_TYPE_NOT_GRANTED, CAT_ADMIN),
|
||||
ERRCONNECT_DEFINE(NO_OR_MISSING_CREDENTIALS, CAT_USE),
|
||||
ERRCONNECT_DEFINE(ACTIVATION_TIMEOUT, CAT_PROTOCOL),
|
||||
ERRCONNECT_DEFINE(TARGET_BOOTING, CAT_ADMIN),
|
||||
|
||||
ERRCONNECT_DEFINE(NONE, CAT_NONE)
|
||||
};
|
||||
|
||||
const char* freerdp_get_error_connect_string(UINT32 code)
|
||||
{
|
||||
const ERRINFO* errInfo = nullptr;
|
||||
errInfo = &ERRCONNECT_CODES[0];
|
||||
|
||||
while (errInfo->code != ERRCONNECT_NONE)
|
||||
{
|
||||
if (code == errInfo->code)
|
||||
{
|
||||
return errInfo->info;
|
||||
}
|
||||
|
||||
errInfo++;
|
||||
}
|
||||
|
||||
return "ERRCONNECT_UNKNOWN";
|
||||
}
|
||||
|
||||
const char* freerdp_get_error_connect_category(UINT32 code)
|
||||
{
|
||||
const ERRINFO* errInfo = nullptr;
|
||||
errInfo = &ERRCONNECT_CODES[0];
|
||||
|
||||
while (errInfo->code != ERRCONNECT_NONE)
|
||||
{
|
||||
if (code == errInfo->code)
|
||||
{
|
||||
return errInfo->category;
|
||||
}
|
||||
|
||||
errInfo++;
|
||||
}
|
||||
|
||||
return "ERRCONNECT_UNKNOWN";
|
||||
}
|
||||
|
||||
const char* freerdp_get_error_connect_name(UINT32 code)
|
||||
{
|
||||
const ERRINFO* errInfo = nullptr;
|
||||
errInfo = &ERRCONNECT_CODES[0];
|
||||
|
||||
while (errInfo->code != ERRCONNECT_NONE)
|
||||
{
|
||||
if (code == errInfo->code)
|
||||
{
|
||||
return errInfo->name;
|
||||
}
|
||||
|
||||
errInfo++;
|
||||
}
|
||||
|
||||
return "ERRCONNECT_UNKNOWN";
|
||||
}
|
||||
698
third_party/FreeRDP/libfreerdp/core/errinfo.c
vendored
Normal file
698
third_party/FreeRDP/libfreerdp/core/errinfo.c
vendored
Normal file
@@ -0,0 +1,698 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Error Info
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "errinfo.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core")
|
||||
|
||||
#define ERRINFO_DEFINE(_code, category) \
|
||||
{ \
|
||||
ERRINFO_##_code, "ERRINFO_" #_code, ERRINFO_##_code##_STRING, category \
|
||||
}
|
||||
|
||||
/* Protocol-independent codes */
|
||||
|
||||
#define ERRINFO_RPC_INITIATED_DISCONNECT_STRING \
|
||||
"The disconnection was initiated by an administrative tool on the server in another session."
|
||||
|
||||
#define ERRINFO_RPC_INITIATED_LOGOFF_STRING \
|
||||
"The disconnection was due to a forced logoff initiated by an administrative tool on the " \
|
||||
"server in another session."
|
||||
|
||||
#define ERRINFO_IDLE_TIMEOUT_STRING "The idle session limit timer on the server has elapsed."
|
||||
|
||||
#define ERRINFO_LOGON_TIMEOUT_STRING "The active session limit timer on the server has elapsed."
|
||||
|
||||
#define ERRINFO_DISCONNECTED_BY_OTHER_CONNECTION_STRING \
|
||||
"Another user connected to the server, forcing the disconnection of the current connection."
|
||||
|
||||
#define ERRINFO_OUT_OF_MEMORY_STRING "The server ran out of available memory resources."
|
||||
|
||||
#define ERRINFO_SERVER_DENIED_CONNECTION_STRING "The server denied the connection."
|
||||
|
||||
#define ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES_STRING \
|
||||
"The user cannot connect to the server due to insufficient access privileges."
|
||||
|
||||
#define ERRINFO_SERVER_FRESH_CREDENTIALS_REQUIRED_STRING \
|
||||
"The server does not accept saved user credentials and requires that the user enter their " \
|
||||
"credentials for each connection."
|
||||
|
||||
#define ERRINFO_RPC_INITIATED_DISCONNECT_BY_USER_STRING \
|
||||
"The disconnection was initiated by an administrative tool on the server running in the " \
|
||||
"user's session."
|
||||
|
||||
#define ERRINFO_LOGOFF_BY_USER_STRING \
|
||||
"The disconnection was initiated by the user logging off their session on the server."
|
||||
|
||||
#define ERRINFO_CLOSE_STACK_ON_DRIVER_NOT_READY_STRING \
|
||||
"The display driver in the remote session did not report any status within the time allotted " \
|
||||
"for startup."
|
||||
|
||||
#define ERRINFO_SERVER_DWM_CRASH_STRING \
|
||||
"The DWM process running in the remote session terminated unexpectedly."
|
||||
|
||||
#define ERRINFO_CLOSE_STACK_ON_DRIVER_FAILURE_STRING \
|
||||
"The display driver in the remote session was unable to complete all the tasks required for " \
|
||||
"startup."
|
||||
|
||||
#define ERRINFO_CLOSE_STACK_ON_DRIVER_IFACE_FAILURE_STRING \
|
||||
"The display driver in the remote session started up successfully, but due to internal " \
|
||||
"failures was not usable by the remoting stack."
|
||||
|
||||
#define ERRINFO_SERVER_WINLOGON_CRASH_STRING \
|
||||
"The Winlogon process running in the remote session terminated unexpectedly."
|
||||
|
||||
#define ERRINFO_SERVER_CSRSS_CRASH_STRING \
|
||||
"The CSRSS process running in the remote session terminated unexpectedly."
|
||||
|
||||
/* Protocol-independent codes generated by the Connection Broker */
|
||||
|
||||
#define ERRINFO_CB_DESTINATION_NOT_FOUND_STRING "The target endpoint could not be found."
|
||||
|
||||
#define ERRINFO_CB_LOADING_DESTINATION_STRING \
|
||||
"The target endpoint to which the client is being redirected is disconnecting from the " \
|
||||
"Connection Broker."
|
||||
|
||||
#define ERRINFO_CB_REDIRECTING_TO_DESTINATION_STRING \
|
||||
"An error occurred while the connection was being redirected to the target endpoint."
|
||||
|
||||
#define ERRINFO_CB_SESSION_ONLINE_VM_WAKE_STRING \
|
||||
"An error occurred while the target endpoint (a virtual machine) was being awakened."
|
||||
|
||||
#define ERRINFO_CB_SESSION_ONLINE_VM_BOOT_STRING \
|
||||
"An error occurred while the target endpoint (a virtual machine) was being started."
|
||||
|
||||
#define ERRINFO_CB_SESSION_ONLINE_VM_NO_DNS_STRING \
|
||||
"The IP address of the target endpoint (a virtual machine) cannot be determined."
|
||||
|
||||
#define ERRINFO_CB_DESTINATION_POOL_NOT_FREE_STRING \
|
||||
"There are no available endpoints in the pool managed by the Connection Broker."
|
||||
|
||||
#define ERRINFO_CB_CONNECTION_CANCELLED_STRING "Processing of the connection has been cancelled."
|
||||
|
||||
#define ERRINFO_CB_CONNECTION_ERROR_INVALID_SETTINGS_STRING \
|
||||
"The settings contained in the routingToken field of the X.224 Connection Request PDU " \
|
||||
"(section 2.2.1.1) cannot be validated."
|
||||
|
||||
#define ERRINFO_CB_SESSION_ONLINE_VM_BOOT_TIMEOUT_STRING \
|
||||
"A time-out occurred while the target endpoint (a virtual machine) was being started."
|
||||
|
||||
#define ERRINFO_CB_SESSION_ONLINE_VM_SESSMON_FAILED_STRING \
|
||||
"A session monitoring error occurred while the target endpoint (a virtual machine) was being " \
|
||||
"started."
|
||||
|
||||
/* Protocol-independent licensing codes */
|
||||
|
||||
#define ERRINFO_LICENSE_INTERNAL_STRING \
|
||||
"An internal error has occurred in the Terminal Services licensing component."
|
||||
|
||||
#define ERRINFO_LICENSE_NO_LICENSE_SERVER_STRING \
|
||||
"A Remote Desktop License Server ([MS-RDPELE] section 1.1) could not be found to provide a " \
|
||||
"license."
|
||||
|
||||
#define ERRINFO_LICENSE_NO_LICENSE_STRING \
|
||||
"There are no Client Access Licenses ([MS-RDPELE] section 1.1) available for the target " \
|
||||
"remote computer."
|
||||
|
||||
#define ERRINFO_LICENSE_BAD_CLIENT_MSG_STRING \
|
||||
"The remote computer received an invalid licensing message from the client."
|
||||
|
||||
#define ERRINFO_LICENSE_HWID_DOESNT_MATCH_LICENSE_STRING \
|
||||
"The Client Access License ([MS-RDPELE] section 1.1) stored by the client has been modified."
|
||||
|
||||
#define ERRINFO_LICENSE_BAD_CLIENT_LICENSE_STRING \
|
||||
"The Client Access License ([MS-RDPELE] section 1.1) stored by the client is in an invalid " \
|
||||
"format."
|
||||
|
||||
#define ERRINFO_LICENSE_CANT_FINISH_PROTOCOL_STRING \
|
||||
"Network problems have caused the licensing protocol ([MS-RDPELE] section 1.3.3) to be " \
|
||||
"terminated."
|
||||
|
||||
#define ERRINFO_LICENSE_CLIENT_ENDED_PROTOCOL_STRING \
|
||||
"The client prematurely ended the licensing protocol ([MS-RDPELE] section 1.3.3)."
|
||||
|
||||
#define ERRINFO_LICENSE_BAD_CLIENT_ENCRYPTION_STRING \
|
||||
"A licensing message ([MS-RDPELE] sections 2.2 and 5.1) was incorrectly encrypted."
|
||||
|
||||
#define ERRINFO_LICENSE_CANT_UPGRADE_LICENSE_STRING \
|
||||
"The Client Access License ([MS-RDPELE] section 1.1) stored by the client could not be " \
|
||||
"upgraded or renewed."
|
||||
|
||||
#define ERRINFO_LICENSE_NO_REMOTE_CONNECTIONS_STRING \
|
||||
"The remote computer is not licensed to accept remote connections."
|
||||
|
||||
/* RDP specific codes */
|
||||
|
||||
#define ERRINFO_UNKNOWN_DATA_PDU_TYPE_STRING \
|
||||
"Unknown pduType2 field in a received Share Data Header (section 2.2.8.1.1.1.2)."
|
||||
|
||||
#define ERRINFO_UNKNOWN_PDU_TYPE_STRING \
|
||||
"Unknown pduType field in a received Share Control Header (section 2.2.8.1.1.1.1)."
|
||||
|
||||
#define ERRINFO_DATA_PDU_SEQUENCE_STRING \
|
||||
"An out-of-sequence Slow-Path Data PDU (section 2.2.8.1.1.1.1) has been received."
|
||||
|
||||
#define ERRINFO_CONTROL_PDU_SEQUENCE_STRING \
|
||||
"An out-of-sequence Slow-Path Non-Data PDU (section 2.2.8.1.1.1.1) has been received."
|
||||
|
||||
#define ERRINFO_INVALID_CONTROL_PDU_ACTION_STRING \
|
||||
"A Control PDU (sections 2.2.1.15 and 2.2.1.16) has been received with an invalid action " \
|
||||
"field."
|
||||
|
||||
#define ERRINFO_INVALID_INPUT_PDU_TYPE_STRING \
|
||||
"(a) A Slow-Path Input Event (section 2.2.8.1.1.3.1.1) has been received with an invalid " \
|
||||
"messageType field.\n" \
|
||||
"(b) A Fast-Path Input Event (section 2.2.8.1.2.2) has been received with an invalid " \
|
||||
"eventCode field."
|
||||
|
||||
#define ERRINFO_INVALID_INPUT_PDU_MOUSE_STRING \
|
||||
"(a) A Slow-Path Mouse Event (section 2.2.8.1.1.3.1.1.3) or Extended Mouse Event " \
|
||||
"(section 2.2.8.1.1.3.1.1.4) has been received with an invalid pointerFlags field.\n" \
|
||||
"(b) A Fast-Path Mouse Event (section 2.2.8.1.2.2.3) or Fast-Path Extended Mouse Event " \
|
||||
"(section 2.2.8.1.2.2.4) has been received with an invalid pointerFlags field."
|
||||
|
||||
#define ERRINFO_INVALID_REFRESH_RECT_PDU_STRING \
|
||||
"An invalid Refresh Rect PDU (section 2.2.11.2) has been received."
|
||||
|
||||
#define ERRINFO_CREATE_USER_DATA_FAILED_STRING \
|
||||
"The server failed to construct the GCC Conference Create Response user data (section " \
|
||||
"2.2.1.4)."
|
||||
|
||||
#define ERRINFO_CONNECT_FAILED_STRING \
|
||||
"Processing during the Channel Connection phase of the RDP Connection Sequence " \
|
||||
"(see section 1.3.1.1 for an overview of the RDP Connection Sequence phases) has failed."
|
||||
|
||||
#define ERRINFO_CONFIRM_ACTIVE_HAS_WRONG_SHAREID_STRING \
|
||||
"A Confirm Active PDU (section 2.2.1.13.2) was received from the client with an invalid " \
|
||||
"shareId field."
|
||||
|
||||
#define ERRINFO_CONFIRM_ACTIVE_HAS_WRONG_ORIGINATOR_STRING \
|
||||
"A Confirm Active PDU (section 2.2.1.13.2) was received from the client with an invalid " \
|
||||
"originatorId field."
|
||||
|
||||
#define ERRINFO_PERSISTENT_KEY_PDU_BAD_LENGTH_STRING \
|
||||
"There is not enough data to process a Persistent Key List PDU (section 2.2.1.17)."
|
||||
|
||||
#define ERRINFO_PERSISTENT_KEY_PDU_ILLEGAL_FIRST_STRING \
|
||||
"A Persistent Key List PDU (section 2.2.1.17) marked as PERSIST_PDU_FIRST (0x01) was " \
|
||||
"received after the reception " \
|
||||
"of a prior Persistent Key List PDU also marked as PERSIST_PDU_FIRST."
|
||||
|
||||
#define ERRINFO_PERSISTENT_KEY_PDU_TOO_MANY_TOTAL_KEYS_STRING \
|
||||
"A Persistent Key List PDU (section 2.2.1.17) was received which specified a total number of " \
|
||||
"bitmap cache entries larger than 262144."
|
||||
|
||||
#define ERRINFO_PERSISTENT_KEY_PDU_TOO_MANY_CACHE_KEYS_STRING \
|
||||
"A Persistent Key List PDU (section 2.2.1.17) was received which specified an invalid total " \
|
||||
"number of keys for a bitmap cache " \
|
||||
"(the number of entries that can be stored within each bitmap cache is specified in the " \
|
||||
"Revision 1 or 2 Bitmap Cache Capability Set " \
|
||||
"(section 2.2.7.1.4) that is sent from client to server)."
|
||||
|
||||
#define ERRINFO_INPUT_PDU_BAD_LENGTH_STRING \
|
||||
"There is not enough data to process Input Event PDU Data (section 2.2.8.1.1.3.1) or a " \
|
||||
"Fast-Path Input Event PDU (section 2.2.8.1.2)."
|
||||
|
||||
#define ERRINFO_BITMAP_CACHE_ERROR_PDU_BAD_LENGTH_STRING \
|
||||
"There is not enough data to process the shareDataHeader, NumInfoBlocks, " \
|
||||
"Pad1, and Pad2 fields of the Bitmap Cache Error PDU Data ([MS-RDPEGDI] section 2.2.2.3.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT_STRING \
|
||||
"(a) The dataSignature field of the Fast-Path Input Event PDU (section 2.2.8.1.2) does not " \
|
||||
"contain enough data.\n" \
|
||||
"(b) The fipsInformation and dataSignature fields of the Fast-Path Input Event PDU (section " \
|
||||
"2.2.8.1.2) do not contain enough data."
|
||||
|
||||
#define ERRINFO_VCHANNEL_DATA_TOO_SHORT_STRING \
|
||||
"(a) There is not enough data in the Client Network Data (section 2.2.1.3.4) to read the " \
|
||||
"virtual channel configuration data.\n" \
|
||||
"(b) There is not enough data to read a complete Channel PDU Header (section 2.2.6.1.1)."
|
||||
|
||||
#define ERRINFO_SHARE_DATA_TOO_SHORT_STRING \
|
||||
"(a) There is not enough data to process Control PDU Data (section 2.2.1.15.1).\n" \
|
||||
"(b) There is not enough data to read a complete Share Control Header (section " \
|
||||
"2.2.8.1.1.1.1).\n" \
|
||||
"(c) There is not enough data to read a complete Share Data Header (section 2.2.8.1.1.1.2) " \
|
||||
"of a Slow-Path Data PDU (section 2.2.8.1.1.1.1).\n" \
|
||||
"(d) There is not enough data to process Font List PDU Data (section 2.2.1.18.1)."
|
||||
|
||||
#define ERRINFO_BAD_SUPPRESS_OUTPUT_PDU_STRING \
|
||||
"(a) There is not enough data to process Suppress Output PDU Data (section 2.2.11.3.1).\n" \
|
||||
"(b) The allowDisplayUpdates field of the Suppress Output PDU Data (section 2.2.11.3.1) is " \
|
||||
"invalid."
|
||||
|
||||
#define ERRINFO_CONFIRM_ACTIVE_PDU_TOO_SHORT_STRING \
|
||||
"(a) There is not enough data to read the shareControlHeader, shareId, originatorId, " \
|
||||
"lengthSourceDescriptor, " \
|
||||
"and lengthCombinedCapabilities fields of the Confirm Active PDU Data (section " \
|
||||
"2.2.1.13.2.1).\n" \
|
||||
"(b) There is not enough data to read the sourceDescriptor, numberCapabilities, pad2Octets, " \
|
||||
"and capabilitySets " \
|
||||
"fields of the Confirm Active PDU Data (section 2.2.1.13.2.1)."
|
||||
|
||||
#define ERRINFO_CAPABILITY_SET_TOO_SMALL_STRING \
|
||||
"There is not enough data to read the capabilitySetType and the lengthCapability fields in a " \
|
||||
"received Capability Set (section 2.2.1.13.1.1.1)."
|
||||
|
||||
#define ERRINFO_CAPABILITY_SET_TOO_LARGE_STRING \
|
||||
"A Capability Set (section 2.2.1.13.1.1.1) has been received with a lengthCapability " \
|
||||
"field that contains a value greater than the total length of the data received."
|
||||
|
||||
#define ERRINFO_NO_CURSOR_CACHE_STRING \
|
||||
"(a) Both the colorPointerCacheSize and pointerCacheSize fields in the Pointer Capability " \
|
||||
"Set (section 2.2.7.1.5) are set to zero.\n" \
|
||||
"(b) The pointerCacheSize field in the Pointer Capability Set (section 2.2.7.1.5) is not " \
|
||||
"present, and the colorPointerCacheSize field is set to zero."
|
||||
|
||||
#define ERRINFO_BAD_CAPABILITIES_STRING \
|
||||
"The capabilities received from the client in the Confirm Active PDU (section 2.2.1.13.2) " \
|
||||
"were not accepted by the server."
|
||||
|
||||
#define ERRINFO_VIRTUAL_CHANNEL_DECOMPRESSION_STRING \
|
||||
"An error occurred while using the bulk compressor (section 3.1.8 and [MS-RDPEGDI] section " \
|
||||
"3.1.8) to decompress a Virtual Channel PDU (section 2.2.6.1)"
|
||||
|
||||
#define ERRINFO_INVALID_VC_COMPRESSION_TYPE_STRING \
|
||||
"An invalid bulk compression package was specified in the flags field of the Channel PDU " \
|
||||
"Header (section 2.2.6.1.1)."
|
||||
|
||||
#define ERRINFO_INVALID_CHANNEL_ID_STRING \
|
||||
"An invalid MCS channel ID was specified in the mcsPdu field of the Virtual Channel PDU " \
|
||||
"(section 2.2.6.1)."
|
||||
|
||||
#define ERRINFO_VCHANNELS_TOO_MANY_STRING \
|
||||
"The client requested more than the maximum allowed 31 static virtual channels in the Client " \
|
||||
"Network Data (section 2.2.1.3.4)."
|
||||
|
||||
#define ERRINFO_REMOTEAPP_NOT_ENABLED_STRING \
|
||||
"The INFO_RAIL flag (0x00008000) MUST be set in the flags field of the Info Packet (section " \
|
||||
"2.2.1.11.1.1) " \
|
||||
"as the session on the remote server can only host remote applications."
|
||||
|
||||
#define ERRINFO_CACHE_CAP_NOT_SET_STRING \
|
||||
"The client sent a Persistent Key List PDU (section 2.2.1.17) without including the " \
|
||||
"prerequisite Revision 2 Bitmap Cache " \
|
||||
"Capability Set (section 2.2.7.1.4.2) in the Confirm Active PDU (section 2.2.1.13.2)."
|
||||
|
||||
#define ERRINFO_BITMAP_CACHE_ERROR_PDU_BAD_LENGTH2_STRING \
|
||||
"The NumInfoBlocks field in the Bitmap Cache Error PDU Data is inconsistent with the amount " \
|
||||
"of data in the " \
|
||||
"Info field ([MS-RDPEGDI] section 2.2.2.3.1.1)."
|
||||
|
||||
#define ERRINFO_OFFSCREEN_CACHE_ERROR_PDU_BAD_LENGTH_STRING \
|
||||
"There is not enough data to process an Offscreen Bitmap Cache Error PDU ([MS-RDPEGDI] " \
|
||||
"section 2.2.2.3.2)."
|
||||
|
||||
#define ERRINFO_DRAWNINEGRID_CACHE_ERROR_PDU_BAD_LENGTH_STRING \
|
||||
"There is not enough data to process a DrawNineGrid Cache Error PDU ([MS-RDPEGDI] section " \
|
||||
"2.2.2.3.3)."
|
||||
|
||||
#define ERRINFO_GDIPLUS_PDU_BAD_LENGTH_STRING \
|
||||
"There is not enough data to process a GDI+ Error PDU ([MS-RDPEGDI] section 2.2.2.3.4)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT2_STRING \
|
||||
"There is not enough data to read a Basic Security Header (section 2.2.8.1.1.2.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT3_STRING \
|
||||
"There is not enough data to read a Non-FIPS Security Header (section 2.2.8.1.1.2.2) or FIPS " \
|
||||
"Security Header (section 2.2.8.1.1.2.3)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT4_STRING \
|
||||
"There is not enough data to read the basicSecurityHeader and length fields of the Security " \
|
||||
"Exchange PDU Data (section 2.2.1.10.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT5_STRING \
|
||||
"There is not enough data to read the CodePage, flags, cbDomain, cbUserName, cbPassword, " \
|
||||
"cbAlternateShell, " \
|
||||
"cbWorkingDir, Domain, UserName, Password, AlternateShell, and WorkingDir fields in the Info " \
|
||||
"Packet (section 2.2.1.11.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT6_STRING \
|
||||
"There is not enough data to read the CodePage, flags, cbDomain, cbUserName, cbPassword, " \
|
||||
"cbAlternateShell, " \
|
||||
"and cbWorkingDir fields in the Info Packet (section 2.2.1.11.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT7_STRING \
|
||||
"There is not enough data to read the clientAddressFamily and cbClientAddress fields in the " \
|
||||
"Extended Info Packet (section 2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT8_STRING \
|
||||
"There is not enough data to read the clientAddress field in the Extended Info Packet " \
|
||||
"(section 2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT9_STRING \
|
||||
"There is not enough data to read the cbClientDir field in the Extended Info Packet (section " \
|
||||
"2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT10_STRING \
|
||||
"There is not enough data to read the clientDir field in the Extended Info Packet (section " \
|
||||
"2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT11_STRING \
|
||||
"There is not enough data to read the clientTimeZone field in the Extended Info Packet " \
|
||||
"(section 2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT12_STRING \
|
||||
"There is not enough data to read the clientSessionId field in the Extended Info Packet " \
|
||||
"(section 2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT13_STRING \
|
||||
"There is not enough data to read the performanceFlags field in the Extended Info Packet " \
|
||||
"(section 2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT14_STRING \
|
||||
"There is not enough data to read the cbAutoReconnectLen field in the Extended Info Packet " \
|
||||
"(section 2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT15_STRING \
|
||||
"There is not enough data to read the autoReconnectCookie field in the Extended Info Packet " \
|
||||
"(section 2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT16_STRING \
|
||||
"The cbAutoReconnectLen field in the Extended Info Packet (section 2.2.1.11.1.1.1) contains " \
|
||||
"a value " \
|
||||
"which is larger than the maximum allowed length of 128 bytes."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT17_STRING \
|
||||
"There is not enough data to read the clientAddressFamily and cbClientAddress fields in the " \
|
||||
"Extended Info Packet (section 2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT18_STRING \
|
||||
"There is not enough data to read the clientAddress field in the Extended Info Packet " \
|
||||
"(section 2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT19_STRING \
|
||||
"There is not enough data to read the cbClientDir field in the Extended Info Packet (section " \
|
||||
"2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT20_STRING \
|
||||
"There is not enough data to read the clientDir field in the Extended Info Packet (section " \
|
||||
"2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT21_STRING \
|
||||
"There is not enough data to read the clientTimeZone field in the Extended Info Packet " \
|
||||
"(section 2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT22_STRING \
|
||||
"There is not enough data to read the clientSessionId field in the Extended Info Packet " \
|
||||
"(section 2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_SECURITY_DATA_TOO_SHORT23_STRING \
|
||||
"There is not enough data to read the Client Info PDU Data (section 2.2.1.11.1)."
|
||||
|
||||
#define ERRINFO_BAD_MONITOR_DATA_STRING \
|
||||
"The monitorCount field in the Client Monitor Data (section 2.2.1.3.6) is invalid."
|
||||
|
||||
#define ERRINFO_VC_DECOMPRESSED_REASSEMBLE_FAILED_STRING \
|
||||
"The server-side decompression buffer is invalid, or the size of the decompressed VC data " \
|
||||
"exceeds " \
|
||||
"the chunking size specified in the Virtual Channel Capability Set (section 2.2.7.1.10)."
|
||||
|
||||
#define ERRINFO_VC_DATA_TOO_LONG_STRING \
|
||||
"The size of a received Virtual Channel PDU (section 2.2.6.1) exceeds the chunking size " \
|
||||
"specified " \
|
||||
"in the Virtual Channel Capability Set (section 2.2.7.1.10)."
|
||||
|
||||
#define ERRINFO_BAD_FRAME_ACK_DATA_STRING \
|
||||
"There is not enough data to read a TS_FRAME_ACKNOWLEDGE_PDU ([MS-RDPRFX] section 2.2.3.1)."
|
||||
|
||||
#define ERRINFO_GRAPHICS_MODE_NOT_SUPPORTED_STRING \
|
||||
"The graphics mode requested by the client is not supported by the server."
|
||||
|
||||
#define ERRINFO_GRAPHICS_SUBSYSTEM_RESET_FAILED_STRING \
|
||||
"The server-side graphics subsystem failed to reset."
|
||||
|
||||
#define ERRINFO_GRAPHICS_SUBSYSTEM_FAILED_STRING \
|
||||
"The server-side graphics subsystem is in an error state and unable to continue graphics " \
|
||||
"encoding."
|
||||
|
||||
#define ERRINFO_TIMEZONE_KEY_NAME_LENGTH_TOO_SHORT_STRING \
|
||||
"There is not enough data to read the cbDynamicDSTTimeZoneKeyName field in the Extended Info " \
|
||||
"Packet (section 2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_TIMEZONE_KEY_NAME_LENGTH_TOO_LONG_STRING \
|
||||
"The length reported in the cbDynamicDSTTimeZoneKeyName field of the Extended Info Packet " \
|
||||
"(section 2.2.1.11.1.1.1) is too long."
|
||||
|
||||
#define ERRINFO_DYNAMIC_DST_DISABLED_FIELD_MISSING_STRING \
|
||||
"The dynamicDaylightTimeDisabled field is not present in the Extended Info Packet (section " \
|
||||
"2.2.1.11.1.1.1)."
|
||||
|
||||
#define ERRINFO_VC_DECODING_ERROR_STRING \
|
||||
"An error occurred when processing dynamic virtual channel data ([MS-RDPEDYC] section 3.3.5)."
|
||||
|
||||
#define ERRINFO_VIRTUALDESKTOPTOOLARGE_STRING \
|
||||
"The width or height of the virtual desktop defined by the monitor layout in the Client " \
|
||||
"Monitor Data " \
|
||||
"(section 2.2.1.3.6) is larger than the maximum allowed value of 32,766."
|
||||
|
||||
#define ERRINFO_MONITORGEOMETRYVALIDATIONFAILED_STRING \
|
||||
"The monitor geometry defined by the Client Monitor Data (section 2.2.1.3.6) is invalid."
|
||||
|
||||
#define ERRINFO_INVALIDMONITORCOUNT_STRING \
|
||||
"The monitorCount field in the Client Monitor Data(section 2.2.1.3.6) is too large."
|
||||
|
||||
#define ERRINFO_UPDATE_SESSION_KEY_FAILED_STRING \
|
||||
"An attempt to update the session keys while using Standard RDP Security mechanisms (section " \
|
||||
"5.3.7) failed."
|
||||
|
||||
#define ERRINFO_DECRYPT_FAILED_STRING \
|
||||
"(a) Decryption using Standard RDP Security mechanisms (section 5.3.6) failed.\n" \
|
||||
"(b) Session key creation using Standard RDP Security mechanisms (section 5.3.5) failed."
|
||||
|
||||
#define ERRINFO_ENCRYPT_FAILED_STRING \
|
||||
"Encryption using Standard RDP Security mechanisms (section 5.3.6) failed."
|
||||
|
||||
#define ERRINFO_ENCRYPTION_PACKAGE_MISMATCH_STRING \
|
||||
"Failed to find a usable Encryption Method (section 5.3.2) in the encryptionMethods field of " \
|
||||
"the Client Security Data (section 2.2.1.4.3)."
|
||||
|
||||
#define ERRINFO_DECRYPT_FAILED2_STRING \
|
||||
"Unencrypted data was encountered in a protocol stream which is meant to be encrypted with " \
|
||||
"Standard RDP Security mechanisms (section 5.3.6)."
|
||||
|
||||
#define ERRINFO_PEER_DISCONNECTED_STRING "The peer connection was lost."
|
||||
|
||||
/* Special codes */
|
||||
#define ERRINFO_SUCCESS_STRING "Success."
|
||||
#define ERRINFO_NONE_STRING ""
|
||||
|
||||
static const ERRINFO ERRINFO_CODES[] = {
|
||||
ERRINFO_DEFINE(SUCCESS, CAT_NONE),
|
||||
|
||||
/* Protocol-independent codes */
|
||||
ERRINFO_DEFINE(RPC_INITIATED_DISCONNECT, CAT_ADMIN),
|
||||
ERRINFO_DEFINE(RPC_INITIATED_LOGOFF, CAT_ADMIN), ERRINFO_DEFINE(IDLE_TIMEOUT, CAT_ADMIN),
|
||||
ERRINFO_DEFINE(LOGON_TIMEOUT, CAT_ADMIN),
|
||||
ERRINFO_DEFINE(DISCONNECTED_BY_OTHER_CONNECTION, CAT_USE),
|
||||
ERRINFO_DEFINE(OUT_OF_MEMORY, CAT_ADMIN), ERRINFO_DEFINE(SERVER_DENIED_CONNECTION, CAT_ADMIN),
|
||||
ERRINFO_DEFINE(SERVER_INSUFFICIENT_PRIVILEGES, CAT_ADMIN),
|
||||
ERRINFO_DEFINE(SERVER_FRESH_CREDENTIALS_REQUIRED, CAT_ADMIN),
|
||||
ERRINFO_DEFINE(RPC_INITIATED_DISCONNECT_BY_USER, CAT_ADMIN),
|
||||
ERRINFO_DEFINE(LOGOFF_BY_USER, CAT_USE),
|
||||
ERRINFO_DEFINE(CLOSE_STACK_ON_DRIVER_NOT_READY, CAT_SERVER),
|
||||
ERRINFO_DEFINE(SERVER_DWM_CRASH, CAT_SERVER),
|
||||
ERRINFO_DEFINE(CLOSE_STACK_ON_DRIVER_FAILURE, CAT_SERVER),
|
||||
ERRINFO_DEFINE(CLOSE_STACK_ON_DRIVER_IFACE_FAILURE, CAT_SERVER),
|
||||
ERRINFO_DEFINE(SERVER_WINLOGON_CRASH, CAT_SERVER),
|
||||
ERRINFO_DEFINE(SERVER_CSRSS_CRASH, CAT_SERVER),
|
||||
|
||||
/* Protocol-independent licensing codes */
|
||||
ERRINFO_DEFINE(LICENSE_INTERNAL, CAT_LICENSING),
|
||||
ERRINFO_DEFINE(LICENSE_NO_LICENSE_SERVER, CAT_LICENSING),
|
||||
ERRINFO_DEFINE(LICENSE_NO_LICENSE, CAT_LICENSING),
|
||||
ERRINFO_DEFINE(LICENSE_BAD_CLIENT_MSG, CAT_LICENSING),
|
||||
ERRINFO_DEFINE(LICENSE_HWID_DOESNT_MATCH_LICENSE, CAT_LICENSING),
|
||||
ERRINFO_DEFINE(LICENSE_BAD_CLIENT_LICENSE, CAT_LICENSING),
|
||||
ERRINFO_DEFINE(LICENSE_CANT_FINISH_PROTOCOL, CAT_LICENSING),
|
||||
ERRINFO_DEFINE(LICENSE_CLIENT_ENDED_PROTOCOL, CAT_LICENSING),
|
||||
ERRINFO_DEFINE(LICENSE_BAD_CLIENT_ENCRYPTION, CAT_LICENSING),
|
||||
ERRINFO_DEFINE(LICENSE_CANT_UPGRADE_LICENSE, CAT_LICENSING),
|
||||
ERRINFO_DEFINE(LICENSE_NO_REMOTE_CONNECTIONS, CAT_LICENSING),
|
||||
|
||||
/* Protocol-independent codes generated by the Connection Broker */
|
||||
ERRINFO_DEFINE(CB_DESTINATION_NOT_FOUND, CAT_BROKER),
|
||||
ERRINFO_DEFINE(CB_LOADING_DESTINATION, CAT_BROKER),
|
||||
ERRINFO_DEFINE(CB_REDIRECTING_TO_DESTINATION, CAT_BROKER),
|
||||
ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_WAKE, CAT_BROKER),
|
||||
ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_BOOT, CAT_BROKER),
|
||||
ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_NO_DNS, CAT_BROKER),
|
||||
ERRINFO_DEFINE(CB_DESTINATION_POOL_NOT_FREE, CAT_BROKER),
|
||||
ERRINFO_DEFINE(CB_CONNECTION_CANCELLED, CAT_BROKER),
|
||||
ERRINFO_DEFINE(CB_CONNECTION_ERROR_INVALID_SETTINGS, CAT_BROKER),
|
||||
ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_BOOT_TIMEOUT, CAT_BROKER),
|
||||
ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_SESSMON_FAILED, CAT_BROKER),
|
||||
|
||||
/* RDP specific codes */
|
||||
ERRINFO_DEFINE(UNKNOWN_DATA_PDU_TYPE, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(UNKNOWN_PDU_TYPE, CAT_PROTOCOL), ERRINFO_DEFINE(DATA_PDU_SEQUENCE, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(CONTROL_PDU_SEQUENCE, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(INVALID_CONTROL_PDU_ACTION, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(INVALID_INPUT_PDU_TYPE, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(INVALID_INPUT_PDU_MOUSE, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(INVALID_REFRESH_RECT_PDU, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(CREATE_USER_DATA_FAILED, CAT_PROTOCOL), ERRINFO_DEFINE(CONNECT_FAILED, CAT_USE),
|
||||
ERRINFO_DEFINE(CONFIRM_ACTIVE_HAS_WRONG_SHAREID, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(CONFIRM_ACTIVE_HAS_WRONG_ORIGINATOR, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(PERSISTENT_KEY_PDU_BAD_LENGTH, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(PERSISTENT_KEY_PDU_ILLEGAL_FIRST, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(PERSISTENT_KEY_PDU_TOO_MANY_TOTAL_KEYS, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(PERSISTENT_KEY_PDU_TOO_MANY_CACHE_KEYS, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(INPUT_PDU_BAD_LENGTH, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(BITMAP_CACHE_ERROR_PDU_BAD_LENGTH, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(VCHANNEL_DATA_TOO_SHORT, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SHARE_DATA_TOO_SHORT, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(BAD_SUPPRESS_OUTPUT_PDU, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(CONFIRM_ACTIVE_PDU_TOO_SHORT, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(CAPABILITY_SET_TOO_SMALL, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(CAPABILITY_SET_TOO_LARGE, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(NO_CURSOR_CACHE, CAT_PROTOCOL), ERRINFO_DEFINE(BAD_CAPABILITIES, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(VIRTUAL_CHANNEL_DECOMPRESSION, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(INVALID_VC_COMPRESSION_TYPE, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(INVALID_CHANNEL_ID, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(VCHANNELS_TOO_MANY, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(REMOTEAPP_NOT_ENABLED, CAT_ADMIN),
|
||||
ERRINFO_DEFINE(CACHE_CAP_NOT_SET, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(BITMAP_CACHE_ERROR_PDU_BAD_LENGTH2, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(OFFSCREEN_CACHE_ERROR_PDU_BAD_LENGTH, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(DRAWNINEGRID_CACHE_ERROR_PDU_BAD_LENGTH, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(GDIPLUS_PDU_BAD_LENGTH, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT2, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT3, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT4, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT5, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT6, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT7, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT8, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT9, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT10, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT11, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT12, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT13, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT14, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT15, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT16, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT17, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT18, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT19, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT20, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT21, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT22, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT23, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(BAD_MONITOR_DATA, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(VC_DECOMPRESSED_REASSEMBLE_FAILED, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(VC_DATA_TOO_LONG, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(BAD_FRAME_ACK_DATA, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(GRAPHICS_MODE_NOT_SUPPORTED, CAT_SERVER),
|
||||
ERRINFO_DEFINE(GRAPHICS_SUBSYSTEM_RESET_FAILED, CAT_SERVER),
|
||||
ERRINFO_DEFINE(GRAPHICS_SUBSYSTEM_FAILED, CAT_SERVER),
|
||||
ERRINFO_DEFINE(TIMEZONE_KEY_NAME_LENGTH_TOO_SHORT, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(TIMEZONE_KEY_NAME_LENGTH_TOO_LONG, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(DYNAMIC_DST_DISABLED_FIELD_MISSING, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(VC_DECODING_ERROR, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(VIRTUALDESKTOPTOOLARGE, CAT_SERVER),
|
||||
ERRINFO_DEFINE(MONITORGEOMETRYVALIDATIONFAILED, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(INVALIDMONITORCOUNT, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(UPDATE_SESSION_KEY_FAILED, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(DECRYPT_FAILED, CAT_PROTOCOL), ERRINFO_DEFINE(ENCRYPT_FAILED, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(ENCRYPTION_PACKAGE_MISMATCH, CAT_PROTOCOL),
|
||||
ERRINFO_DEFINE(DECRYPT_FAILED2, CAT_PROTOCOL), ERRINFO_DEFINE(PEER_DISCONNECTED, CAT_USE),
|
||||
|
||||
ERRINFO_DEFINE(NONE, CAT_NONE)
|
||||
};
|
||||
|
||||
const char* freerdp_get_error_info_string(UINT32 code)
|
||||
{
|
||||
const ERRINFO* errInfo = nullptr;
|
||||
errInfo = &ERRINFO_CODES[0];
|
||||
|
||||
while (errInfo->code != ERRINFO_NONE)
|
||||
{
|
||||
if (code == errInfo->code)
|
||||
{
|
||||
return errInfo->info;
|
||||
}
|
||||
|
||||
errInfo++;
|
||||
}
|
||||
|
||||
return "Unknown error.";
|
||||
}
|
||||
|
||||
const char* freerdp_get_error_info_category(UINT32 code)
|
||||
{
|
||||
const ERRINFO* errInfo = nullptr;
|
||||
errInfo = &ERRINFO_CODES[0];
|
||||
|
||||
while (errInfo->code != ERRINFO_NONE)
|
||||
{
|
||||
if (code == errInfo->code)
|
||||
{
|
||||
return errInfo->category;
|
||||
}
|
||||
|
||||
errInfo++;
|
||||
}
|
||||
|
||||
return "ERRINFO_UNKNOWN";
|
||||
}
|
||||
|
||||
const char* freerdp_get_error_info_name(UINT32 code)
|
||||
{
|
||||
const ERRINFO* errInfo = nullptr;
|
||||
errInfo = &ERRINFO_CODES[0];
|
||||
|
||||
while (errInfo->code != ERRINFO_NONE)
|
||||
{
|
||||
if (code == errInfo->code)
|
||||
{
|
||||
return errInfo->name;
|
||||
}
|
||||
|
||||
errInfo++;
|
||||
}
|
||||
|
||||
return "ERRINFO_UNKNOWN";
|
||||
}
|
||||
|
||||
void rdp_print_errinfo(UINT32 code)
|
||||
{
|
||||
const ERRINFO* errInfo = nullptr;
|
||||
errInfo = &ERRINFO_CODES[0];
|
||||
|
||||
while (errInfo->code != ERRINFO_NONE)
|
||||
{
|
||||
if (code == errInfo->code)
|
||||
{
|
||||
WLog_INFO(TAG, "%s (0x%08" PRIX32 "):%s", errInfo->name, code, errInfo->info);
|
||||
return;
|
||||
}
|
||||
|
||||
errInfo++;
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "ERRINFO_UNKNOWN 0x%08" PRIX32 ": Unknown error.", code);
|
||||
}
|
||||
36
third_party/FreeRDP/libfreerdp/core/errinfo.h
vendored
Normal file
36
third_party/FreeRDP/libfreerdp/core/errinfo.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Error Info
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_ERRINFO_H
|
||||
#define FREERDP_LIB_CORE_ERRINFO_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 code;
|
||||
const char* name;
|
||||
const char* info;
|
||||
const char* category;
|
||||
} ERRINFO;
|
||||
|
||||
FREERDP_LOCAL void rdp_print_errinfo(UINT32 code);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_ERRINFO_H */
|
||||
1433
third_party/FreeRDP/libfreerdp/core/fastpath.c
vendored
Normal file
1433
third_party/FreeRDP/libfreerdp/core/fastpath.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
182
third_party/FreeRDP/libfreerdp/core/fastpath.h
vendored
Normal file
182
third_party/FreeRDP/libfreerdp/core/fastpath.h
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Fast Path
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_FASTPATH_H
|
||||
#define FREERDP_LIB_CORE_FASTPATH_H
|
||||
|
||||
/*
|
||||
* Fast-Path has 15 bits available for length information which would lead to a
|
||||
* maximal pdu size of 0x8000. However in practice only 14 bits are used
|
||||
* this isn't documented anywhere but it looks like most implementations will
|
||||
* fail if fast-path packages > 0x3FFF arrive.
|
||||
*/
|
||||
#define FASTPATH_MAX_PACKET_SIZE 0x3FFF
|
||||
|
||||
/*
|
||||
* The following size guarantees that no fast-path PDU fragmentation occurs.
|
||||
* It was calculated by subtracting 128 from FASTPATH_MAX_PACKET_SIZE.
|
||||
* 128 was chosen because it includes all required and optional headers as well as
|
||||
* possible paddings and some extra bytes for safety.
|
||||
*/
|
||||
#define FASTPATH_FRAGMENT_SAFE_SIZE 0x3F80
|
||||
|
||||
typedef struct rdp_fastpath rdpFastPath;
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
#include <winpr/stream.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
enum FASTPATH_INPUT_ACTION_TYPE
|
||||
{
|
||||
FASTPATH_INPUT_ACTION_FASTPATH = 0x0,
|
||||
FASTPATH_INPUT_ACTION_X224 = 0x3
|
||||
};
|
||||
|
||||
enum FASTPATH_OUTPUT_ACTION_TYPE
|
||||
{
|
||||
FASTPATH_OUTPUT_ACTION_FASTPATH = 0x0,
|
||||
FASTPATH_OUTPUT_ACTION_X224 = 0x3
|
||||
};
|
||||
|
||||
enum FASTPATH_UPDATETYPE
|
||||
{
|
||||
FASTPATH_UPDATETYPE_ORDERS = 0x0,
|
||||
FASTPATH_UPDATETYPE_BITMAP = 0x1,
|
||||
FASTPATH_UPDATETYPE_PALETTE = 0x2,
|
||||
FASTPATH_UPDATETYPE_SYNCHRONIZE = 0x3,
|
||||
FASTPATH_UPDATETYPE_SURFCMDS = 0x4,
|
||||
FASTPATH_UPDATETYPE_PTR_NULL = 0x5,
|
||||
FASTPATH_UPDATETYPE_PTR_DEFAULT = 0x6,
|
||||
FASTPATH_UPDATETYPE_PTR_POSITION = 0x8,
|
||||
FASTPATH_UPDATETYPE_COLOR = 0x9,
|
||||
FASTPATH_UPDATETYPE_CACHED = 0xA,
|
||||
FASTPATH_UPDATETYPE_POINTER = 0xB,
|
||||
FASTPATH_UPDATETYPE_LARGE_POINTER = 0xC
|
||||
};
|
||||
|
||||
enum FASTPATH_FRAGMENT
|
||||
{
|
||||
FASTPATH_FRAGMENT_SINGLE = 0x0,
|
||||
FASTPATH_FRAGMENT_LAST = 0x1,
|
||||
FASTPATH_FRAGMENT_FIRST = 0x2,
|
||||
FASTPATH_FRAGMENT_NEXT = 0x3
|
||||
};
|
||||
|
||||
enum FASTPATH_OUTPUT_COMPRESSION
|
||||
{
|
||||
FASTPATH_OUTPUT_COMPRESSION_USED = 0x2
|
||||
};
|
||||
|
||||
/* FastPath Input Events */
|
||||
enum FASTPATH_INPUT_EVENT_CODE
|
||||
{
|
||||
FASTPATH_INPUT_EVENT_SCANCODE = 0x0,
|
||||
FASTPATH_INPUT_EVENT_MOUSE = 0x1,
|
||||
FASTPATH_INPUT_EVENT_MOUSEX = 0x2,
|
||||
FASTPATH_INPUT_EVENT_SYNC = 0x3,
|
||||
FASTPATH_INPUT_EVENT_UNICODE = 0x4,
|
||||
TS_FP_RELPOINTER_EVENT = 0x5,
|
||||
TS_FP_QOETIMESTAMP_EVENT = 0x6
|
||||
};
|
||||
|
||||
/* FastPath Keyboard Event Flags */
|
||||
enum FASTPATH_INPUT_KBDFLAGS
|
||||
{
|
||||
FASTPATH_INPUT_KBDFLAGS_RELEASE = 0x01,
|
||||
FASTPATH_INPUT_KBDFLAGS_EXTENDED = 0x02,
|
||||
FASTPATH_INPUT_KBDFLAGS_PREFIX_E1 = 0x04 /* for pause sequence */
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE length1;
|
||||
BYTE length2;
|
||||
BYTE fipsInformation[4];
|
||||
BYTE dataSignature[8];
|
||||
|
||||
BYTE action;
|
||||
BYTE secFlags;
|
||||
UINT16 length;
|
||||
} FASTPATH_UPDATE_PDU_HEADER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE compressionFlags;
|
||||
UINT16 size;
|
||||
|
||||
BYTE updateCode;
|
||||
BYTE fragmentation;
|
||||
BYTE compression;
|
||||
} FASTPATH_UPDATE_HEADER;
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL fastpath_read_header_rdp(rdpFastPath* fastpath, wStream* s, UINT16* length);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t fastpath_recv_updates(rdpFastPath* fastpath, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t fastpath_recv_inputs(rdpFastPath* fastpath, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL fastpath_decrypt(rdpFastPath* fastpath, wStream* s, UINT16* length);
|
||||
|
||||
WINPR_ATTR_MALLOC(Stream_Release, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL wStream* fastpath_input_pdu_init_header(rdpFastPath* fastpath, UINT16* sec_flags);
|
||||
|
||||
WINPR_ATTR_MALLOC(Stream_Release, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL wStream* fastpath_input_pdu_init(rdpFastPath* fastpath, BYTE eventFlags,
|
||||
BYTE eventCode, UINT16* sec_flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s,
|
||||
size_t iNumEvents, UINT16 sec_flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL fastpath_send_input_pdu(rdpFastPath* fastpath, wStream* s, UINT16 sec_flags);
|
||||
|
||||
WINPR_ATTR_MALLOC(Stream_Release, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL wStream* fastpath_update_pdu_init(rdpFastPath* fastpath);
|
||||
|
||||
WINPR_ATTR_MALLOC(Stream_Free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL wStream* fastpath_update_pdu_init_new(rdpFastPath* fastpath);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL fastpath_send_update_pdu(rdpFastPath* fastpath, BYTE updateCode, wStream* s,
|
||||
BOOL skipCompression);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL fastpath_send_surfcmd_frame_marker(rdpFastPath* fastpath, UINT16 frameAction,
|
||||
UINT32 frameId);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BYTE fastpath_get_encryption_flags(rdpFastPath* fastpath);
|
||||
|
||||
FREERDP_LOCAL void fastpath_free(rdpFastPath* fastpath);
|
||||
|
||||
WINPR_ATTR_MALLOC(fastpath_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpFastPath* fastpath_new(rdpRdp* rdp);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_FASTPATH_H */
|
||||
1604
third_party/FreeRDP/libfreerdp/core/freerdp.c
vendored
Normal file
1604
third_party/FreeRDP/libfreerdp/core/freerdp.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1296
third_party/FreeRDP/libfreerdp/core/gateway/arm.c
vendored
Normal file
1296
third_party/FreeRDP/libfreerdp/core/gateway/arm.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
32
third_party/FreeRDP/libfreerdp/core/gateway/arm.h
vendored
Normal file
32
third_party/FreeRDP/libfreerdp/core/gateway/arm.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Azure Virtual Desktop Gateway / Azure Resource Manager
|
||||
*
|
||||
* Copyright 2023 Michael Saxl <mike@mwsys.mine.bz>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_ARM_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_ARM_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL arm_resolve_endpoint(wLog* log, rdpContext* context, DWORD timeout);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_ARM_H */
|
||||
1714
third_party/FreeRDP/libfreerdp/core/gateway/http.c
vendored
Normal file
1714
third_party/FreeRDP/libfreerdp/core/gateway/http.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
225
third_party/FreeRDP/libfreerdp/core/gateway/http.h
vendored
Normal file
225
third_party/FreeRDP/libfreerdp/core/gateway/http.h
vendored
Normal file
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Hypertext Transfer Protocol (HTTP)
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_HTTP_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_HTTP_H
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/utils/http.h>
|
||||
|
||||
#include "../../crypto/tls.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TransferEncodingUnknown,
|
||||
TransferEncodingIdentity,
|
||||
TransferEncodingChunked
|
||||
} TRANSFER_ENCODING;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ChunkStateLenghHeader,
|
||||
ChunkStateData,
|
||||
ChunkStateFooter,
|
||||
ChunkStateEnd
|
||||
} CHUNK_STATE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t nextOffset;
|
||||
size_t headerFooterPos;
|
||||
CHUNK_STATE state;
|
||||
char lenBuffer[11];
|
||||
} http_encoding_chunked_context;
|
||||
|
||||
/* HTTP context */
|
||||
typedef struct s_http_context HttpContext;
|
||||
|
||||
FREERDP_LOCAL void http_context_free(HttpContext* context);
|
||||
|
||||
WINPR_ATTR_MALLOC(http_context_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL HttpContext* http_context_new(void);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_method(HttpContext* context, const char* Method);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* http_context_get_uri(HttpContext* context);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_uri(HttpContext* context, const char* URI);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_user_agent(HttpContext* context, const char* UserAgent);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_x_ms_user_agent(HttpContext* context, const char* UserAgent);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_host(HttpContext* context, const char* Host);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_accept(HttpContext* context, const char* Accept);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_cache_control(HttpContext* context, const char* CacheControl);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_connection(HttpContext* context, const char* Connection);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_pragma(HttpContext* context,
|
||||
WINPR_FORMAT_ARG const char* Pragma, ...);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_append_pragma(HttpContext* context,
|
||||
WINPR_FORMAT_ARG const char* Pragma, ...);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_cookie(HttpContext* context, const char* CookieName,
|
||||
const char* CookieValue);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_rdg_connection_id(HttpContext* context,
|
||||
const GUID* RdgConnectionId);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_rdg_correlation_id(HttpContext* context,
|
||||
const GUID* RdgCorrelationId);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
WINPR_ATTR_FORMAT_ARG(3, 4)
|
||||
FREERDP_LOCAL BOOL http_context_set_header(HttpContext* context, const char* key,
|
||||
WINPR_FORMAT_ARG const char* value, ...);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
WINPR_ATTR_FORMAT_ARG(3, 0)
|
||||
FREERDP_LOCAL BOOL http_context_set_header_va(HttpContext* context, const char* key,
|
||||
WINPR_FORMAT_ARG const char* value, va_list ap);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_set_rdg_auth_scheme(HttpContext* context,
|
||||
const char* RdgAuthScheme);
|
||||
|
||||
FREERDP_LOCAL BOOL http_context_enable_websocket_upgrade(HttpContext* context, BOOL enable);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_context_is_websocket_upgrade_enabled(HttpContext* context);
|
||||
|
||||
/* HTTP request */
|
||||
typedef struct s_http_request HttpRequest;
|
||||
|
||||
FREERDP_LOCAL void http_request_free(HttpRequest* request);
|
||||
|
||||
WINPR_ATTR_MALLOC(http_request_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL HttpRequest* http_request_new(void);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_request_set_method(HttpRequest* request, const char* Method);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_request_set_content_type(HttpRequest* request, const char* ContentType);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL SSIZE_T http_request_get_content_length(HttpRequest* request);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_request_set_content_length(HttpRequest* request, size_t length);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* http_request_get_uri(HttpRequest* request);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_request_set_uri(HttpRequest* request, const char* URI);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_request_set_auth_scheme(HttpRequest* request, const char* AuthScheme);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_request_set_auth_param(HttpRequest* request, const char* AuthParam);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_request_set_transfer_encoding(HttpRequest* request,
|
||||
TRANSFER_ENCODING TransferEncoding);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
WINPR_ATTR_FORMAT_ARG(3, 4)
|
||||
FREERDP_LOCAL BOOL http_request_set_header(HttpRequest* request, const char* key,
|
||||
WINPR_FORMAT_ARG const char* value, ...);
|
||||
|
||||
WINPR_ATTR_MALLOC(Stream_Free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL wStream* http_request_write(HttpContext* context, HttpRequest* request);
|
||||
|
||||
/* HTTP response */
|
||||
typedef struct s_http_response HttpResponse;
|
||||
|
||||
FREERDP_LOCAL void http_response_free(HttpResponse* response);
|
||||
|
||||
WINPR_ATTR_MALLOC(http_response_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL HttpResponse* http_response_new(void);
|
||||
|
||||
WINPR_ATTR_MALLOC(http_response_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL UINT16 http_response_get_status_code(const HttpResponse* response);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t http_response_get_body_length(const HttpResponse* response);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* http_response_get_body(const HttpResponse* response);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* http_response_get_auth_token(const HttpResponse* response,
|
||||
const char* method);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* http_response_get_setcookie(const HttpResponse* response,
|
||||
const char* cookie);
|
||||
|
||||
FREERDP_LOCAL BOOL http_response_extract_cookies(const HttpResponse* response,
|
||||
HttpContext* context);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL TRANSFER_ENCODING http_response_get_transfer_encoding(const HttpResponse* response);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL http_response_is_websocket(const HttpContext* http,
|
||||
const HttpResponse* response);
|
||||
|
||||
#define http_response_log_error_status(log, level, response) \
|
||||
http_response_log_error_status_((log), (level), (response), __FILE__, __LINE__, __func__)
|
||||
FREERDP_LOCAL void http_response_log_error_status_(wLog* log, DWORD level,
|
||||
const HttpResponse* response, const char* file,
|
||||
size_t line, const char* fkt);
|
||||
|
||||
/* chunked read helper */
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int http_chuncked_read(BIO* bio, BYTE* pBuffer, size_t size,
|
||||
http_encoding_chunked_context* encodingContext);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_HTTP_H */
|
||||
278
third_party/FreeRDP/libfreerdp/core/gateway/ncacn_http.c
vendored
Normal file
278
third_party/FreeRDP/libfreerdp/core/gateway/ncacn_http.c
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RPC over HTTP (ncacn_http)
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "../settings.h"
|
||||
#include "ncacn_http.h"
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/dsparse.h>
|
||||
|
||||
#include "../utils.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.ntlm")
|
||||
|
||||
#define AUTH_PKG NTLM_SSP_NAME
|
||||
|
||||
static wStream* rpc_auth_http_request(HttpContext* http, const char* method, size_t contentLength,
|
||||
const SecBuffer* authToken, const char* auth_scheme)
|
||||
{
|
||||
wStream* s = nullptr;
|
||||
HttpRequest* request = nullptr;
|
||||
char* base64AuthToken = nullptr;
|
||||
const char* uri = nullptr;
|
||||
|
||||
if (!http || !method)
|
||||
goto fail;
|
||||
|
||||
request = http_request_new();
|
||||
|
||||
if (!request)
|
||||
goto fail;
|
||||
|
||||
if (authToken)
|
||||
base64AuthToken = crypto_base64_encode(authToken->pvBuffer, authToken->cbBuffer);
|
||||
|
||||
uri = http_context_get_uri(http);
|
||||
|
||||
if (!http_request_set_method(request, method) ||
|
||||
!http_request_set_content_length(request, contentLength) ||
|
||||
!http_request_set_uri(request, uri))
|
||||
goto fail;
|
||||
|
||||
if (base64AuthToken)
|
||||
{
|
||||
if (!http_request_set_auth_scheme(request, auth_scheme) ||
|
||||
!http_request_set_auth_param(request, base64AuthToken))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
s = http_request_write(http, request);
|
||||
fail:
|
||||
http_request_free(request);
|
||||
free(base64AuthToken);
|
||||
return s;
|
||||
}
|
||||
|
||||
BOOL rpc_ncacn_http_send_in_channel_request(RpcChannel* inChannel)
|
||||
{
|
||||
wStream* s = nullptr;
|
||||
SSIZE_T status = 0;
|
||||
rdpCredsspAuth* auth = nullptr;
|
||||
HttpContext* http = nullptr;
|
||||
const SecBuffer* buffer = nullptr;
|
||||
int rc = 0;
|
||||
|
||||
if (!inChannel || !inChannel->auth || !inChannel->http)
|
||||
return FALSE;
|
||||
|
||||
auth = inChannel->auth;
|
||||
http = inChannel->http;
|
||||
|
||||
rc = credssp_auth_authenticate(auth);
|
||||
if (rc < 0)
|
||||
return FALSE;
|
||||
|
||||
const size_t contentLength = (rc == 0) ? 0 : 0x40000000;
|
||||
buffer = credssp_auth_have_output_token(auth) ? credssp_auth_get_output_buffer(auth) : nullptr;
|
||||
s = rpc_auth_http_request(http, "RPC_IN_DATA", contentLength, buffer,
|
||||
credssp_auth_pkg_name(auth));
|
||||
|
||||
if (!s)
|
||||
return -1;
|
||||
|
||||
status = rpc_channel_write(inChannel, Stream_Buffer(s), Stream_Length(s));
|
||||
Stream_Free(s, TRUE);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
BOOL rpc_ncacn_http_recv_in_channel_response(RpcChannel* inChannel, HttpResponse* response)
|
||||
{
|
||||
size_t authTokenLength = 0;
|
||||
BYTE* authTokenData = nullptr;
|
||||
|
||||
if (!inChannel || !response || !inChannel->auth)
|
||||
return FALSE;
|
||||
|
||||
rdpCredsspAuth* auth = inChannel->auth;
|
||||
const char* token64 = http_response_get_auth_token(response, credssp_auth_pkg_name(auth));
|
||||
|
||||
if (token64)
|
||||
crypto_base64_decode(token64, strlen(token64), &authTokenData, &authTokenLength);
|
||||
|
||||
if (authTokenLength > UINT32_MAX)
|
||||
{
|
||||
free(authTokenData);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SecBuffer buffer = { .pvBuffer = authTokenData, .cbBuffer = (UINT32)authTokenLength };
|
||||
|
||||
if (authTokenData && authTokenLength)
|
||||
{
|
||||
credssp_auth_take_input_buffer(auth, &buffer);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
sspi_SecBufferFree(&buffer);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rpc_ncacn_http_auth_init(rdpContext* context, RpcChannel* channel)
|
||||
{
|
||||
rdpTls* tls = nullptr;
|
||||
rdpCredsspAuth* auth = nullptr;
|
||||
rdpSettings* settings = nullptr;
|
||||
freerdp* instance = nullptr;
|
||||
auth_status rc = AUTH_FAILED;
|
||||
SEC_WINNT_AUTH_IDENTITY identity = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (!context || !channel)
|
||||
return FALSE;
|
||||
|
||||
tls = channel->tls;
|
||||
auth = channel->auth;
|
||||
settings = context->settings;
|
||||
instance = context->instance;
|
||||
|
||||
if (!tls || !auth || !instance || !settings)
|
||||
return FALSE;
|
||||
|
||||
rc = utils_authenticate_gateway(instance, GW_AUTH_HTTP);
|
||||
switch (rc)
|
||||
{
|
||||
case AUTH_SUCCESS:
|
||||
case AUTH_SKIP:
|
||||
break;
|
||||
case AUTH_CANCELLED:
|
||||
freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
return FALSE;
|
||||
case AUTH_NO_CREDENTIALS:
|
||||
WLog_INFO(TAG, "No credentials provided - using nullptr identity");
|
||||
break;
|
||||
case AUTH_FAILED:
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!credssp_auth_init(auth, AUTH_PKG, tls->Bindings))
|
||||
return FALSE;
|
||||
|
||||
if (!identity_set_from_settings(&identity, settings, FreeRDP_GatewayUsername,
|
||||
FreeRDP_GatewayDomain, FreeRDP_GatewayPassword))
|
||||
return FALSE;
|
||||
|
||||
SEC_WINNT_AUTH_IDENTITY* identityArg = (settings->GatewayUsername ? &identity : nullptr);
|
||||
const BOOL res =
|
||||
credssp_auth_setup_client(auth, "HTTP", settings->GatewayHostname, identityArg, nullptr);
|
||||
|
||||
sspi_FreeAuthIdentity(&identity);
|
||||
|
||||
credssp_auth_set_flags(auth, ISC_REQ_CONFIDENTIALITY);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void rpc_ncacn_http_auth_uninit(RpcChannel* channel)
|
||||
{
|
||||
if (!channel)
|
||||
return;
|
||||
|
||||
credssp_auth_free(channel->auth);
|
||||
channel->auth = nullptr;
|
||||
}
|
||||
|
||||
BOOL rpc_ncacn_http_send_out_channel_request(RpcChannel* outChannel, BOOL replacement)
|
||||
{
|
||||
BOOL status = TRUE;
|
||||
wStream* s = nullptr;
|
||||
size_t contentLength = 0;
|
||||
rdpCredsspAuth* auth = nullptr;
|
||||
HttpContext* http = nullptr;
|
||||
const SecBuffer* buffer = nullptr;
|
||||
int rc = 0;
|
||||
|
||||
if (!outChannel || !outChannel->auth || !outChannel->http)
|
||||
return FALSE;
|
||||
|
||||
auth = outChannel->auth;
|
||||
http = outChannel->http;
|
||||
|
||||
rc = credssp_auth_authenticate(auth);
|
||||
if (rc < 0)
|
||||
return FALSE;
|
||||
|
||||
if (!replacement)
|
||||
contentLength = (rc == 0) ? 0 : 76;
|
||||
else
|
||||
contentLength = (rc == 0) ? 0 : 120;
|
||||
|
||||
buffer = credssp_auth_have_output_token(auth) ? credssp_auth_get_output_buffer(auth) : nullptr;
|
||||
s = rpc_auth_http_request(http, "RPC_OUT_DATA", contentLength, buffer,
|
||||
credssp_auth_pkg_name(auth));
|
||||
|
||||
if (!s)
|
||||
return -1;
|
||||
|
||||
if (rpc_channel_write(outChannel, Stream_Buffer(s), Stream_Length(s)) < 0)
|
||||
status = FALSE;
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOL rpc_ncacn_http_recv_out_channel_response(RpcChannel* outChannel, HttpResponse* response)
|
||||
{
|
||||
size_t authTokenLength = 0;
|
||||
BYTE* authTokenData = nullptr;
|
||||
|
||||
if (!outChannel || !response || !outChannel->auth)
|
||||
return FALSE;
|
||||
|
||||
rdpCredsspAuth* auth = outChannel->auth;
|
||||
const char* token64 = http_response_get_auth_token(response, credssp_auth_pkg_name(auth));
|
||||
|
||||
if (token64)
|
||||
crypto_base64_decode(token64, strlen(token64), &authTokenData, &authTokenLength);
|
||||
|
||||
if (authTokenLength > UINT32_MAX)
|
||||
{
|
||||
free(authTokenData);
|
||||
return FALSE;
|
||||
}
|
||||
SecBuffer buffer = { .pvBuffer = authTokenData, .cbBuffer = (UINT32)authTokenLength };
|
||||
|
||||
if (authTokenData && authTokenLength)
|
||||
{
|
||||
credssp_auth_take_input_buffer(auth, &buffer);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
sspi_SecBufferFree(&buffer);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rpc_ncacn_http_is_final_request(RpcChannel* channel)
|
||||
{
|
||||
WINPR_ASSERT(channel);
|
||||
return credssp_auth_is_complete(channel->auth);
|
||||
}
|
||||
51
third_party/FreeRDP/libfreerdp/core/gateway/ncacn_http.h
vendored
Normal file
51
third_party/FreeRDP/libfreerdp/core/gateway/ncacn_http.h
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RPC over HTTP (ncacn_http)
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_NCACN_HTTP_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_NCACN_HTTP_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include "rpc.h"
|
||||
#include "http.h"
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rpc_ncacn_http_auth_init(rdpContext* context, RpcChannel* channel);
|
||||
|
||||
FREERDP_LOCAL void rpc_ncacn_http_auth_uninit(RpcChannel* channel);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rpc_ncacn_http_send_in_channel_request(RpcChannel* inChannel);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rpc_ncacn_http_recv_in_channel_response(RpcChannel* inChannel,
|
||||
HttpResponse* response);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rpc_ncacn_http_send_out_channel_request(RpcChannel* outChannel,
|
||||
BOOL replacement);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rpc_ncacn_http_recv_out_channel_response(RpcChannel* outChannel,
|
||||
HttpResponse* response);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rpc_ncacn_http_is_final_request(RpcChannel* channel);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_NCACN_HTTP_H */
|
||||
2354
third_party/FreeRDP/libfreerdp/core/gateway/rdg.c
vendored
Normal file
2354
third_party/FreeRDP/libfreerdp/core/gateway/rdg.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
50
third_party/FreeRDP/libfreerdp/core/gateway/rdg.h
vendored
Normal file
50
third_party/FreeRDP/libfreerdp/core/gateway/rdg.h
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Remote Desktop Gateway (RDG)
|
||||
*
|
||||
* Copyright 2015 Denis Vincent <dvincent@devolutions.net>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_RDG_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_RDG_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/winpr.h>
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
/* needed for BIO */
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
typedef struct rdp_rdg rdpRdg;
|
||||
|
||||
FREERDP_LOCAL void rdg_free(rdpRdg* rdg);
|
||||
|
||||
WINPR_ATTR_MALLOC(rdg_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpRdg* rdg_new(rdpContext* context);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BIO* rdg_get_front_bio_and_take_ownership(rdpRdg* rdg);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdg_connect(rdpRdg* rdg, DWORD timeout, BOOL* rpcFallback);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events, DWORD count);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_RDG_H */
|
||||
983
third_party/FreeRDP/libfreerdp/core/gateway/rpc.c
vendored
Normal file
983
third_party/FreeRDP/libfreerdp/core/gateway/rpc.c
vendored
Normal file
@@ -0,0 +1,983 @@
|
||||
/*
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RPC over HTTP
|
||||
*
|
||||
* Copyright 2012 Fujitsu Technology Solutions GmbH
|
||||
* Copyright 2012 Dmitrij Jasnov <dmitrij.jasnov@ts.fujitsu.com>
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "../settings.h"
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/dsparse.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
|
||||
#include <valgrind/memcheck.h>
|
||||
#endif
|
||||
|
||||
#include "../proxy.h"
|
||||
#include "http.h"
|
||||
#include "../credssp_auth.h"
|
||||
#include "ncacn_http.h"
|
||||
#include "rpc_bind.h"
|
||||
#include "rpc_fault.h"
|
||||
#include "rpc_client.h"
|
||||
|
||||
#include "rpc.h"
|
||||
#include "rts.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.rpc")
|
||||
|
||||
static const char* PTYPE_STRINGS[] = { "PTYPE_REQUEST", "PTYPE_PING",
|
||||
"PTYPE_RESPONSE", "PTYPE_FAULT",
|
||||
"PTYPE_WORKING", "PTYPE_NOCALL",
|
||||
"PTYPE_REJECT", "PTYPE_ACK",
|
||||
"PTYPE_CL_CANCEL", "PTYPE_FACK",
|
||||
"PTYPE_CANCEL_ACK", "PTYPE_BIND",
|
||||
"PTYPE_BIND_ACK", "PTYPE_BIND_NAK",
|
||||
"PTYPE_ALTER_CONTEXT", "PTYPE_ALTER_CONTEXT_RESP",
|
||||
"PTYPE_RPC_AUTH_3", "PTYPE_SHUTDOWN",
|
||||
"PTYPE_CO_CANCEL", "PTYPE_ORPHANED",
|
||||
"PTYPE_RTS", "" };
|
||||
|
||||
static const char* client_in_state_str(CLIENT_IN_CHANNEL_STATE state)
|
||||
{
|
||||
// NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
|
||||
const char* str = "CLIENT_IN_CHANNEL_STATE_UNKNOWN";
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case CLIENT_IN_CHANNEL_STATE_INITIAL:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_INITIAL";
|
||||
break;
|
||||
|
||||
case CLIENT_IN_CHANNEL_STATE_CONNECTED:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_CONNECTED";
|
||||
break;
|
||||
|
||||
case CLIENT_IN_CHANNEL_STATE_SECURITY:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_SECURITY";
|
||||
break;
|
||||
|
||||
case CLIENT_IN_CHANNEL_STATE_NEGOTIATED:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_NEGOTIATED";
|
||||
break;
|
||||
|
||||
case CLIENT_IN_CHANNEL_STATE_OPENED:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_OPENED";
|
||||
break;
|
||||
|
||||
case CLIENT_IN_CHANNEL_STATE_OPENED_A4W:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_OPENED_A4W";
|
||||
break;
|
||||
|
||||
case CLIENT_IN_CHANNEL_STATE_FINAL:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_FINAL";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static const char* client_out_state_str(CLIENT_OUT_CHANNEL_STATE state)
|
||||
{
|
||||
// NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
|
||||
const char* str = "CLIENT_OUT_CHANNEL_STATE_UNKNOWN";
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case CLIENT_OUT_CHANNEL_STATE_INITIAL:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_INITIAL";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_CONNECTED:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_CONNECTED";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_SECURITY:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_SECURITY";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_NEGOTIATED:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_NEGOTIATED";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_OPENED:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_OPENED";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_OPENED_A6W:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_OPENED_A6W";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_OPENED_A10W:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_OPENED_A10W";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_OPENED_B3W:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_OPENED_B3W";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_RECYCLED:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_RECYCLED";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_FINAL:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_FINAL";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
const char* rpc_vc_state_str(VIRTUAL_CONNECTION_STATE state)
|
||||
{
|
||||
// NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
|
||||
const char* str = "VIRTUAL_CONNECTION_STATE_UNKNOWN";
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case VIRTUAL_CONNECTION_STATE_INITIAL:
|
||||
str = "VIRTUAL_CONNECTION_STATE_INITIAL";
|
||||
break;
|
||||
|
||||
case VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT:
|
||||
str = "VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT";
|
||||
break;
|
||||
|
||||
case VIRTUAL_CONNECTION_STATE_WAIT_A3W:
|
||||
str = "VIRTUAL_CONNECTION_STATE_WAIT_A3W";
|
||||
break;
|
||||
|
||||
case VIRTUAL_CONNECTION_STATE_WAIT_C2:
|
||||
str = "VIRTUAL_CONNECTION_STATE_WAIT_C2";
|
||||
break;
|
||||
|
||||
case VIRTUAL_CONNECTION_STATE_OPENED:
|
||||
str = "VIRTUAL_CONNECTION_STATE_OPENED";
|
||||
break;
|
||||
|
||||
case VIRTUAL_CONNECTION_STATE_FINAL:
|
||||
str = "VIRTUAL_CONNECTION_STATE_FINAL";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* [MS-RPCH]: Remote Procedure Call over HTTP Protocol Specification:
|
||||
* http://msdn.microsoft.com/en-us/library/cc243950/
|
||||
*
|
||||
*
|
||||
*
|
||||
* Connection Establishment
|
||||
*
|
||||
* Client Outbound Proxy Inbound Proxy Server
|
||||
* | | | |
|
||||
* |-----------------IN Channel Request--------------->| |
|
||||
* |---OUT Channel Request-->| |<-Legacy Server Response-|
|
||||
* | |<--------------Legacy Server Response--------------|
|
||||
* | | | |
|
||||
* |---------CONN_A1-------->| | |
|
||||
* |----------------------CONN_B1--------------------->| |
|
||||
* | |----------------------CONN_A2--------------------->|
|
||||
* | | | |
|
||||
* |<--OUT Channel Response--| |---------CONN_B2-------->|
|
||||
* |<--------CONN_A3---------| | |
|
||||
* | |<---------------------CONN_C1----------------------|
|
||||
* | | |<--------CONN_B3---------|
|
||||
* |<--------CONN_C2---------| | |
|
||||
* | | | |
|
||||
*
|
||||
*/
|
||||
|
||||
void rpc_pdu_header_print(wLog* log, const rpcconn_hdr_t* header)
|
||||
{
|
||||
WINPR_ASSERT(header);
|
||||
|
||||
WLog_Print(log, WLOG_INFO, "rpc_vers: %" PRIu8 "", header->common.rpc_vers);
|
||||
WLog_Print(log, WLOG_INFO, "rpc_vers_minor: %" PRIu8 "", header->common.rpc_vers_minor);
|
||||
|
||||
if (header->common.ptype > PTYPE_RTS)
|
||||
WLog_Print(log, WLOG_INFO, "ptype: %s (%" PRIu8 ")", "PTYPE_UNKNOWN", header->common.ptype);
|
||||
else
|
||||
WLog_Print(log, WLOG_INFO, "ptype: %s (%" PRIu8 ")", PTYPE_STRINGS[header->common.ptype],
|
||||
header->common.ptype);
|
||||
|
||||
WLog_Print(log, WLOG_INFO, "pfc_flags (0x%02" PRIX8 ") = {", header->common.pfc_flags);
|
||||
|
||||
if (header->common.pfc_flags & PFC_FIRST_FRAG)
|
||||
WLog_Print(log, WLOG_INFO, " PFC_FIRST_FRAG");
|
||||
|
||||
if (header->common.pfc_flags & PFC_LAST_FRAG)
|
||||
WLog_Print(log, WLOG_INFO, " PFC_LAST_FRAG");
|
||||
|
||||
if (header->common.pfc_flags & PFC_PENDING_CANCEL)
|
||||
WLog_Print(log, WLOG_INFO, " PFC_PENDING_CANCEL");
|
||||
|
||||
if (header->common.pfc_flags & PFC_RESERVED_1)
|
||||
WLog_Print(log, WLOG_INFO, " PFC_RESERVED_1");
|
||||
|
||||
if (header->common.pfc_flags & PFC_CONC_MPX)
|
||||
WLog_Print(log, WLOG_INFO, " PFC_CONC_MPX");
|
||||
|
||||
if (header->common.pfc_flags & PFC_DID_NOT_EXECUTE)
|
||||
WLog_Print(log, WLOG_INFO, " PFC_DID_NOT_EXECUTE");
|
||||
|
||||
if (header->common.pfc_flags & PFC_OBJECT_UUID)
|
||||
WLog_Print(log, WLOG_INFO, " PFC_OBJECT_UUID");
|
||||
|
||||
WLog_Print(log, WLOG_INFO, " }");
|
||||
WLog_Print(log, WLOG_INFO,
|
||||
"packed_drep[4]: %02" PRIX8 " %02" PRIX8 " %02" PRIX8 " %02" PRIX8 "",
|
||||
header->common.packed_drep[0], header->common.packed_drep[1],
|
||||
header->common.packed_drep[2], header->common.packed_drep[3]);
|
||||
WLog_Print(log, WLOG_INFO, "frag_length: %" PRIu16 "", header->common.frag_length);
|
||||
WLog_Print(log, WLOG_INFO, "auth_length: %" PRIu16 "", header->common.auth_length);
|
||||
WLog_Print(log, WLOG_INFO, "call_id: %" PRIu32 "", header->common.call_id);
|
||||
|
||||
if (header->common.ptype == PTYPE_RESPONSE)
|
||||
{
|
||||
WLog_Print(log, WLOG_INFO, "alloc_hint: %" PRIu32 "", header->response.alloc_hint);
|
||||
WLog_Print(log, WLOG_INFO, "p_cont_id: %" PRIu16 "", header->response.p_cont_id);
|
||||
WLog_Print(log, WLOG_INFO, "cancel_count: %" PRIu8 "", header->response.cancel_count);
|
||||
WLog_Print(log, WLOG_INFO, "reserved: %" PRIu8 "", header->response.reserved);
|
||||
}
|
||||
}
|
||||
|
||||
rpcconn_common_hdr_t rpc_pdu_header_init(const rdpRpc* rpc)
|
||||
{
|
||||
rpcconn_common_hdr_t header = WINPR_C_ARRAY_INIT;
|
||||
WINPR_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;
|
||||
}
|
||||
|
||||
size_t rpc_offset_align(size_t* offset, size_t alignment)
|
||||
{
|
||||
size_t pad = 0;
|
||||
pad = *offset;
|
||||
*offset = (*offset + alignment - 1) & ~(alignment - 1);
|
||||
pad = *offset - pad;
|
||||
return pad;
|
||||
}
|
||||
|
||||
size_t rpc_offset_pad(size_t* offset, size_t pad)
|
||||
{
|
||||
*offset += pad;
|
||||
return pad;
|
||||
}
|
||||
|
||||
/*
|
||||
* PDU Segments:
|
||||
* ________________________________
|
||||
* | |
|
||||
* | PDU Header |
|
||||
* |________________________________|
|
||||
* | |
|
||||
* | |
|
||||
* | PDU Body |
|
||||
* | |
|
||||
* |________________________________|
|
||||
* | |
|
||||
* | Security Trailer |
|
||||
* |________________________________|
|
||||
* | |
|
||||
* | Authentication Token |
|
||||
* |________________________________|
|
||||
*/
|
||||
|
||||
/*
|
||||
* PDU Structure with verification trailer
|
||||
*
|
||||
* MUST only appear in a request PDU!
|
||||
* ________________________________
|
||||
* | |
|
||||
* | PDU Header |
|
||||
* |________________________________| _______
|
||||
* | | /|\
|
||||
* | | |
|
||||
* | Stub Data | |
|
||||
* | | |
|
||||
* |________________________________| |
|
||||
* | | PDU Body
|
||||
* | Stub Pad | |
|
||||
* |________________________________| |
|
||||
* | | |
|
||||
* | Verification Trailer | |
|
||||
* |________________________________| |
|
||||
* | | |
|
||||
* | Authentication Pad | |
|
||||
* |________________________________| __\|/__
|
||||
* | |
|
||||
* | Security Trailer |
|
||||
* |________________________________|
|
||||
* | |
|
||||
* | Authentication Token |
|
||||
* |________________________________|
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Security Trailer:
|
||||
*
|
||||
* The sec_trailer structure MUST be placed at the end of the PDU, including past stub data,
|
||||
* when present. The sec_trailer structure MUST be 4-byte aligned with respect to the beginning
|
||||
* of the PDU. Padding octets MUST be used to align the sec_trailer structure if its natural
|
||||
* beginning is not already 4-byte aligned.
|
||||
*
|
||||
* All PDUs that carry sec_trailer information share certain common fields:
|
||||
* frag_length and auth_length. The beginning of the sec_trailer structure for each PDU MUST be
|
||||
* calculated to start from offset (frag_length – auth_length – 8) from the beginning of the PDU.
|
||||
*
|
||||
* Immediately after the sec_trailer structure, there MUST be a BLOB carrying the authentication
|
||||
* information produced by the security provider. This BLOB is called the authentication token and
|
||||
* MUST be of size auth_length. The size MUST also be equal to the length from the first octet
|
||||
* immediately after the sec_trailer structure all the way to the end of the fragment;
|
||||
* the two values MUST be the same.
|
||||
*
|
||||
* A client or a server that (during composing of a PDU) has allocated more space for the
|
||||
* authentication token than the security provider fills in SHOULD fill in the rest of
|
||||
* the allocated space with zero octets. These zero octets are still considered to belong
|
||||
* to the authentication token part of the PDU.
|
||||
*
|
||||
*/
|
||||
|
||||
BOOL rpc_get_stub_data_info(rdpRpc* rpc, const rpcconn_hdr_t* header, size_t* poffset,
|
||||
size_t* length)
|
||||
{
|
||||
size_t used = 0;
|
||||
size_t offset = 0;
|
||||
BOOL rc = FALSE;
|
||||
UINT32 frag_length = 0;
|
||||
UINT32 auth_length = 0;
|
||||
UINT32 auth_pad_length = 0;
|
||||
UINT32 sec_trailer_offset = 0;
|
||||
const rpc_sec_trailer* sec_trailer = nullptr;
|
||||
|
||||
WINPR_ASSERT(rpc);
|
||||
WINPR_ASSERT(header);
|
||||
WINPR_ASSERT(poffset);
|
||||
WINPR_ASSERT(length);
|
||||
|
||||
offset = RPC_COMMON_FIELDS_LENGTH;
|
||||
|
||||
switch (header->common.ptype)
|
||||
{
|
||||
case PTYPE_RESPONSE:
|
||||
offset += 8;
|
||||
rpc_offset_align(&offset, 8);
|
||||
sec_trailer = &header->response.auth_verifier;
|
||||
break;
|
||||
|
||||
case PTYPE_REQUEST:
|
||||
offset += 4;
|
||||
rpc_offset_align(&offset, 8);
|
||||
sec_trailer = &header->request.auth_verifier;
|
||||
break;
|
||||
|
||||
case PTYPE_RTS:
|
||||
offset += 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_Print(rpc->log, WLOG_ERROR, "Unknown PTYPE: 0x%02" PRIX8 "", header->common.ptype);
|
||||
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;
|
||||
|
||||
/*
|
||||
* According to [MS-RPCE], auth_pad_length is the number of padding
|
||||
* octets used to 4-byte align the security trailer, but in practice
|
||||
* we get values up to 15, which indicates 16-byte alignment.
|
||||
*/
|
||||
|
||||
if ((frag_length - (sec_trailer_offset + 8)) != auth_length)
|
||||
{
|
||||
WLog_Print(rpc->log, WLOG_ERROR,
|
||||
"invalid auth_length: actual: %" PRIu32 ", expected: %" PRIu32 "", auth_length,
|
||||
(frag_length - (sec_trailer_offset + 8)));
|
||||
}
|
||||
|
||||
*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 = 0;
|
||||
|
||||
if (!channel || (length > INT32_MAX))
|
||||
return -1;
|
||||
|
||||
ERR_clear_error();
|
||||
status = BIO_read(channel->tls->bio, Stream_Pointer(s), (INT32)length);
|
||||
|
||||
if (status > 0)
|
||||
{
|
||||
Stream_Seek(s, (size_t)status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (BIO_should_retry(channel->tls->bio))
|
||||
return 0;
|
||||
|
||||
WLog_Print(channel->rpc->log, WLOG_ERROR, "rpc_channel_read: Out of retries");
|
||||
return -1;
|
||||
}
|
||||
|
||||
SSIZE_T rpc_channel_write_int(RpcChannel* channel, const BYTE* data, size_t length,
|
||||
const char* file, size_t line, const char* fkt)
|
||||
{
|
||||
WINPR_ASSERT(channel);
|
||||
WINPR_ASSERT(channel->rpc);
|
||||
|
||||
const DWORD level = WLOG_TRACE;
|
||||
if (WLog_IsLevelActive(channel->rpc->log, level))
|
||||
{
|
||||
WLog_PrintTextMessage(channel->rpc->log, level, line, file, fkt,
|
||||
"Sending [%s] %" PRIuz " bytes", fkt, length);
|
||||
}
|
||||
|
||||
return freerdp_tls_write_all(channel->tls, data, length);
|
||||
}
|
||||
|
||||
BOOL rpc_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state)
|
||||
{
|
||||
WINPR_ASSERT(inChannel);
|
||||
inChannel->State = state;
|
||||
WLog_Print(inChannel->common.rpc->log, WLOG_DEBUG, "%s", client_in_state_str(state));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int rpc_channel_rpch_init(RpcClient* client, RpcChannel* channel, const char* inout,
|
||||
const GUID* guid)
|
||||
{
|
||||
HttpContext* http = nullptr;
|
||||
rdpSettings* settings = nullptr;
|
||||
UINT32 timeout = 0;
|
||||
|
||||
if (!client || !channel || !inout || !client->context || !client->context->settings)
|
||||
return -1;
|
||||
|
||||
settings = client->context->settings;
|
||||
channel->auth = credssp_auth_new(client->context);
|
||||
if (!rts_generate_cookie((BYTE*)&channel->Cookie))
|
||||
return -1;
|
||||
channel->client = client;
|
||||
|
||||
if (!channel->auth)
|
||||
return -1;
|
||||
|
||||
channel->http = http_context_new();
|
||||
|
||||
if (!channel->http)
|
||||
return -1;
|
||||
|
||||
http = channel->http;
|
||||
|
||||
{
|
||||
if (!http_context_set_pragma(http, "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729"))
|
||||
return -1;
|
||||
|
||||
if (guid)
|
||||
{
|
||||
RPC_CSTR strguid = nullptr;
|
||||
RPC_STATUS rpcStatus = UuidToStringA(guid, &strguid);
|
||||
|
||||
if (rpcStatus != RPC_S_OK)
|
||||
return -1;
|
||||
|
||||
const BOOL rc = http_context_append_pragma(http, "SessionId=%s", strguid);
|
||||
RpcStringFreeA(&strguid);
|
||||
if (!rc)
|
||||
return -1;
|
||||
}
|
||||
if (timeout)
|
||||
{
|
||||
if (!http_context_append_pragma(http, "MinConnTimeout=%" PRIu32, timeout))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!http_context_set_rdg_correlation_id(http, guid) ||
|
||||
!http_context_set_rdg_connection_id(http, guid))
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: "/rpcwithcert/rpcproxy.dll". */
|
||||
if (!http_context_set_method(http, inout) ||
|
||||
!http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388") ||
|
||||
!http_context_set_accept(http, "application/rpc") ||
|
||||
!http_context_set_cache_control(http, "no-cache") ||
|
||||
!http_context_set_connection(http, "Keep-Alive") ||
|
||||
!http_context_set_user_agent(http, "MSRPC") ||
|
||||
!http_context_set_host(http, settings->GatewayHostname))
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rpc_in_channel_init(rdpRpc* rpc, RpcInChannel* inChannel, const GUID* guid)
|
||||
{
|
||||
WINPR_ASSERT(rpc);
|
||||
WINPR_ASSERT(inChannel);
|
||||
|
||||
inChannel->common.rpc = rpc;
|
||||
inChannel->State = CLIENT_IN_CHANNEL_STATE_INITIAL;
|
||||
inChannel->BytesSent = 0;
|
||||
inChannel->SenderAvailableWindow = rpc->ReceiveWindow;
|
||||
inChannel->PingOriginator.ConnectionTimeout = 30;
|
||||
inChannel->PingOriginator.KeepAliveInterval = 0;
|
||||
|
||||
if (rpc_channel_rpch_init(rpc->client, &inChannel->common, "RPC_IN_DATA", guid) < 0)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static RpcInChannel* rpc_in_channel_new(rdpRpc* rpc, const GUID* guid)
|
||||
{
|
||||
RpcInChannel* inChannel = (RpcInChannel*)calloc(1, sizeof(RpcInChannel));
|
||||
|
||||
if (inChannel)
|
||||
{
|
||||
rpc_in_channel_init(rpc, inChannel, guid);
|
||||
}
|
||||
|
||||
return inChannel;
|
||||
}
|
||||
|
||||
void rpc_channel_free(RpcChannel* channel)
|
||||
{
|
||||
if (!channel)
|
||||
return;
|
||||
|
||||
credssp_auth_free(channel->auth);
|
||||
http_context_free(channel->http);
|
||||
freerdp_tls_free(channel->tls);
|
||||
free(channel);
|
||||
}
|
||||
|
||||
BOOL rpc_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
|
||||
{
|
||||
WINPR_ASSERT(outChannel);
|
||||
|
||||
outChannel->State = state;
|
||||
WLog_Print(outChannel->common.rpc->log, WLOG_DEBUG, "%s", client_out_state_str(state));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int rpc_out_channel_init(rdpRpc* rpc, RpcOutChannel* outChannel, const GUID* guid)
|
||||
{
|
||||
WINPR_ASSERT(rpc);
|
||||
WINPR_ASSERT(outChannel);
|
||||
|
||||
outChannel->common.rpc = rpc;
|
||||
outChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL;
|
||||
outChannel->BytesReceived = 0;
|
||||
outChannel->ReceiverAvailableWindow = rpc->ReceiveWindow;
|
||||
outChannel->ReceiveWindow = rpc->ReceiveWindow;
|
||||
outChannel->ReceiveWindowSize = rpc->ReceiveWindow;
|
||||
outChannel->AvailableWindowAdvertised = rpc->ReceiveWindow;
|
||||
|
||||
if (rpc_channel_rpch_init(rpc->client, &outChannel->common, "RPC_OUT_DATA", guid) < 0)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc, const GUID* guid)
|
||||
{
|
||||
RpcOutChannel* outChannel = (RpcOutChannel*)calloc(1, sizeof(RpcOutChannel));
|
||||
|
||||
if (outChannel)
|
||||
{
|
||||
rpc_out_channel_init(rpc, outChannel, guid);
|
||||
}
|
||||
|
||||
return outChannel;
|
||||
}
|
||||
|
||||
BOOL rpc_virtual_connection_transition_to_state(rdpRpc* rpc, RpcVirtualConnection* connection,
|
||||
VIRTUAL_CONNECTION_STATE state)
|
||||
{
|
||||
WINPR_ASSERT(connection);
|
||||
WINPR_ASSERT(rpc);
|
||||
connection->State = state;
|
||||
WLog_Print(rpc->log, WLOG_DEBUG, "%s", rpc_vc_state_str(state));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void rpc_virtual_connection_free(RpcVirtualConnection* connection)
|
||||
{
|
||||
if (!connection)
|
||||
return;
|
||||
|
||||
if (connection->DefaultInChannel)
|
||||
rpc_channel_free(&connection->DefaultInChannel->common);
|
||||
if (connection->NonDefaultInChannel)
|
||||
rpc_channel_free(&connection->NonDefaultInChannel->common);
|
||||
if (connection->DefaultOutChannel)
|
||||
rpc_channel_free(&connection->DefaultOutChannel->common);
|
||||
if (connection->NonDefaultOutChannel)
|
||||
rpc_channel_free(&connection->NonDefaultOutChannel->common);
|
||||
free(connection);
|
||||
}
|
||||
|
||||
static RpcVirtualConnection* rpc_virtual_connection_new(rdpRpc* rpc)
|
||||
{
|
||||
WINPR_ASSERT(rpc);
|
||||
|
||||
RpcVirtualConnection* connection =
|
||||
(RpcVirtualConnection*)calloc(1, sizeof(RpcVirtualConnection));
|
||||
|
||||
if (!connection)
|
||||
return nullptr;
|
||||
|
||||
if (!rts_generate_cookie((BYTE*)&(connection->Cookie)))
|
||||
goto fail;
|
||||
if (!rts_generate_cookie((BYTE*)&(connection->AssociationGroupId)))
|
||||
goto fail;
|
||||
connection->State = VIRTUAL_CONNECTION_STATE_INITIAL;
|
||||
|
||||
connection->DefaultInChannel = rpc_in_channel_new(rpc, &connection->Cookie);
|
||||
|
||||
if (!connection->DefaultInChannel)
|
||||
goto fail;
|
||||
|
||||
connection->DefaultOutChannel = rpc_out_channel_new(rpc, &connection->Cookie);
|
||||
|
||||
if (!connection->DefaultOutChannel)
|
||||
goto fail;
|
||||
|
||||
return connection;
|
||||
fail:
|
||||
rpc_virtual_connection_free(connection);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static BOOL rpc_channel_tls_connect(RpcChannel* channel, UINT32 timeout)
|
||||
{
|
||||
if (!channel || !channel->client || !channel->client->context ||
|
||||
!channel->client->context->settings)
|
||||
return FALSE;
|
||||
|
||||
rdpContext* context = channel->client->context;
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
rdpSettings* settings = context->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
const char* proxyUsername = freerdp_settings_get_string(settings, FreeRDP_ProxyUsername);
|
||||
const char* proxyPassword = freerdp_settings_get_string(settings, FreeRDP_ProxyPassword);
|
||||
|
||||
rdpTransport* transport = freerdp_get_transport(context);
|
||||
rdpTransportLayer* layer =
|
||||
transport_connect_layer(transport, channel->client->host, channel->client->port, timeout);
|
||||
|
||||
if (!layer)
|
||||
return FALSE;
|
||||
|
||||
BIO* layerBio = BIO_new(BIO_s_transport_layer());
|
||||
if (!layerBio)
|
||||
{
|
||||
transport_layer_free(layer);
|
||||
return FALSE;
|
||||
}
|
||||
BIO_set_data(layerBio, layer);
|
||||
|
||||
BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
|
||||
if (!bufferedBio)
|
||||
{
|
||||
BIO_free_all(layerBio);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bufferedBio = BIO_push(bufferedBio, layerBio);
|
||||
|
||||
if (!BIO_set_nonblock(bufferedBio, TRUE))
|
||||
{
|
||||
BIO_free_all(bufferedBio);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (channel->client->isProxy)
|
||||
{
|
||||
WINPR_ASSERT(settings->GatewayPort <= UINT16_MAX);
|
||||
if (!proxy_connect(context, bufferedBio, proxyUsername, proxyPassword,
|
||||
settings->GatewayHostname, (UINT16)settings->GatewayPort))
|
||||
{
|
||||
BIO_free_all(bufferedBio);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
channel->bio = bufferedBio;
|
||||
rdpTls* tls = channel->tls = freerdp_tls_new(context);
|
||||
|
||||
if (!tls)
|
||||
return FALSE;
|
||||
|
||||
tls->hostname = settings->GatewayHostname;
|
||||
tls->port = WINPR_ASSERTING_INT_CAST(int32_t, MIN(UINT16_MAX, settings->GatewayPort));
|
||||
tls->isGatewayTransport = TRUE;
|
||||
int tlsStatus = freerdp_tls_connect(tls, bufferedBio);
|
||||
|
||||
if (tlsStatus < 1)
|
||||
{
|
||||
if (tlsStatus < 0)
|
||||
{
|
||||
freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
||||
}
|
||||
else
|
||||
{
|
||||
freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int rpc_in_channel_connect(RpcInChannel* inChannel, UINT32 timeout)
|
||||
{
|
||||
rdpContext* context = nullptr;
|
||||
|
||||
if (!inChannel || !inChannel->common.client || !inChannel->common.client->context)
|
||||
return -1;
|
||||
|
||||
context = inChannel->common.client->context;
|
||||
|
||||
/* Connect IN Channel */
|
||||
|
||||
if (!rpc_channel_tls_connect(&inChannel->common, timeout))
|
||||
return -1;
|
||||
|
||||
rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_CONNECTED);
|
||||
|
||||
if (!rpc_ncacn_http_auth_init(context, &inChannel->common))
|
||||
return -1;
|
||||
|
||||
/* Send IN Channel Request */
|
||||
|
||||
if (!rpc_ncacn_http_send_in_channel_request(&inChannel->common))
|
||||
{
|
||||
WLog_Print(inChannel->common.rpc->log, WLOG_ERROR,
|
||||
"rpc_ncacn_http_send_in_channel_request failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_SECURITY))
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rpc_out_channel_connect(RpcOutChannel* outChannel, UINT32 timeout)
|
||||
{
|
||||
rdpContext* context = nullptr;
|
||||
|
||||
if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
|
||||
return -1;
|
||||
|
||||
context = outChannel->common.client->context;
|
||||
|
||||
/* Connect OUT Channel */
|
||||
|
||||
if (!rpc_channel_tls_connect(&outChannel->common, timeout))
|
||||
return -1;
|
||||
|
||||
rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
|
||||
|
||||
if (!rpc_ncacn_http_auth_init(context, &outChannel->common))
|
||||
return FALSE;
|
||||
|
||||
/* Send OUT Channel Request */
|
||||
|
||||
if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, FALSE))
|
||||
{
|
||||
WLog_Print(outChannel->common.rpc->log, WLOG_ERROR,
|
||||
"rpc_ncacn_http_send_out_channel_request failure");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel, uint32_t timeout)
|
||||
{
|
||||
rdpContext* context = nullptr;
|
||||
|
||||
if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
|
||||
return -1;
|
||||
|
||||
context = outChannel->common.client->context;
|
||||
|
||||
/* Connect OUT Channel */
|
||||
|
||||
if (!rpc_channel_tls_connect(&outChannel->common, timeout))
|
||||
return -1;
|
||||
|
||||
rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
|
||||
|
||||
if (!rpc_ncacn_http_auth_init(context, (RpcChannel*)outChannel))
|
||||
return FALSE;
|
||||
|
||||
/* Send OUT Channel Request */
|
||||
|
||||
if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, TRUE))
|
||||
{
|
||||
WLog_Print(outChannel->common.rpc->log, WLOG_ERROR,
|
||||
"rpc_ncacn_http_send_out_channel_request failure");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL rpc_connect(rdpRpc* rpc, UINT32 timeout)
|
||||
{
|
||||
RpcInChannel* inChannel = nullptr;
|
||||
RpcOutChannel* outChannel = nullptr;
|
||||
RpcVirtualConnection* connection = nullptr;
|
||||
rpc->VirtualConnection = rpc_virtual_connection_new(rpc);
|
||||
|
||||
if (!rpc->VirtualConnection)
|
||||
return FALSE;
|
||||
|
||||
connection = rpc->VirtualConnection;
|
||||
inChannel = connection->DefaultInChannel;
|
||||
outChannel = connection->DefaultOutChannel;
|
||||
rpc_virtual_connection_transition_to_state(rpc, connection, VIRTUAL_CONNECTION_STATE_INITIAL);
|
||||
|
||||
if (rpc_in_channel_connect(inChannel, timeout) < 0)
|
||||
return FALSE;
|
||||
|
||||
if (rpc_out_channel_connect(outChannel, timeout) < 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rdpRpc* rpc_new(rdpTransport* transport)
|
||||
{
|
||||
rdpContext* context = transport_get_context(transport);
|
||||
rdpRpc* rpc = nullptr;
|
||||
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
rpc = (rdpRpc*)calloc(1, sizeof(rdpRpc));
|
||||
|
||||
if (!rpc)
|
||||
return nullptr;
|
||||
|
||||
rpc->log = WLog_Get(TAG);
|
||||
rpc->State = RPC_CLIENT_STATE_INITIAL;
|
||||
rpc->transport = transport;
|
||||
rpc->SendSeqNum = 0;
|
||||
rpc->auth = credssp_auth_new(context);
|
||||
|
||||
if (!rpc->auth)
|
||||
goto out_free;
|
||||
|
||||
rpc->PipeCallId = 0;
|
||||
rpc->StubCallId = 0;
|
||||
rpc->StubFragCount = 0;
|
||||
rpc->rpc_vers = 5;
|
||||
rpc->rpc_vers_minor = 0;
|
||||
/* little-endian data representation */
|
||||
rpc->packed_drep[0] = 0x10;
|
||||
rpc->packed_drep[1] = 0x00;
|
||||
rpc->packed_drep[2] = 0x00;
|
||||
rpc->packed_drep[3] = 0x00;
|
||||
rpc->max_xmit_frag = 0x0FF8;
|
||||
rpc->max_recv_frag = 0x0FF8;
|
||||
rpc->ReceiveWindow = 0x00010000;
|
||||
rpc->ChannelLifetime = 0x40000000;
|
||||
rpc->KeepAliveInterval = 300000;
|
||||
rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
|
||||
rpc->CurrentKeepAliveTime = 0;
|
||||
rpc->CallId = 2;
|
||||
rpc->client = rpc_client_new(context, rpc->max_recv_frag);
|
||||
|
||||
if (!rpc->client)
|
||||
goto out_free;
|
||||
|
||||
return rpc;
|
||||
out_free:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
rpc_free(rpc);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void rpc_free(rdpRpc* rpc)
|
||||
{
|
||||
if (rpc)
|
||||
{
|
||||
rpc_client_free(rpc->client);
|
||||
credssp_auth_free(rpc->auth);
|
||||
rpc_virtual_connection_free(rpc->VirtualConnection);
|
||||
free(rpc);
|
||||
}
|
||||
}
|
||||
819
third_party/FreeRDP/libfreerdp/core/gateway/rpc.h
vendored
Normal file
819
third_party/FreeRDP/libfreerdp/core/gateway/rpc.h
vendored
Normal file
@@ -0,0 +1,819 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RPC over HTTP
|
||||
*
|
||||
* Copyright 2012 Fujitsu Technology Solutions GmbH
|
||||
* Copyright 2012 Dmitrij Jasnov <dmitrij.jasnov@ts.fujitsu.com>
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_RPC_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_RPC_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/collections.h>
|
||||
#include <winpr/interlocked.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/utils/ringbuffer.h>
|
||||
|
||||
#include "../../crypto/tls.h"
|
||||
|
||||
typedef struct rdp_rpc rdpRpc;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE rpc_vers;
|
||||
BYTE rpc_vers_minor;
|
||||
BYTE ptype;
|
||||
BYTE pfc_flags;
|
||||
BYTE packed_drep[4];
|
||||
UINT16 frag_length;
|
||||
UINT16 auth_length;
|
||||
UINT32 call_id;
|
||||
} rpcconn_common_hdr_t;
|
||||
|
||||
#define RPC_COMMON_FIELDS_LENGTH sizeof(rpcconn_common_hdr_t)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
|
||||
UINT16 Flags;
|
||||
UINT16 NumberOfCommands;
|
||||
} rpcconn_rts_hdr_t;
|
||||
|
||||
#define RTS_PDU_HEADER_LENGTH 20
|
||||
|
||||
#define RPC_PDU_FLAG_STUB 0x00000001
|
||||
|
||||
typedef struct
|
||||
{
|
||||
wStream* s;
|
||||
UINT32 Type;
|
||||
UINT32 Flags;
|
||||
UINT32 CallId;
|
||||
} RPC_PDU, *PRPC_PDU;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#include "../tcp.h"
|
||||
#include "../transport.h"
|
||||
|
||||
#include "http.h"
|
||||
#include "../credssp_auth.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/interlocked.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/print.h>
|
||||
|
||||
/**
|
||||
* CAE Specification
|
||||
* DCE 1.1: Remote Procedure Call
|
||||
* Document Number: C706
|
||||
* http://pubs.opengroup.org/onlinepubs/9629399/
|
||||
*/
|
||||
|
||||
#define PTYPE_REQUEST 0x00
|
||||
#define PTYPE_PING 0x01
|
||||
#define PTYPE_RESPONSE 0x02
|
||||
#define PTYPE_FAULT 0x03
|
||||
#define PTYPE_WORKING 0x04
|
||||
#define PTYPE_NOCALL 0x05
|
||||
#define PTYPE_REJECT 0x06
|
||||
#define PTYPE_ACK 0x07
|
||||
#define PTYPE_CL_CANCEL 0x08
|
||||
#define PTYPE_FACK 0x09
|
||||
#define PTYPE_CANCEL_ACK 0x0A
|
||||
#define PTYPE_BIND 0x0B
|
||||
#define PTYPE_BIND_ACK 0x0C
|
||||
#define PTYPE_BIND_NAK 0x0D
|
||||
#define PTYPE_ALTER_CONTEXT 0x0E
|
||||
#define PTYPE_ALTER_CONTEXT_RESP 0x0F
|
||||
#define PTYPE_RPC_AUTH_3 0x10
|
||||
#define PTYPE_SHUTDOWN 0x11
|
||||
#define PTYPE_CO_CANCEL 0x12
|
||||
#define PTYPE_ORPHANED 0x13
|
||||
#define PTYPE_RTS 0x14
|
||||
|
||||
#define PFC_FIRST_FRAG 0x01
|
||||
#define PFC_LAST_FRAG 0x02
|
||||
#define PFC_PENDING_CANCEL 0x04
|
||||
#define PFC_SUPPORT_HEADER_SIGN 0x04
|
||||
#define PFC_RESERVED_1 0x08
|
||||
#define PFC_CONC_MPX 0x10
|
||||
#define PFC_DID_NOT_EXECUTE 0x20
|
||||
#define PFC_MAYBE 0x40
|
||||
#define PFC_OBJECT_UUID 0x80
|
||||
|
||||
/* Minimum fragment sizes */
|
||||
#define RPC_CO_MUST_RECV_FRAG_SIZE 1432
|
||||
#define RPC_CL_MUST_RECV_FRAG_SIZE 1464
|
||||
|
||||
/**
|
||||
* The PDU maximum header length is enough
|
||||
* to contain either the RPC common fields
|
||||
* or all fields up to the stub data in PDUs
|
||||
* that use it (request, response, fault)
|
||||
*/
|
||||
#define RPC_PDU_HEADER_MAX_LENGTH 32
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef UINT16 p_context_id_t;
|
||||
typedef UINT16 p_reject_reason_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 time_low;
|
||||
UINT16 time_mid;
|
||||
UINT16 time_hi_and_version;
|
||||
BYTE clock_seq_hi_and_reserved;
|
||||
BYTE clock_seq_low;
|
||||
BYTE node[6];
|
||||
} p_uuid_t;
|
||||
|
||||
#define ndr_c_int_big_endian 0
|
||||
#define ndr_c_int_little_endian 1
|
||||
#define ndr_c_float_ieee 0
|
||||
#define ndr_c_float_vax 1
|
||||
#define ndr_c_float_cray 2
|
||||
#define ndr_c_float_ibm 3
|
||||
#define ndr_c_char_ascii 0
|
||||
#define ndr_c_char_ebcdic 1
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE int_rep;
|
||||
BYTE char_rep;
|
||||
BYTE float_rep;
|
||||
BYTE reserved;
|
||||
} ndr_format_t, *ndr_format_p_t;
|
||||
|
||||
typedef struct ndr_context_handle
|
||||
{
|
||||
UINT32 context_handle_attributes;
|
||||
p_uuid_t context_handle_uuid;
|
||||
} ndr_context_handle;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
p_uuid_t if_uuid;
|
||||
UINT32 if_version;
|
||||
} p_syntax_id_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
p_context_id_t p_cont_id;
|
||||
BYTE n_transfer_syn; /* number of items */
|
||||
BYTE reserved; /* alignment pad, m.b.z. */
|
||||
p_syntax_id_t abstract_syntax; /* transfer syntax list */
|
||||
p_syntax_id_t* transfer_syntaxes; /* size_is(n_transfer_syn) */
|
||||
} p_cont_elem_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE n_context_elem; /* number of items */
|
||||
BYTE reserved; /* alignment pad, m.b.z. */
|
||||
UINT16 reserved2; /* alignment pad, m.b.z. */
|
||||
p_cont_elem_t* p_cont_elem; /* size_is(n_cont_elem) */
|
||||
} p_cont_list_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
acceptance,
|
||||
user_rejection,
|
||||
provider_rejection,
|
||||
negotiate_ack
|
||||
} p_cont_def_result_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
reason_not_specified,
|
||||
abstract_syntax_not_supported,
|
||||
proposed_transfer_syntaxes_not_supported,
|
||||
local_limit_exceeded
|
||||
} p_provider_reason_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
p_cont_def_result_t result;
|
||||
p_provider_reason_t reason;
|
||||
p_syntax_id_t transfer_syntax;
|
||||
} p_result_t;
|
||||
|
||||
/* Same order and number of elements as in bind request */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE n_results; /* count */
|
||||
BYTE reserved; /* alignment pad, m.b.z. */
|
||||
UINT16 reserved2; /* alignment pad, m.b.z. */
|
||||
p_result_t* p_results; /* size_is(n_results) */
|
||||
} p_result_list_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE major;
|
||||
BYTE minor;
|
||||
} version_t;
|
||||
typedef version_t p_rt_version_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE n_protocols; /* count */
|
||||
p_rt_version_t* p_protocols; /* size_is(n_protocols) */
|
||||
} p_rt_versions_supported_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 length;
|
||||
char* port_spec; /* port string spec; size_is(length) */
|
||||
} port_any_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
REASON_NOT_SPECIFIED = 0,
|
||||
TEMPORARY_CONGESTION = 1,
|
||||
LOCAL_LIMIT_EXCEEDED = 2,
|
||||
CALLED_PADDR_UNKNOWN = 3,
|
||||
PROTOCOL_VERSION_NOT_SUPPORTED = 4,
|
||||
DEFAULT_CONTEXT_NOT_SUPPORTED = 5,
|
||||
USER_DATA_NOT_READABLE = 6,
|
||||
NO_PSAP_AVAILABLE = 7,
|
||||
authentication_type_not_recognized = 8,
|
||||
invalid_checksum = 9
|
||||
} bind_rejection_t;
|
||||
|
||||
typedef UINT16 rpcrt_reason_code_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE rpc_vers;
|
||||
BYTE rpc_vers_minor;
|
||||
BYTE reserved[2];
|
||||
BYTE packed_drep[4];
|
||||
UINT32 reject_status;
|
||||
BYTE reserved2[4];
|
||||
} rpcrt_optional_data_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcrt_reason_code_t reason_code;
|
||||
rpcrt_optional_data_t rpc_info;
|
||||
} rpcconn_reject_optional_data_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcrt_reason_code_t reason_code;
|
||||
rpcrt_optional_data_t rpc_info;
|
||||
} rpcconn_disc_optional_data_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE signature[8];
|
||||
} rpc_sec_verification_trailer;
|
||||
|
||||
struct auth_verifier_co_s
|
||||
{
|
||||
/* restore 4-byte alignment */
|
||||
|
||||
BYTE auth_type;
|
||||
BYTE auth_level;
|
||||
BYTE auth_pad_length;
|
||||
BYTE auth_reserved;
|
||||
UINT32 auth_context_id;
|
||||
|
||||
BYTE* auth_value;
|
||||
};
|
||||
|
||||
typedef struct auth_verifier_co_s rpc_sec_trailer;
|
||||
typedef struct auth_verifier_co_s auth_verifier_co_t;
|
||||
|
||||
/* Connection-oriented PDU Definitions */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
|
||||
UINT16 max_xmit_frag;
|
||||
UINT16 max_recv_frag;
|
||||
UINT32 assoc_group_id;
|
||||
|
||||
p_cont_list_t p_context_elem;
|
||||
|
||||
auth_verifier_co_t auth_verifier;
|
||||
|
||||
} rpcconn_alter_context_hdr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
|
||||
UINT16 max_xmit_frag;
|
||||
UINT16 max_recv_frag;
|
||||
UINT32 assoc_group_id;
|
||||
port_any_t sec_addr;
|
||||
|
||||
/* restore 4-octet alignment */
|
||||
|
||||
p_result_list_t p_result_list;
|
||||
|
||||
auth_verifier_co_t auth_verifier;
|
||||
} rpcconn_alter_context_response_hdr_t;
|
||||
|
||||
/* bind header */
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
|
||||
UINT16 max_xmit_frag;
|
||||
UINT16 max_recv_frag;
|
||||
UINT32 assoc_group_id;
|
||||
|
||||
p_cont_list_t p_context_elem;
|
||||
|
||||
auth_verifier_co_t auth_verifier;
|
||||
} rpcconn_bind_hdr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
|
||||
UINT16 max_xmit_frag;
|
||||
UINT16 max_recv_frag;
|
||||
UINT32 assoc_group_id;
|
||||
|
||||
port_any_t sec_addr;
|
||||
|
||||
/* restore 4-octet alignment */
|
||||
|
||||
p_result_list_t p_result_list;
|
||||
|
||||
auth_verifier_co_t auth_verifier;
|
||||
} rpcconn_bind_ack_hdr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
|
||||
UINT16 max_xmit_frag;
|
||||
UINT16 max_recv_frag;
|
||||
|
||||
auth_verifier_co_t auth_verifier;
|
||||
} rpcconn_rpc_auth_3_hdr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
|
||||
p_reject_reason_t provider_reject_reason;
|
||||
|
||||
p_rt_versions_supported_t versions;
|
||||
} rpcconn_bind_nak_hdr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
|
||||
auth_verifier_co_t auth_verifier;
|
||||
|
||||
} rpcconn_cancel_hdr_t;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* fault codes */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 code;
|
||||
const char* name;
|
||||
const char* category;
|
||||
} RPC_FAULT_CODE;
|
||||
|
||||
#define DEFINE_RPC_FAULT_CODE(_code, cat) \
|
||||
{ \
|
||||
_code, #_code, cat \
|
||||
}
|
||||
|
||||
#define nca_s_comm_failure 0x1C010001
|
||||
#define nca_s_op_rng_error 0x1C010002
|
||||
#define nca_s_unk_if 0x1C010003
|
||||
#define nca_s_wrong_boot_time 0x1C010006
|
||||
#define nca_s_you_crashed 0x1C010009
|
||||
#define nca_s_proto_error 0x1C01000B
|
||||
#define nca_s_out_args_too_big 0x1C010013
|
||||
#define nca_s_server_too_busy 0x1C010014
|
||||
#define nca_s_fault_string_too_long 0x1C010015
|
||||
#define nca_s_unsupported_type 0x1C010017
|
||||
#define nca_s_fault_int_div_by_zero 0x1C000001
|
||||
#define nca_s_fault_addr_error 0x1C000002
|
||||
#define nca_s_fault_fp_div_zero 0x1C000003
|
||||
#define nca_s_fault_fp_underflow 0x1C000004
|
||||
#define nca_s_fault_fp_overflow 0x1C000005
|
||||
#define nca_s_fault_invalid_tag 0x1C000006
|
||||
#define nca_s_fault_invalid_bound 0x1C000007
|
||||
#define nca_s_rpc_version_mismatch 0x1C000008
|
||||
#define nca_s_unspec_reject 0x1C000009
|
||||
#define nca_s_bad_actid 0x1C00000A
|
||||
#define nca_s_who_are_you_failed 0x1C00000B
|
||||
#define nca_s_manager_not_entered 0x1C00000C
|
||||
#define nca_s_fault_cancel 0x1C00000D
|
||||
#define nca_s_fault_ill_inst 0x1C00000E
|
||||
#define nca_s_fault_fp_error 0x1C00000F
|
||||
#define nca_s_fault_int_overflow 0x1C000010
|
||||
#define nca_s_fault_unspec 0x1C000012
|
||||
#define nca_s_fault_remote_comm_failure 0x1C000013
|
||||
#define nca_s_fault_pipe_empty 0x1C000014
|
||||
#define nca_s_fault_pipe_closed 0x1C000015
|
||||
#define nca_s_fault_pipe_order 0x1C000016
|
||||
#define nca_s_fault_pipe_discipline 0x1C000017
|
||||
#define nca_s_fault_pipe_comm_error 0x1C000018
|
||||
#define nca_s_fault_pipe_memory 0x1C000019
|
||||
#define nca_s_fault_context_mismatch 0x1C00001A
|
||||
#define nca_s_fault_remote_no_memory 0x1C00001B
|
||||
#define nca_s_invalid_pres_context_id 0x1C00001C
|
||||
#define nca_s_unsupported_authn_level 0x1C00001D
|
||||
#define nca_s_invalid_checksum 0x1C00001F
|
||||
#define nca_s_invalid_crc 0x1C000020
|
||||
#define nca_s_fault_user_defined 0x1C000021
|
||||
#define nca_s_fault_tx_open_failed 0x1C000022
|
||||
#define nca_s_fault_codeset_conv_error 0x1C000023
|
||||
#define nca_s_fault_object_not_found 0x1C000024
|
||||
#define nca_s_fault_no_client_stub 0x1C000025
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
|
||||
UINT32 alloc_hint;
|
||||
p_context_id_t p_cont_id;
|
||||
|
||||
BYTE cancel_count;
|
||||
BYTE reserved;
|
||||
|
||||
UINT32 status;
|
||||
|
||||
/* align(8) */
|
||||
|
||||
BYTE* stub_data;
|
||||
|
||||
auth_verifier_co_t auth_verifier;
|
||||
} rpcconn_fault_hdr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
|
||||
auth_verifier_co_t auth_verifier;
|
||||
} rpcconn_orphaned_hdr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
|
||||
UINT32 alloc_hint;
|
||||
|
||||
p_context_id_t p_cont_id;
|
||||
UINT16 opnum;
|
||||
|
||||
/* optional field for request, only present if the PFC_OBJECT_UUID field is non-zero */
|
||||
p_uuid_t object;
|
||||
|
||||
/* align(8) */
|
||||
|
||||
BYTE* stub_data;
|
||||
|
||||
auth_verifier_co_t auth_verifier;
|
||||
} rpcconn_request_hdr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
|
||||
UINT32 alloc_hint;
|
||||
p_context_id_t p_cont_id;
|
||||
|
||||
BYTE cancel_count;
|
||||
BYTE reserved;
|
||||
|
||||
/* align(8) */
|
||||
|
||||
BYTE* stub_data;
|
||||
|
||||
auth_verifier_co_t auth_verifier;
|
||||
} rpcconn_response_hdr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rpcconn_common_hdr_t header;
|
||||
} rpcconn_shutdown_hdr_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
rpcconn_common_hdr_t common;
|
||||
rpcconn_alter_context_hdr_t alter_context;
|
||||
rpcconn_alter_context_response_hdr_t alter_context_response;
|
||||
rpcconn_bind_hdr_t bind;
|
||||
rpcconn_bind_ack_hdr_t bind_ack;
|
||||
rpcconn_rpc_auth_3_hdr_t rpc_auth_3;
|
||||
rpcconn_bind_nak_hdr_t bind_nak;
|
||||
rpcconn_cancel_hdr_t cancel;
|
||||
rpcconn_fault_hdr_t fault;
|
||||
rpcconn_orphaned_hdr_t orphaned;
|
||||
rpcconn_request_hdr_t request;
|
||||
rpcconn_response_hdr_t response;
|
||||
rpcconn_shutdown_hdr_t shutdown;
|
||||
rpcconn_rts_hdr_t rts;
|
||||
} rpcconn_hdr_t;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 Id;
|
||||
LONG EvenLegs;
|
||||
LONG NumLegs;
|
||||
} RPC_SECURITY_PROVIDER_INFO;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RPC_CLIENT_STATE_INITIAL,
|
||||
RPC_CLIENT_STATE_ESTABLISHED,
|
||||
RPC_CLIENT_STATE_WAIT_SECURE_BIND_ACK,
|
||||
RPC_CLIENT_STATE_WAIT_UNSECURE_BIND_ACK,
|
||||
RPC_CLIENT_STATE_WAIT_SECURE_ALTER_CONTEXT_RESPONSE,
|
||||
RPC_CLIENT_STATE_CONTEXT_NEGOTIATED,
|
||||
RPC_CLIENT_STATE_WAIT_RESPONSE,
|
||||
RPC_CLIENT_STATE_FINAL
|
||||
} RPC_CLIENT_STATE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RPC_CLIENT_CALL_STATE_INITIAL,
|
||||
RPC_CLIENT_CALL_STATE_SEND_PDUS,
|
||||
RPC_CLIENT_CALL_STATE_DISPATCHED,
|
||||
RPC_CLIENT_CALL_STATE_RECEIVE_PDU,
|
||||
RPC_CLIENT_CALL_STATE_COMPLETE,
|
||||
RPC_CLIENT_CALL_STATE_FAULT,
|
||||
RPC_CLIENT_CALL_STATE_FINAL
|
||||
} RPC_CLIENT_CALL_STATE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 CallId;
|
||||
UINT32 OpNum;
|
||||
RPC_CLIENT_CALL_STATE State;
|
||||
} RpcClientCall;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rdpContext* context;
|
||||
RPC_PDU* pdu;
|
||||
HANDLE PipeEvent;
|
||||
RingBuffer ReceivePipe;
|
||||
wStream* ReceiveFragment;
|
||||
CRITICAL_SECTION PipeLock;
|
||||
wArrayList* ClientCallList;
|
||||
char* host;
|
||||
UINT16 port;
|
||||
BOOL isProxy;
|
||||
} RpcClient;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
RpcClient* client;
|
||||
BIO* bio;
|
||||
rdpTls* tls;
|
||||
rdpCredsspAuth* auth;
|
||||
HttpContext* http;
|
||||
GUID Cookie;
|
||||
rdpRpc* rpc;
|
||||
} RpcChannel;
|
||||
|
||||
/* Ping Originator */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 ConnectionTimeout;
|
||||
UINT32 LastPacketSentTimestamp;
|
||||
UINT32 KeepAliveInterval;
|
||||
} RpcPingOriginator;
|
||||
|
||||
/* Client In Channel */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLIENT_IN_CHANNEL_STATE_INITIAL,
|
||||
CLIENT_IN_CHANNEL_STATE_CONNECTED,
|
||||
CLIENT_IN_CHANNEL_STATE_SECURITY,
|
||||
CLIENT_IN_CHANNEL_STATE_NEGOTIATED,
|
||||
CLIENT_IN_CHANNEL_STATE_OPENED,
|
||||
CLIENT_IN_CHANNEL_STATE_OPENED_A4W,
|
||||
CLIENT_IN_CHANNEL_STATE_FINAL
|
||||
} CLIENT_IN_CHANNEL_STATE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Sending Channel */
|
||||
|
||||
RpcChannel common;
|
||||
|
||||
CLIENT_IN_CHANNEL_STATE State;
|
||||
|
||||
UINT32 PlugState;
|
||||
void* SendQueue;
|
||||
UINT32 BytesSent;
|
||||
UINT32 SenderAvailableWindow;
|
||||
UINT32 PeerReceiveWindow;
|
||||
|
||||
/* Ping Originator */
|
||||
|
||||
RpcPingOriginator PingOriginator;
|
||||
} RpcInChannel;
|
||||
|
||||
/* Client Out Channel */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLIENT_OUT_CHANNEL_STATE_INITIAL,
|
||||
CLIENT_OUT_CHANNEL_STATE_CONNECTED,
|
||||
CLIENT_OUT_CHANNEL_STATE_SECURITY,
|
||||
CLIENT_OUT_CHANNEL_STATE_NEGOTIATED,
|
||||
CLIENT_OUT_CHANNEL_STATE_OPENED,
|
||||
CLIENT_OUT_CHANNEL_STATE_OPENED_A6W,
|
||||
CLIENT_OUT_CHANNEL_STATE_OPENED_A10W,
|
||||
CLIENT_OUT_CHANNEL_STATE_OPENED_B3W,
|
||||
CLIENT_OUT_CHANNEL_STATE_RECYCLED,
|
||||
CLIENT_OUT_CHANNEL_STATE_FINAL
|
||||
} CLIENT_OUT_CHANNEL_STATE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Receiving Channel */
|
||||
|
||||
RpcChannel common;
|
||||
|
||||
CLIENT_OUT_CHANNEL_STATE State;
|
||||
|
||||
UINT32 ReceiveWindow;
|
||||
UINT32 ReceiveWindowSize;
|
||||
UINT32 ReceiverAvailableWindow;
|
||||
UINT32 BytesReceived;
|
||||
UINT32 AvailableWindowAdvertised;
|
||||
} RpcOutChannel;
|
||||
|
||||
/* Client Virtual Connection */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VIRTUAL_CONNECTION_STATE_INITIAL,
|
||||
VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT,
|
||||
VIRTUAL_CONNECTION_STATE_WAIT_A3W,
|
||||
VIRTUAL_CONNECTION_STATE_WAIT_C2,
|
||||
VIRTUAL_CONNECTION_STATE_OPENED,
|
||||
VIRTUAL_CONNECTION_STATE_FINAL
|
||||
} VIRTUAL_CONNECTION_STATE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GUID Cookie;
|
||||
GUID AssociationGroupId;
|
||||
VIRTUAL_CONNECTION_STATE State;
|
||||
RpcInChannel* DefaultInChannel;
|
||||
RpcInChannel* NonDefaultInChannel;
|
||||
RpcOutChannel* DefaultOutChannel;
|
||||
RpcOutChannel* NonDefaultOutChannel;
|
||||
} RpcVirtualConnection;
|
||||
|
||||
/* Virtual Connection Cookie Table */
|
||||
|
||||
#define RPC_UUID_FORMAT_STRING \
|
||||
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
|
||||
#define RPC_UUID_FORMAT_ARGUMENTS(_rpc_uuid) \
|
||||
_rpc_uuid[0], _rpc_uuid[1], _rpc_uuid[2], _rpc_uuid[3], _rpc_uuid[4], _rpc_uuid[5], \
|
||||
_rpc_uuid[6], _rpc_uuid[7], _rpc_uuid[8], _rpc_uuid[9], _rpc_uuid[10], _rpc_uuid[11], \
|
||||
_rpc_uuid[12], _rpc_uuid[13], _rpc_uuid[14], _rpc_uuid[15]
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GUID Cookie;
|
||||
UINT32 ReferenceCount;
|
||||
RpcVirtualConnection* Reference;
|
||||
} RpcVirtualConnectionCookieEntry;
|
||||
|
||||
struct rdp_rpc
|
||||
{
|
||||
RPC_CLIENT_STATE State;
|
||||
|
||||
UINT32 result;
|
||||
|
||||
rdpCredsspAuth* auth;
|
||||
UINT32 SendSeqNum;
|
||||
|
||||
RpcClient* client;
|
||||
|
||||
rdpTransport* transport;
|
||||
|
||||
UINT32 CallId;
|
||||
UINT32 PipeCallId;
|
||||
|
||||
UINT32 StubCallId;
|
||||
UINT32 StubFragCount;
|
||||
|
||||
BYTE rpc_vers;
|
||||
BYTE rpc_vers_minor;
|
||||
BYTE packed_drep[4];
|
||||
|
||||
UINT16 max_xmit_frag;
|
||||
UINT16 max_recv_frag;
|
||||
|
||||
UINT32 ReceiveWindow;
|
||||
UINT32 ChannelLifetime;
|
||||
UINT32 KeepAliveInterval;
|
||||
UINT32 CurrentKeepAliveTime;
|
||||
UINT32 CurrentKeepAliveInterval;
|
||||
|
||||
RpcVirtualConnection* VirtualConnection;
|
||||
wLog* log;
|
||||
};
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* rpc_vc_state_str(VIRTUAL_CONNECTION_STATE state);
|
||||
|
||||
FREERDP_LOCAL void rpc_pdu_header_print(wLog* log, const rpcconn_hdr_t* header);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rpcconn_common_hdr_t rpc_pdu_header_init(const rdpRpc* rpc);
|
||||
|
||||
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);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rpc_get_stub_data_info(rdpRpc* rpc, const rpcconn_hdr_t* header, size_t* offset,
|
||||
size_t* length);
|
||||
|
||||
#define rpc_channel_write(channel, data, length) \
|
||||
rpc_channel_write_int((channel), (data), (length), __FILE__, __LINE__, __func__)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL SSIZE_T rpc_channel_write_int(RpcChannel* channel, const BYTE* data, size_t length,
|
||||
const char* file, size_t line, const char* fkt);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL SSIZE_T rpc_channel_read(RpcChannel* channel, wStream* s, size_t length);
|
||||
|
||||
FREERDP_LOCAL void rpc_channel_free(RpcChannel* channel);
|
||||
|
||||
WINPR_ATTR_MALLOC(rpc_channel_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc, const GUID* guid);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel, uint32_t timeout);
|
||||
|
||||
FREERDP_LOCAL BOOL rpc_in_channel_transition_to_state(RpcInChannel* inChannel,
|
||||
CLIENT_IN_CHANNEL_STATE state);
|
||||
|
||||
FREERDP_LOCAL BOOL rpc_out_channel_transition_to_state(RpcOutChannel* outChannel,
|
||||
CLIENT_OUT_CHANNEL_STATE state);
|
||||
|
||||
FREERDP_LOCAL BOOL rpc_virtual_connection_transition_to_state(rdpRpc* rpc,
|
||||
RpcVirtualConnection* connection,
|
||||
VIRTUAL_CONNECTION_STATE state);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rpc_connect(rdpRpc* rpc, UINT32 timeout);
|
||||
|
||||
FREERDP_LOCAL void rpc_free(rdpRpc* rpc);
|
||||
|
||||
WINPR_ATTR_MALLOC(rpc_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpRpc* rpc_new(rdpTransport* transport);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_RPC_H */
|
||||
471
third_party/FreeRDP/libfreerdp/core/gateway/rpc_bind.c
vendored
Normal file
471
third_party/FreeRDP/libfreerdp/core/gateway/rpc_bind.c
vendored
Normal file
@@ -0,0 +1,471 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RPC Secure Context Binding
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "../settings.h"
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "rpc_client.h"
|
||||
|
||||
#include "rts.h"
|
||||
|
||||
#include "rpc_bind.h"
|
||||
#include "../utils.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.rpc")
|
||||
|
||||
#define AUTH_PKG NTLM_SSP_NAME
|
||||
|
||||
/**
|
||||
* Connection-Oriented RPC Protocol Client Details:
|
||||
* http://msdn.microsoft.com/en-us/library/cc243724/
|
||||
*/
|
||||
|
||||
/* Syntax UUIDs */
|
||||
|
||||
const p_uuid_t TSGU_UUID = {
|
||||
0x44E265DD, /* time_low */
|
||||
0x7DAF, /* time_mid */
|
||||
0x42CD, /* time_hi_and_version */
|
||||
0x85, /* clock_seq_hi_and_reserved */
|
||||
0x60, /* clock_seq_low */
|
||||
{ 0x3C, 0xDB, 0x6E, 0x7A, 0x27, 0x29 } /* node[6] */
|
||||
};
|
||||
|
||||
const p_uuid_t NDR_UUID = {
|
||||
0x8A885D04, /* time_low */
|
||||
0x1CEB, /* time_mid */
|
||||
0x11C9, /* time_hi_and_version */
|
||||
0x9F, /* clock_seq_hi_and_reserved */
|
||||
0xE8, /* clock_seq_low */
|
||||
{ 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60 } /* node[6] */
|
||||
};
|
||||
|
||||
const p_uuid_t BTFN_UUID = {
|
||||
0x6CB71C2C, /* time_low */
|
||||
0x9812, /* time_mid */
|
||||
0x4540, /* time_hi_and_version */
|
||||
0x03, /* clock_seq_hi_and_reserved */
|
||||
0x00, /* clock_seq_low */
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } /* node[6] */
|
||||
};
|
||||
|
||||
/**
|
||||
* Secure Connection-Oriented RPC Packet Sequence
|
||||
*
|
||||
* Client Server
|
||||
* | |
|
||||
* |-------------------SECURE_BIND-------------------->|
|
||||
* | |
|
||||
* |<----------------SECURE_BIND_ACK-------------------|
|
||||
* | |
|
||||
* |--------------------RPC_AUTH_3-------------------->|
|
||||
* | |
|
||||
* | |
|
||||
* |------------------REQUEST_PDU_#1------------------>|
|
||||
* |------------------REQUEST_PDU_#2------------------>|
|
||||
* | |
|
||||
* | ... |
|
||||
* | |
|
||||
* |<-----------------RESPONSE_PDU_#1------------------|
|
||||
* |<-----------------RESPONSE_PDU_#2------------------|
|
||||
* | |
|
||||
* | ... |
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECURE_BIND: RPC bind PDU with sec_trailer and auth_token. Auth_token is generated by calling
|
||||
* the implementation equivalent of the abstract GSS_Init_sec_context call. Upon receiving that, the
|
||||
* server calls the implementation equivalent of the abstract GSS_Accept_sec_context call, which
|
||||
* returns an auth_token and continue status in this example. Assume the following:
|
||||
*
|
||||
* 1) The client chooses the auth_context_id field in the sec_trailer sent with this PDU to be 1.
|
||||
*
|
||||
* 2) The client uses the RPC_C_AUTHN_LEVEL_PKT_PRIVACY authentication level and the
|
||||
* Authentication Service (AS) NTLM.
|
||||
*
|
||||
* 3) The client sets the PFC_SUPPORT_HEADER_SIGN flag in the PDU header.
|
||||
*/
|
||||
|
||||
static int rpc_bind_setup(rdpRpc* rpc)
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY identity = WINPR_C_ARRAY_INIT;
|
||||
|
||||
WINPR_ASSERT(rpc);
|
||||
|
||||
rdpContext* context = transport_get_context(rpc->transport);
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
rdpSettings* settings = context->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
freerdp* instance = context->instance;
|
||||
WINPR_ASSERT(instance);
|
||||
|
||||
credssp_auth_free(rpc->auth);
|
||||
rpc->auth = credssp_auth_new(context);
|
||||
if (!rpc->auth)
|
||||
return -1;
|
||||
|
||||
auth_status rc = utils_authenticate_gateway(instance, GW_AUTH_RPC);
|
||||
switch (rc)
|
||||
{
|
||||
case AUTH_SUCCESS:
|
||||
case AUTH_SKIP:
|
||||
break;
|
||||
case AUTH_CANCELLED:
|
||||
freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
return -1;
|
||||
case AUTH_NO_CREDENTIALS:
|
||||
WLog_INFO(TAG, "No credentials provided - using nullptr identity");
|
||||
break;
|
||||
case AUTH_FAILED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!credssp_auth_init(rpc->auth, AUTH_PKG, nullptr))
|
||||
return -1;
|
||||
|
||||
if (!identity_set_from_settings(&identity, settings, FreeRDP_GatewayUsername,
|
||||
FreeRDP_GatewayDomain, FreeRDP_GatewayPassword))
|
||||
return -1;
|
||||
|
||||
SEC_WINNT_AUTH_IDENTITY* identityArg = (settings->GatewayUsername ? &identity : nullptr);
|
||||
if (!credssp_auth_setup_client(rpc->auth, nullptr, settings->GatewayHostname, identityArg,
|
||||
nullptr))
|
||||
{
|
||||
sspi_FreeAuthIdentity(&identity);
|
||||
return -1;
|
||||
}
|
||||
sspi_FreeAuthIdentity(&identity);
|
||||
|
||||
credssp_auth_set_flags(rpc->auth, ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE |
|
||||
ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT);
|
||||
|
||||
if (credssp_auth_authenticate(rpc->auth) < 0)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rpc_send_bind_pdu(rdpRpc* rpc, BOOL initial)
|
||||
{
|
||||
int status = -1;
|
||||
wStream* buffer = nullptr;
|
||||
UINT32 offset = 0;
|
||||
RpcClientCall* clientCall = nullptr;
|
||||
p_cont_elem_t* p_cont_elem = nullptr;
|
||||
rpcconn_bind_hdr_t bind_pdu = WINPR_C_ARRAY_INIT;
|
||||
RpcVirtualConnection* connection = nullptr;
|
||||
RpcInChannel* inChannel = nullptr;
|
||||
const SecBuffer* sbuffer = nullptr;
|
||||
|
||||
WINPR_ASSERT(rpc);
|
||||
|
||||
connection = rpc->VirtualConnection;
|
||||
|
||||
WINPR_ASSERT(connection);
|
||||
|
||||
inChannel = connection->DefaultInChannel;
|
||||
|
||||
if (initial && rpc_bind_setup(rpc) < 0)
|
||||
return -1;
|
||||
|
||||
WLog_DBG(TAG, initial ? "Sending Bind PDU" : "Sending Alter Context PDU");
|
||||
|
||||
sbuffer = credssp_auth_get_output_buffer(rpc->auth);
|
||||
|
||||
if (!sbuffer)
|
||||
goto fail;
|
||||
|
||||
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 = initial ? PTYPE_BIND : PTYPE_ALTER_CONTEXT;
|
||||
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));
|
||||
|
||||
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->p_cont_id = 0;
|
||||
p_cont_elem->n_transfer_syn = 1;
|
||||
p_cont_elem->reserved = 0;
|
||||
CopyMemory(&(p_cont_elem->abstract_syntax.if_uuid), &TSGU_UUID, sizeof(p_uuid_t));
|
||||
p_cont_elem->abstract_syntax.if_version = TSGU_SYNTAX_IF_VERSION;
|
||||
p_cont_elem->transfer_syntaxes = malloc(sizeof(p_syntax_id_t));
|
||||
|
||||
if (!p_cont_elem->transfer_syntaxes)
|
||||
goto fail;
|
||||
|
||||
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->p_cont_id = 1;
|
||||
p_cont_elem->n_transfer_syn = 1;
|
||||
p_cont_elem->reserved = 0;
|
||||
CopyMemory(&(p_cont_elem->abstract_syntax.if_uuid), &TSGU_UUID, sizeof(p_uuid_t));
|
||||
p_cont_elem->abstract_syntax.if_version = TSGU_SYNTAX_IF_VERSION;
|
||||
p_cont_elem->transfer_syntaxes = malloc(sizeof(p_syntax_id_t));
|
||||
|
||||
if (!p_cont_elem->transfer_syntaxes)
|
||||
goto fail;
|
||||
|
||||
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_type =
|
||||
rpc_auth_pkg_to_security_provider(credssp_auth_pkg_name(rpc->auth));
|
||||
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);
|
||||
|
||||
WINPR_ASSERT(offset <= UINT16_MAX);
|
||||
bind_pdu.header.frag_length = (UINT16)offset;
|
||||
|
||||
buffer = Stream_New(nullptr, bind_pdu.header.frag_length);
|
||||
|
||||
if (!buffer)
|
||||
goto fail;
|
||||
|
||||
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;
|
||||
|
||||
if (!ArrayList_Append(rpc->client->ClientCallList, clientCall))
|
||||
{
|
||||
rpc_client_call_free(clientCall);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
Stream_SealLength(buffer);
|
||||
status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer));
|
||||
fail:
|
||||
|
||||
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);
|
||||
bind_pdu.p_context_elem.p_cont_elem = nullptr;
|
||||
|
||||
Stream_Free(buffer, TRUE);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum Transmit/Receive Fragment Size Negotiation
|
||||
*
|
||||
* The client determines, and then sends in the bind PDU, its desired maximum size for transmitting
|
||||
* fragments, and its desired maximum receive fragment size. Similarly, the server determines its
|
||||
* desired maximum sizes for transmitting and receiving fragments. Transmit and receive sizes may be
|
||||
* different to help preserve buffering. When the server receives the client’s values, it sets its
|
||||
* operational transmit size to the minimum of the client’s receive size (from the bind PDU) and its
|
||||
* own desired transmit size. Then it sets its actual receive size to the minimum of the client’s
|
||||
* transmit size (from the bind) and its own desired receive size. The server then returns its
|
||||
* operational values in the bind_ack PDU. The client then sets its operational values from the
|
||||
* received bind_ack PDU. The received transmit size becomes the client’s receive size, and the
|
||||
* received receive size becomes the client’s transmit size. Either party may use receive buffers
|
||||
* larger than negotiated — although this will not provide any advantage — but may not transmit
|
||||
* larger fragments than negotiated.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* SECURE_BIND_ACK: RPC bind_ack PDU with sec_trailer and auth_token. The PFC_SUPPORT_HEADER_SIGN
|
||||
* flag in the PDU header is also set in this example. Auth_token is generated by the server in the
|
||||
* previous step. Upon receiving that PDU, the client calls the implementation equivalent of the
|
||||
* abstract GSS_Init_sec_context call, which returns an auth_token and continue status in this
|
||||
* example.
|
||||
*/
|
||||
|
||||
BOOL rpc_recv_bind_ack_pdu(rdpRpc* rpc, wStream* s)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
const BYTE* auth_data = nullptr;
|
||||
size_t pos = 0;
|
||||
size_t end = 0;
|
||||
rpcconn_hdr_t header = WINPR_C_ARRAY_INIT;
|
||||
SecBuffer buffer = WINPR_C_ARRAY_INIT;
|
||||
|
||||
WINPR_ASSERT(rpc);
|
||||
WINPR_ASSERT(rpc->auth);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
pos = Stream_GetPosition(s);
|
||||
if (!rts_read_pdu_header(s, &header))
|
||||
goto fail;
|
||||
|
||||
WLog_DBG(TAG, header.common.ptype == PTYPE_BIND_ACK ? "Receiving BindAck PDU"
|
||||
: "Receiving AlterContextResp PDU");
|
||||
|
||||
rpc->max_recv_frag = header.bind_ack.max_xmit_frag;
|
||||
rpc->max_xmit_frag = header.bind_ack.max_recv_frag;
|
||||
|
||||
/* 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_ConstPointer(s);
|
||||
Stream_SetPosition(s, end);
|
||||
|
||||
buffer.cbBuffer = header.common.auth_length;
|
||||
buffer.pvBuffer = malloc(buffer.cbBuffer);
|
||||
if (!buffer.pvBuffer)
|
||||
goto fail;
|
||||
memcpy(buffer.pvBuffer, auth_data, buffer.cbBuffer);
|
||||
credssp_auth_take_input_buffer(rpc->auth, &buffer);
|
||||
|
||||
if (credssp_auth_authenticate(rpc->auth) < 0)
|
||||
goto fail;
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
rts_free_pdu_header(&header, FALSE);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* RPC_AUTH_3: The client knows that this is an NTLM that uses three legs. It sends an rpc_auth_3
|
||||
* PDU with the auth_token obtained in the previous step. Upon receiving this PDU, the server calls
|
||||
* the implementation equivalent of the abstract GSS_Accept_sec_context call, which returns success
|
||||
* status in this example.
|
||||
*/
|
||||
|
||||
int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
|
||||
{
|
||||
int status = -1;
|
||||
wStream* buffer = nullptr;
|
||||
size_t offset = 0;
|
||||
const SecBuffer* sbuffer = nullptr;
|
||||
RpcClientCall* clientCall = nullptr;
|
||||
rpcconn_rpc_auth_3_hdr_t auth_3_pdu = WINPR_C_ARRAY_INIT;
|
||||
RpcVirtualConnection* connection = nullptr;
|
||||
RpcInChannel* inChannel = nullptr;
|
||||
|
||||
WINPR_ASSERT(rpc);
|
||||
|
||||
connection = rpc->VirtualConnection;
|
||||
WINPR_ASSERT(connection);
|
||||
|
||||
inChannel = connection->DefaultInChannel;
|
||||
WINPR_ASSERT(inChannel);
|
||||
|
||||
WLog_DBG(TAG, "Sending RpcAuth3 PDU");
|
||||
|
||||
sbuffer = credssp_auth_get_output_buffer(rpc->auth);
|
||||
|
||||
if (!sbuffer)
|
||||
return -1;
|
||||
|
||||
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;
|
||||
|
||||
const size_t align = rpc_offset_align(&offset, 4);
|
||||
WINPR_ASSERT(align <= UINT8_MAX);
|
||||
auth_3_pdu.auth_verifier.auth_pad_length = (BYTE)align;
|
||||
auth_3_pdu.auth_verifier.auth_type =
|
||||
rpc_auth_pkg_to_security_provider(credssp_auth_pkg_name(rpc->auth));
|
||||
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);
|
||||
|
||||
WINPR_ASSERT(offset <= UINT16_MAX);
|
||||
auth_3_pdu.header.frag_length = (UINT16)offset;
|
||||
|
||||
buffer = Stream_New(nullptr, auth_3_pdu.header.frag_length);
|
||||
|
||||
if (!buffer)
|
||||
return -1;
|
||||
|
||||
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_Append(rpc->client->ClientCallList, clientCall))
|
||||
{
|
||||
Stream_SealLength(buffer);
|
||||
status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer));
|
||||
}
|
||||
|
||||
fail:
|
||||
Stream_Free(buffer, TRUE);
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
enum RPC_BIND_STATE rpc_bind_state(rdpRpc* rpc)
|
||||
{
|
||||
BOOL complete = 0;
|
||||
BOOL have_token = 0;
|
||||
WINPR_ASSERT(rpc);
|
||||
|
||||
complete = credssp_auth_is_complete(rpc->auth);
|
||||
have_token = credssp_auth_have_output_token(rpc->auth);
|
||||
|
||||
return complete ? (have_token ? RPC_BIND_STATE_LAST_LEG : RPC_BIND_STATE_COMPLETE)
|
||||
: RPC_BIND_STATE_INCOMPLETE;
|
||||
}
|
||||
|
||||
BYTE rpc_auth_pkg_to_security_provider(const char* name)
|
||||
{
|
||||
if (strcmp(name, CREDSSP_AUTH_PKG_SPNEGO) == 0)
|
||||
return RPC_C_AUTHN_GSS_NEGOTIATE;
|
||||
else if (strcmp(name, CREDSSP_AUTH_PKG_NTLM) == 0)
|
||||
return RPC_C_AUTHN_WINNT;
|
||||
else if (strcmp(name, CREDSSP_AUTH_PKG_KERBEROS) == 0)
|
||||
return RPC_C_AUTHN_GSS_KERBEROS;
|
||||
else if (strcmp(name, CREDSSP_AUTH_PKG_SCHANNEL) == 0)
|
||||
return RPC_C_AUTHN_GSS_SCHANNEL;
|
||||
else
|
||||
return RPC_C_AUTHN_NONE;
|
||||
}
|
||||
59
third_party/FreeRDP/libfreerdp/core/gateway/rpc_bind.h
vendored
Normal file
59
third_party/FreeRDP/libfreerdp/core/gateway/rpc_bind.h
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RPC Secure Context Binding
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_RPC_BIND_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_RPC_BIND_H
|
||||
|
||||
#include "rpc.h"
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL extern const p_uuid_t TSGU_UUID;
|
||||
#define TSGU_SYNTAX_IF_VERSION 0x00030001
|
||||
|
||||
FREERDP_LOCAL extern const p_uuid_t NDR_UUID;
|
||||
#define NDR_SYNTAX_IF_VERSION 0x00000002
|
||||
|
||||
FREERDP_LOCAL extern const p_uuid_t BTFN_UUID;
|
||||
#define BTFN_SYNTAX_IF_VERSION 0x00000001
|
||||
|
||||
enum RPC_BIND_STATE
|
||||
{
|
||||
RPC_BIND_STATE_INCOMPLETE,
|
||||
RPC_BIND_STATE_LAST_LEG,
|
||||
RPC_BIND_STATE_COMPLETE
|
||||
};
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int rpc_send_bind_pdu(rdpRpc* rpc, BOOL initial);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rpc_recv_bind_ack_pdu(rdpRpc* rpc, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL enum RPC_BIND_STATE rpc_bind_state(rdpRpc* rpc);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BYTE rpc_auth_pkg_to_security_provider(const char* name);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_RPC_BIND_H */
|
||||
1267
third_party/FreeRDP/libfreerdp/core/gateway/rpc_client.c
vendored
Normal file
1267
third_party/FreeRDP/libfreerdp/core/gateway/rpc_client.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
60
third_party/FreeRDP/libfreerdp/core/gateway/rpc_client.h
vendored
Normal file
60
third_party/FreeRDP/libfreerdp/core/gateway/rpc_client.h
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RPC Client
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_RPC_CLIENT_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_RPC_CLIENT_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include "rpc.h"
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL RpcClientCall* rpc_client_call_find_by_id(RpcClient* client, UINT32 CallId);
|
||||
|
||||
FREERDP_LOCAL void rpc_client_call_free(RpcClientCall* clientCall);
|
||||
|
||||
WINPR_ATTR_MALLOC(rpc_client_call_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int rpc_in_channel_send_pdu(RpcInChannel* inChannel, const BYTE* buffer,
|
||||
size_t length);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int rpc_client_in_channel_recv(rdpRpc* rpc);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int rpc_client_out_channel_recv(rdpRpc* rpc);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int rpc_client_receive_pipe_read(RpcClient* client, BYTE* buffer, size_t length);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum);
|
||||
|
||||
FREERDP_LOCAL void rpc_client_free(RpcClient* client);
|
||||
|
||||
WINPR_ATTR_MALLOC(rpc_client_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL RpcClient* rpc_client_new(rdpContext* context, UINT32 max_recv_frag);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_RPC_CLIENT_H */
|
||||
428
third_party/FreeRDP/libfreerdp/core/gateway/rpc_fault.c
vendored
Normal file
428
third_party/FreeRDP/libfreerdp/core/gateway/rpc_fault.c
vendored
Normal file
@@ -0,0 +1,428 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RPC Fault Handling
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "rpc_fault.h"
|
||||
|
||||
#include "rpc.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.rpc")
|
||||
|
||||
ALIGN64
|
||||
static const RPC_FAULT_CODE RPC_FAULT_CODES[] = {
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_object_not_found, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_cancel, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_addr_error, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_context_mismatch, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_fp_div_zero, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_fp_error, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_fp_overflow, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_fp_underflow, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_ill_inst, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_int_div_by_zero, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_int_overflow, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_invalid_bound, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_invalid_tag, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_closed, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_comm_error, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_discipline, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_empty, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_memory, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_order, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_remote_no_memory, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_user_defined, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_tx_open_failed, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_codeset_conv_error, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(nca_s_fault_no_client_stub, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_STRING_BINDING, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_WRONG_KIND_OF_BINDING, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_BINDING, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_PROTSEQ_NOT_SUPPORTED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_RPC_PROTSEQ, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_STRING_UUID, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_ENDPOINT_FORMAT, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_NET_ADDR, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NO_ENDPOINT_FOUND, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_TIMEOUT, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_OBJECT_NOT_FOUND, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_ALREADY_REGISTERED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_TYPE_ALREADY_REGISTERED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_ALREADY_LISTENING, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NO_PROTSEQS_REGISTERED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NOT_LISTENING, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_MGR_TYPE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_IF, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NO_BINDINGS, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NO_PROTSEQS, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_CANT_CREATE_ENDPOINT, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_OUT_OF_RESOURCES, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_SERVER_UNAVAILABLE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_SERVER_TOO_BUSY, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_NETWORK_OPTIONS, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NO_CALL_ACTIVE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_CALL_FAILED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_CALL_FAILED_DNE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_PROTOCOL_ERROR, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_PROXY_ACCESS_DENIED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UNSUPPORTED_TRANS_SYN, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UNSUPPORTED_TYPE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_TAG, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_BOUND, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NO_ENTRY_NAME, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_NAME_SYNTAX, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UNSUPPORTED_NAME_SYNTAX, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UUID_NO_ADDRESS, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_DUPLICATE_ENDPOINT, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_AUTHN_TYPE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_MAX_CALLS_TOO_SMALL, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_STRING_TOO_LONG, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_PROTSEQ_NOT_FOUND, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_PROCNUM_OUT_OF_RANGE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_BINDING_HAS_NO_AUTH, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_AUTHN_SERVICE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_AUTHN_LEVEL, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_AUTH_IDENTITY, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_AUTHZ_SERVICE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(EPT_S_INVALID_ENTRY, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(EPT_S_CANT_PERFORM_OP, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(EPT_S_NOT_REGISTERED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NOTHING_TO_EXPORT, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INCOMPLETE_NAME, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_VERS_OPTION, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NO_MORE_MEMBERS, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NOT_ALL_OBJS_UNEXPORTED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INTERFACE_NOT_FOUND, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_ENTRY_ALREADY_EXISTS, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_ENTRY_NOT_FOUND, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NAME_SERVICE_UNAVAILABLE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_NAF_ID, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_CANNOT_SUPPORT, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NO_CONTEXT_AVAILABLE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INTERNAL_ERROR, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_ZERO_DIVIDE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_ADDRESS_ERROR, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_FP_DIV_ZERO, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_FP_UNDERFLOW, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_FP_OVERFLOW, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_NO_MORE_ENTRIES, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_SS_CHAR_TRANS_OPEN_FAIL, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_SS_CHAR_TRANS_SHORT_FILE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_SS_IN_NULL_CONTEXT, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_SS_CONTEXT_DAMAGED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_SS_HANDLES_MISMATCH, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_SS_CANNOT_GET_CALL_HANDLE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_NULL_REF_POINTER, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_ENUM_VALUE_OUT_OF_RANGE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_BYTE_COUNT_TOO_SMALL, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_BAD_STUB_DATA, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NO_INTERFACES, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_CALL_CANCELLED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_BINDING_INCOMPLETE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_COMM_FAILURE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UNSUPPORTED_AUTHN_LEVEL, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NO_PRINC_NAME, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NOT_RPC_ERROR, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UUID_LOCAL_ONLY, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_SEC_PKG_ERROR, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_NOT_CANCELLED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_ES_ACTION, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_WRONG_ES_VERSION, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_WRONG_STUB_VERSION, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_PIPE_OBJECT, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_WRONG_PIPE_ORDER, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_WRONG_PIPE_VERSION, CAT_GATEWAY),
|
||||
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)
|
||||
};
|
||||
|
||||
static const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[] = {
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_OK, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_ARG, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_OUT_OF_MEMORY, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_OUT_OF_THREADS, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_LEVEL, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_BUFFER_TOO_SMALL, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_SECURITY_DESC, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_ACCESS_DENIED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_SERVER_OUT_OF_MEMORY, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_ASYNC_CALL_PENDING, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_PRINCIPAL, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_S_TIMEOUT, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_NO_MEMORY, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_BOUND, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_TAG, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_ENUM_VALUE_TOO_LARGE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_SS_CONTEXT_MISMATCH, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_BUFFER, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_PIPE_APP_MEMORY, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_PIPE_OPERATION, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(ERROR_ONLY_IF_CONNECTED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(ERROR_GRACEFUL_DISCONNECT, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(ERROR_OPERATION_ABORTED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(ERROR_BAD_ARGUMENTS, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(E_PROXY_INTERNALERROR, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(E_PROXY_RAP_ACCESSDENIED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(E_PROXY_NAP_ACCESSDENIED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(E_PROXY_TS_CONNECTFAILED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(E_PROXY_ALREADYDISCONNECTED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(E_PROXY_QUARANTINE_ACCESSDENIED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(E_PROXY_NOCERTAVAILABLE, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(E_PROXY_COOKIE_BADPACKET, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(E_PROXY_COOKIE_AUTHENTICATION_ACCESS_DENIED, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(E_PROXY_UNSUPPORTED_AUTHENTICATION_METHOD, CAT_GATEWAY),
|
||||
DEFINE_RPC_FAULT_CODE(E_PROXY_CAPABILITYMISMATCH, CAT_GATEWAY),
|
||||
{ HRESULT_CODE(E_PROXY_NOTSUPPORTED), "E_PROXY_NOTSUPPORTED", CAT_GATEWAY },
|
||||
{ HRESULT_CODE(E_PROXY_TS_CONNECTFAILED), "E_PROXY_TS_CONNECTFAILED", CAT_GATEWAY },
|
||||
{ HRESULT_CODE(E_PROXY_MAXCONNECTIONSREACHED), "E_PROXY_MAXCONNECTIONSREACHED", CAT_GATEWAY },
|
||||
{ HRESULT_CODE(E_PROXY_INTERNALERROR), "E_PROXY_INTERNALERROR", CAT_GATEWAY },
|
||||
{ HRESULT_CODE(E_PROXY_SESSIONTIMEOUT), "E_PROXY_SESSIONTIMEOUT", CAT_GATEWAY },
|
||||
{ HRESULT_CODE(E_PROXY_REAUTH_AUTHN_FAILED), "E_PROXY_REAUTH_AUTHN_FAILED", CAT_GATEWAY },
|
||||
{ HRESULT_CODE(E_PROXY_REAUTH_CAP_FAILED), "E_PROXY_REAUTH_CAP_FAILED", CAT_GATEWAY },
|
||||
{ HRESULT_CODE(E_PROXY_REAUTH_RAP_FAILED), "E_PROXY_REAUTH_RAP_FAILED", CAT_GATEWAY },
|
||||
{ HRESULT_CODE(E_PROXY_SDR_NOT_SUPPORTED_BY_TS), "E_PROXY_SDR_NOT_SUPPORTED_BY_TS",
|
||||
CAT_GATEWAY },
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
/**
|
||||
* [MS-RPCE] 3.1.1.5.5 Returning Win32 Error Values:
|
||||
* http://msdn.microsoft.com/en-us/library/ee442005/
|
||||
*/
|
||||
|
||||
static UINT32 rpc_map_status_code_to_win32_error_code(UINT32 code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case nca_s_comm_failure:
|
||||
return RPC_S_COMM_FAILURE;
|
||||
|
||||
case nca_s_op_rng_error:
|
||||
return RPC_S_PROCNUM_OUT_OF_RANGE;
|
||||
|
||||
case nca_s_unk_if:
|
||||
return RPC_S_UNKNOWN_IF;
|
||||
|
||||
case nca_s_wrong_boot_time:
|
||||
return nca_s_wrong_boot_time;
|
||||
|
||||
case nca_s_you_crashed:
|
||||
return RPC_S_CALL_FAILED;
|
||||
|
||||
case nca_s_proto_error:
|
||||
return RPC_S_PROTOCOL_ERROR;
|
||||
|
||||
case nca_s_out_args_too_big:
|
||||
return RPC_S_SERVER_OUT_OF_MEMORY;
|
||||
|
||||
case nca_s_server_too_busy:
|
||||
return RPC_S_SERVER_TOO_BUSY;
|
||||
|
||||
case nca_s_unsupported_type:
|
||||
return RPC_S_UNSUPPORTED_TYPE;
|
||||
|
||||
case nca_s_fault_int_div_by_zero:
|
||||
return RPC_S_ZERO_DIVIDE;
|
||||
|
||||
case nca_s_fault_addr_error:
|
||||
return RPC_S_ADDRESS_ERROR;
|
||||
|
||||
case nca_s_fault_fp_div_zero:
|
||||
return RPC_S_FP_DIV_ZERO;
|
||||
|
||||
case nca_s_fault_fp_underflow:
|
||||
return RPC_S_FP_UNDERFLOW;
|
||||
|
||||
case nca_s_fault_fp_overflow:
|
||||
return RPC_S_FP_OVERFLOW;
|
||||
|
||||
case nca_s_fault_invalid_tag:
|
||||
return RPC_S_INVALID_TAG;
|
||||
|
||||
case nca_s_fault_invalid_bound:
|
||||
return RPC_S_INVALID_BOUND;
|
||||
|
||||
case nca_s_rpc_version_mismatch:
|
||||
return RPC_S_PROTOCOL_ERROR;
|
||||
|
||||
case nca_s_unspec_reject:
|
||||
return RPC_S_CALL_FAILED;
|
||||
|
||||
case nca_s_bad_actid:
|
||||
return RPC_S_CALL_FAILED_DNE;
|
||||
|
||||
case nca_s_who_are_you_failed:
|
||||
return RPC_S_CALL_FAILED;
|
||||
|
||||
case nca_s_manager_not_entered:
|
||||
return RPC_S_CALL_FAILED_DNE;
|
||||
|
||||
case nca_s_fault_cancel:
|
||||
return RPC_S_CALL_CANCELLED;
|
||||
|
||||
case nca_s_fault_ill_inst:
|
||||
return RPC_S_ADDRESS_ERROR;
|
||||
|
||||
case nca_s_fault_fp_error:
|
||||
return RPC_S_FP_OVERFLOW;
|
||||
|
||||
case nca_s_fault_int_overflow:
|
||||
return RPC_S_ADDRESS_ERROR;
|
||||
|
||||
case nca_s_fault_unspec:
|
||||
return RPC_S_CALL_FAILED;
|
||||
|
||||
case nca_s_fault_remote_comm_failure:
|
||||
return nca_s_fault_remote_comm_failure;
|
||||
|
||||
case nca_s_fault_pipe_empty:
|
||||
return RPC_X_PIPE_EMPTY;
|
||||
|
||||
case nca_s_fault_pipe_closed:
|
||||
return RPC_X_PIPE_CLOSED;
|
||||
|
||||
case nca_s_fault_pipe_order:
|
||||
return RPC_X_WRONG_PIPE_ORDER;
|
||||
|
||||
case nca_s_fault_pipe_discipline:
|
||||
return RPC_X_PIPE_DISCIPLINE_ERROR;
|
||||
|
||||
case nca_s_fault_pipe_comm_error:
|
||||
return RPC_S_COMM_FAILURE;
|
||||
|
||||
case nca_s_fault_pipe_memory:
|
||||
return RPC_S_OUT_OF_MEMORY;
|
||||
|
||||
case nca_s_fault_context_mismatch:
|
||||
return RPC_X_SS_CONTEXT_MISMATCH;
|
||||
|
||||
case nca_s_fault_remote_no_memory:
|
||||
return RPC_S_SERVER_OUT_OF_MEMORY;
|
||||
|
||||
case nca_s_invalid_pres_context_id:
|
||||
return RPC_S_PROTOCOL_ERROR;
|
||||
|
||||
case nca_s_unsupported_authn_level:
|
||||
return RPC_S_UNSUPPORTED_AUTHN_LEVEL;
|
||||
|
||||
case nca_s_invalid_checksum:
|
||||
return RPC_S_CALL_FAILED_DNE;
|
||||
|
||||
case nca_s_invalid_crc:
|
||||
return RPC_S_CALL_FAILED_DNE;
|
||||
|
||||
case nca_s_fault_user_defined:
|
||||
return nca_s_fault_user_defined;
|
||||
|
||||
case nca_s_fault_tx_open_failed:
|
||||
return nca_s_fault_tx_open_failed;
|
||||
|
||||
case nca_s_fault_codeset_conv_error:
|
||||
return nca_s_fault_codeset_conv_error;
|
||||
|
||||
case nca_s_fault_object_not_found:
|
||||
return nca_s_fault_object_not_found;
|
||||
|
||||
case nca_s_fault_no_client_stub:
|
||||
return nca_s_fault_no_client_stub;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
const char* rpc_error_to_string(UINT32 code)
|
||||
{
|
||||
static char buffer[1024];
|
||||
|
||||
for (size_t index = 0; index < ARRAYSIZE(RPC_FAULT_CODES); index++)
|
||||
{
|
||||
const RPC_FAULT_CODE* current = &RPC_FAULT_CODES[index];
|
||||
if (current->code == code)
|
||||
{
|
||||
(void)sprintf_s(buffer, ARRAYSIZE(buffer), "%s", current->name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < ARRAYSIZE(RPC_TSG_FAULT_CODES); index++)
|
||||
{
|
||||
const RPC_FAULT_CODE* current = &RPC_TSG_FAULT_CODES[index];
|
||||
if (current->code == code)
|
||||
{
|
||||
(void)sprintf_s(buffer, ARRAYSIZE(buffer), "%s", current->name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < ARRAYSIZE(RPC_TSG_FAULT_CODES); index++)
|
||||
{
|
||||
const RPC_FAULT_CODE* current = &RPC_TSG_FAULT_CODES[index];
|
||||
if (current->code == HRESULT_CODE(code))
|
||||
{
|
||||
(void)sprintf_s(buffer, ARRAYSIZE(buffer), "%s", current->name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
(void)sprintf_s(buffer, ARRAYSIZE(buffer), "%s [0x%08" PRIX32 "]", "UNKNOWN", code);
|
||||
out:
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char* rpc_error_to_category(UINT32 code)
|
||||
{
|
||||
for (size_t index = 0; index < ARRAYSIZE(RPC_FAULT_CODES); index++)
|
||||
{
|
||||
const RPC_FAULT_CODE* current = &RPC_FAULT_CODES[index];
|
||||
if (current->code == code)
|
||||
return current->category;
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < ARRAYSIZE(RPC_TSG_FAULT_CODES); index++)
|
||||
{
|
||||
const RPC_FAULT_CODE* current = &RPC_TSG_FAULT_CODES[index];
|
||||
if (current->code == code)
|
||||
return current->category;
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < ARRAYSIZE(RPC_TSG_FAULT_CODES); index++)
|
||||
{
|
||||
const RPC_FAULT_CODE* current = &RPC_TSG_FAULT_CODES[index];
|
||||
if (current->code == HRESULT_CODE(code))
|
||||
return current->category;
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
int rpc_recv_fault_pdu(UINT32 status)
|
||||
{
|
||||
UINT32 code = rpc_map_status_code_to_win32_error_code(status);
|
||||
WLog_ERR(TAG, "RPC Fault PDU: status=%s", rpc_error_to_string(code));
|
||||
return 0;
|
||||
}
|
||||
34
third_party/FreeRDP/libfreerdp/core/gateway/rpc_fault.h
vendored
Normal file
34
third_party/FreeRDP/libfreerdp/core/gateway/rpc_fault.h
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RPC Fault Handling
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_RPC_FAULT_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_RPC_FAULT_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL int rpc_recv_fault_pdu(UINT32 status);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* rpc_error_to_string(UINT32 code);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* rpc_error_to_category(UINT32 code);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_RPC_FAULT_H */
|
||||
2523
third_party/FreeRDP/libfreerdp/core/gateway/rts.c
vendored
Normal file
2523
third_party/FreeRDP/libfreerdp/core/gateway/rts.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
150
third_party/FreeRDP/libfreerdp/core/gateway/rts.h
vendored
Normal file
150
third_party/FreeRDP/libfreerdp/core/gateway/rts.h
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Request To Send (RTS) PDUs
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_RTS_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_RTS_H
|
||||
|
||||
#include <freerdp/config.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
|
||||
#define RTS_FLAG_RECYCLE_CHANNEL 0x0004
|
||||
#define RTS_FLAG_IN_CHANNEL 0x0008
|
||||
#define RTS_FLAG_OUT_CHANNEL 0x0010
|
||||
#define RTS_FLAG_EOF 0x0020
|
||||
#define RTS_FLAG_ECHO 0x0040
|
||||
|
||||
#define RTS_CMD_RECEIVE_WINDOW_SIZE 0x00000000
|
||||
#define RTS_CMD_FLOW_CONTROL_ACK 0x00000001
|
||||
#define RTS_CMD_CONNECTION_TIMEOUT 0x00000002
|
||||
#define RTS_CMD_COOKIE 0x00000003
|
||||
#define RTS_CMD_CHANNEL_LIFETIME 0x00000004
|
||||
#define RTS_CMD_CLIENT_KEEPALIVE 0x00000005
|
||||
#define RTS_CMD_VERSION 0x00000006
|
||||
#define RTS_CMD_EMPTY 0x00000007
|
||||
#define RTS_CMD_PADDING 0x00000008
|
||||
#define RTS_CMD_NEGATIVE_ANCE 0x00000009
|
||||
#define RTS_CMD_ANCE 0x0000000A
|
||||
#define RTS_CMD_CLIENT_ADDRESS 0x0000000B
|
||||
#define RTS_CMD_ASSOCIATION_GROUP_ID 0x0000000C
|
||||
#define RTS_CMD_DESTINATION 0x0000000D
|
||||
#define RTS_CMD_PING_TRAFFIC_SENT_NOTIFY 0x0000000E
|
||||
#define RTS_CMD_LAST_ID 0x0000000F
|
||||
|
||||
#define RTS_CMD_RECEIVE_WINDOW_SIZE_LENGTH 0x00000004
|
||||
#define RTS_CMD_FLOW_CONTROL_ACK_LENGTH 0x00000018
|
||||
#define RTS_CMD_CONNECTION_TIMEOUT_LENGTH 0x00000004
|
||||
#define RTS_CMD_COOKIE_LENGTH 0x00000010
|
||||
#define RTS_CMD_CHANNEL_LIFETIME_LENGTH 0x00000004
|
||||
#define RTS_CMD_CLIENT_KEEPALIVE_LENGTH 0x00000004
|
||||
#define RTS_CMD_VERSION_LENGTH 0x00000004
|
||||
#define RTS_CMD_EMPTY_LENGTH 0x00000000
|
||||
#define RTS_CMD_PADDING_LENGTH 0x00000000 /* variable-size */
|
||||
#define RTS_CMD_NEGATIVE_ANCE_LENGTH 0x00000000
|
||||
#define RTS_CMD_ANCE_LENGTH 0x00000000
|
||||
#define RTS_CMD_CLIENT_ADDRESS_LENGTH 0x00000000 /* variable-size */
|
||||
#define RTS_CMD_ASSOCIATION_GROUP_ID_LENGTH 0x00000010
|
||||
#define RTS_CMD_DESTINATION_LENGTH 0x00000004
|
||||
#define RTS_CMD_PING_TRAFFIC_SENT_NOTIFY_LENGTH 0x00000004
|
||||
|
||||
#define FDClient 0x00000000
|
||||
#define FDInProxy 0x00000001
|
||||
#define FDServer 0x00000002
|
||||
#define FDOutProxy 0x00000003
|
||||
|
||||
FREERDP_LOCAL BOOL rts_generate_cookie(BYTE* cookie);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_write_pdu_auth3(wStream* s, const rpcconn_rpc_auth_3_hdr_t* auth);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_write_pdu_bind(wStream* s, const rpcconn_bind_hdr_t* bind);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_read_pdu_header(wStream* s, rpcconn_hdr_t* header);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_read_pdu_header_ex(wStream* s, rpcconn_hdr_t* header, BOOL silent);
|
||||
|
||||
FREERDP_LOCAL void rts_free_pdu_header(rpcconn_hdr_t* header, BOOL allocated);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RTS_PDU_FAIL = -1,
|
||||
RTS_PDU_INCOMPLETE = 0,
|
||||
RTS_PDU_VALID = 1
|
||||
} rts_pdu_status_t;
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rts_pdu_status_t rts_read_common_pdu_header(wStream* s, rpcconn_common_hdr_t* header,
|
||||
BOOL ignoreErrors);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_command_length(UINT32 CommandType, wStream* s, size_t* length, BOOL silent);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_send_CONN_A1_pdu(rdpRpc* rpc);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_recv_CONN_A3_pdu(rdpRpc* rpc, wStream* buffer);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_send_CONN_B1_pdu(rdpRpc* rpc);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_recv_CONN_C2_pdu(rdpRpc* rpc, wStream* buffer);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_send_OUT_R1_A3_pdu(rdpRpc* rpc);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_send_flow_control_ack_pdu(rdpRpc* rpc);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_recv_out_of_sequence_pdu(rdpRpc* rpc, wStream* buffer,
|
||||
const rpcconn_hdr_t* header);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_recv_ping_pdu(rdpRpc* rpc, wStream* s);
|
||||
|
||||
#define Stream_ConditionalCheckAndLogRequiredLength(tag, s, size, silent) \
|
||||
rts_conditional_check_and_log(tag, s, size, silent, __func__, __FILE__, __LINE__)
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_conditional_check_and_log(const char* tag, wStream* s, size_t size,
|
||||
BOOL silent, const char* fkt, const char* file,
|
||||
size_t line);
|
||||
|
||||
#define Stream_ConditionalSafeSeek(s, size, silent) \
|
||||
rts_conditional_safe_seek(s, size, silent, __func__, __FILE__, __LINE__)
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_conditional_safe_seek(wStream* s, size_t size, BOOL silent, const char* fkt,
|
||||
const char* file, size_t line);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_RTS_H */
|
||||
416
third_party/FreeRDP/libfreerdp/core/gateway/rts_signature.c
vendored
Normal file
416
third_party/FreeRDP/libfreerdp/core/gateway/rts_signature.c
vendored
Normal file
@@ -0,0 +1,416 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Request To Send (RTS) PDU Signatures
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "rts_signature.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.rts")
|
||||
|
||||
const RtsPduSignature RTS_PDU_CONN_A1_SIGNATURE = {
|
||||
RTS_FLAG_NONE,
|
||||
4,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_CONN_A2_SIGNATURE = { RTS_FLAG_OUT_CHANNEL,
|
||||
5,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE,
|
||||
RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME,
|
||||
RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_CONN_A3_SIGNATURE = {
|
||||
RTS_FLAG_NONE, 1, { RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
const RtsPduSignature RTS_PDU_CONN_B1_SIGNATURE = {
|
||||
RTS_FLAG_NONE,
|
||||
6,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME,
|
||||
RTS_CMD_CLIENT_KEEPALIVE, RTS_CMD_ASSOCIATION_GROUP_ID, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_CONN_B2_SIGNATURE = {
|
||||
RTS_FLAG_IN_CHANNEL,
|
||||
7,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_RECEIVE_WINDOW_SIZE,
|
||||
RTS_CMD_CONNECTION_TIMEOUT, RTS_CMD_ASSOCIATION_GROUP_ID, RTS_CMD_CLIENT_ADDRESS, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_CONN_B3_SIGNATURE = {
|
||||
RTS_FLAG_NONE, 2, { RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_VERSION, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
const RtsPduSignature RTS_PDU_CONN_C1_SIGNATURE = { RTS_FLAG_NONE,
|
||||
3,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE,
|
||||
RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_CONN_C2_SIGNATURE = { RTS_FLAG_NONE,
|
||||
3,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_RECEIVE_WINDOW_SIZE,
|
||||
RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 } };
|
||||
|
||||
const RtsPduSignature RTS_PDU_IN_R1_A1_SIGNATURE = {
|
||||
RTS_FLAG_RECYCLE_CHANNEL,
|
||||
4,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_IN_R1_A2_SIGNATURE = {
|
||||
RTS_FLAG_NONE,
|
||||
4,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_RECEIVE_WINDOW_SIZE,
|
||||
RTS_CMD_CONNECTION_TIMEOUT, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_IN_R1_A3_SIGNATURE = { RTS_FLAG_NONE,
|
||||
4,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_VERSION,
|
||||
RTS_CMD_RECEIVE_WINDOW_SIZE,
|
||||
RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_IN_R1_A4_SIGNATURE = { RTS_FLAG_NONE,
|
||||
4,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_VERSION,
|
||||
RTS_CMD_RECEIVE_WINDOW_SIZE,
|
||||
RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_IN_R1_A5_SIGNATURE = { RTS_FLAG_NONE,
|
||||
1,
|
||||
{ RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_IN_R1_A6_SIGNATURE = { RTS_FLAG_NONE,
|
||||
1,
|
||||
{ RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
|
||||
const RtsPduSignature RTS_PDU_IN_R1_B1_SIGNATURE = { RTS_FLAG_NONE,
|
||||
1,
|
||||
{ RTS_CMD_EMPTY, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_IN_R1_B2_SIGNATURE = {
|
||||
RTS_FLAG_NONE, 1, { RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
const RtsPduSignature RTS_PDU_IN_R2_A1_SIGNATURE = {
|
||||
RTS_FLAG_RECYCLE_CHANNEL,
|
||||
4,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_IN_R2_A2_SIGNATURE = { RTS_FLAG_NONE,
|
||||
1,
|
||||
{ RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_IN_R2_A3_SIGNATURE = { RTS_FLAG_NONE,
|
||||
1,
|
||||
{ RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_IN_R2_A4_SIGNATURE = { RTS_FLAG_NONE,
|
||||
1,
|
||||
{ RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_IN_R2_A5_SIGNATURE = { RTS_FLAG_NONE,
|
||||
1,
|
||||
{ RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A1_SIGNATURE = {
|
||||
RTS_FLAG_RECYCLE_CHANNEL, 1, { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A2_SIGNATURE = {
|
||||
RTS_FLAG_RECYCLE_CHANNEL, 1, { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A3_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL,
|
||||
5,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE,
|
||||
RTS_CMD_COOKIE, RTS_CMD_COOKIE,
|
||||
RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A4_SIGNATURE = {
|
||||
RTS_FLAG_RECYCLE_CHANNEL | RTS_FLAG_OUT_CHANNEL,
|
||||
7,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_COOKIE, RTS_CMD_CHANNEL_LIFETIME,
|
||||
RTS_CMD_RECEIVE_WINDOW_SIZE, RTS_CMD_CONNECTION_TIMEOUT, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A5_SIGNATURE = {
|
||||
RTS_FLAG_OUT_CHANNEL,
|
||||
3,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A6_SIGNATURE = {
|
||||
RTS_FLAG_OUT_CHANNEL,
|
||||
3,
|
||||
{ RTS_CMD_DESTINATION, RTS_CMD_VERSION, RTS_CMD_CONNECTION_TIMEOUT, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A7_SIGNATURE = {
|
||||
RTS_FLAG_OUT_CHANNEL, 2, { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A8_SIGNATURE = {
|
||||
RTS_FLAG_OUT_CHANNEL, 2, { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A9_SIGNATURE = { RTS_FLAG_NONE,
|
||||
1,
|
||||
{ RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A10_SIGNATURE = { RTS_FLAG_NONE,
|
||||
1,
|
||||
{ RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_OUT_R1_A11_SIGNATURE = { RTS_FLAG_NONE,
|
||||
1,
|
||||
{ RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A1_SIGNATURE = {
|
||||
RTS_FLAG_RECYCLE_CHANNEL, 1, { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A2_SIGNATURE = {
|
||||
RTS_FLAG_RECYCLE_CHANNEL, 1, { RTS_CMD_DESTINATION, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A3_SIGNATURE = { RTS_FLAG_RECYCLE_CHANNEL,
|
||||
5,
|
||||
{ RTS_CMD_VERSION, RTS_CMD_COOKIE,
|
||||
RTS_CMD_COOKIE, RTS_CMD_COOKIE,
|
||||
RTS_CMD_RECEIVE_WINDOW_SIZE, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A4_SIGNATURE = { RTS_FLAG_NONE,
|
||||
1,
|
||||
{ RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A5_SIGNATURE = {
|
||||
RTS_FLAG_NONE, 2, { RTS_CMD_DESTINATION, RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A6_SIGNATURE = {
|
||||
RTS_FLAG_NONE, 2, { RTS_CMD_DESTINATION, RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A7_SIGNATURE = {
|
||||
RTS_FLAG_NONE, 3, { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, RTS_CMD_VERSION, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_A8_SIGNATURE = {
|
||||
RTS_FLAG_OUT_CHANNEL, 2, { RTS_CMD_DESTINATION, RTS_CMD_COOKIE, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_B1_SIGNATURE = { RTS_FLAG_NONE,
|
||||
1,
|
||||
{ RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_B2_SIGNATURE = {
|
||||
RTS_FLAG_NONE, 1, { RTS_CMD_NEGATIVE_ANCE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_B3_SIGNATURE = { RTS_FLAG_EOF,
|
||||
1,
|
||||
{ RTS_CMD_ANCE, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
|
||||
const RtsPduSignature RTS_PDU_OUT_R2_C1_SIGNATURE = { RTS_FLAG_PING,
|
||||
1,
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
|
||||
const RtsPduSignature RTS_PDU_KEEP_ALIVE_SIGNATURE = {
|
||||
RTS_FLAG_OTHER_CMD, 1, { RTS_CMD_CLIENT_KEEPALIVE, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_PING_TRAFFIC_SENT_NOTIFY_SIGNATURE = {
|
||||
RTS_FLAG_OTHER_CMD, 1, { RTS_CMD_PING_TRAFFIC_SENT_NOTIFY, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_ECHO_SIGNATURE = { RTS_FLAG_ECHO, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_PING_SIGNATURE = { RTS_FLAG_PING, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
const RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE = {
|
||||
RTS_FLAG_OTHER_CMD, 1, { RTS_CMD_FLOW_CONTROL_ACK, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
const RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE = {
|
||||
RTS_FLAG_OTHER_CMD, 2, { RTS_CMD_DESTINATION, RTS_CMD_FLOW_CONTROL_ACK, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const RTS_PDU_SIGNATURE_ENTRY RTS_PDU_SIGNATURE_TABLE[] = {
|
||||
{ RTS_PDU_CONN_A1, FALSE, &RTS_PDU_CONN_A1_SIGNATURE, "CONN/A1" },
|
||||
{ RTS_PDU_CONN_A2, FALSE, &RTS_PDU_CONN_A2_SIGNATURE, "CONN/A2" },
|
||||
{ RTS_PDU_CONN_A3, TRUE, &RTS_PDU_CONN_A3_SIGNATURE, "CONN/A3" },
|
||||
|
||||
{ RTS_PDU_CONN_B1, FALSE, &RTS_PDU_CONN_B1_SIGNATURE, "CONN/B1" },
|
||||
{ RTS_PDU_CONN_B2, FALSE, &RTS_PDU_CONN_B2_SIGNATURE, "CONN/B2" },
|
||||
{ RTS_PDU_CONN_B3, FALSE, &RTS_PDU_CONN_B3_SIGNATURE, "CONN/B3" },
|
||||
|
||||
{ RTS_PDU_CONN_C1, FALSE, &RTS_PDU_CONN_C1_SIGNATURE, "CONN/C1" },
|
||||
{ RTS_PDU_CONN_C2, TRUE, &RTS_PDU_CONN_C2_SIGNATURE, "CONN/C2" },
|
||||
|
||||
{ RTS_PDU_IN_R1_A1, FALSE, &RTS_PDU_IN_R1_A1_SIGNATURE, "IN_R1/A1" },
|
||||
{ RTS_PDU_IN_R1_A2, FALSE, &RTS_PDU_IN_R1_A2_SIGNATURE, "IN_R1/A2" },
|
||||
{ RTS_PDU_IN_R1_A3, FALSE, &RTS_PDU_IN_R1_A3_SIGNATURE, "IN_R1/A3" },
|
||||
{ RTS_PDU_IN_R1_A4, TRUE, &RTS_PDU_IN_R1_A4_SIGNATURE, "IN_R1/A4" },
|
||||
{ RTS_PDU_IN_R1_A5, TRUE, &RTS_PDU_IN_R1_A5_SIGNATURE, "IN_R1/A5" },
|
||||
{ RTS_PDU_IN_R1_A6, FALSE, &RTS_PDU_IN_R1_A6_SIGNATURE, "IN_R1/A6" },
|
||||
|
||||
{ RTS_PDU_IN_R1_B1, FALSE, &RTS_PDU_IN_R1_B1_SIGNATURE, "IN_R1/B1" },
|
||||
{ RTS_PDU_IN_R1_B2, FALSE, &RTS_PDU_IN_R1_B2_SIGNATURE, "IN_R1/B2" },
|
||||
|
||||
{ RTS_PDU_IN_R2_A1, FALSE, &RTS_PDU_IN_R2_A1_SIGNATURE, "IN_R2/A1" },
|
||||
{ RTS_PDU_IN_R2_A2, FALSE, &RTS_PDU_IN_R2_A2_SIGNATURE, "IN_R2/A2" },
|
||||
{ RTS_PDU_IN_R2_A3, FALSE, &RTS_PDU_IN_R2_A3_SIGNATURE, "IN_R2/A3" },
|
||||
{ RTS_PDU_IN_R2_A4, TRUE, &RTS_PDU_IN_R2_A4_SIGNATURE, "IN_R2/A4" },
|
||||
{ RTS_PDU_IN_R2_A5, FALSE, &RTS_PDU_IN_R2_A5_SIGNATURE, "IN_R2/A5" },
|
||||
|
||||
{ RTS_PDU_OUT_R1_A1, FALSE, &RTS_PDU_OUT_R1_A1_SIGNATURE, "OUT_R1/A1" },
|
||||
{ RTS_PDU_OUT_R1_A2, TRUE, &RTS_PDU_OUT_R1_A2_SIGNATURE, "OUT_R1/A2" },
|
||||
{ RTS_PDU_OUT_R1_A3, FALSE, &RTS_PDU_OUT_R1_A3_SIGNATURE, "OUT_R1/A3" },
|
||||
{ RTS_PDU_OUT_R1_A4, FALSE, &RTS_PDU_OUT_R1_A4_SIGNATURE, "OUT_R1/A4" },
|
||||
{ RTS_PDU_OUT_R1_A5, FALSE, &RTS_PDU_OUT_R1_A5_SIGNATURE, "OUT_R1/A5" },
|
||||
{ RTS_PDU_OUT_R1_A6, TRUE, &RTS_PDU_OUT_R1_A6_SIGNATURE, "OUT_R1/A6" },
|
||||
{ RTS_PDU_OUT_R1_A7, FALSE, &RTS_PDU_OUT_R1_A7_SIGNATURE, "OUT_R1/A7" },
|
||||
{ RTS_PDU_OUT_R1_A8, FALSE, &RTS_PDU_OUT_R1_A8_SIGNATURE, "OUT_R1/A8" },
|
||||
{ RTS_PDU_OUT_R1_A9, FALSE, &RTS_PDU_OUT_R1_A9_SIGNATURE, "OUT_R1/A9" },
|
||||
{ RTS_PDU_OUT_R1_A10, TRUE, &RTS_PDU_OUT_R1_A10_SIGNATURE, "OUT_R1/A10" },
|
||||
{ RTS_PDU_OUT_R1_A11, FALSE, &RTS_PDU_OUT_R1_A11_SIGNATURE, "OUT_R1/A11" },
|
||||
|
||||
{ RTS_PDU_OUT_R2_A1, FALSE, &RTS_PDU_OUT_R2_A1_SIGNATURE, "OUT_R2/A1" },
|
||||
{ RTS_PDU_OUT_R2_A2, TRUE, &RTS_PDU_OUT_R2_A2_SIGNATURE, "OUT_R2/A2" },
|
||||
{ RTS_PDU_OUT_R2_A3, FALSE, &RTS_PDU_OUT_R2_A3_SIGNATURE, "OUT_R2/A3" },
|
||||
{ RTS_PDU_OUT_R2_A4, FALSE, &RTS_PDU_OUT_R2_A4_SIGNATURE, "OUT_R2/A4" },
|
||||
{ RTS_PDU_OUT_R2_A5, FALSE, &RTS_PDU_OUT_R2_A5_SIGNATURE, "OUT_R2/A5" },
|
||||
{ RTS_PDU_OUT_R2_A6, TRUE, &RTS_PDU_OUT_R2_A6_SIGNATURE, "OUT_R2/A6" },
|
||||
{ RTS_PDU_OUT_R2_A7, FALSE, &RTS_PDU_OUT_R2_A7_SIGNATURE, "OUT_R2/A7" },
|
||||
{ RTS_PDU_OUT_R2_A8, FALSE, &RTS_PDU_OUT_R2_A8_SIGNATURE, "OUT_R2/A8" },
|
||||
|
||||
{ RTS_PDU_OUT_R2_B1, FALSE, &RTS_PDU_OUT_R2_B1_SIGNATURE, "OUT_R2/B1" },
|
||||
{ RTS_PDU_OUT_R2_B2, FALSE, &RTS_PDU_OUT_R2_B2_SIGNATURE, "OUT_R2/B2" },
|
||||
{ RTS_PDU_OUT_R2_B3, TRUE, &RTS_PDU_OUT_R2_B3_SIGNATURE, "OUT_R2/B3" },
|
||||
|
||||
{ RTS_PDU_OUT_R2_C1, FALSE, &RTS_PDU_OUT_R2_C1_SIGNATURE, "OUT_R2/C1" },
|
||||
|
||||
{ RTS_PDU_KEEP_ALIVE, TRUE, &RTS_PDU_KEEP_ALIVE_SIGNATURE, "Keep-Alive" },
|
||||
{ RTS_PDU_PING_TRAFFIC_SENT_NOTIFY, TRUE, &RTS_PDU_PING_TRAFFIC_SENT_NOTIFY_SIGNATURE,
|
||||
"Ping Traffic Sent Notify" },
|
||||
{ RTS_PDU_ECHO, TRUE, &RTS_PDU_ECHO_SIGNATURE, "Echo" },
|
||||
{ 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" }
|
||||
};
|
||||
|
||||
BOOL rts_match_pdu_signature(const RtsPduSignature* signature, wStream* src,
|
||||
const rpcconn_hdr_t* header)
|
||||
{
|
||||
return rts_match_pdu_signature_ex(signature, src, header, nullptr, FALSE);
|
||||
}
|
||||
|
||||
BOOL rts_match_pdu_signature_ex(const RtsPduSignature* signature, wStream* src,
|
||||
const rpcconn_hdr_t* header, RtsPduSignature* found_signature,
|
||||
BOOL silent)
|
||||
{
|
||||
RtsPduSignature extracted = WINPR_C_ARRAY_INIT;
|
||||
|
||||
WINPR_ASSERT(signature);
|
||||
WINPR_ASSERT(src);
|
||||
|
||||
if (!rts_extract_pdu_signature_ex(&extracted, src, header, silent))
|
||||
return FALSE;
|
||||
|
||||
if (found_signature)
|
||||
*found_signature = extracted;
|
||||
return memcmp(signature, &extracted, sizeof(extracted)) == 0;
|
||||
}
|
||||
|
||||
BOOL rts_extract_pdu_signature(RtsPduSignature* signature, wStream* src,
|
||||
const rpcconn_hdr_t* header)
|
||||
{
|
||||
return rts_extract_pdu_signature_ex(signature, src, header, FALSE);
|
||||
}
|
||||
|
||||
BOOL rts_extract_pdu_signature_ex(RtsPduSignature* signature, wStream* src,
|
||||
const rpcconn_hdr_t* header, BOOL silent)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
wStream sbuffer = WINPR_C_ARRAY_INIT;
|
||||
rpcconn_hdr_t rheader = WINPR_C_ARRAY_INIT;
|
||||
const rpcconn_rts_hdr_t* rts = nullptr;
|
||||
|
||||
WINPR_ASSERT(signature);
|
||||
WINPR_ASSERT(src);
|
||||
|
||||
wStream* s = Stream_StaticInit(&sbuffer, Stream_Pointer(src), Stream_GetRemainingLength(src));
|
||||
if (!header)
|
||||
{
|
||||
if (!rts_read_pdu_header_ex(s, &rheader, silent))
|
||||
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;
|
||||
|
||||
for (UINT16 i = 0; i < rts->NumberOfCommands; i++)
|
||||
{
|
||||
UINT32 CommandType = 0;
|
||||
size_t CommandLength = 0;
|
||||
|
||||
if (!Stream_ConditionalCheckAndLogRequiredLength(TAG, s, 4, silent))
|
||||
goto fail;
|
||||
|
||||
Stream_Read_UINT32(s, 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, s, &CommandLength, silent))
|
||||
goto fail;
|
||||
if (!Stream_ConditionalSafeSeek(s, CommandLength, silent))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
rts_free_pdu_header(&rheader, FALSE);
|
||||
return rc;
|
||||
}
|
||||
|
||||
UINT32 rts_identify_pdu_signature(const RtsPduSignature* signature,
|
||||
const RTS_PDU_SIGNATURE_ENTRY** entry)
|
||||
{
|
||||
if (entry)
|
||||
*entry = nullptr;
|
||||
|
||||
for (size_t 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)
|
||||
continue;
|
||||
|
||||
if (signature->NumberOfCommands != pSignature->NumberOfCommands)
|
||||
continue;
|
||||
|
||||
for (size_t j = 0; j < signature->NumberOfCommands; j++)
|
||||
{
|
||||
if (signature->CommandTypes[j] != pSignature->CommandTypes[j])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry)
|
||||
*entry = current;
|
||||
|
||||
return current->SignatureId;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL rts_print_pdu_signature(wLog* log, DWORD level, const RtsPduSignature* signature)
|
||||
{
|
||||
UINT32 SignatureId = 0;
|
||||
const RTS_PDU_SIGNATURE_ENTRY* entry = nullptr;
|
||||
|
||||
WINPR_ASSERT(signature);
|
||||
|
||||
WLog_Print(log, level,
|
||||
"RTS PDU Signature: Flags: 0x%04" PRIX16 " NumberOfCommands: %" PRIu16 "",
|
||||
signature->Flags, signature->NumberOfCommands);
|
||||
SignatureId = rts_identify_pdu_signature(signature, &entry);
|
||||
|
||||
if (SignatureId)
|
||||
WLog_Print(log, level, "Identified %s RTS PDU", entry->PduName);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
202
third_party/FreeRDP/libfreerdp/core/gateway/rts_signature.h
vendored
Normal file
202
third_party/FreeRDP/libfreerdp/core/gateway/rts_signature.h
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Request To Send (RTS) PDU Signatures
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_RTS_SIGNATURE_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_RTS_SIGNATURE_H
|
||||
|
||||
#include "rts.h"
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 Flags;
|
||||
UINT16 NumberOfCommands;
|
||||
UINT32 CommandTypes[8];
|
||||
} RtsPduSignature;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 SignatureId;
|
||||
BOOL SignatureClient;
|
||||
const RtsPduSignature* Signature;
|
||||
const char* PduName;
|
||||
} RTS_PDU_SIGNATURE_ENTRY;
|
||||
|
||||
/* RTS PDU Signature IDs */
|
||||
|
||||
#define RTS_PDU_CONN_A 0x10000000
|
||||
#define RTS_PDU_CONN_A1 (RTS_PDU_CONN_A | 0x00000001)
|
||||
#define RTS_PDU_CONN_A2 (RTS_PDU_CONN_A | 0x00000002)
|
||||
#define RTS_PDU_CONN_A3 (RTS_PDU_CONN_A | 0x00000003)
|
||||
|
||||
#define RTS_PDU_CONN_B 0x20000000
|
||||
#define RTS_PDU_CONN_B1 (RTS_PDU_CONN_B | 0x00000001)
|
||||
#define RTS_PDU_CONN_B2 (RTS_PDU_CONN_B | 0x00000002)
|
||||
#define RTS_PDU_CONN_B3 (RTS_PDU_CONN_B | 0x00000003)
|
||||
|
||||
#define RTS_PDU_CONN_C 0x40000000
|
||||
#define RTS_PDU_CONN_C1 (RTS_PDU_CONN_C | 0x00000001)
|
||||
#define RTS_PDU_CONN_C2 (RTS_PDU_CONN_C | 0x00000002)
|
||||
|
||||
#define RTS_PDU_IN_R1_A 0x01000000
|
||||
#define RTS_PDU_IN_R1_A1 (RTS_PDU_IN_R1_A | 0x00000001)
|
||||
#define RTS_PDU_IN_R1_A2 (RTS_PDU_IN_R1_A | 0x00000002)
|
||||
#define RTS_PDU_IN_R1_A3 (RTS_PDU_IN_R1_A | 0x00000003)
|
||||
#define RTS_PDU_IN_R1_A4 (RTS_PDU_IN_R1_A | 0x00000004)
|
||||
#define RTS_PDU_IN_R1_A5 (RTS_PDU_IN_R1_A | 0x00000005)
|
||||
#define RTS_PDU_IN_R1_A6 (RTS_PDU_IN_R1_A | 0x00000006)
|
||||
|
||||
#define RTS_PDU_IN_R1_B 0x02000000
|
||||
#define RTS_PDU_IN_R1_B1 (RTS_PDU_IN_R1_B | 0x00000001)
|
||||
#define RTS_PDU_IN_R1_B2 (RTS_PDU_IN_R1_B | 0x00000002)
|
||||
|
||||
#define RTS_PDU_IN_R2_A 0x04000000
|
||||
#define RTS_PDU_IN_R2_A1 (RTS_PDU_IN_R2_A | 0x00000001)
|
||||
#define RTS_PDU_IN_R2_A2 (RTS_PDU_IN_R2_A | 0x00000002)
|
||||
#define RTS_PDU_IN_R2_A3 (RTS_PDU_IN_R2_A | 0x00000003)
|
||||
#define RTS_PDU_IN_R2_A4 (RTS_PDU_IN_R2_A | 0x00000004)
|
||||
#define RTS_PDU_IN_R2_A5 (RTS_PDU_IN_R2_A | 0x00000005)
|
||||
|
||||
#define RTS_PDU_OUT_R1_A 0x00100000
|
||||
#define RTS_PDU_OUT_R1_A1 (RTS_PDU_OUT_R1_A | 0x00000001)
|
||||
#define RTS_PDU_OUT_R1_A2 (RTS_PDU_OUT_R1_A | 0x00000002)
|
||||
#define RTS_PDU_OUT_R1_A3 (RTS_PDU_OUT_R1_A | 0x00000003)
|
||||
#define RTS_PDU_OUT_R1_A4 (RTS_PDU_OUT_R1_A | 0x00000004)
|
||||
#define RTS_PDU_OUT_R1_A5 (RTS_PDU_OUT_R1_A | 0x00000005)
|
||||
#define RTS_PDU_OUT_R1_A6 (RTS_PDU_OUT_R1_A | 0x00000006)
|
||||
#define RTS_PDU_OUT_R1_A7 (RTS_PDU_OUT_R1_A | 0x00000007)
|
||||
#define RTS_PDU_OUT_R1_A8 (RTS_PDU_OUT_R1_A | 0x00000008)
|
||||
#define RTS_PDU_OUT_R1_A9 (RTS_PDU_OUT_R1_A | 0x00000009)
|
||||
#define RTS_PDU_OUT_R1_A10 (RTS_PDU_OUT_R1_A | 0x0000000A)
|
||||
#define RTS_PDU_OUT_R1_A11 (RTS_PDU_OUT_R1_A | 0x0000000B)
|
||||
|
||||
#define RTS_PDU_OUT_R2_A 0x00200000
|
||||
#define RTS_PDU_OUT_R2_A1 (RTS_PDU_OUT_R2_A | 0x00000001)
|
||||
#define RTS_PDU_OUT_R2_A2 (RTS_PDU_OUT_R2_A | 0x00000002)
|
||||
#define RTS_PDU_OUT_R2_A3 (RTS_PDU_OUT_R2_A | 0x00000003)
|
||||
#define RTS_PDU_OUT_R2_A4 (RTS_PDU_OUT_R2_A | 0x00000004)
|
||||
#define RTS_PDU_OUT_R2_A5 (RTS_PDU_OUT_R2_A | 0x00000005)
|
||||
#define RTS_PDU_OUT_R2_A6 (RTS_PDU_OUT_R2_A | 0x00000006)
|
||||
#define RTS_PDU_OUT_R2_A7 (RTS_PDU_OUT_R2_A | 0x00000007)
|
||||
#define RTS_PDU_OUT_R2_A8 (RTS_PDU_OUT_R2_A | 0x00000008)
|
||||
|
||||
#define RTS_PDU_OUT_R2_B 0x00400000
|
||||
#define RTS_PDU_OUT_R2_B1 (RTS_PDU_OUT_R2_B | 0x00000001)
|
||||
#define RTS_PDU_OUT_R2_B2 (RTS_PDU_OUT_R2_B | 0x00000002)
|
||||
#define RTS_PDU_OUT_R2_B3 (RTS_PDU_OUT_R2_B | 0x00000003)
|
||||
|
||||
#define RTS_PDU_OUT_R2_C 0x00800000
|
||||
#define RTS_PDU_OUT_R2_C1 (RTS_PDU_OUT_R2_C | 0x00000001)
|
||||
|
||||
#define RTS_PDU_OUT_OF_SEQUENCE 0x00010000
|
||||
#define RTS_PDU_KEEP_ALIVE (RTS_PDU_OUT_OF_SEQUENCE | 0x00000001)
|
||||
#define RTS_PDU_PING_TRAFFIC_SENT_NOTIFY (RTS_PDU_OUT_OF_SEQUENCE | 0x00000002)
|
||||
#define RTS_PDU_ECHO (RTS_PDU_OUT_OF_SEQUENCE | 0x00000003)
|
||||
#define RTS_PDU_PING (RTS_PDU_OUT_OF_SEQUENCE | 0x00000004)
|
||||
#define RTS_PDU_FLOW_CONTROL_ACK (RTS_PDU_OUT_OF_SEQUENCE | 0x00000005)
|
||||
#define RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION (RTS_PDU_OUT_OF_SEQUENCE | 0x00000006)
|
||||
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_A3_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_B1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_B2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_B3_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_C1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_CONN_C2_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_A4_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_A5_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_A6_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_B1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R1_B2_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R2_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R2_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R2_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R2_A4_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_IN_R2_A5_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A4_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A5_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A6_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A7_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A8_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A9_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A10_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R1_A11_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A3_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A4_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A5_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A6_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A7_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_A8_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_B1_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_B2_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_B3_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_OUT_R2_C1_SIGNATURE;
|
||||
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_KEEP_ALIVE_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_PING_TRAFFIC_SENT_NOTIFY_SIGNATURE;
|
||||
FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_ECHO_SIGNATURE;
|
||||
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;
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_match_pdu_signature(const RtsPduSignature* signature, wStream* s,
|
||||
const rpcconn_hdr_t* header);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_match_pdu_signature_ex(const RtsPduSignature* signature, wStream* s,
|
||||
const rpcconn_hdr_t* header,
|
||||
RtsPduSignature* found_signature, BOOL silent);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_extract_pdu_signature(RtsPduSignature* signature, wStream* s,
|
||||
const rpcconn_hdr_t* header);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rts_extract_pdu_signature_ex(RtsPduSignature* signature, wStream* s,
|
||||
const rpcconn_hdr_t* header, BOOL silent);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL UINT32 rts_identify_pdu_signature(const RtsPduSignature* signature,
|
||||
const RTS_PDU_SIGNATURE_ENTRY** entry);
|
||||
|
||||
FREERDP_LOCAL BOOL rts_print_pdu_signature(wLog* log, DWORD level,
|
||||
const RtsPduSignature* signature);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_RTS_SIGNATURE_H */
|
||||
3341
third_party/FreeRDP/libfreerdp/core/gateway/tsg.c
vendored
Normal file
3341
third_party/FreeRDP/libfreerdp/core/gateway/tsg.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
132
third_party/FreeRDP/libfreerdp/core/gateway/tsg.h
vendored
Normal file
132
third_party/FreeRDP/libfreerdp/core/gateway/tsg.h
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Terminal Server Gateway (TSG)
|
||||
*
|
||||
* Copyright 2012 Fujitsu Technology Solutions GmbH
|
||||
* Copyright 2012 Dmitrij Jasnov <dmitrij.jasnov@ts.fujitsu.com>
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_TSG_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_TSG_H
|
||||
|
||||
typedef struct rdp_tsg rdpTsg;
|
||||
|
||||
#include "rpc.h"
|
||||
|
||||
#include "../transport.h"
|
||||
|
||||
#include <winpr/rpc.h>
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TSG_STATE_INITIAL,
|
||||
TSG_STATE_CONNECTED,
|
||||
TSG_STATE_AUTHORIZED,
|
||||
TSG_STATE_CHANNEL_CREATED,
|
||||
TSG_STATE_PIPE_CREATED,
|
||||
TSG_STATE_TUNNEL_CLOSE_PENDING,
|
||||
TSG_STATE_CHANNEL_CLOSE_PENDING,
|
||||
TSG_STATE_FINAL
|
||||
} TSG_STATE;
|
||||
|
||||
static const uint16_t TsProxyCreateTunnelOpnum = 1u;
|
||||
static const uint16_t TsProxyAuthorizeTunnelOpnum = 2u;
|
||||
static const uint16_t TsProxyMakeTunnelCallOpnum = 3u;
|
||||
static const uint16_t TsProxyCreateChannelOpnum = 4u;
|
||||
static const uint16_t TsProxyUnused5Opnum = 5u;
|
||||
static const uint16_t TsProxyCloseChannelOpnum = 6u;
|
||||
static const uint16_t TsProxyCloseTunnelOpnum = 7u;
|
||||
static const uint16_t TsProxySetupReceivePipeOpnum = 8u;
|
||||
static const uint16_t TsProxySendToServerOpnum = 9u;
|
||||
|
||||
#define TS_GATEWAY_TRANSPORT 0x5452u
|
||||
|
||||
#define TSG_ASYNC_MESSAGE_CONSENT_MESSAGE 0x00000001u
|
||||
#define TSG_ASYNC_MESSAGE_SERVICE_MESSAGE 0x00000002u
|
||||
#define TSG_ASYNC_MESSAGE_REAUTH 0x00000003u
|
||||
|
||||
#define TSG_TUNNEL_CALL_ASYNC_MSG_REQUEST 0x00000001u
|
||||
#define TSG_TUNNEL_CANCEL_ASYNC_MSG_REQUEST 0x00000002u
|
||||
|
||||
#define TSG_NAP_CAPABILITY_QUAR_SOH 0x00000001u
|
||||
#define TSG_NAP_CAPABILITY_IDLE_TIMEOUT 0x00000002u
|
||||
#define TSG_MESSAGING_CAP_CONSENT_SIGN 0x00000004u
|
||||
#define TSG_MESSAGING_CAP_SERVICE_MSG 0x00000008u
|
||||
#define TSG_MESSAGING_CAP_REAUTH 0x00000010u
|
||||
#define TSG_MESSAGING_MAX_MESSAGE_LENGTH 65536u
|
||||
|
||||
/* Error Codes */
|
||||
|
||||
#define E_PROXY_INTERNALERROR 0x800759D8
|
||||
#define E_PROXY_RAP_ACCESSDENIED 0x800759DA
|
||||
#define E_PROXY_NAP_ACCESSDENIED 0x800759DB
|
||||
#define E_PROXY_TS_CONNECTFAILED 0x800759DD
|
||||
#define E_PROXY_ALREADYDISCONNECTED 0x800759DF
|
||||
#define E_PROXY_QUARANTINE_ACCESSDENIED 0x800759ED
|
||||
#define E_PROXY_NOCERTAVAILABLE 0x800759EE
|
||||
#define E_PROXY_COOKIE_BADPACKET 0x800759F7
|
||||
#define E_PROXY_COOKIE_AUTHENTICATION_ACCESS_DENIED 0x800759F8
|
||||
#define E_PROXY_UNSUPPORTED_AUTHENTICATION_METHOD 0x800759F9
|
||||
#define E_PROXY_CAPABILITYMISMATCH 0x800759E9
|
||||
|
||||
#define E_PROXY_NOTSUPPORTED 0x000059E8
|
||||
#define E_PROXY_MAXCONNECTIONSREACHED 0x000059E6
|
||||
#define E_PROXY_SESSIONTIMEOUT 0x000059F6
|
||||
#define E_PROXY_REAUTH_AUTHN_FAILED 0x000059FA
|
||||
#define E_PROXY_REAUTH_CAP_FAILED 0x000059FB
|
||||
#define E_PROXY_REAUTH_RAP_FAILED 0x000059FC
|
||||
#define E_PROXY_SDR_NOT_SUPPORTED_BY_TS 0x000059FD
|
||||
#define E_PROXY_REAUTH_NAP_FAILED 0x00005A00
|
||||
#define E_PROXY_CONNECTIONABORTED 0x000004D4
|
||||
|
||||
FREERDP_LOCAL void tsg_free(rdpTsg* tsg);
|
||||
|
||||
WINPR_ATTR_MALLOC(tsg_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpTsg* tsg_new(rdpTransport* transport);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL tsg_proxy_begin(rdpTsg* tsg);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, DWORD timeout);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL tsg_disconnect(rdpTsg* tsg);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL tsg_recv_pdu(rdpTsg* tsg, const RPC_PDU* pdu);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL tsg_check_event_handles(rdpTsg* tsg);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL DWORD tsg_get_event_handles(rdpTsg* tsg, HANDLE* events, DWORD count);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL TSG_STATE tsg_get_state(rdpTsg* tsg);
|
||||
|
||||
FREERDP_LOCAL BOOL tsg_set_state(rdpTsg* tsg, TSG_STATE state);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BIO* tsg_get_bio(rdpTsg* tsg);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_TSG_H */
|
||||
495
third_party/FreeRDP/libfreerdp/core/gateway/websocket.c
vendored
Normal file
495
third_party/FreeRDP/libfreerdp/core/gateway/websocket.c
vendored
Normal file
@@ -0,0 +1,495 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Websocket Framing
|
||||
*
|
||||
* Copyright 2023 Michael Saxl <mike@mwsys.mine.bz>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "websocket.h"
|
||||
#include <freerdp/log.h>
|
||||
#include "../tcp.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.websocket")
|
||||
|
||||
struct s_websocket_context
|
||||
{
|
||||
size_t payloadLength;
|
||||
uint32_t maskingKey;
|
||||
BOOL masking;
|
||||
BOOL closeSent;
|
||||
BYTE opcode;
|
||||
BYTE fragmentOriginalOpcode;
|
||||
BYTE lengthAndMaskPosition;
|
||||
WEBSOCKET_STATE state;
|
||||
wStream* responseStreamBuffer;
|
||||
};
|
||||
|
||||
static int websocket_write_all(BIO* bio, const BYTE* data, size_t length);
|
||||
|
||||
BOOL websocket_context_mask_and_send(BIO* bio, wStream* sPacket, wStream* sDataPacket,
|
||||
UINT32 maskingKey)
|
||||
{
|
||||
const size_t len = Stream_Length(sDataPacket);
|
||||
Stream_ResetPosition(sDataPacket);
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(sPacket, len))
|
||||
return FALSE;
|
||||
|
||||
/* mask as much as possible with 32bit access */
|
||||
size_t streamPos = 0;
|
||||
for (; streamPos + 4 <= len; streamPos += 4)
|
||||
{
|
||||
const uint32_t data = Stream_Get_UINT32(sDataPacket);
|
||||
Stream_Write_UINT32(sPacket, data ^ maskingKey);
|
||||
}
|
||||
|
||||
/* mask the rest byte by byte */
|
||||
for (; streamPos < len; streamPos++)
|
||||
{
|
||||
BYTE data = 0;
|
||||
BYTE* partialMask = ((BYTE*)&maskingKey) + (streamPos % 4);
|
||||
Stream_Read_UINT8(sDataPacket, data);
|
||||
Stream_Write_UINT8(sPacket, data ^ *partialMask);
|
||||
}
|
||||
|
||||
Stream_SealLength(sPacket);
|
||||
|
||||
ERR_clear_error();
|
||||
const size_t size = Stream_Length(sPacket);
|
||||
const int status = websocket_write_all(bio, Stream_Buffer(sPacket), size);
|
||||
Stream_Free(sPacket, TRUE);
|
||||
|
||||
return !((status < 0) || ((size_t)status != size));
|
||||
}
|
||||
|
||||
wStream* websocket_context_packet_new(size_t len, WEBSOCKET_OPCODE opcode, UINT32* pMaskingKey)
|
||||
{
|
||||
WINPR_ASSERT(pMaskingKey);
|
||||
if (len > INT_MAX)
|
||||
return nullptr;
|
||||
|
||||
size_t fullLen = 0;
|
||||
if (len < 126)
|
||||
fullLen = len + 6; /* 2 byte "mini header" + 4 byte masking key */
|
||||
else if (len < 0x10000)
|
||||
fullLen = len + 8; /* 2 byte "mini header" + 2 byte length + 4 byte masking key */
|
||||
else
|
||||
fullLen = len + 14; /* 2 byte "mini header" + 8 byte length + 4 byte masking key */
|
||||
|
||||
UINT32 maskingKey = 0;
|
||||
if (winpr_RAND(&maskingKey, sizeof(maskingKey)) < 0)
|
||||
return nullptr;
|
||||
|
||||
wStream* sWS = Stream_New(nullptr, fullLen);
|
||||
if (!sWS)
|
||||
return nullptr;
|
||||
|
||||
Stream_Write_UINT8(sWS, (UINT8)(WEBSOCKET_FIN_BIT | opcode));
|
||||
if (len < 126)
|
||||
Stream_Write_UINT8(sWS, (UINT8)len | WEBSOCKET_MASK_BIT);
|
||||
else if (len < 0x10000)
|
||||
{
|
||||
Stream_Write_UINT8(sWS, 126 | WEBSOCKET_MASK_BIT);
|
||||
Stream_Write_UINT16_BE(sWS, (UINT16)len);
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream_Write_UINT8(sWS, 127 | WEBSOCKET_MASK_BIT);
|
||||
Stream_Write_UINT32_BE(sWS, 0); /* payload is limited to INT_MAX */
|
||||
Stream_Write_UINT32_BE(sWS, (UINT32)len);
|
||||
}
|
||||
Stream_Write_UINT32(sWS, maskingKey);
|
||||
*pMaskingKey = maskingKey;
|
||||
return sWS;
|
||||
}
|
||||
|
||||
BOOL websocket_context_write_wstream(websocket_context* context, BIO* bio, wStream* sPacket,
|
||||
WEBSOCKET_OPCODE opcode)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
if (context->closeSent)
|
||||
return FALSE;
|
||||
|
||||
if (opcode == WebsocketCloseOpcode)
|
||||
context->closeSent = TRUE;
|
||||
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(sPacket);
|
||||
|
||||
const size_t len = Stream_Length(sPacket);
|
||||
uint32_t maskingKey = 0;
|
||||
wStream* sWS = websocket_context_packet_new(len, opcode, &maskingKey);
|
||||
if (!sWS)
|
||||
return FALSE;
|
||||
|
||||
return websocket_context_mask_and_send(bio, sWS, sPacket, maskingKey);
|
||||
}
|
||||
|
||||
int websocket_write_all(BIO* bio, const BYTE* data, size_t length)
|
||||
{
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(data);
|
||||
size_t offset = 0;
|
||||
|
||||
if (length > INT32_MAX)
|
||||
return -1;
|
||||
|
||||
while (offset < length)
|
||||
{
|
||||
ERR_clear_error();
|
||||
const size_t diff = length - offset;
|
||||
int status = BIO_write(bio, &data[offset], (int)diff);
|
||||
|
||||
if (status > 0)
|
||||
offset += (size_t)status;
|
||||
else
|
||||
{
|
||||
if (!BIO_should_retry(bio))
|
||||
return -1;
|
||||
|
||||
if (BIO_write_blocked(bio))
|
||||
{
|
||||
const long rstatus = BIO_wait_write(bio, 100);
|
||||
if (rstatus < 0)
|
||||
return -1;
|
||||
}
|
||||
else if (BIO_read_blocked(bio))
|
||||
return -2; /* Abort write, there is data that must be read */
|
||||
else
|
||||
USleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
return (int)length;
|
||||
}
|
||||
|
||||
int websocket_context_write(websocket_context* context, BIO* bio, const BYTE* buf, int isize,
|
||||
WEBSOCKET_OPCODE opcode)
|
||||
{
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(buf);
|
||||
|
||||
if (isize < 0)
|
||||
return -1;
|
||||
|
||||
wStream sbuffer = WINPR_C_ARRAY_INIT;
|
||||
wStream* s = Stream_StaticConstInit(&sbuffer, buf, (size_t)isize);
|
||||
if (!websocket_context_write_wstream(context, bio, s, opcode))
|
||||
return -2;
|
||||
return isize;
|
||||
}
|
||||
|
||||
static int websocket_read_data(BIO* bio, BYTE* pBuffer, size_t size,
|
||||
websocket_context* encodingContext)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(pBuffer);
|
||||
WINPR_ASSERT(encodingContext);
|
||||
|
||||
if (encodingContext->payloadLength == 0)
|
||||
{
|
||||
encodingContext->state = WebsocketStateOpcodeAndFin;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t rlen =
|
||||
(encodingContext->payloadLength < size ? encodingContext->payloadLength : size);
|
||||
if (rlen > INT32_MAX)
|
||||
return -1;
|
||||
|
||||
ERR_clear_error();
|
||||
status = BIO_read(bio, pBuffer, (int)rlen);
|
||||
if ((status <= 0) || ((size_t)status > encodingContext->payloadLength))
|
||||
return status;
|
||||
|
||||
encodingContext->payloadLength -= (size_t)status;
|
||||
|
||||
if (encodingContext->payloadLength == 0)
|
||||
encodingContext->state = WebsocketStateOpcodeAndFin;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int websocket_read_wstream(BIO* bio, websocket_context* encodingContext)
|
||||
{
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(encodingContext);
|
||||
|
||||
wStream* s = encodingContext->responseStreamBuffer;
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
if (encodingContext->payloadLength == 0)
|
||||
{
|
||||
encodingContext->state = WebsocketStateOpcodeAndFin;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, encodingContext->payloadLength))
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"wStream::capacity [%" PRIuz "] != encodingContext::paylaodLangth [%" PRIuz "]",
|
||||
Stream_GetRemainingCapacity(s), encodingContext->payloadLength);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int status = websocket_read_data(bio, Stream_Pointer(s), Stream_GetRemainingCapacity(s),
|
||||
encodingContext);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
if (!Stream_SafeSeek(s, (size_t)status))
|
||||
return -1;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static BOOL websocket_reply_close(BIO* bio, websocket_context* context, wStream* s)
|
||||
{
|
||||
WINPR_ASSERT(bio);
|
||||
|
||||
return websocket_context_write_wstream(context, bio, s, WebsocketCloseOpcode);
|
||||
}
|
||||
|
||||
static BOOL websocket_reply_pong(BIO* bio, websocket_context* context, wStream* s)
|
||||
{
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
if (Stream_GetPosition(s) != 0)
|
||||
return websocket_context_write_wstream(context, bio, s, WebsocketPongOpcode);
|
||||
|
||||
return websocket_reply_close(bio, context, nullptr);
|
||||
}
|
||||
|
||||
static int websocket_handle_payload(BIO* bio, BYTE* pBuffer, size_t size,
|
||||
websocket_context* encodingContext)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(pBuffer);
|
||||
WINPR_ASSERT(encodingContext);
|
||||
|
||||
const BYTE effectiveOpcode = ((encodingContext->opcode & 0xf) == WebsocketContinuationOpcode
|
||||
? encodingContext->fragmentOriginalOpcode & 0xf
|
||||
: encodingContext->opcode & 0xf);
|
||||
|
||||
switch (effectiveOpcode)
|
||||
{
|
||||
case WebsocketBinaryOpcode:
|
||||
{
|
||||
status = websocket_read_data(bio, pBuffer, size, encodingContext);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
return status;
|
||||
}
|
||||
case WebsocketPingOpcode:
|
||||
{
|
||||
status = websocket_read_wstream(bio, encodingContext);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
if (encodingContext->payloadLength == 0)
|
||||
{
|
||||
websocket_reply_pong(bio, encodingContext, encodingContext->responseStreamBuffer);
|
||||
Stream_ResetPosition(encodingContext->responseStreamBuffer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WebsocketPongOpcode:
|
||||
{
|
||||
status = websocket_read_wstream(bio, encodingContext);
|
||||
if (status < 0)
|
||||
return status;
|
||||
/* We don´t care about pong response data, discard. */
|
||||
Stream_ResetPosition(encodingContext->responseStreamBuffer);
|
||||
}
|
||||
break;
|
||||
case WebsocketCloseOpcode:
|
||||
{
|
||||
status = websocket_read_wstream(bio, encodingContext);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
if (encodingContext->payloadLength == 0)
|
||||
{
|
||||
websocket_reply_close(bio, encodingContext, encodingContext->responseStreamBuffer);
|
||||
encodingContext->closeSent = TRUE;
|
||||
Stream_ResetPosition(encodingContext->responseStreamBuffer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
WLog_WARN(TAG, "Unimplemented websocket opcode %" PRIx8 ". Dropping", effectiveOpcode);
|
||||
|
||||
status = websocket_read_wstream(bio, encodingContext);
|
||||
if (status < 0)
|
||||
return status;
|
||||
Stream_ResetPosition(encodingContext->responseStreamBuffer);
|
||||
break;
|
||||
}
|
||||
/* return how many bytes have been written to pBuffer.
|
||||
* Only WebsocketBinaryOpcode writes into it and it returns directly */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int websocket_context_read(websocket_context* encodingContext, BIO* bio, BYTE* pBuffer, size_t size)
|
||||
{
|
||||
int status = 0;
|
||||
size_t effectiveDataLen = 0;
|
||||
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(pBuffer);
|
||||
WINPR_ASSERT(encodingContext);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (encodingContext->state)
|
||||
{
|
||||
case WebsocketStateOpcodeAndFin:
|
||||
{
|
||||
BYTE buffer[1] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
ERR_clear_error();
|
||||
status = BIO_read(bio, (char*)buffer, sizeof(buffer));
|
||||
if (status <= 0)
|
||||
return (effectiveDataLen > 0 ? WINPR_ASSERTING_INT_CAST(int, effectiveDataLen)
|
||||
: status);
|
||||
|
||||
encodingContext->opcode = buffer[0];
|
||||
if (((encodingContext->opcode & 0xf) != WebsocketContinuationOpcode) &&
|
||||
(encodingContext->opcode & 0xf) < 0x08)
|
||||
encodingContext->fragmentOriginalOpcode = encodingContext->opcode;
|
||||
encodingContext->state = WebsocketStateLengthAndMasking;
|
||||
}
|
||||
break;
|
||||
case WebsocketStateLengthAndMasking:
|
||||
{
|
||||
BYTE buffer[1] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
ERR_clear_error();
|
||||
status = BIO_read(bio, (char*)buffer, sizeof(buffer));
|
||||
if (status <= 0)
|
||||
return (effectiveDataLen > 0 ? WINPR_ASSERTING_INT_CAST(int, effectiveDataLen)
|
||||
: status);
|
||||
|
||||
encodingContext->masking = ((buffer[0] & WEBSOCKET_MASK_BIT) == WEBSOCKET_MASK_BIT);
|
||||
encodingContext->lengthAndMaskPosition = 0;
|
||||
encodingContext->payloadLength = 0;
|
||||
const BYTE len = buffer[0] & 0x7f;
|
||||
if (len < 126)
|
||||
{
|
||||
encodingContext->payloadLength = len;
|
||||
encodingContext->state = (encodingContext->masking ? WebSocketStateMaskingKey
|
||||
: WebSocketStatePayload);
|
||||
}
|
||||
else if (len == 126)
|
||||
encodingContext->state = WebsocketStateShortLength;
|
||||
else
|
||||
encodingContext->state = WebsocketStateLongLength;
|
||||
}
|
||||
break;
|
||||
case WebsocketStateShortLength:
|
||||
case WebsocketStateLongLength:
|
||||
{
|
||||
BYTE buffer[1] = WINPR_C_ARRAY_INIT;
|
||||
const BYTE lenLength =
|
||||
(encodingContext->state == WebsocketStateShortLength ? 2 : 8);
|
||||
while (encodingContext->lengthAndMaskPosition < lenLength)
|
||||
{
|
||||
ERR_clear_error();
|
||||
status = BIO_read(bio, (char*)buffer, sizeof(buffer));
|
||||
if (status <= 0)
|
||||
return (effectiveDataLen > 0
|
||||
? WINPR_ASSERTING_INT_CAST(int, effectiveDataLen)
|
||||
: status);
|
||||
if (status > UINT8_MAX)
|
||||
return -1;
|
||||
encodingContext->payloadLength =
|
||||
(encodingContext->payloadLength) << 8 | buffer[0];
|
||||
encodingContext->lengthAndMaskPosition +=
|
||||
WINPR_ASSERTING_INT_CAST(BYTE, status);
|
||||
}
|
||||
encodingContext->state =
|
||||
(encodingContext->masking ? WebSocketStateMaskingKey : WebSocketStatePayload);
|
||||
}
|
||||
break;
|
||||
case WebSocketStateMaskingKey:
|
||||
{
|
||||
WLog_WARN(
|
||||
TAG, "Websocket Server sends data with masking key. This is against RFC 6455.");
|
||||
return -1;
|
||||
}
|
||||
case WebSocketStatePayload:
|
||||
{
|
||||
status = websocket_handle_payload(bio, pBuffer, size, encodingContext);
|
||||
if (status < 0)
|
||||
return (effectiveDataLen > 0 ? WINPR_ASSERTING_INT_CAST(int, effectiveDataLen)
|
||||
: status);
|
||||
|
||||
effectiveDataLen += WINPR_ASSERTING_INT_CAST(size_t, status);
|
||||
|
||||
if (WINPR_ASSERTING_INT_CAST(size_t, status) >= size)
|
||||
return WINPR_ASSERTING_INT_CAST(int, effectiveDataLen);
|
||||
pBuffer += status;
|
||||
size -= WINPR_ASSERTING_INT_CAST(size_t, status);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* should be unreachable */
|
||||
}
|
||||
|
||||
websocket_context* websocket_context_new(void)
|
||||
{
|
||||
websocket_context* context = calloc(1, sizeof(websocket_context));
|
||||
if (!context)
|
||||
goto fail;
|
||||
|
||||
context->responseStreamBuffer = Stream_New(nullptr, 1024);
|
||||
if (!context->responseStreamBuffer)
|
||||
goto fail;
|
||||
|
||||
if (!websocket_context_reset(context))
|
||||
goto fail;
|
||||
|
||||
return context;
|
||||
fail:
|
||||
websocket_context_free(context);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void websocket_context_free(websocket_context* context)
|
||||
{
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
Stream_Free(context->responseStreamBuffer, TRUE);
|
||||
free(context);
|
||||
}
|
||||
|
||||
BOOL websocket_context_reset(websocket_context* context)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
context->state = WebsocketStateOpcodeAndFin;
|
||||
return Stream_SetPosition(context->responseStreamBuffer, 0);
|
||||
}
|
||||
85
third_party/FreeRDP/libfreerdp/core/gateway/websocket.h
vendored
Normal file
85
third_party/FreeRDP/libfreerdp/core/gateway/websocket.h
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Websocket Framing
|
||||
*
|
||||
* Copyright 2023 Michael Saxl <mike@mwsys.mine.bz>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_WEBSOCKET_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_WEBSOCKET_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include "../../crypto/tls.h"
|
||||
|
||||
#define WEBSOCKET_MASK_BIT 0x80
|
||||
#define WEBSOCKET_FIN_BIT 0x80
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WebsocketContinuationOpcode = 0x0,
|
||||
WebsocketTextOpcode = 0x1,
|
||||
WebsocketBinaryOpcode = 0x2,
|
||||
WebsocketCloseOpcode = 0x8,
|
||||
WebsocketPingOpcode = 0x9,
|
||||
WebsocketPongOpcode = 0xa,
|
||||
} WEBSOCKET_OPCODE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WebsocketStateOpcodeAndFin,
|
||||
WebsocketStateLengthAndMasking,
|
||||
WebsocketStateShortLength,
|
||||
WebsocketStateLongLength,
|
||||
WebSocketStateMaskingKey,
|
||||
WebSocketStatePayload,
|
||||
} WEBSOCKET_STATE;
|
||||
|
||||
typedef struct s_websocket_context websocket_context;
|
||||
|
||||
FREERDP_LOCAL void websocket_context_free(websocket_context* context);
|
||||
|
||||
WINPR_ATTR_MALLOC(websocket_context_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL websocket_context* websocket_context_new(void);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL websocket_context_reset(websocket_context* context);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL websocket_context_write_wstream(websocket_context* context, BIO* bio,
|
||||
wStream* sPacket, WEBSOCKET_OPCODE opcode);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int websocket_context_write(websocket_context* context, BIO* bio, const BYTE* buf,
|
||||
int isize, WEBSOCKET_OPCODE opcode);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int websocket_context_read(websocket_context* encodingContext, BIO* bio,
|
||||
BYTE* pBuffer, size_t size);
|
||||
|
||||
WINPR_ATTR_MALLOC(Stream_Free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL wStream* websocket_context_packet_new(size_t len, WEBSOCKET_OPCODE opcode,
|
||||
UINT32* pMaskingKey);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL websocket_context_mask_and_send(BIO* bio, wStream* sPacket, wStream* sDataPacket,
|
||||
UINT32 maskingKey);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_WEBSOCKET_H */
|
||||
944
third_party/FreeRDP/libfreerdp/core/gateway/wst.c
vendored
Normal file
944
third_party/FreeRDP/libfreerdp/core/gateway/wst.c
vendored
Normal file
@@ -0,0 +1,944 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Websocket Transport
|
||||
*
|
||||
* Copyright 2023 Michael Saxl <mike@mwsys.mine.bz>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <freerdp/config.h>
|
||||
#include <freerdp/version.h>
|
||||
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/winsock.h>
|
||||
#include <winpr/cred.h>
|
||||
|
||||
#include "../settings.h"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/error.h>
|
||||
#include <freerdp/utils/ringbuffer.h>
|
||||
#include <freerdp/utils/smartcardlogon.h>
|
||||
|
||||
#include "wst.h"
|
||||
#include "websocket.h"
|
||||
#include "http.h"
|
||||
#include "../credssp_auth.h"
|
||||
#include "../proxy.h"
|
||||
#include "../rdp.h"
|
||||
#include "../../crypto/opensslcompat.h"
|
||||
#include "rpc_fault.h"
|
||||
#include "../utils.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.gateway.wst")
|
||||
|
||||
#define AUTH_PKG NEGO_SSP_NAME
|
||||
|
||||
struct rdp_wst
|
||||
{
|
||||
rdpContext* context;
|
||||
BOOL attached;
|
||||
BIO* frontBio;
|
||||
rdpTls* tls;
|
||||
rdpCredsspAuth* auth;
|
||||
BOOL auth_required;
|
||||
HttpContext* http;
|
||||
CRITICAL_SECTION writeSection;
|
||||
char* gwhostname;
|
||||
uint16_t gwport;
|
||||
char* gwpath;
|
||||
websocket_context* wscontext;
|
||||
wLog* log;
|
||||
};
|
||||
|
||||
static const char arm_query_param[] = "%s%cClmTk=Bearer%%20%s";
|
||||
|
||||
static BOOL wst_get_gateway_credentials(wLog* log, rdpContext* context, rdp_auth_reason reason)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
freerdp* instance = context->instance;
|
||||
|
||||
auth_status rc = utils_authenticate_gateway(instance, reason);
|
||||
switch (rc)
|
||||
{
|
||||
case AUTH_SUCCESS:
|
||||
case AUTH_SKIP:
|
||||
return TRUE;
|
||||
case AUTH_CANCELLED:
|
||||
freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
return FALSE;
|
||||
case AUTH_NO_CREDENTIALS:
|
||||
WLog_Print(log, WLOG_INFO, "No credentials provided - using nullptr identity");
|
||||
return TRUE;
|
||||
case AUTH_FAILED:
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL wst_auth_init(rdpWst* wst, rdpTls* tls, TCHAR* authPkg)
|
||||
{
|
||||
WINPR_ASSERT(wst);
|
||||
WINPR_ASSERT(tls);
|
||||
WINPR_ASSERT(authPkg);
|
||||
|
||||
rdpContext* context = wst->context;
|
||||
rdpSettings* settings = context->settings;
|
||||
SEC_WINNT_AUTH_IDENTITY identity = WINPR_C_ARRAY_INIT;
|
||||
int rc = 0;
|
||||
|
||||
wst->auth_required = TRUE;
|
||||
if (!credssp_auth_init(wst->auth, authPkg, tls->Bindings))
|
||||
return FALSE;
|
||||
|
||||
if (!wst_get_gateway_credentials(wst->log, context, GW_AUTH_RDG))
|
||||
return FALSE;
|
||||
|
||||
if (!identity_set_from_settings(&identity, settings, FreeRDP_GatewayUsername,
|
||||
FreeRDP_GatewayDomain, FreeRDP_GatewayPassword))
|
||||
return FALSE;
|
||||
|
||||
SEC_WINNT_AUTH_IDENTITY* identityArg = (settings->GatewayUsername ? &identity : nullptr);
|
||||
if (!credssp_auth_setup_client(wst->auth, "HTTP", wst->gwhostname, identityArg, nullptr))
|
||||
{
|
||||
sspi_FreeAuthIdentity(&identity);
|
||||
return FALSE;
|
||||
}
|
||||
sspi_FreeAuthIdentity(&identity);
|
||||
|
||||
credssp_auth_set_flags(wst->auth, ISC_REQ_CONFIDENTIALITY | ISC_REQ_MUTUAL_AUTH);
|
||||
|
||||
rc = credssp_auth_authenticate(wst->auth);
|
||||
return (rc >= 0);
|
||||
}
|
||||
|
||||
static BOOL wst_set_auth_header(rdpCredsspAuth* auth, HttpRequest* request)
|
||||
{
|
||||
WINPR_ASSERT(auth);
|
||||
WINPR_ASSERT(request);
|
||||
|
||||
const SecBuffer* authToken = credssp_auth_get_output_buffer(auth);
|
||||
char* base64AuthToken = nullptr;
|
||||
|
||||
if (authToken)
|
||||
{
|
||||
if (authToken->cbBuffer > INT_MAX)
|
||||
return FALSE;
|
||||
|
||||
base64AuthToken = crypto_base64_encode(authToken->pvBuffer, authToken->cbBuffer);
|
||||
}
|
||||
|
||||
if (base64AuthToken)
|
||||
{
|
||||
BOOL rc = http_request_set_auth_scheme(request, credssp_auth_pkg_name(auth)) &&
|
||||
http_request_set_auth_param(request, base64AuthToken);
|
||||
free(base64AuthToken);
|
||||
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wst_recv_auth_token(rdpCredsspAuth* auth, HttpResponse* response)
|
||||
{
|
||||
size_t len = 0;
|
||||
size_t authTokenLength = 0;
|
||||
BYTE* authTokenData = nullptr;
|
||||
SecBuffer authToken = WINPR_C_ARRAY_INIT;
|
||||
int rc = 0;
|
||||
|
||||
if (!auth || !response)
|
||||
return FALSE;
|
||||
|
||||
const UINT16 StatusCode = http_response_get_status_code(response);
|
||||
switch (StatusCode)
|
||||
{
|
||||
case HTTP_STATUS_DENIED:
|
||||
case HTTP_STATUS_OK:
|
||||
break;
|
||||
default:
|
||||
http_response_log_error_status(WLog_Get(TAG), WLOG_WARN, response);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const char* token64 = http_response_get_auth_token(response, credssp_auth_pkg_name(auth));
|
||||
|
||||
if (!token64)
|
||||
return FALSE;
|
||||
|
||||
len = strlen(token64);
|
||||
|
||||
crypto_base64_decode(token64, len, &authTokenData, &authTokenLength);
|
||||
|
||||
if (authTokenLength && (authTokenLength <= UINT32_MAX) && authTokenData)
|
||||
{
|
||||
authToken.pvBuffer = authTokenData;
|
||||
authToken.cbBuffer = (UINT32)authTokenLength;
|
||||
credssp_auth_take_input_buffer(auth, &authToken);
|
||||
}
|
||||
else
|
||||
free(authTokenData);
|
||||
|
||||
rc = credssp_auth_authenticate(auth);
|
||||
return (rc >= 0);
|
||||
}
|
||||
|
||||
static BOOL wst_tls_connect(rdpWst* wst, rdpTls* tls, UINT32 timeout)
|
||||
{
|
||||
WINPR_ASSERT(wst);
|
||||
WINPR_ASSERT(tls);
|
||||
int sockfd = 0;
|
||||
long status = 0;
|
||||
BIO* socketBio = nullptr;
|
||||
BIO* bufferedBio = nullptr;
|
||||
rdpSettings* settings = wst->context->settings;
|
||||
const char* peerHostname = wst->gwhostname;
|
||||
UINT16 peerPort = wst->gwport;
|
||||
const char* proxyUsername = nullptr;
|
||||
const char* proxyPassword = nullptr;
|
||||
BOOL isProxyConnection =
|
||||
proxy_prepare(settings, &peerHostname, &peerPort, &proxyUsername, &proxyPassword);
|
||||
|
||||
sockfd = freerdp_tcp_connect(wst->context, peerHostname, peerPort, timeout);
|
||||
|
||||
WLog_Print(wst->log, WLOG_DEBUG, "connecting to %s %d", peerHostname, peerPort);
|
||||
if (sockfd < 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
socketBio = BIO_new(BIO_s_simple_socket());
|
||||
|
||||
if (!socketBio)
|
||||
{
|
||||
closesocket((SOCKET)sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
|
||||
bufferedBio = BIO_new(BIO_s_buffered_socket());
|
||||
|
||||
if (!bufferedBio)
|
||||
{
|
||||
BIO_free_all(socketBio);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bufferedBio = BIO_push(bufferedBio, socketBio);
|
||||
status = BIO_set_nonblock(bufferedBio, TRUE);
|
||||
|
||||
if (isProxyConnection)
|
||||
{
|
||||
if (!proxy_connect(wst->context, bufferedBio, proxyUsername, proxyPassword, wst->gwhostname,
|
||||
wst->gwport))
|
||||
{
|
||||
BIO_free_all(bufferedBio);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!status)
|
||||
{
|
||||
BIO_free_all(bufferedBio);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tls->hostname = wst->gwhostname;
|
||||
tls->port = MIN(UINT16_MAX, wst->gwport);
|
||||
tls->isGatewayTransport = TRUE;
|
||||
status = freerdp_tls_connect(tls, bufferedBio);
|
||||
if (status < 1)
|
||||
{
|
||||
rdpContext* context = wst->context;
|
||||
if (status < 0)
|
||||
{
|
||||
freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
||||
}
|
||||
else
|
||||
{
|
||||
freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
return (status >= 1);
|
||||
}
|
||||
|
||||
static wStream* wst_build_http_request(rdpWst* wst)
|
||||
{
|
||||
wStream* s = nullptr;
|
||||
HttpRequest* request = nullptr;
|
||||
const char* uri = nullptr;
|
||||
|
||||
if (!wst)
|
||||
return nullptr;
|
||||
|
||||
uri = http_context_get_uri(wst->http);
|
||||
request = http_request_new();
|
||||
|
||||
if (!request)
|
||||
return nullptr;
|
||||
|
||||
if (!http_request_set_method(request, "GET") || !http_request_set_uri(request, uri))
|
||||
goto out;
|
||||
|
||||
if (wst->auth_required)
|
||||
{
|
||||
if (!wst_set_auth_header(wst->auth, request))
|
||||
goto out;
|
||||
}
|
||||
else if (freerdp_settings_get_string(wst->context->settings, FreeRDP_GatewayHttpExtAuthBearer))
|
||||
{
|
||||
if (!http_request_set_auth_scheme(request, "Bearer"))
|
||||
goto out;
|
||||
if (!http_request_set_auth_param(
|
||||
request, freerdp_settings_get_string(wst->context->settings,
|
||||
FreeRDP_GatewayHttpExtAuthBearer)))
|
||||
goto out;
|
||||
}
|
||||
|
||||
s = http_request_write(wst->http, request);
|
||||
out:
|
||||
http_request_free(request);
|
||||
|
||||
if (s)
|
||||
Stream_SealLength(s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static BOOL wst_send_http_request(rdpWst* wst, rdpTls* tls)
|
||||
{
|
||||
WINPR_ASSERT(wst);
|
||||
WINPR_ASSERT(tls);
|
||||
|
||||
wStream* s = wst_build_http_request(wst);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
const size_t sz = Stream_Length(s);
|
||||
WLog_Print(wst->log, WLOG_TRACE, "header [%" PRIuz "]: %s", sz, Stream_Buffer(s));
|
||||
|
||||
const int status = freerdp_tls_write_all(tls, Stream_Buffer(s), sz);
|
||||
Stream_Free(s, TRUE);
|
||||
return (status >= 0);
|
||||
}
|
||||
|
||||
static BOOL wst_handle_ok_or_forbidden(rdpWst* wst, HttpResponse** ppresponse, DWORD timeout,
|
||||
UINT16* pStatusCode)
|
||||
{
|
||||
WINPR_ASSERT(wst);
|
||||
WINPR_ASSERT(ppresponse);
|
||||
WINPR_ASSERT(*ppresponse);
|
||||
WINPR_ASSERT(pStatusCode);
|
||||
|
||||
/* AVD returns a 403 response with a ARRAffinity cookie set. retry with that cookie */
|
||||
const char* affinity = http_response_get_setcookie(*ppresponse, "ARRAffinity");
|
||||
const char* samesite = http_response_get_setcookie(*ppresponse, "ARRAffinitySameSite");
|
||||
if ((affinity || samesite) &&
|
||||
freerdp_settings_get_bool(wst->context->settings, FreeRDP_GatewayArmTransport))
|
||||
{
|
||||
WLog_Print(wst->log, WLOG_INFO, "Got ARRAffinity cookie %s", affinity);
|
||||
WLog_Print(wst->log, WLOG_INFO, "Got ARRAffinitySameSite cookie %s", samesite);
|
||||
if (affinity)
|
||||
{
|
||||
if (!http_context_set_cookie(wst->http, "ARRAffinity", affinity))
|
||||
return FALSE;
|
||||
}
|
||||
if (samesite)
|
||||
{
|
||||
if (!http_context_set_cookie(wst->http, "ARRAffinitySameSite", samesite))
|
||||
return FALSE;
|
||||
}
|
||||
http_response_free(*ppresponse);
|
||||
*ppresponse = nullptr;
|
||||
/* Terminate this connection and make a new one with the Loadbalancing Cookie */
|
||||
const long fd = BIO_get_fd(wst->tls->bio, nullptr);
|
||||
if ((fd >= 0) && (fd <= INT32_MAX))
|
||||
closesocket((SOCKET)fd);
|
||||
freerdp_tls_free(wst->tls);
|
||||
|
||||
wst->tls = freerdp_tls_new(wst->context);
|
||||
if (!wst_tls_connect(wst, wst->tls, timeout))
|
||||
return FALSE;
|
||||
|
||||
if (freerdp_settings_get_string(wst->context->settings, FreeRDP_GatewayHttpExtAuthBearer) &&
|
||||
freerdp_settings_get_bool(wst->context->settings, FreeRDP_GatewayArmTransport))
|
||||
{
|
||||
char* urlWithAuth = nullptr;
|
||||
size_t urlLen = 0;
|
||||
char firstParam = (strchr(wst->gwpath, '?') != nullptr) ? '&' : '?';
|
||||
const char* bearer = freerdp_settings_get_string(wst->context->settings,
|
||||
FreeRDP_GatewayHttpExtAuthBearer);
|
||||
const char* ua =
|
||||
freerdp_settings_get_string(wst->context->settings, FreeRDP_GatewayHttpMsUserAgent);
|
||||
winpr_asprintf(&urlWithAuth, &urlLen, arm_query_param, wst->gwpath, firstParam, bearer,
|
||||
ua);
|
||||
if (!urlWithAuth)
|
||||
return FALSE;
|
||||
free(wst->gwpath);
|
||||
wst->gwpath = urlWithAuth;
|
||||
if (!utils_str_is_empty(ua))
|
||||
{
|
||||
size_t ualen = 0;
|
||||
char* uastr = nullptr;
|
||||
winpr_asprintf(&uastr, &ualen, "%s&X-MS-User-Agent=%s", wst->gwpath, ua);
|
||||
if (!uastr)
|
||||
return FALSE;
|
||||
free(wst->gwpath);
|
||||
wst->gwpath = uastr;
|
||||
}
|
||||
if (!http_context_set_uri(wst->http, wst->gwpath))
|
||||
return FALSE;
|
||||
if (!http_context_enable_websocket_upgrade(wst->http, TRUE))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!wst_send_http_request(wst, wst->tls))
|
||||
return FALSE;
|
||||
*ppresponse = http_response_recv(wst->tls, TRUE);
|
||||
if (!*ppresponse)
|
||||
return FALSE;
|
||||
|
||||
(void)http_response_extract_cookies(*ppresponse, wst->http);
|
||||
*pStatusCode = http_response_get_status_code(*ppresponse);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wst_handle_denied(rdpWst* wst, HttpResponse** ppresponse, UINT16* pStatusCode)
|
||||
{
|
||||
WINPR_ASSERT(wst);
|
||||
WINPR_ASSERT(ppresponse);
|
||||
WINPR_ASSERT(*ppresponse);
|
||||
WINPR_ASSERT(pStatusCode);
|
||||
|
||||
if (freerdp_settings_get_string(wst->context->settings, FreeRDP_GatewayHttpExtAuthBearer))
|
||||
return FALSE;
|
||||
|
||||
if (!wst_auth_init(wst, wst->tls, AUTH_PKG))
|
||||
return FALSE;
|
||||
if (!wst_send_http_request(wst, wst->tls))
|
||||
return FALSE;
|
||||
|
||||
http_response_free(*ppresponse);
|
||||
*ppresponse = http_response_recv(wst->tls, TRUE);
|
||||
if (!*ppresponse)
|
||||
return FALSE;
|
||||
|
||||
(void)http_response_extract_cookies(*ppresponse, wst->http);
|
||||
|
||||
while (!credssp_auth_is_complete(wst->auth))
|
||||
{
|
||||
if (!wst_recv_auth_token(wst->auth, *ppresponse))
|
||||
return FALSE;
|
||||
|
||||
if (credssp_auth_have_output_token(wst->auth))
|
||||
{
|
||||
if (!wst_send_http_request(wst, wst->tls))
|
||||
return FALSE;
|
||||
|
||||
http_response_free(*ppresponse);
|
||||
*ppresponse = http_response_recv(wst->tls, TRUE);
|
||||
if (!*ppresponse)
|
||||
return FALSE;
|
||||
(void)http_response_extract_cookies(*ppresponse, wst->http);
|
||||
}
|
||||
}
|
||||
*pStatusCode = http_response_get_status_code(*ppresponse);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL wst_handle_http_code(rdpWst* wst, UINT16 StatusCode)
|
||||
{
|
||||
switch (StatusCode)
|
||||
{
|
||||
case HTTP_STATUS_PAYMENT_REQ:
|
||||
case HTTP_STATUS_FORBIDDEN:
|
||||
case HTTP_STATUS_DENIED:
|
||||
freerdp_set_last_error_if_not(wst->context, FREERDP_ERROR_CONNECT_ACCESS_DENIED);
|
||||
break;
|
||||
case HTTP_STATUS_MOVED:
|
||||
case HTTP_STATUS_USE_PROXY:
|
||||
case HTTP_STATUS_BAD_REQUEST:
|
||||
case HTTP_STATUS_NOT_FOUND:
|
||||
case HTTP_STATUS_GONE:
|
||||
freerdp_set_last_error_if_not(wst->context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
|
||||
break;
|
||||
case HTTP_STATUS_SERVER_ERROR:
|
||||
case HTTP_STATUS_NOT_SUPPORTED:
|
||||
case HTTP_STATUS_BAD_GATEWAY:
|
||||
case HTTP_STATUS_SERVICE_UNAVAIL:
|
||||
case HTTP_STATUS_VERSION_NOT_SUP:
|
||||
freerdp_set_last_error_if_not(wst->context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
|
||||
break;
|
||||
case HTTP_STATUS_GATEWAY_TIMEOUT:
|
||||
freerdp_set_last_error_if_not(wst->context, FREERDP_ERROR_CONNECT_ACTIVATION_TIMEOUT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
char buffer[64] = WINPR_C_ARRAY_INIT;
|
||||
WLog_Print(wst->log, WLOG_ERROR, "Unexpected HTTP status: %s",
|
||||
freerdp_http_status_string_format(StatusCode, buffer, ARRAYSIZE(buffer)));
|
||||
freerdp_set_last_error_if_not(wst->context, FREERDP_ERROR_CONNECT_FAILED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL wst_connect(rdpWst* wst, DWORD timeout)
|
||||
{
|
||||
WINPR_ASSERT(wst);
|
||||
WINPR_ASSERT(wst->context);
|
||||
|
||||
if (!wst_tls_connect(wst, wst->tls, timeout))
|
||||
{
|
||||
freerdp_set_last_error_if_not(wst->context, FREERDP_ERROR_CONNECT_FAILED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (freerdp_settings_get_bool(wst->context->settings, FreeRDP_GatewayArmTransport))
|
||||
{
|
||||
/*
|
||||
* If we are directed here from a ARM Gateway first
|
||||
* we need to get a Loadbalancing Cookie (ARRAffinity)
|
||||
* This is done by a plain GET request on the websocket URL
|
||||
*/
|
||||
if (!http_context_enable_websocket_upgrade(wst->http, FALSE))
|
||||
{
|
||||
freerdp_set_last_error_if_not(wst->context, FREERDP_ERROR_CONNECT_FAILED);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (!wst_send_http_request(wst, wst->tls))
|
||||
{
|
||||
freerdp_set_last_error_if_not(wst->context, FREERDP_ERROR_CONNECT_FAILED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HttpResponse* response = http_response_recv(wst->tls, TRUE);
|
||||
if (!response)
|
||||
{
|
||||
freerdp_set_last_error_if_not(wst->context, FREERDP_ERROR_CONNECT_FAILED);
|
||||
return FALSE;
|
||||
}
|
||||
(void)http_response_extract_cookies(response, wst->http);
|
||||
|
||||
UINT16 StatusCode = http_response_get_status_code(response);
|
||||
BOOL success = TRUE;
|
||||
switch (StatusCode)
|
||||
{
|
||||
case HTTP_STATUS_FORBIDDEN:
|
||||
case HTTP_STATUS_OK:
|
||||
success = wst_handle_ok_or_forbidden(wst, &response, timeout, &StatusCode);
|
||||
break;
|
||||
|
||||
case HTTP_STATUS_DENIED:
|
||||
success = wst_handle_denied(wst, &response, &StatusCode);
|
||||
break;
|
||||
default:
|
||||
http_response_log_error_status(WLog_Get(TAG), WLOG_WARN, response);
|
||||
break;
|
||||
}
|
||||
|
||||
const BOOL isWebsocket = http_response_is_websocket(wst->http, response);
|
||||
http_response_free(response);
|
||||
if (!success)
|
||||
return wst_handle_http_code(wst, StatusCode);
|
||||
|
||||
if (isWebsocket)
|
||||
return websocket_context_reset(wst->wscontext);
|
||||
|
||||
return wst_handle_http_code(wst, StatusCode);
|
||||
}
|
||||
|
||||
DWORD wst_get_event_handles(rdpWst* wst, HANDLE* events, DWORD count)
|
||||
{
|
||||
DWORD nCount = 0;
|
||||
WINPR_ASSERT(wst != nullptr);
|
||||
|
||||
if (wst->tls)
|
||||
{
|
||||
if (events && (nCount < count))
|
||||
{
|
||||
BIO_get_event(wst->tls->bio, &events[nCount]);
|
||||
nCount++;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return nCount;
|
||||
}
|
||||
|
||||
static int wst_bio_write(BIO* bio, const char* buf, int num)
|
||||
{
|
||||
int status = 0;
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(buf);
|
||||
|
||||
rdpWst* wst = (rdpWst*)BIO_get_data(bio);
|
||||
WINPR_ASSERT(wst);
|
||||
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||
EnterCriticalSection(&wst->writeSection);
|
||||
status = websocket_context_write(wst->wscontext, wst->tls->bio, (const BYTE*)buf, num,
|
||||
WebsocketBinaryOpcode);
|
||||
LeaveCriticalSection(&wst->writeSection);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
return -1;
|
||||
}
|
||||
else if (status < num)
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_WRITE);
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_WRITE);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int wst_bio_read(BIO* bio, char* buf, int size)
|
||||
{
|
||||
int status = 0;
|
||||
WINPR_ASSERT(bio);
|
||||
WINPR_ASSERT(buf);
|
||||
WINPR_ASSERT(size >= 0);
|
||||
|
||||
rdpWst* wst = (rdpWst*)BIO_get_data(bio);
|
||||
WINPR_ASSERT(wst);
|
||||
|
||||
while (status <= 0)
|
||||
{
|
||||
status = websocket_context_read(wst->wscontext, wst->tls->bio, (BYTE*)buf, (size_t)size);
|
||||
if (status <= 0)
|
||||
{
|
||||
if (!BIO_should_retry(wst->tls->bio))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
BIO_clear_retry_flags(bio);
|
||||
return -1;
|
||||
}
|
||||
else if (status == 0)
|
||||
{
|
||||
BIO_set_retry_read(bio);
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_READ);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int wst_bio_puts(BIO* bio, const char* str)
|
||||
{
|
||||
WINPR_UNUSED(bio);
|
||||
WINPR_UNUSED(str);
|
||||
return -2;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-non-const-parameter)
|
||||
static int wst_bio_gets(BIO* bio, char* str, int size)
|
||||
{
|
||||
WINPR_UNUSED(bio);
|
||||
WINPR_UNUSED(str);
|
||||
WINPR_UNUSED(size);
|
||||
return -2;
|
||||
}
|
||||
|
||||
static long wst_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
{
|
||||
long status = -1;
|
||||
WINPR_ASSERT(bio);
|
||||
|
||||
rdpWst* wst = (rdpWst*)BIO_get_data(bio);
|
||||
WINPR_ASSERT(wst);
|
||||
rdpTls* tls = wst->tls;
|
||||
|
||||
if (cmd == BIO_CTRL_FLUSH)
|
||||
{
|
||||
(void)BIO_flush(tls->bio);
|
||||
status = 1;
|
||||
}
|
||||
else if (cmd == BIO_C_SET_NONBLOCK)
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
else if (cmd == BIO_C_READ_BLOCKED)
|
||||
{
|
||||
status = BIO_read_blocked(tls->bio);
|
||||
}
|
||||
else if (cmd == BIO_C_WRITE_BLOCKED)
|
||||
{
|
||||
status = BIO_write_blocked(tls->bio);
|
||||
}
|
||||
else if (cmd == BIO_C_WAIT_READ)
|
||||
{
|
||||
int timeout = (int)arg1;
|
||||
|
||||
if (BIO_read_blocked(tls->bio))
|
||||
return BIO_wait_read(tls->bio, timeout);
|
||||
status = 1;
|
||||
}
|
||||
else if (cmd == BIO_C_WAIT_WRITE)
|
||||
{
|
||||
int timeout = (int)arg1;
|
||||
|
||||
if (BIO_write_blocked(tls->bio))
|
||||
status = BIO_wait_write(tls->bio, timeout);
|
||||
else
|
||||
status = 1;
|
||||
}
|
||||
else if (cmd == BIO_C_GET_EVENT || cmd == BIO_C_GET_FD)
|
||||
{
|
||||
status = BIO_ctrl(tls->bio, cmd, arg1, arg2);
|
||||
}
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
else if (cmd == BIO_CTRL_GET_KTLS_SEND)
|
||||
{
|
||||
/* Even though BIO_get_ktls_send says that returning negative values is valid
|
||||
* openssl internal sources are full of if(!BIO_get_ktls_send && ) stuff. This has some
|
||||
* nasty sideeffects. return 0 as proper no KTLS offloading flag
|
||||
*/
|
||||
status = 0;
|
||||
}
|
||||
else if (cmd == BIO_CTRL_GET_KTLS_RECV)
|
||||
{
|
||||
/* Even though BIO_get_ktls_recv says that returning negative values is valid
|
||||
* there is no reason to trust trust negative values are implemented right everywhere
|
||||
*/
|
||||
status = 0;
|
||||
}
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
static int wst_bio_new(BIO* bio)
|
||||
{
|
||||
BIO_set_init(bio, 1);
|
||||
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int wst_bio_free(BIO* bio)
|
||||
{
|
||||
WINPR_UNUSED(bio);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BIO_METHOD* BIO_s_wst(void)
|
||||
{
|
||||
static BIO_METHOD* bio_methods = nullptr;
|
||||
|
||||
if (bio_methods == nullptr)
|
||||
{
|
||||
if (!(bio_methods = BIO_meth_new(BIO_TYPE_TSG, "WSTransport")))
|
||||
return nullptr;
|
||||
|
||||
BIO_meth_set_write(bio_methods, wst_bio_write);
|
||||
BIO_meth_set_read(bio_methods, wst_bio_read);
|
||||
BIO_meth_set_puts(bio_methods, wst_bio_puts);
|
||||
BIO_meth_set_gets(bio_methods, wst_bio_gets);
|
||||
BIO_meth_set_ctrl(bio_methods, wst_bio_ctrl);
|
||||
BIO_meth_set_create(bio_methods, wst_bio_new);
|
||||
BIO_meth_set_destroy(bio_methods, wst_bio_free);
|
||||
}
|
||||
|
||||
return bio_methods;
|
||||
}
|
||||
|
||||
static BOOL wst_parse_url(rdpWst* wst, const char* url)
|
||||
{
|
||||
const char* hostStart = nullptr;
|
||||
const char* pos = nullptr;
|
||||
WINPR_ASSERT(wst);
|
||||
WINPR_ASSERT(url);
|
||||
|
||||
free(wst->gwhostname);
|
||||
wst->gwhostname = nullptr;
|
||||
free(wst->gwpath);
|
||||
wst->gwpath = nullptr;
|
||||
|
||||
if (strncmp("wss://", url, 6) != 0)
|
||||
{
|
||||
if (strncmp("https://", url, 8) != 0)
|
||||
{
|
||||
WLog_Print(wst->log, WLOG_ERROR,
|
||||
"Websocket URL is invalid. Only wss:// or https:// URLs are supported");
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
hostStart = url + 8;
|
||||
}
|
||||
else
|
||||
hostStart = url + 6;
|
||||
|
||||
pos = hostStart;
|
||||
while (*pos != '\0' && *pos != ':' && *pos != '/')
|
||||
pos++;
|
||||
free(wst->gwhostname);
|
||||
wst->gwhostname = nullptr;
|
||||
if (pos - hostStart == 0)
|
||||
return FALSE;
|
||||
wst->gwhostname = strndup(hostStart, WINPR_ASSERTING_INT_CAST(size_t, (pos - hostStart)));
|
||||
if (!wst->gwhostname)
|
||||
return FALSE;
|
||||
|
||||
if (*pos == ':')
|
||||
{
|
||||
char port[6] = WINPR_C_ARRAY_INIT;
|
||||
char* portNumberEnd = nullptr;
|
||||
pos++;
|
||||
const char* portStart = pos;
|
||||
while (*pos != '\0' && *pos != '/')
|
||||
pos++;
|
||||
if (pos - portStart > 5 || pos - portStart == 0)
|
||||
return FALSE;
|
||||
strncpy(port, portStart, WINPR_ASSERTING_INT_CAST(size_t, (pos - portStart)));
|
||||
port[pos - portStart] = '\0';
|
||||
long _p = strtol(port, &portNumberEnd, 10);
|
||||
if (portNumberEnd && (*portNumberEnd == '\0') && (_p > 0) && (_p <= UINT16_MAX))
|
||||
wst->gwport = (uint16_t)_p;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
wst->gwport = 443;
|
||||
wst->gwpath = _strdup(pos);
|
||||
return (wst->gwpath != nullptr);
|
||||
}
|
||||
|
||||
rdpWst* wst_new(rdpContext* context)
|
||||
{
|
||||
if (!context)
|
||||
return nullptr;
|
||||
|
||||
rdpWst* wst = (rdpWst*)calloc(1, sizeof(rdpWst));
|
||||
if (!wst)
|
||||
return nullptr;
|
||||
|
||||
wst->log = WLog_Get(TAG);
|
||||
wst->context = context;
|
||||
|
||||
wst->gwhostname = nullptr;
|
||||
wst->gwport = 443;
|
||||
wst->gwpath = nullptr;
|
||||
|
||||
if (!wst_parse_url(wst, context->settings->GatewayUrl))
|
||||
goto wst_alloc_error;
|
||||
|
||||
wst->tls = freerdp_tls_new(wst->context);
|
||||
if (!wst->tls)
|
||||
goto wst_alloc_error;
|
||||
|
||||
wst->http = http_context_new();
|
||||
|
||||
if (!wst->http)
|
||||
goto wst_alloc_error;
|
||||
|
||||
{
|
||||
const char* useragent =
|
||||
freerdp_settings_get_string(context->settings, FreeRDP_GatewayHttpUserAgent);
|
||||
const char* msuseragent =
|
||||
freerdp_settings_get_string(context->settings, FreeRDP_GatewayHttpMsUserAgent);
|
||||
if (!http_context_set_uri(wst->http, wst->gwpath) ||
|
||||
!http_context_set_accept(wst->http, "*/*") ||
|
||||
!http_context_set_cache_control(wst->http, "no-cache") ||
|
||||
!http_context_set_pragma(wst->http, "no-cache") ||
|
||||
!http_context_set_connection(wst->http, "Keep-Alive") ||
|
||||
!http_context_set_user_agent(wst->http, useragent) ||
|
||||
!http_context_set_x_ms_user_agent(wst->http, msuseragent) ||
|
||||
!http_context_set_host(wst->http, wst->gwhostname) ||
|
||||
!http_context_enable_websocket_upgrade(wst->http, TRUE))
|
||||
{
|
||||
goto wst_alloc_error;
|
||||
}
|
||||
}
|
||||
|
||||
wst->frontBio = BIO_new(BIO_s_wst());
|
||||
|
||||
if (!wst->frontBio)
|
||||
goto wst_alloc_error;
|
||||
|
||||
BIO_set_data(wst->frontBio, wst);
|
||||
InitializeCriticalSection(&wst->writeSection);
|
||||
wst->auth = credssp_auth_new(context);
|
||||
if (!wst->auth)
|
||||
goto wst_alloc_error;
|
||||
|
||||
wst->wscontext = websocket_context_new();
|
||||
if (!wst->wscontext)
|
||||
goto wst_alloc_error;
|
||||
|
||||
return wst;
|
||||
wst_alloc_error:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
wst_free(wst);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void wst_free(rdpWst* wst)
|
||||
{
|
||||
if (!wst)
|
||||
return;
|
||||
|
||||
freerdp_tls_free(wst->tls);
|
||||
http_context_free(wst->http);
|
||||
credssp_auth_free(wst->auth);
|
||||
free(wst->gwhostname);
|
||||
free(wst->gwpath);
|
||||
|
||||
if (!wst->attached)
|
||||
BIO_free_all(wst->frontBio);
|
||||
|
||||
DeleteCriticalSection(&wst->writeSection);
|
||||
|
||||
websocket_context_free(wst->wscontext);
|
||||
|
||||
free(wst);
|
||||
}
|
||||
|
||||
BIO* wst_get_front_bio_and_take_ownership(rdpWst* wst)
|
||||
{
|
||||
if (!wst)
|
||||
return nullptr;
|
||||
|
||||
wst->attached = TRUE;
|
||||
return wst->frontBio;
|
||||
}
|
||||
50
third_party/FreeRDP/libfreerdp/core/gateway/wst.h
vendored
Normal file
50
third_party/FreeRDP/libfreerdp/core/gateway/wst.h
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Websocket Transport
|
||||
*
|
||||
* Copyright 2023 Michael Saxl <mike@mwsys.mine.bz>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GATEWAY_WEBSOCKET_TRANSPORT_H
|
||||
#define FREERDP_LIB_CORE_GATEWAY_WEBSOCKET_TRANSPORT_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/winpr.h>
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
/* needed for BIO */
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
typedef struct rdp_wst rdpWst;
|
||||
|
||||
FREERDP_LOCAL void wst_free(rdpWst* wst);
|
||||
|
||||
WINPR_ATTR_MALLOC(wst_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpWst* wst_new(rdpContext* context);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BIO* wst_get_front_bio_and_take_ownership(rdpWst* wst);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL wst_connect(rdpWst* wst, DWORD timeout);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL DWORD wst_get_event_handles(rdpWst* wst, HANDLE* events, DWORD count);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GATEWAY_WEBSOCKET_TRANSPORT_H */
|
||||
2478
third_party/FreeRDP/libfreerdp/core/gcc.c
vendored
Normal file
2478
third_party/FreeRDP/libfreerdp/core/gcc.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
51
third_party/FreeRDP/libfreerdp/core/gcc.h
vendored
Normal file
51
third_party/FreeRDP/libfreerdp/core/gcc.h
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* T.124 Generic Conference Control (GCC)
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GCC_H
|
||||
#define FREERDP_LIB_CORE_GCC_H
|
||||
|
||||
#include "mcs.h"
|
||||
|
||||
#include <freerdp/crypto/per.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL gcc_read_conference_create_request(wStream* s, rdpMcs* mcs);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL gcc_write_conference_create_request(wStream* s, wStream* userData);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL gcc_read_conference_create_response(wStream* s, rdpMcs* mcs);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL gcc_write_conference_create_response(wStream* s, wStream* userData);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL gcc_write_client_data_blocks(wStream* s, const rdpMcs* mcs);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL gcc_write_server_data_blocks(wStream* s, rdpMcs* mcs);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GCC_H */
|
||||
221
third_party/FreeRDP/libfreerdp/core/graphics.c
vendored
Normal file
221
third_party/FreeRDP/libfreerdp/core/graphics.c
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Graphical Objects
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/graphics.h>
|
||||
|
||||
#include "graphics.h"
|
||||
|
||||
/* Bitmap Class */
|
||||
|
||||
rdpBitmap* Bitmap_Alloc(rdpContext* context)
|
||||
{
|
||||
rdpBitmap* bitmap = nullptr;
|
||||
rdpGraphics* graphics = nullptr;
|
||||
graphics = context->graphics;
|
||||
bitmap = (rdpBitmap*)calloc(1, graphics->Bitmap_Prototype->size);
|
||||
|
||||
if (bitmap)
|
||||
{
|
||||
*bitmap = *graphics->Bitmap_Prototype;
|
||||
bitmap->data = nullptr;
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
void Bitmap_Free(rdpContext* context, rdpBitmap* bitmap)
|
||||
{
|
||||
if (bitmap)
|
||||
bitmap->Free(context, bitmap);
|
||||
}
|
||||
|
||||
BOOL Bitmap_SetRectangle(rdpBitmap* bitmap, UINT16 left, UINT16 top, UINT16 right, UINT16 bottom)
|
||||
{
|
||||
if (!bitmap)
|
||||
return FALSE;
|
||||
|
||||
bitmap->left = left;
|
||||
bitmap->top = top;
|
||||
bitmap->right = right;
|
||||
bitmap->bottom = bottom;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL Bitmap_SetDimensions(rdpBitmap* bitmap, UINT16 width, UINT16 height)
|
||||
{
|
||||
if (!bitmap)
|
||||
return FALSE;
|
||||
|
||||
bitmap->right = bitmap->left + width - 1;
|
||||
bitmap->bottom = bitmap->top + height - 1;
|
||||
bitmap->width = width;
|
||||
bitmap->height = height;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void graphics_register_bitmap(rdpGraphics* graphics, const rdpBitmap* bitmap)
|
||||
{
|
||||
WINPR_ASSERT(graphics);
|
||||
WINPR_ASSERT(graphics->Bitmap_Prototype);
|
||||
WINPR_ASSERT(bitmap);
|
||||
|
||||
*graphics->Bitmap_Prototype = *bitmap;
|
||||
}
|
||||
|
||||
/* Pointer Class */
|
||||
rdpPointer* Pointer_Alloc(rdpContext* context)
|
||||
{
|
||||
rdpPointer* pointer = nullptr;
|
||||
rdpGraphics* graphics = nullptr;
|
||||
graphics = context->graphics;
|
||||
pointer = (rdpPointer*)calloc(1, graphics->Pointer_Prototype->size);
|
||||
|
||||
if (pointer)
|
||||
{
|
||||
*pointer = *graphics->Pointer_Prototype;
|
||||
}
|
||||
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/* static method */
|
||||
void graphics_register_pointer(rdpGraphics* graphics, const rdpPointer* pointer)
|
||||
{
|
||||
WINPR_ASSERT(graphics);
|
||||
WINPR_ASSERT(graphics->Pointer_Prototype);
|
||||
WINPR_ASSERT(pointer);
|
||||
|
||||
*graphics->Pointer_Prototype = *pointer;
|
||||
}
|
||||
|
||||
/* Glyph Class */
|
||||
|
||||
rdpGlyph* Glyph_Alloc(rdpContext* context, INT32 x, INT32 y, UINT32 cx, UINT32 cy, UINT32 cb,
|
||||
const BYTE* aj)
|
||||
{
|
||||
rdpGlyph* glyph = nullptr;
|
||||
rdpGraphics* graphics = nullptr;
|
||||
|
||||
if (!context || !context->graphics)
|
||||
return nullptr;
|
||||
|
||||
graphics = context->graphics;
|
||||
|
||||
if (!graphics->Glyph_Prototype)
|
||||
return nullptr;
|
||||
|
||||
glyph = (rdpGlyph*)calloc(1, graphics->Glyph_Prototype->size);
|
||||
|
||||
if (!glyph)
|
||||
return nullptr;
|
||||
|
||||
*glyph = *graphics->Glyph_Prototype;
|
||||
glyph->cb = cb;
|
||||
glyph->cx = cx;
|
||||
glyph->cy = cy;
|
||||
glyph->x = x;
|
||||
glyph->y = y;
|
||||
glyph->aj = malloc(glyph->cb);
|
||||
|
||||
if (!glyph->aj)
|
||||
{
|
||||
free(glyph);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CopyMemory(glyph->aj, aj, cb);
|
||||
|
||||
if (!glyph->New(context, glyph))
|
||||
{
|
||||
free(glyph->aj);
|
||||
free(glyph);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return glyph;
|
||||
}
|
||||
|
||||
void graphics_register_glyph(rdpGraphics* graphics, const rdpGlyph* glyph)
|
||||
{
|
||||
WINPR_ASSERT(graphics);
|
||||
WINPR_ASSERT(graphics->Glyph_Prototype);
|
||||
WINPR_ASSERT(glyph);
|
||||
|
||||
*graphics->Glyph_Prototype = *glyph;
|
||||
}
|
||||
|
||||
/* Graphics Module */
|
||||
|
||||
rdpGraphics* graphics_new(rdpContext* context)
|
||||
{
|
||||
rdpGraphics* graphics = nullptr;
|
||||
graphics = (rdpGraphics*)calloc(1, sizeof(rdpGraphics));
|
||||
|
||||
if (graphics)
|
||||
{
|
||||
graphics->context = context;
|
||||
graphics->Bitmap_Prototype = (rdpBitmap*)calloc(1, sizeof(rdpBitmap));
|
||||
|
||||
if (!graphics->Bitmap_Prototype)
|
||||
{
|
||||
free(graphics);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
graphics->Bitmap_Prototype->size = sizeof(rdpBitmap);
|
||||
graphics->Pointer_Prototype = (rdpPointer*)calloc(1, sizeof(rdpPointer));
|
||||
|
||||
if (!graphics->Pointer_Prototype)
|
||||
{
|
||||
free(graphics->Bitmap_Prototype);
|
||||
free(graphics);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
graphics->Pointer_Prototype->size = sizeof(rdpPointer);
|
||||
graphics->Glyph_Prototype = (rdpGlyph*)calloc(1, sizeof(rdpGlyph));
|
||||
|
||||
if (!graphics->Glyph_Prototype)
|
||||
{
|
||||
free(graphics->Pointer_Prototype);
|
||||
free(graphics->Bitmap_Prototype);
|
||||
free(graphics);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
graphics->Glyph_Prototype->size = sizeof(rdpGlyph);
|
||||
}
|
||||
|
||||
return graphics;
|
||||
}
|
||||
|
||||
void graphics_free(rdpGraphics* graphics)
|
||||
{
|
||||
if (graphics)
|
||||
{
|
||||
free(graphics->Bitmap_Prototype);
|
||||
free(graphics->Pointer_Prototype);
|
||||
free(graphics->Glyph_Prototype);
|
||||
free(graphics);
|
||||
}
|
||||
}
|
||||
30
third_party/FreeRDP/libfreerdp/core/graphics.h
vendored
Normal file
30
third_party/FreeRDP/libfreerdp/core/graphics.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Client Channels
|
||||
*
|
||||
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2016 Thinast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_GRAPHICS_H
|
||||
#define FREERDP_LIB_CORE_GRAPHICS_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/graphics.h>
|
||||
|
||||
FREERDP_LOCAL void Bitmap_Free(rdpContext* context, rdpBitmap* bitmap);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_GRAPHICS_H */
|
||||
93
third_party/FreeRDP/libfreerdp/core/heartbeat.c
vendored
Normal file
93
third_party/FreeRDP/libfreerdp/core/heartbeat.c
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Heartbeat PDUs
|
||||
*
|
||||
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "heartbeat.h"
|
||||
|
||||
state_run_t rdp_recv_heartbeat_packet(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
BYTE period = 0;
|
||||
BYTE count1 = 0;
|
||||
BYTE count2 = 0;
|
||||
BOOL rc = 0;
|
||||
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(rdp->context);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(AUTODETECT_TAG, s, 4))
|
||||
return STATE_RUN_FAILED;
|
||||
|
||||
Stream_Seek_UINT8(s); /* reserved (1 byte) */
|
||||
Stream_Read_UINT8(s, period); /* period (1 byte) */
|
||||
Stream_Read_UINT8(s, count1); /* count1 (1 byte) */
|
||||
Stream_Read_UINT8(s, count2); /* count2 (1 byte) */
|
||||
|
||||
WLog_VRB(HEARTBEAT_TAG,
|
||||
"received Heartbeat PDU -> period=%" PRIu8 ", count1=%" PRIu8 ", count2=%" PRIu8 "",
|
||||
period, count1, count2);
|
||||
|
||||
rc = IFCALLRESULT(TRUE, rdp->heartbeat->ServerHeartbeat, rdp->context->instance, period, count1,
|
||||
count2);
|
||||
if (!rc)
|
||||
{
|
||||
WLog_ERR(HEARTBEAT_TAG, "heartbeat->ServerHeartbeat callback failed!");
|
||||
return STATE_RUN_FAILED;
|
||||
}
|
||||
|
||||
return STATE_RUN_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL freerdp_heartbeat_send_heartbeat_pdu(freerdp_peer* peer, BYTE period, BYTE count1, BYTE count2)
|
||||
{
|
||||
rdpRdp* rdp = peer->context->rdp;
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_message_channel_pdu_init(rdp, &sec_flags);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
Stream_Seek_UINT8(s); /* reserved (1 byte) */
|
||||
Stream_Write_UINT8(s, period); /* period (1 byte) */
|
||||
Stream_Write_UINT8(s, count1); /* count1 (1 byte) */
|
||||
Stream_Write_UINT8(s, count2); /* count2 (1 byte) */
|
||||
|
||||
WLog_DBG(HEARTBEAT_TAG,
|
||||
"sending Heartbeat PDU -> period=%" PRIu8 ", count1=%" PRIu8 ", count2=%" PRIu8 "",
|
||||
period, count1, count2);
|
||||
|
||||
return (rdp_send_message_channel_pdu(rdp, s, sec_flags | SEC_HEARTBEAT));
|
||||
}
|
||||
|
||||
rdpHeartbeat* heartbeat_new(void)
|
||||
{
|
||||
rdpHeartbeat* heartbeat = (rdpHeartbeat*)calloc(1, sizeof(rdpHeartbeat));
|
||||
|
||||
if (heartbeat)
|
||||
{
|
||||
}
|
||||
|
||||
return heartbeat;
|
||||
}
|
||||
|
||||
void heartbeat_free(rdpHeartbeat* heartbeat)
|
||||
{
|
||||
free(heartbeat);
|
||||
}
|
||||
45
third_party/FreeRDP/libfreerdp/core/heartbeat.h
vendored
Normal file
45
third_party/FreeRDP/libfreerdp/core/heartbeat.h
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Heartbeat PDUs
|
||||
*
|
||||
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_HEARTBEET_H
|
||||
#define FREERDP_LIB_CORE_HEARTBEET_H
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
#include <freerdp/heartbeat.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include "state.h"
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t rdp_recv_heartbeat_packet(rdpRdp* rdp, wStream* s);
|
||||
|
||||
FREERDP_LOCAL void heartbeat_free(rdpHeartbeat* heartbeat);
|
||||
|
||||
WINPR_ATTR_MALLOC(heartbeat_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpHeartbeat* heartbeat_new(void);
|
||||
|
||||
#define HEARTBEAT_TAG FREERDP_TAG("core.heartbeat")
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_HEARTBEET_H */
|
||||
1602
third_party/FreeRDP/libfreerdp/core/info.c
vendored
Normal file
1602
third_party/FreeRDP/libfreerdp/core/info.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
76
third_party/FreeRDP/libfreerdp/core/info.h
vendored
Normal file
76
third_party/FreeRDP/libfreerdp/core/info.h
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Client Info
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_INFO_H
|
||||
#define FREERDP_LIB_CORE_INFO_H
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
/* Client Address Family */
|
||||
#define ADDRESS_FAMILY_INET 0x0002
|
||||
#define ADDRESS_FAMILY_INET6 0x0017
|
||||
|
||||
/* Client Info Packet Flags */
|
||||
#define INFO_MOUSE 0x00000001
|
||||
#define INFO_DISABLECTRLALTDEL 0x00000002
|
||||
#define INFO_AUTOLOGON 0x00000008
|
||||
#define INFO_UNICODE 0x00000010
|
||||
#define INFO_MAXIMIZESHELL 0x00000020
|
||||
#define INFO_LOGONNOTIFY 0x00000040
|
||||
#define INFO_COMPRESSION 0x00000080
|
||||
#define INFO_ENABLEWINDOWSKEY 0x00000100
|
||||
#define INFO_REMOTECONSOLEAUDIO 0x00002000
|
||||
#define INFO_FORCE_ENCRYPTED_CS_PDU 0x00004000
|
||||
#define INFO_RAIL 0x00008000
|
||||
#define INFO_LOGONERRORS 0x00010000
|
||||
#define INFO_MOUSE_HAS_WHEEL 0x00020000
|
||||
#define INFO_PASSWORD_IS_SC_PIN 0x00040000
|
||||
#define INFO_NOAUDIOPLAYBACK 0x00080000
|
||||
#define INFO_USING_SAVED_CREDS 0x00100000
|
||||
#define INFO_AUDIOCAPTURE 0x00200000
|
||||
#define INFO_VIDEO_DISABLE 0x00400000
|
||||
#define INFO_HIDEF_RAIL_SUPPORTED 0x02000000
|
||||
|
||||
/* Extended Logon Info */
|
||||
#define LOGON_EX_AUTORECONNECTCOOKIE 0x00000001
|
||||
#define LOGON_EX_LOGONERRORS 0x00000002
|
||||
|
||||
#define SAVE_SESSION_PDU_VERSION_ONE 0x0001
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_recv_client_info(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_client_info(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_save_session_info(rdpContext* context, UINT32 type, void* data);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_server_status_info(rdpContext* context, UINT32 status);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_INFO_H */
|
||||
1155
third_party/FreeRDP/libfreerdp/core/input.c
vendored
Normal file
1155
third_party/FreeRDP/libfreerdp/core/input.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
76
third_party/FreeRDP/libfreerdp/core/input.h
vendored
Normal file
76
third_party/FreeRDP/libfreerdp/core/input.h
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Input PDUs
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_INPUT_H
|
||||
#define FREERDP_LIB_CORE_INPUT_H
|
||||
|
||||
#include "rdp.h"
|
||||
#include "fastpath.h"
|
||||
#include "message.h"
|
||||
|
||||
#include <freerdp/input.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rdpInput common;
|
||||
/* Internal */
|
||||
|
||||
rdpInputProxy* proxy;
|
||||
wMessageQueue* queue;
|
||||
|
||||
UINT64 lastInputTimestamp;
|
||||
UINT16 lastX;
|
||||
UINT16 lastY;
|
||||
wLog* log;
|
||||
} rdp_input_internal;
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
static inline rdp_input_internal* input_cast(rdpInput* input)
|
||||
{
|
||||
union
|
||||
{
|
||||
rdpInput* pub;
|
||||
rdp_input_internal* internal;
|
||||
} cnv;
|
||||
|
||||
WINPR_ASSERT(input);
|
||||
cnv.pub = input;
|
||||
return cnv.internal;
|
||||
}
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL input_recv(rdpInput* input, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int input_process_events(rdpInput* input);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL input_register_client_callbacks(rdpInput* input);
|
||||
|
||||
FREERDP_LOCAL void input_free(rdpInput* input);
|
||||
|
||||
WINPR_ATTR_MALLOC(input_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpInput* input_new(rdpRdp* rdp);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_INPUT_H */
|
||||
3022
third_party/FreeRDP/libfreerdp/core/license.c
vendored
Normal file
3022
third_party/FreeRDP/libfreerdp/core/license.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
88
third_party/FreeRDP/libfreerdp/core/license.h
vendored
Normal file
88
third_party/FreeRDP/libfreerdp/core/license.h
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Licensing
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2022 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2022 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_LICENSE_H
|
||||
#define FREERDP_LIB_CORE_LICENSE_H
|
||||
|
||||
#include "rdp.h"
|
||||
#include "state.h"
|
||||
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/license.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#define CLIENT_RANDOM_LENGTH 32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 dwVersion;
|
||||
UINT32 cbCompanyName;
|
||||
BYTE* pbCompanyName;
|
||||
UINT32 cbProductId;
|
||||
BYTE* pbProductId;
|
||||
} LICENSE_PRODUCT_INFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 type;
|
||||
UINT16 length;
|
||||
BYTE* data;
|
||||
} LICENSE_BLOB;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 count;
|
||||
LICENSE_BLOB** array;
|
||||
} SCOPE_LIST;
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL license_send_valid_client_error_packet(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t license_recv(rdpLicense* license, wStream* s);
|
||||
|
||||
/* the configuration is applied from settings. Set FreeRDP_ServerLicense* settings */
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL license_server_configure(rdpLicense* license);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL license_server_send_request(rdpLicense* license);
|
||||
|
||||
FREERDP_LOCAL void license_free(rdpLicense* license);
|
||||
|
||||
WINPR_ATTR_MALLOC(license_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpLicense* license_new(rdpRdp* rdp);
|
||||
|
||||
#define LICENSE_TAG FREERDP_TAG("core.license")
|
||||
#ifdef WITH_DEBUG_LICENSE
|
||||
#define DEBUG_LICENSE(...) WLog_INFO(LICENSE_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_LICENSE(...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_LICENSE_H */
|
||||
559
third_party/FreeRDP/libfreerdp/core/listener.c
vendored
Normal file
559
third_party/FreeRDP/libfreerdp/core/listener.c
vendored
Normal file
@@ -0,0 +1,559 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Server Listener
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/windows.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_AF_VSOCK_H)
|
||||
#include <ctype.h>
|
||||
#include <linux/vm_sockets.h>
|
||||
#endif
|
||||
|
||||
#include <winpr/handle.h>
|
||||
|
||||
#include "listener.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.listener")
|
||||
|
||||
static BOOL freerdp_listener_open_from_vsock(WINPR_ATTR_UNUSED freerdp_listener* instance,
|
||||
WINPR_ATTR_UNUSED const char* bind_address,
|
||||
WINPR_ATTR_UNUSED UINT16 port)
|
||||
{
|
||||
#if defined(HAVE_AF_VSOCK_H)
|
||||
rdpListener* listener = (rdpListener*)instance->listener;
|
||||
const int sockfd = socket(AF_VSOCK, SOCK_STREAM, 0);
|
||||
if (sockfd == -1)
|
||||
{
|
||||
char ebuffer[256] = WINPR_C_ARRAY_INIT;
|
||||
WLog_ERR(TAG, "Error creating socket: %s", winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
return FALSE;
|
||||
}
|
||||
const int flags = fcntl(sockfd, F_GETFL, 0);
|
||||
if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
{
|
||||
char ebuffer[256] = WINPR_C_ARRAY_INIT;
|
||||
WLog_ERR(TAG, "Error making socket nonblocking: %s",
|
||||
winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
close(sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
struct sockaddr_vm addr = WINPR_C_ARRAY_INIT;
|
||||
|
||||
addr.svm_family = AF_VSOCK;
|
||||
addr.svm_port = port;
|
||||
|
||||
errno = 0;
|
||||
char* ptr = nullptr;
|
||||
unsigned long val = strtoul(bind_address, &ptr, 10);
|
||||
if (errno || (val > UINT32_MAX))
|
||||
{
|
||||
/* handle VMADDR_CID_ANY (-1U) */
|
||||
if ((val == ULONG_MAX) && (errno == 0))
|
||||
val = UINT32_MAX;
|
||||
else
|
||||
{
|
||||
char ebuffer[256] = WINPR_C_ARRAY_INIT;
|
||||
WLog_ERR(TAG, "could not extract port from '%s', value=%lu, error=%s", bind_address,
|
||||
val, winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
close(sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
addr.svm_cid = WINPR_ASSERTING_INT_CAST(unsigned int, val);
|
||||
if (bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_vm)) == -1)
|
||||
{
|
||||
char ebuffer[256] = WINPR_C_ARRAY_INIT;
|
||||
WLog_ERR(TAG, "Error binding vsock at cid %u port %d: %s", addr.svm_cid, port,
|
||||
winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
close(sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (listen(sockfd, 10) == -1)
|
||||
{
|
||||
char ebuffer[256] = WINPR_C_ARRAY_INIT;
|
||||
WLog_ERR(TAG, "Error listening to socket at cid %u port %d: %s", addr.svm_cid, port,
|
||||
winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
close(sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
listener->sockfds[listener->num_sockfds] = sockfd;
|
||||
listener->events[listener->num_sockfds] = WSACreateEvent();
|
||||
|
||||
if (!listener->events[listener->num_sockfds])
|
||||
{
|
||||
listener->num_sockfds = 0;
|
||||
}
|
||||
|
||||
WSAEventSelect((SOCKET)sockfd, listener->events[listener->num_sockfds],
|
||||
FD_READ | FD_ACCEPT | FD_CLOSE);
|
||||
listener->num_sockfds++;
|
||||
|
||||
WLog_INFO(TAG, "Listening on %s:%d", bind_address, port);
|
||||
return TRUE;
|
||||
#else
|
||||
WLog_ERR(TAG, "compiled without AF_VSOCK, '%s' not supported", bind_address);
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_address, UINT16 port)
|
||||
{
|
||||
int ai_flags = 0;
|
||||
int status = 0;
|
||||
int sockfd = 0;
|
||||
char addr[64];
|
||||
void* sin_addr = nullptr;
|
||||
int option_value = 0;
|
||||
struct addrinfo* res = nullptr;
|
||||
rdpListener* listener = (rdpListener*)instance->listener;
|
||||
#ifdef _WIN32
|
||||
u_long arg;
|
||||
#endif
|
||||
|
||||
if (!bind_address)
|
||||
ai_flags = AI_PASSIVE;
|
||||
|
||||
if (utils_is_vsock(bind_address))
|
||||
{
|
||||
bind_address = utils_is_vsock(bind_address);
|
||||
return freerdp_listener_open_from_vsock(instance, bind_address, port);
|
||||
}
|
||||
|
||||
res = freerdp_tcp_resolve_host(bind_address, port, ai_flags);
|
||||
|
||||
if (!res)
|
||||
return FALSE;
|
||||
|
||||
for (struct addrinfo* ai = res; ai && (listener->num_sockfds < 5); ai = ai->ai_next)
|
||||
{
|
||||
if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6))
|
||||
continue;
|
||||
|
||||
if (listener->num_sockfds == MAX_LISTENER_HANDLES)
|
||||
{
|
||||
WLog_ERR(TAG, "too many listening sockets");
|
||||
continue;
|
||||
}
|
||||
|
||||
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
|
||||
if (sockfd == -1)
|
||||
{
|
||||
WLog_ERR(TAG, "socket");
|
||||
continue;
|
||||
}
|
||||
|
||||
option_value = 1;
|
||||
|
||||
if (ai->ai_family == AF_INET)
|
||||
sin_addr = &(((struct sockaddr_in*)ai->ai_addr)->sin_addr);
|
||||
else
|
||||
{
|
||||
sin_addr = &(((struct sockaddr_in6*)ai->ai_addr)->sin6_addr);
|
||||
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&option_value,
|
||||
sizeof(option_value)) == -1)
|
||||
WLog_ERR(TAG, "setsockopt");
|
||||
}
|
||||
|
||||
inet_ntop(ai->ai_family, sin_addr, addr, sizeof(addr));
|
||||
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&option_value,
|
||||
sizeof(option_value)) == -1)
|
||||
WLog_ERR(TAG, "setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR)");
|
||||
|
||||
#ifndef _WIN32
|
||||
if (fcntl(sockfd, F_SETFL, O_NONBLOCK) != 0)
|
||||
WLog_ERR(TAG, "fcntl(sockfd, F_SETFL, O_NONBLOCK)");
|
||||
#else
|
||||
arg = 1;
|
||||
ioctlsocket(sockfd, FIONBIO, &arg);
|
||||
#endif
|
||||
status = _bind((SOCKET)sockfd, ai->ai_addr, WINPR_ASSERTING_INT_CAST(int, ai->ai_addrlen));
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
closesocket((SOCKET)sockfd);
|
||||
continue;
|
||||
}
|
||||
|
||||
status = _listen((SOCKET)sockfd, 10);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "listen");
|
||||
closesocket((SOCKET)sockfd);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* FIXME: these file descriptors do not work on Windows */
|
||||
listener->sockfds[listener->num_sockfds] = sockfd;
|
||||
listener->events[listener->num_sockfds] = WSACreateEvent();
|
||||
|
||||
if (!listener->events[listener->num_sockfds])
|
||||
{
|
||||
listener->num_sockfds = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
WSAEventSelect((SOCKET)sockfd, listener->events[listener->num_sockfds],
|
||||
FD_READ | FD_ACCEPT | FD_CLOSE);
|
||||
listener->num_sockfds++;
|
||||
WLog_INFO(TAG, "Listening on [%s]:%" PRIu16, addr, port);
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
return ((listener->num_sockfds > 0));
|
||||
}
|
||||
|
||||
static BOOL freerdp_listener_open_local(freerdp_listener* instance, const char* path)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
int status = 0;
|
||||
int sockfd = 0;
|
||||
struct sockaddr_un addr = WINPR_C_ARRAY_INIT;
|
||||
rdpListener* listener = (rdpListener*)instance->listener;
|
||||
HANDLE hevent = nullptr;
|
||||
|
||||
if (listener->num_sockfds == MAX_LISTENER_HANDLES)
|
||||
{
|
||||
WLog_ERR(TAG, "too many listening sockets");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
if (sockfd == -1)
|
||||
{
|
||||
WLog_ERR(TAG, "socket");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int rc = fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
||||
if (rc != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "fcntl(sockfd, F_SETFL, O_NONBLOCK)");
|
||||
closesocket((SOCKET)sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
|
||||
unlink(path);
|
||||
status = _bind((SOCKET)sockfd, (struct sockaddr*)&addr, sizeof(addr));
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "bind");
|
||||
closesocket((SOCKET)sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = _listen((SOCKET)sockfd, 10);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "listen");
|
||||
closesocket((SOCKET)sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hevent = CreateFileDescriptorEvent(nullptr, FALSE, FALSE, sockfd, WINPR_FD_READ);
|
||||
|
||||
if (!hevent)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to create sockfd event");
|
||||
closesocket((SOCKET)sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
listener->sockfds[listener->num_sockfds] = sockfd;
|
||||
listener->events[listener->num_sockfds] = hevent;
|
||||
listener->num_sockfds++;
|
||||
WLog_INFO(TAG, "Listening on socket %s.", addr.sun_path);
|
||||
return TRUE;
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BOOL freerdp_listener_open_from_socket(freerdp_listener* instance, int fd)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
rdpListener* listener = (rdpListener*)instance->listener;
|
||||
|
||||
if (listener->num_sockfds == MAX_LISTENER_HANDLES)
|
||||
{
|
||||
WLog_ERR(TAG, "too many listening sockets");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
|
||||
return FALSE;
|
||||
|
||||
listener->sockfds[listener->num_sockfds] = fd;
|
||||
listener->events[listener->num_sockfds] = WSACreateEvent();
|
||||
|
||||
if (!listener->events[listener->num_sockfds])
|
||||
return FALSE;
|
||||
|
||||
WSAEventSelect((SOCKET)fd, listener->events[listener->num_sockfds],
|
||||
FD_READ | FD_ACCEPT | FD_CLOSE);
|
||||
|
||||
listener->num_sockfds++;
|
||||
WLog_INFO(TAG, "Listening on socket %d.", fd);
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void freerdp_listener_close(freerdp_listener* instance)
|
||||
{
|
||||
rdpListener* listener = (rdpListener*)instance->listener;
|
||||
|
||||
for (int i = 0; i < listener->num_sockfds; i++)
|
||||
{
|
||||
closesocket((SOCKET)listener->sockfds[i]);
|
||||
(void)CloseHandle(listener->events[i]);
|
||||
}
|
||||
|
||||
listener->num_sockfds = 0;
|
||||
}
|
||||
|
||||
#if defined(WITH_FREERDP_DEPRECATED)
|
||||
static BOOL freerdp_listener_get_fds(freerdp_listener* instance, void** rfds, int* rcount)
|
||||
{
|
||||
rdpListener* listener = (rdpListener*)instance->listener;
|
||||
|
||||
if (listener->num_sockfds < 1)
|
||||
return FALSE;
|
||||
|
||||
for (int index = 0; index < listener->num_sockfds; index++)
|
||||
{
|
||||
rfds[*rcount] = (void*)(long)(listener->sockfds[index]);
|
||||
(*rcount)++;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static DWORD freerdp_listener_get_event_handles(freerdp_listener* instance, HANDLE* events,
|
||||
DWORD nCount)
|
||||
{
|
||||
rdpListener* listener = (rdpListener*)instance->listener;
|
||||
|
||||
if (listener->num_sockfds < 1)
|
||||
return 0;
|
||||
|
||||
if (listener->num_sockfds > (INT64)nCount)
|
||||
return 0;
|
||||
|
||||
for (int index = 0; index < listener->num_sockfds; index++)
|
||||
{
|
||||
events[index] = listener->events[index];
|
||||
}
|
||||
|
||||
return WINPR_ASSERTING_INT_CAST(uint32_t, listener->num_sockfds);
|
||||
}
|
||||
|
||||
BOOL freerdp_peer_set_local_and_hostname(freerdp_peer* client,
|
||||
const struct sockaddr_storage* peer_addr)
|
||||
{
|
||||
const void* sin_addr = nullptr;
|
||||
const BYTE localhost6_bytes[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
|
||||
|
||||
WINPR_ASSERT(client);
|
||||
WINPR_ASSERT(peer_addr);
|
||||
|
||||
if (peer_addr->ss_family == AF_INET)
|
||||
{
|
||||
const UINT32* usin_addr = sin_addr = &(((const struct sockaddr_in*)peer_addr)->sin_addr);
|
||||
|
||||
if ((*usin_addr) == 0x0100007f)
|
||||
client->local = TRUE;
|
||||
}
|
||||
else if (peer_addr->ss_family == AF_INET6)
|
||||
{
|
||||
const struct sockaddr_in6* usin_addr = sin_addr =
|
||||
&(((const struct sockaddr_in6*)peer_addr)->sin6_addr);
|
||||
|
||||
if (memcmp(usin_addr, localhost6_bytes, 16) == 0)
|
||||
client->local = TRUE;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
#if defined(HAVE_AF_VSOCK_H)
|
||||
else if (peer_addr->ss_family == AF_UNIX || peer_addr->ss_family == AF_VSOCK)
|
||||
#else
|
||||
else if (peer_addr->ss_family == AF_UNIX)
|
||||
#endif
|
||||
client->local = TRUE;
|
||||
#endif
|
||||
|
||||
if (client->local)
|
||||
WLog_INFO(TAG, "Accepting client from localhost");
|
||||
|
||||
if (sin_addr)
|
||||
inet_ntop(peer_addr->ss_family, sin_addr, client->hostname, sizeof(client->hostname));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL freerdp_check_and_create_client(freerdp_listener* instance, int peer_sockfd,
|
||||
const struct sockaddr_storage* peer_addr)
|
||||
{
|
||||
WINPR_ASSERT(instance);
|
||||
WINPR_ASSERT(peer_sockfd >= 0);
|
||||
WINPR_ASSERT(peer_addr);
|
||||
|
||||
const BOOL check = IFCALLRESULT(TRUE, instance->CheckPeerAcceptRestrictions, instance);
|
||||
if (!check)
|
||||
{
|
||||
closesocket((SOCKET)peer_sockfd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
freerdp_peer* client = freerdp_peer_new(peer_sockfd);
|
||||
if (!client)
|
||||
{
|
||||
closesocket((SOCKET)peer_sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!freerdp_peer_set_local_and_hostname(client, peer_addr))
|
||||
{
|
||||
freerdp_peer_free(client);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const BOOL peer_accepted = IFCALLRESULT(FALSE, instance->PeerAccepted, instance, client);
|
||||
if (!peer_accepted)
|
||||
{
|
||||
WLog_ERR(TAG, "PeerAccepted callback failed");
|
||||
freerdp_peer_free(client);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL freerdp_listener_check_fds(freerdp_listener* instance)
|
||||
{
|
||||
rdpListener* listener = (rdpListener*)instance->listener;
|
||||
|
||||
if (listener->num_sockfds < 1)
|
||||
return FALSE;
|
||||
|
||||
for (int i = 0; i < listener->num_sockfds; i++)
|
||||
{
|
||||
struct sockaddr_storage peer_addr = WINPR_C_ARRAY_INIT;
|
||||
|
||||
(void)WSAResetEvent(listener->events[i]);
|
||||
int peer_addr_size = sizeof(peer_addr);
|
||||
SOCKET peer_sockfd =
|
||||
_accept((SOCKET)listener->sockfds[i], (struct sockaddr*)&peer_addr, &peer_addr_size);
|
||||
|
||||
if (peer_sockfd == (SOCKET)-1)
|
||||
{
|
||||
char buffer[128] = WINPR_C_ARRAY_INIT;
|
||||
#ifdef _WIN32
|
||||
int wsa_error = WSAGetLastError();
|
||||
|
||||
/* No data available */
|
||||
if (wsa_error == WSAEWOULDBLOCK)
|
||||
continue;
|
||||
|
||||
#else
|
||||
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
continue;
|
||||
|
||||
#endif
|
||||
WLog_WARN(TAG, "accept failed with %s", winpr_strerror(errno, buffer, sizeof(buffer)));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!freerdp_check_and_create_client(instance, (int)peer_sockfd, &peer_addr))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
freerdp_listener* freerdp_listener_new(void)
|
||||
{
|
||||
freerdp_listener* instance = nullptr;
|
||||
rdpListener* listener = nullptr;
|
||||
instance = (freerdp_listener*)calloc(1, sizeof(freerdp_listener));
|
||||
|
||||
if (!instance)
|
||||
return nullptr;
|
||||
|
||||
instance->Open = freerdp_listener_open;
|
||||
instance->OpenLocal = freerdp_listener_open_local;
|
||||
instance->OpenFromSocket = freerdp_listener_open_from_socket;
|
||||
#if defined(WITH_FREERDP_DEPRECATED)
|
||||
instance->GetFileDescriptor = freerdp_listener_get_fds;
|
||||
#endif
|
||||
instance->GetEventHandles = freerdp_listener_get_event_handles;
|
||||
instance->CheckFileDescriptor = freerdp_listener_check_fds;
|
||||
instance->Close = freerdp_listener_close;
|
||||
listener = (rdpListener*)calloc(1, sizeof(rdpListener));
|
||||
|
||||
if (!listener)
|
||||
{
|
||||
free(instance);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
listener->instance = instance;
|
||||
instance->listener = (void*)listener;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void freerdp_listener_free(freerdp_listener* instance)
|
||||
{
|
||||
if (instance)
|
||||
{
|
||||
free(instance->listener);
|
||||
free(instance);
|
||||
}
|
||||
}
|
||||
43
third_party/FreeRDP/libfreerdp/core/listener.h
vendored
Normal file
43
third_party/FreeRDP/libfreerdp/core/listener.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Server Listener
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_LISTENER_H
|
||||
#define FREERDP_LIB_CORE_LISTENER_H
|
||||
|
||||
typedef struct rdp_listener rdpListener;
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#include <freerdp/listener.h>
|
||||
|
||||
#define MAX_LISTENER_HANDLES 5
|
||||
|
||||
struct rdp_listener
|
||||
{
|
||||
freerdp_listener* instance;
|
||||
|
||||
int num_sockfds;
|
||||
int sockfds[MAX_LISTENER_HANDLES];
|
||||
HANDLE events[MAX_LISTENER_HANDLES];
|
||||
};
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_LISTENER_H */
|
||||
1543
third_party/FreeRDP/libfreerdp/core/mcs.c
vendored
Normal file
1543
third_party/FreeRDP/libfreerdp/core/mcs.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
224
third_party/FreeRDP/libfreerdp/core/mcs.h
vendored
Normal file
224
third_party/FreeRDP/libfreerdp/core/mcs.h
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* T.125 Multipoint Communication Service (MCS) Protocol
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_MCS_H
|
||||
#define FREERDP_LIB_CORE_MCS_H
|
||||
|
||||
typedef struct rdp_mcs rdpMcs;
|
||||
|
||||
#include "transport.h"
|
||||
|
||||
#include <freerdp/crypto/ber.h>
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/wtsapi.h>
|
||||
|
||||
enum MCS_Result
|
||||
{
|
||||
MCS_Result_successful = 0,
|
||||
MCS_Result_domain_merging = 1,
|
||||
MCS_Result_domain_not_hierarchical = 2,
|
||||
MCS_Result_no_such_channel = 3,
|
||||
MCS_Result_no_such_domain = 4,
|
||||
MCS_Result_no_such_user = 5,
|
||||
MCS_Result_not_admitted = 6,
|
||||
MCS_Result_other_user_id = 7,
|
||||
MCS_Result_parameters_unacceptable = 8,
|
||||
MCS_Result_token_not_available = 9,
|
||||
MCS_Result_token_not_possessed = 10,
|
||||
MCS_Result_too_many_channels = 11,
|
||||
MCS_Result_too_many_tokens = 12,
|
||||
MCS_Result_too_many_users = 13,
|
||||
MCS_Result_unspecified_failure = 14,
|
||||
MCS_Result_user_rejected = 15,
|
||||
MCS_Result_enum_length = 16
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DomainMCSPDU_invalid = -1,
|
||||
DomainMCSPDU_PlumbDomainIndication = 0,
|
||||
DomainMCSPDU_ErectDomainRequest = 1,
|
||||
DomainMCSPDU_MergeChannelsRequest = 2,
|
||||
DomainMCSPDU_MergeChannelsConfirm = 3,
|
||||
DomainMCSPDU_PurgeChannelsIndication = 4,
|
||||
DomainMCSPDU_MergeTokensRequest = 5,
|
||||
DomainMCSPDU_MergeTokensConfirm = 6,
|
||||
DomainMCSPDU_PurgeTokensIndication = 7,
|
||||
DomainMCSPDU_DisconnectProviderUltimatum = 8,
|
||||
DomainMCSPDU_RejectMCSPDUUltimatum = 9,
|
||||
DomainMCSPDU_AttachUserRequest = 10,
|
||||
DomainMCSPDU_AttachUserConfirm = 11,
|
||||
DomainMCSPDU_DetachUserRequest = 12,
|
||||
DomainMCSPDU_DetachUserIndication = 13,
|
||||
DomainMCSPDU_ChannelJoinRequest = 14,
|
||||
DomainMCSPDU_ChannelJoinConfirm = 15,
|
||||
DomainMCSPDU_ChannelLeaveRequest = 16,
|
||||
DomainMCSPDU_ChannelConveneRequest = 17,
|
||||
DomainMCSPDU_ChannelConveneConfirm = 18,
|
||||
DomainMCSPDU_ChannelDisbandRequest = 19,
|
||||
DomainMCSPDU_ChannelDisbandIndication = 20,
|
||||
DomainMCSPDU_ChannelAdmitRequest = 21,
|
||||
DomainMCSPDU_ChannelAdmitIndication = 22,
|
||||
DomainMCSPDU_ChannelExpelRequest = 23,
|
||||
DomainMCSPDU_ChannelExpelIndication = 24,
|
||||
DomainMCSPDU_SendDataRequest = 25,
|
||||
DomainMCSPDU_SendDataIndication = 26,
|
||||
DomainMCSPDU_UniformSendDataRequest = 27,
|
||||
DomainMCSPDU_UniformSendDataIndication = 28,
|
||||
DomainMCSPDU_TokenGrabRequest = 29,
|
||||
DomainMCSPDU_TokenGrabConfirm = 30,
|
||||
DomainMCSPDU_TokenInhibitRequest = 31,
|
||||
DomainMCSPDU_TokenInhibitConfirm = 32,
|
||||
DomainMCSPDU_TokenGiveRequest = 33,
|
||||
DomainMCSPDU_TokenGiveIndication = 34,
|
||||
DomainMCSPDU_TokenGiveResponse = 35,
|
||||
DomainMCSPDU_TokenGiveConfirm = 36,
|
||||
DomainMCSPDU_TokenPleaseRequest = 37,
|
||||
DomainMCSPDU_TokenPleaseConfirm = 38,
|
||||
DomainMCSPDU_TokenReleaseRequest = 39,
|
||||
DomainMCSPDU_TokenReleaseConfirm = 40,
|
||||
DomainMCSPDU_TokenTestRequest = 41,
|
||||
DomainMCSPDU_TokenTestConfirm = 42,
|
||||
DomainMCSPDU_enum_length = 43
|
||||
} DomainMCSPDU;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 maxChannelIds;
|
||||
UINT32 maxUserIds;
|
||||
UINT32 maxTokenIds;
|
||||
UINT32 numPriorities;
|
||||
UINT32 minThroughput;
|
||||
UINT32 maxHeight;
|
||||
UINT32 maxMCSPDUsize;
|
||||
UINT32 protocolVersion;
|
||||
} DomainParameters;
|
||||
|
||||
struct rdp_mcs_channel
|
||||
{
|
||||
char Name[CHANNEL_NAME_LEN + 1];
|
||||
UINT32 options;
|
||||
UINT16 ChannelId;
|
||||
BOOL joined;
|
||||
void* handle;
|
||||
};
|
||||
typedef struct rdp_mcs_channel rdpMcsChannel;
|
||||
|
||||
struct rdp_mcs
|
||||
{
|
||||
rdpContext* context;
|
||||
|
||||
UINT16 userId;
|
||||
UINT16 baseChannelId;
|
||||
UINT16 IOChannelId;
|
||||
UINT16 messageChannelId;
|
||||
|
||||
UINT32 flags;
|
||||
|
||||
DomainParameters domainParameters;
|
||||
DomainParameters targetParameters;
|
||||
DomainParameters minimumParameters;
|
||||
DomainParameters maximumParameters;
|
||||
|
||||
BOOL userChannelJoined;
|
||||
BOOL globalChannelJoined;
|
||||
BOOL messageChannelJoined;
|
||||
|
||||
UINT32 channelCount;
|
||||
UINT32 channelMaxCount;
|
||||
rdpMcsChannel* channels;
|
||||
wLog* log;
|
||||
};
|
||||
|
||||
#define MCS_SEND_DATA_HEADER_MAX_LENGTH 8
|
||||
|
||||
#define MCS_TYPE_CONNECT_INITIAL 0x65
|
||||
#define MCS_TYPE_CONNECT_RESPONSE 0x66
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* mcs_domain_pdu_string(DomainMCSPDU pdu);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_server_apply_to_settings(const rdpMcs* mcs, rdpSettings* settings);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_recv_connect_response(rdpMcs* mcs, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_send_connect_response(rdpMcs* mcs);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_recv_erect_domain_request(rdpMcs* mcs, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_send_erect_domain_request(rdpMcs* mcs);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_recv_attach_user_request(rdpMcs* mcs, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_send_attach_user_request(rdpMcs* mcs);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_recv_attach_user_confirm(rdpMcs* mcs, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_send_attach_user_confirm(rdpMcs* mcs);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_recv_channel_join_request(rdpMcs* mcs, const rdpSettings* settings,
|
||||
wStream* s, UINT16* channelId);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channelId);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channelId);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channelId);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_recv_disconnect_provider_ultimatum(rdpMcs* mcs, wStream* s, int* reason);
|
||||
|
||||
FREERDP_LOCAL BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs,
|
||||
enum Disconnect_Ultimatum reason);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_write_domain_mcspdu_header(wStream* s, DomainMCSPDU domainMCSPDU,
|
||||
UINT16 length, BYTE options);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL mcs_client_begin(rdpMcs* mcs);
|
||||
|
||||
FREERDP_LOCAL void mcs_free(rdpMcs* mcs);
|
||||
|
||||
WINPR_ATTR_MALLOC(mcs_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpMcs* mcs_new(rdpContext* context);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_MCS_H */
|
||||
3131
third_party/FreeRDP/libfreerdp/core/message.c
vendored
Normal file
3131
third_party/FreeRDP/libfreerdp/core/message.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
170
third_party/FreeRDP/libfreerdp/core/message.h
vendored
Normal file
170
third_party/FreeRDP/libfreerdp/core/message.h
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Asynchronous Message Queue
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_MESSAGE_H
|
||||
#define FREERDP_LIB_CORE_MESSAGE_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/message.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
/**
|
||||
* Update Message Queue
|
||||
*/
|
||||
|
||||
/* Update Proxy Interface */
|
||||
|
||||
struct rdp_update_proxy
|
||||
{
|
||||
rdpUpdate* update;
|
||||
|
||||
/* Update */
|
||||
|
||||
WINPR_ATTR_NODISCARD pBeginPaint BeginPaint;
|
||||
WINPR_ATTR_NODISCARD pEndPaint EndPaint;
|
||||
WINPR_ATTR_NODISCARD pSetBounds SetBounds;
|
||||
WINPR_ATTR_NODISCARD pSynchronize Synchronize;
|
||||
WINPR_ATTR_NODISCARD pDesktopResize DesktopResize;
|
||||
WINPR_ATTR_NODISCARD pBitmapUpdate BitmapUpdate;
|
||||
WINPR_ATTR_NODISCARD pPalette Palette;
|
||||
WINPR_ATTR_NODISCARD pPlaySound PlaySound;
|
||||
WINPR_ATTR_NODISCARD pSetKeyboardIndicators SetKeyboardIndicators;
|
||||
WINPR_ATTR_NODISCARD pSetKeyboardImeStatus SetKeyboardImeStatus;
|
||||
WINPR_ATTR_NODISCARD pRefreshRect RefreshRect;
|
||||
WINPR_ATTR_NODISCARD pSuppressOutput SuppressOutput;
|
||||
WINPR_ATTR_NODISCARD pSurfaceCommand SurfaceCommand;
|
||||
WINPR_ATTR_NODISCARD pSurfaceBits SurfaceBits;
|
||||
WINPR_ATTR_NODISCARD pSurfaceFrameMarker SurfaceFrameMarker;
|
||||
WINPR_ATTR_NODISCARD pSurfaceFrameAcknowledge SurfaceFrameAcknowledge;
|
||||
|
||||
/* Primary Update */
|
||||
|
||||
WINPR_ATTR_NODISCARD pDstBlt DstBlt;
|
||||
WINPR_ATTR_NODISCARD pPatBlt PatBlt;
|
||||
WINPR_ATTR_NODISCARD pScrBlt ScrBlt;
|
||||
WINPR_ATTR_NODISCARD pOpaqueRect OpaqueRect;
|
||||
WINPR_ATTR_NODISCARD pDrawNineGrid DrawNineGrid;
|
||||
WINPR_ATTR_NODISCARD pMultiDstBlt MultiDstBlt;
|
||||
WINPR_ATTR_NODISCARD pMultiPatBlt MultiPatBlt;
|
||||
WINPR_ATTR_NODISCARD pMultiScrBlt MultiScrBlt;
|
||||
WINPR_ATTR_NODISCARD pMultiOpaqueRect MultiOpaqueRect;
|
||||
WINPR_ATTR_NODISCARD pMultiDrawNineGrid MultiDrawNineGrid;
|
||||
WINPR_ATTR_NODISCARD pLineTo LineTo;
|
||||
WINPR_ATTR_NODISCARD pPolyline Polyline;
|
||||
WINPR_ATTR_NODISCARD pMemBlt MemBlt;
|
||||
WINPR_ATTR_NODISCARD pMem3Blt Mem3Blt;
|
||||
WINPR_ATTR_NODISCARD pSaveBitmap SaveBitmap;
|
||||
WINPR_ATTR_NODISCARD pGlyphIndex GlyphIndex;
|
||||
WINPR_ATTR_NODISCARD pFastIndex FastIndex;
|
||||
WINPR_ATTR_NODISCARD pFastGlyph FastGlyph;
|
||||
WINPR_ATTR_NODISCARD pPolygonSC PolygonSC;
|
||||
WINPR_ATTR_NODISCARD pPolygonCB PolygonCB;
|
||||
WINPR_ATTR_NODISCARD pEllipseSC EllipseSC;
|
||||
WINPR_ATTR_NODISCARD pEllipseCB EllipseCB;
|
||||
|
||||
/* Secondary Update */
|
||||
|
||||
WINPR_ATTR_NODISCARD pCacheBitmap CacheBitmap;
|
||||
WINPR_ATTR_NODISCARD pCacheBitmapV2 CacheBitmapV2;
|
||||
WINPR_ATTR_NODISCARD pCacheBitmapV3 CacheBitmapV3;
|
||||
WINPR_ATTR_NODISCARD pCacheColorTable CacheColorTable;
|
||||
WINPR_ATTR_NODISCARD pCacheGlyph CacheGlyph;
|
||||
WINPR_ATTR_NODISCARD pCacheGlyphV2 CacheGlyphV2;
|
||||
WINPR_ATTR_NODISCARD pCacheBrush CacheBrush;
|
||||
|
||||
/* Alternate Secondary Update */
|
||||
|
||||
WINPR_ATTR_NODISCARD pCreateOffscreenBitmap CreateOffscreenBitmap;
|
||||
WINPR_ATTR_NODISCARD pSwitchSurface SwitchSurface;
|
||||
WINPR_ATTR_NODISCARD pCreateNineGridBitmap CreateNineGridBitmap;
|
||||
WINPR_ATTR_NODISCARD pFrameMarker FrameMarker;
|
||||
WINPR_ATTR_NODISCARD pStreamBitmapFirst StreamBitmapFirst;
|
||||
WINPR_ATTR_NODISCARD pStreamBitmapNext StreamBitmapNext;
|
||||
WINPR_ATTR_NODISCARD pDrawGdiPlusFirst DrawGdiPlusFirst;
|
||||
WINPR_ATTR_NODISCARD pDrawGdiPlusNext DrawGdiPlusNext;
|
||||
WINPR_ATTR_NODISCARD pDrawGdiPlusEnd DrawGdiPlusEnd;
|
||||
WINPR_ATTR_NODISCARD pDrawGdiPlusCacheFirst DrawGdiPlusCacheFirst;
|
||||
WINPR_ATTR_NODISCARD pDrawGdiPlusCacheNext DrawGdiPlusCacheNext;
|
||||
WINPR_ATTR_NODISCARD pDrawGdiPlusCacheEnd DrawGdiPlusCacheEnd;
|
||||
|
||||
/* Window Update */
|
||||
|
||||
WINPR_ATTR_NODISCARD pWindowCreate WindowCreate;
|
||||
WINPR_ATTR_NODISCARD pWindowUpdate WindowUpdate;
|
||||
WINPR_ATTR_NODISCARD pWindowIcon WindowIcon;
|
||||
WINPR_ATTR_NODISCARD pWindowCachedIcon WindowCachedIcon;
|
||||
WINPR_ATTR_NODISCARD pWindowDelete WindowDelete;
|
||||
WINPR_ATTR_NODISCARD pNotifyIconCreate NotifyIconCreate;
|
||||
WINPR_ATTR_NODISCARD pNotifyIconUpdate NotifyIconUpdate;
|
||||
WINPR_ATTR_NODISCARD pNotifyIconDelete NotifyIconDelete;
|
||||
WINPR_ATTR_NODISCARD pMonitoredDesktop MonitoredDesktop;
|
||||
WINPR_ATTR_NODISCARD pNonMonitoredDesktop NonMonitoredDesktop;
|
||||
|
||||
/* Pointer Update */
|
||||
|
||||
WINPR_ATTR_NODISCARD pPointerPosition PointerPosition;
|
||||
WINPR_ATTR_NODISCARD pPointerSystem PointerSystem;
|
||||
WINPR_ATTR_NODISCARD pPointerColor PointerColor;
|
||||
WINPR_ATTR_NODISCARD pPointerNew PointerNew;
|
||||
WINPR_ATTR_NODISCARD pPointerCached PointerCached;
|
||||
WINPR_ATTR_NODISCARD pPointerLarge PointerLarge;
|
||||
|
||||
HANDLE thread;
|
||||
};
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int update_message_queue_process_message(rdpUpdate* update, wMessage* message);
|
||||
|
||||
FREERDP_LOCAL int update_message_queue_free_message(wMessage* message);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int update_message_queue_process_pending_messages(rdpUpdate* update);
|
||||
|
||||
FREERDP_LOCAL void update_message_proxy_free(rdpUpdateProxy* message);
|
||||
|
||||
WINPR_ATTR_MALLOC(update_message_proxy_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpUpdateProxy* update_message_proxy_new(rdpUpdate* update);
|
||||
|
||||
/**
|
||||
* Input Message Queue
|
||||
*/
|
||||
|
||||
/* Input Proxy Interface */
|
||||
|
||||
struct rdp_input_proxy
|
||||
{
|
||||
rdpInput* input;
|
||||
|
||||
/* Input */
|
||||
|
||||
pSynchronizeEvent SynchronizeEvent;
|
||||
pKeyboardEvent KeyboardEvent;
|
||||
pUnicodeKeyboardEvent UnicodeKeyboardEvent;
|
||||
pMouseEvent MouseEvent;
|
||||
pExtendedMouseEvent ExtendedMouseEvent;
|
||||
pFocusInEvent FocusInEvent;
|
||||
pKeyboardPauseEvent KeyboardPauseEvent;
|
||||
};
|
||||
|
||||
FREERDP_LOCAL int input_message_queue_process_message(rdpInput* input, wMessage* message);
|
||||
FREERDP_LOCAL int input_message_queue_free_message(wMessage* message);
|
||||
FREERDP_LOCAL int input_message_queue_process_pending_messages(rdpInput* input);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_MESSAGE_H */
|
||||
57
third_party/FreeRDP/libfreerdp/core/metrics.c
vendored
Normal file
57
third_party/FreeRDP/libfreerdp/core/metrics.c
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Protocol Metrics
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
double metrics_write_bytes(rdpMetrics* metrics, UINT32 UncompressedBytes, UINT32 CompressedBytes)
|
||||
{
|
||||
double CompressionRatio = 0.0;
|
||||
|
||||
metrics->TotalUncompressedBytes += UncompressedBytes;
|
||||
metrics->TotalCompressedBytes += CompressedBytes;
|
||||
|
||||
if (UncompressedBytes != 0)
|
||||
CompressionRatio = ((double)CompressedBytes) / ((double)UncompressedBytes);
|
||||
if (metrics->TotalUncompressedBytes != 0)
|
||||
metrics->TotalCompressionRatio =
|
||||
((double)metrics->TotalCompressedBytes) / ((double)metrics->TotalUncompressedBytes);
|
||||
|
||||
return CompressionRatio;
|
||||
}
|
||||
|
||||
rdpMetrics* metrics_new(rdpContext* context)
|
||||
{
|
||||
rdpMetrics* metrics = nullptr;
|
||||
|
||||
metrics = (rdpMetrics*)calloc(1, sizeof(rdpMetrics));
|
||||
|
||||
if (metrics)
|
||||
{
|
||||
metrics->context = context;
|
||||
}
|
||||
|
||||
return metrics;
|
||||
}
|
||||
|
||||
void metrics_free(rdpMetrics* metrics)
|
||||
{
|
||||
free(metrics);
|
||||
}
|
||||
240
third_party/FreeRDP/libfreerdp/core/multitransport.c
vendored
Normal file
240
third_party/FreeRDP/libfreerdp/core/multitransport.c
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* MULTITRANSPORT PDUs
|
||||
*
|
||||
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <freerdp/config.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "settings.h"
|
||||
#include "rdp.h"
|
||||
#include "multitransport.h"
|
||||
|
||||
struct rdp_multitransport
|
||||
{
|
||||
rdpRdp* rdp;
|
||||
|
||||
MultiTransportRequestCb MtRequest;
|
||||
MultiTransportResponseCb MtResponse;
|
||||
|
||||
/* server-side data */
|
||||
UINT32 reliableReqId;
|
||||
|
||||
BYTE reliableCookie[RDPUDP_COOKIE_LEN];
|
||||
BYTE reliableCookieHash[RDPUDP_COOKIE_HASHLEN];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
RDPTUNNEL_ACTION_CREATEREQUEST = 0x00,
|
||||
RDPTUNNEL_ACTION_CREATERESPONSE = 0x01,
|
||||
RDPTUNNEL_ACTION_DATA = 0x02
|
||||
};
|
||||
|
||||
#define TAG FREERDP_TAG("core.multitransport")
|
||||
|
||||
state_run_t multitransport_recv_request(rdpMultitransport* multi, wStream* s)
|
||||
{
|
||||
WINPR_ASSERT(multi);
|
||||
rdpSettings* settings = multi->rdp->settings;
|
||||
|
||||
if (settings->ServerMode)
|
||||
{
|
||||
WLog_ERR(TAG, "not expecting a multi-transport request in server mode");
|
||||
return STATE_RUN_FAILED;
|
||||
}
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 24))
|
||||
return STATE_RUN_FAILED;
|
||||
|
||||
UINT32 requestId = 0;
|
||||
UINT16 requestedProto = 0;
|
||||
UINT16 reserved = 0;
|
||||
const BYTE* cookie = nullptr;
|
||||
|
||||
Stream_Read_UINT32(s, requestId); /* requestId (4 bytes) */
|
||||
Stream_Read_UINT16(s, requestedProto); /* requestedProtocol (2 bytes) */
|
||||
Stream_Read_UINT16(s, reserved); /* reserved (2 bytes) */
|
||||
cookie = Stream_ConstPointer(s);
|
||||
Stream_Seek(s, RDPUDP_COOKIE_LEN); /* securityCookie (16 bytes) */
|
||||
if (reserved != 0)
|
||||
{
|
||||
/*
|
||||
* If the reserved filed is not 0 the request PDU seems to contain some extra data.
|
||||
* If the reserved value is 1, then two bytes of 0 (probably a version field)
|
||||
* are followed by a JSON payload (not null terminated, until the end of the packet.
|
||||
* There seems to be no dedicated length field)
|
||||
*
|
||||
* for now just ignore all that
|
||||
*/
|
||||
WLog_WARN(TAG,
|
||||
"reserved is %" PRIu16 " instead of 0, skipping %" PRIuz "bytes of unknown data",
|
||||
reserved, Stream_GetRemainingLength(s));
|
||||
(void)Stream_SafeSeek(s, Stream_GetRemainingLength(s));
|
||||
}
|
||||
|
||||
WINPR_ASSERT(multi->MtRequest);
|
||||
return multi->MtRequest(multi, requestId, requestedProto, cookie);
|
||||
}
|
||||
|
||||
static BOOL multitransport_request_send(rdpMultitransport* multi, UINT32 reqId, UINT16 reqProto,
|
||||
const BYTE* cookie)
|
||||
{
|
||||
WINPR_ASSERT(multi);
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_message_channel_pdu_init(multi->rdp, &sec_flags);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, 24))
|
||||
{
|
||||
Stream_Release(s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(s, reqId); /* requestId (4 bytes) */
|
||||
Stream_Write_UINT16(s, reqProto); /* requestedProtocol (2 bytes) */
|
||||
Stream_Zero(s, 2); /* reserved (2 bytes) */
|
||||
Stream_Write(s, cookie, RDPUDP_COOKIE_LEN); /* securityCookie (16 bytes) */
|
||||
|
||||
return rdp_send_message_channel_pdu(multi->rdp, s, sec_flags | SEC_TRANSPORT_REQ);
|
||||
}
|
||||
|
||||
state_run_t multitransport_server_request(rdpMultitransport* multi, UINT16 reqProto)
|
||||
{
|
||||
WINPR_ASSERT(multi);
|
||||
|
||||
/* TODO: move this static variable to the listener */
|
||||
static UINT32 reqId = 0;
|
||||
|
||||
if (reqProto == INITIATE_REQUEST_PROTOCOL_UDPFECR)
|
||||
{
|
||||
multi->reliableReqId = reqId++;
|
||||
if (winpr_RAND(multi->reliableCookie, sizeof(multi->reliableCookie)) < 0)
|
||||
return STATE_RUN_FAILED;
|
||||
|
||||
return multitransport_request_send(multi, multi->reliableReqId, reqProto,
|
||||
multi->reliableCookie)
|
||||
? STATE_RUN_SUCCESS
|
||||
: STATE_RUN_FAILED;
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "only reliable transport is supported");
|
||||
return STATE_RUN_CONTINUE;
|
||||
}
|
||||
|
||||
BOOL multitransport_client_send_response(rdpMultitransport* multi, UINT32 reqId, HRESULT hr)
|
||||
{
|
||||
WINPR_ASSERT(multi);
|
||||
|
||||
UINT16 sec_flags = 0;
|
||||
wStream* s = rdp_message_channel_pdu_init(multi->rdp, &sec_flags);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, 28))
|
||||
{
|
||||
Stream_Release(s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(s, reqId); /* requestId (4 bytes) */
|
||||
|
||||
/* [MS-RDPBCGR] 2.2.15.2 Client Initiate Multitransport Response PDU defines this as 4byte
|
||||
* UNSIGNED but https://learn.microsoft.com/en-us/windows/win32/learnwin32/error-codes-in-com
|
||||
* defines this as signed... assume the spec is (implicitly) assuming twos complement. */
|
||||
Stream_Write_INT32(s, hr); /* HResult (4 bytes) */
|
||||
return rdp_send_message_channel_pdu(multi->rdp, s, sec_flags | SEC_TRANSPORT_RSP);
|
||||
}
|
||||
|
||||
state_run_t multitransport_recv_response(rdpMultitransport* multi, wStream* s)
|
||||
{
|
||||
WINPR_ASSERT(multi && multi->rdp);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
rdpSettings* settings = multi->rdp->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
if (!settings->ServerMode)
|
||||
{
|
||||
WLog_ERR(TAG, "client is not expecting a multi-transport resp packet");
|
||||
return STATE_RUN_FAILED;
|
||||
}
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
|
||||
return STATE_RUN_FAILED;
|
||||
|
||||
UINT32 requestId = 0;
|
||||
UINT32 hr = 0;
|
||||
|
||||
Stream_Read_UINT32(s, requestId); /* requestId (4 bytes) */
|
||||
Stream_Read_UINT32(s, hr); /* hrResponse (4 bytes) */
|
||||
|
||||
state_run_t res = STATE_RUN_SUCCESS;
|
||||
IFCALLRET(multi->MtResponse, res, multi, requestId, hr);
|
||||
return res;
|
||||
}
|
||||
|
||||
static state_run_t multitransport_no_udp(rdpMultitransport* multi, UINT32 reqId,
|
||||
WINPR_ATTR_UNUSED UINT16 reqProto,
|
||||
WINPR_ATTR_UNUSED const BYTE* cookie)
|
||||
{
|
||||
return multitransport_client_send_response(multi, reqId, E_ABORT) ? STATE_RUN_SUCCESS
|
||||
: STATE_RUN_FAILED;
|
||||
}
|
||||
|
||||
static state_run_t multitransport_server_handle_response(rdpMultitransport* multi,
|
||||
WINPR_ATTR_UNUSED UINT32 reqId,
|
||||
WINPR_ATTR_UNUSED UINT32 hrResponse)
|
||||
{
|
||||
rdpRdp* rdp = multi->rdp;
|
||||
|
||||
if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE))
|
||||
return STATE_RUN_FAILED;
|
||||
|
||||
return STATE_RUN_CONTINUE;
|
||||
}
|
||||
|
||||
rdpMultitransport* multitransport_new(rdpRdp* rdp, WINPR_ATTR_UNUSED UINT16 protocol)
|
||||
{
|
||||
WINPR_ASSERT(rdp);
|
||||
|
||||
rdpSettings* settings = rdp->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
rdpMultitransport* multi = calloc(1, sizeof(rdpMultitransport));
|
||||
if (!multi)
|
||||
return nullptr;
|
||||
|
||||
if (settings->ServerMode)
|
||||
{
|
||||
multi->MtResponse = multitransport_server_handle_response;
|
||||
}
|
||||
else
|
||||
{
|
||||
multi->MtRequest = multitransport_no_udp;
|
||||
}
|
||||
|
||||
multi->rdp = rdp;
|
||||
return multi;
|
||||
}
|
||||
|
||||
void multitransport_free(rdpMultitransport* multitransport)
|
||||
{
|
||||
free(multitransport);
|
||||
}
|
||||
66
third_party/FreeRDP/libfreerdp/core/multitransport.h
vendored
Normal file
66
third_party/FreeRDP/libfreerdp/core/multitransport.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Multitransport PDUs
|
||||
*
|
||||
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_MULTITRANSPORT_H
|
||||
#define FREERDP_LIB_CORE_MULTITRANSPORT_H
|
||||
|
||||
typedef struct rdp_multitransport rdpMultitransport;
|
||||
|
||||
#include "rdp.h"
|
||||
#include "state.h"
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INITIATE_REQUEST_PROTOCOL_UDPFECR = 0x01,
|
||||
INITIATE_REQUEST_PROTOCOL_UDPFECL = 0x02
|
||||
} MultitransportRequestProtocol;
|
||||
|
||||
typedef state_run_t (*MultiTransportRequestCb)(rdpMultitransport* multi, UINT32 reqId,
|
||||
UINT16 reqProto, const BYTE* cookie);
|
||||
typedef state_run_t (*MultiTransportResponseCb)(rdpMultitransport* multi, UINT32 reqId,
|
||||
UINT32 hrResponse);
|
||||
|
||||
#define RDPUDP_COOKIE_LEN 16
|
||||
#define RDPUDP_COOKIE_HASHLEN 32
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t multitransport_recv_request(rdpMultitransport* multi, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t multitransport_server_request(rdpMultitransport* multi, UINT16 reqProto);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t multitransport_recv_response(rdpMultitransport* multi, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL multitransport_client_send_response(rdpMultitransport* multi, UINT32 reqId,
|
||||
HRESULT hr);
|
||||
|
||||
FREERDP_LOCAL void multitransport_free(rdpMultitransport* multi);
|
||||
|
||||
WINPR_ATTR_MALLOC(multitransport_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpMultitransport* multitransport_new(rdpRdp* rdp, UINT16 protocol);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_MULTITRANSPORT_H */
|
||||
2103
third_party/FreeRDP/libfreerdp/core/nego.c
vendored
Normal file
2103
third_party/FreeRDP/libfreerdp/core/nego.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
191
third_party/FreeRDP/libfreerdp/core/nego.h
vendored
Normal file
191
third_party/FreeRDP/libfreerdp/core/nego.h
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Protocol Security Negotiation
|
||||
*
|
||||
* Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_NEGO_H
|
||||
#define FREERDP_LIB_CORE_NEGO_H
|
||||
|
||||
#include "transport.h"
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
/* Protocol Security Negotiation Protocols
|
||||
* [MS-RDPBCGR] 2.2.1.1.1 RDP Negotiation Request (RDP_NEG_REQ)
|
||||
*/
|
||||
#define PROTOCOL_RDP 0x00000000
|
||||
#define PROTOCOL_SSL 0x00000001
|
||||
#define PROTOCOL_HYBRID 0x00000002
|
||||
#define PROTOCOL_RDSTLS 0x00000004
|
||||
#define PROTOCOL_HYBRID_EX 0x00000008
|
||||
#define PROTOCOL_RDSAAD 0x00000010
|
||||
|
||||
#define PROTOCOL_FAILED_NEGO 0x80000000 /* only used internally, not on the wire */
|
||||
|
||||
/* Protocol Security Negotiation Failure Codes */
|
||||
enum RDP_NEG_FAILURE_FAILURECODES
|
||||
{
|
||||
SSL_REQUIRED_BY_SERVER = 0x00000001,
|
||||
SSL_NOT_ALLOWED_BY_SERVER = 0x00000002,
|
||||
SSL_CERT_NOT_ON_SERVER = 0x00000003,
|
||||
INCONSISTENT_FLAGS = 0x00000004,
|
||||
HYBRID_REQUIRED_BY_SERVER = 0x00000005,
|
||||
SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER = 0x00000006
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NEGO_STATE_INITIAL,
|
||||
NEGO_STATE_RDSTLS, /* RDSTLS (TLS implicit) */
|
||||
NEGO_STATE_AAD, /* Azure AD Authentication (TLS implicit) */
|
||||
NEGO_STATE_EXT, /* Extended NLA (NLA + TLS implicit) */
|
||||
NEGO_STATE_NLA, /* Network Level Authentication (TLS implicit) */
|
||||
NEGO_STATE_TLS, /* TLS Encryption without NLA */
|
||||
NEGO_STATE_RDP, /* Standard Legacy RDP Encryption */
|
||||
NEGO_STATE_FAIL, /* Negotiation failure */
|
||||
NEGO_STATE_FINAL
|
||||
} NEGO_STATE;
|
||||
|
||||
/* RDP Negotiation Messages */
|
||||
enum RDP_NEG_MSG
|
||||
{
|
||||
/* X224_TPDU_CONNECTION_REQUEST */
|
||||
TYPE_RDP_NEG_REQ = 0x1,
|
||||
/* X224_TPDU_CONNECTION_CONFIRM */
|
||||
TYPE_RDP_NEG_RSP = 0x2,
|
||||
TYPE_RDP_NEG_FAILURE = 0x3,
|
||||
TYPE_RDP_CORRELATION_INFO = 0x6
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EXTENDED_CLIENT_DATA_SUPPORTED = 0x01,
|
||||
DYNVC_GFX_PROTOCOL_SUPPORTED = 0x02,
|
||||
RDP_NEGRSP_RESERVED = 0x04,
|
||||
RESTRICTED_ADMIN_MODE_SUPPORTED = 0x08,
|
||||
REDIRECTED_AUTHENTICATION_MODE_SUPPORTED = 0x10
|
||||
} RdpNegRespFlags;
|
||||
|
||||
#define PRECONNECTION_PDU_V1_SIZE 16
|
||||
#define PRECONNECTION_PDU_V2_MIN_SIZE (PRECONNECTION_PDU_V1_SIZE + 2)
|
||||
|
||||
#define PRECONNECTION_PDU_V1 1
|
||||
#define PRECONNECTION_PDU_V2 2
|
||||
|
||||
#define RESTRICTED_ADMIN_MODE_REQUIRED 0x01
|
||||
#define REDIRECTED_AUTHENTICATION_MODE_REQUIRED 0x02
|
||||
#define CORRELATION_INFO_PRESENT 0x08
|
||||
|
||||
typedef struct rdp_nego rdpNego;
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nego_connect(rdpNego* nego);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nego_disconnect(rdpNego* nego);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int nego_recv(rdpTransport* transport, wStream* s, void* extra);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nego_read_request(rdpNego* nego, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nego_send_negotiation_request(rdpNego* nego);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nego_send_negotiation_response(rdpNego* nego);
|
||||
|
||||
FREERDP_LOCAL void nego_free(rdpNego* nego);
|
||||
|
||||
WINPR_ATTR_MALLOC(nego_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpNego* nego_new(rdpTransport* transport);
|
||||
|
||||
FREERDP_LOCAL void nego_init(rdpNego* nego);
|
||||
|
||||
FREERDP_LOCAL BOOL nego_set_target(rdpNego* nego, const char* hostname, UINT16 port);
|
||||
|
||||
FREERDP_LOCAL void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer);
|
||||
FREERDP_LOCAL void nego_set_restricted_admin_mode_required(rdpNego* nego,
|
||||
BOOL RestrictedAdminModeRequired);
|
||||
FREERDP_LOCAL void nego_set_restricted_admin_mode_supported(rdpNego* nego, BOOL enabled);
|
||||
FREERDP_LOCAL void nego_set_RCG_required(rdpNego* nego, BOOL enabled);
|
||||
FREERDP_LOCAL void nego_set_RCG_supported(rdpNego* nego, BOOL enabled);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nego_get_remoteCredentialGuard(const rdpNego* nego);
|
||||
|
||||
FREERDP_LOCAL void nego_set_childsession_enabled(rdpNego* nego, BOOL ChildSessionEnabled);
|
||||
FREERDP_LOCAL void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled);
|
||||
FREERDP_LOCAL void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal);
|
||||
FREERDP_LOCAL void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp);
|
||||
FREERDP_LOCAL void nego_enable_tls(rdpNego* nego, BOOL enable_tls);
|
||||
FREERDP_LOCAL void nego_enable_nla(rdpNego* nego, BOOL enable_nla);
|
||||
FREERDP_LOCAL void nego_enable_rdstls(rdpNego* nego, BOOL enable_rdstls);
|
||||
FREERDP_LOCAL void nego_enable_aad(rdpNego* nego, BOOL enable_aad);
|
||||
FREERDP_LOCAL void nego_enable_ext(rdpNego* nego, BOOL enable_ext);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const BYTE* nego_get_routing_token(const rdpNego* nego, DWORD* RoutingTokenLength);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nego_set_routing_token(rdpNego* nego, const void* RoutingToken,
|
||||
DWORD RoutingTokenLength);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nego_set_cookie(rdpNego* nego, const char* cookie);
|
||||
|
||||
FREERDP_LOCAL void nego_set_cookie_max_length(rdpNego* nego, UINT32 CookieMaxLength);
|
||||
FREERDP_LOCAL void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL SendPreconnectionPdu);
|
||||
FREERDP_LOCAL void nego_set_preconnection_id(rdpNego* nego, UINT32 PreconnectionId);
|
||||
FREERDP_LOCAL void nego_set_preconnection_blob(rdpNego* nego, const char* PreconnectionBlob);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL UINT32 nego_get_selected_protocol(const rdpNego* nego);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nego_set_selected_protocol(rdpNego* nego, UINT32 SelectedProtocol);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL UINT32 nego_get_requested_protocols(const rdpNego* nego);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nego_set_requested_protocols(rdpNego* nego, UINT32 RequestedProtocols);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nego_update_settings_from_state(rdpNego* nego, rdpSettings* settings);
|
||||
|
||||
FREERDP_LOCAL BOOL nego_set_state(rdpNego* nego, NEGO_STATE state);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL NEGO_STATE nego_get_state(const rdpNego* nego);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL SEC_WINNT_AUTH_IDENTITY* nego_get_identity(rdpNego* nego);
|
||||
|
||||
FREERDP_LOCAL void nego_free_nla(rdpNego* nego);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* nego_protocol_to_str(UINT32 protocol, char* buffer, size_t size);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_NEGO_H */
|
||||
2464
third_party/FreeRDP/libfreerdp/core/nla.c
vendored
Normal file
2464
third_party/FreeRDP/libfreerdp/core/nla.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
111
third_party/FreeRDP/libfreerdp/core/nla.h
vendored
Normal file
111
third_party/FreeRDP/libfreerdp/core/nla.h
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Network Level Authentication (NLA)
|
||||
*
|
||||
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_NLA_H
|
||||
#define FREERDP_LIB_CORE_NLA_H
|
||||
|
||||
typedef struct rdp_nla rdpNla;
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#include <freerdp/crypto/ber.h>
|
||||
#include <freerdp/crypto/der.h>
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
|
||||
#include "transport.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NLA_STATE_INITIAL,
|
||||
NLA_STATE_NEGO_TOKEN,
|
||||
NLA_STATE_PUB_KEY_AUTH,
|
||||
NLA_STATE_EARLY_USER_AUTH,
|
||||
NLA_STATE_AUTH_INFO,
|
||||
NLA_STATE_POST_NEGO,
|
||||
NLA_STATE_FINAL
|
||||
} NLA_STATE;
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int nla_authenticate(rdpNla* nla);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int nla_client_begin(rdpNla* nla);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int nla_recv_pdu(rdpNla* nla, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL NLA_STATE nla_get_state(const rdpNla* nla);
|
||||
|
||||
FREERDP_LOCAL BOOL nla_set_state(rdpNla* nla, NLA_STATE state);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* nla_get_state_str(NLA_STATE state);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL DWORD nla_get_error(const rdpNla* nla);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL INT32 nla_get_sspi_error(const rdpNla* nla);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nla_set_service_principal(rdpNla* nla, const char* service,
|
||||
const char* hostname);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nla_set_sspi_module(rdpNla* nla, const char* sspiModule);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nla_sspi_module_init(rdpNla* nla);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nla_impersonate(rdpNla* nla);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nla_revert_to_self(rdpNla* nla);
|
||||
|
||||
FREERDP_LOCAL void nla_free(rdpNla* nla);
|
||||
|
||||
WINPR_ATTR_MALLOC(nla_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpNla* nla_new(rdpContext* context, rdpTransport* transport);
|
||||
|
||||
FREERDP_LOCAL void nla_set_early_user_auth(rdpNla* nla, BOOL earlyUserAuth);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nla_encrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nla_decrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL SECURITY_STATUS nla_FreeContextBuffer(rdpNla* nla, PVOID pBuffer);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_NLA_H */
|
||||
4463
third_party/FreeRDP/libfreerdp/core/orders.c
vendored
Normal file
4463
third_party/FreeRDP/libfreerdp/core/orders.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
338
third_party/FreeRDP/libfreerdp/core/orders.h
vendored
Normal file
338
third_party/FreeRDP/libfreerdp/core/orders.h
vendored
Normal file
@@ -0,0 +1,338 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Drawing Orders
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2016 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_ORDERS_H
|
||||
#define FREERDP_LIB_CORE_ORDERS_H
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/update.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
/* Order Control Flags */
|
||||
#define ORDER_STANDARD 0x01
|
||||
#define ORDER_SECONDARY 0x02
|
||||
#define ORDER_BOUNDS 0x04
|
||||
#define ORDER_TYPE_CHANGE 0x08
|
||||
#define ORDER_DELTA_COORDINATES 0x10
|
||||
#define ORDER_ZERO_BOUNDS_DELTAS 0x20
|
||||
#define ORDER_ZERO_FIELD_BYTE_BIT0 0x40
|
||||
#define ORDER_ZERO_FIELD_BYTE_BIT1 0x80
|
||||
|
||||
/* Bound Field Flags */
|
||||
#define BOUND_LEFT 0x01
|
||||
#define BOUND_TOP 0x02
|
||||
#define BOUND_RIGHT 0x04
|
||||
#define BOUND_BOTTOM 0x08
|
||||
#define BOUND_DELTA_LEFT 0x10
|
||||
#define BOUND_DELTA_TOP 0x20
|
||||
#define BOUND_DELTA_RIGHT 0x40
|
||||
#define BOUND_DELTA_BOTTOM 0x80
|
||||
|
||||
/* Field Presence Flags */
|
||||
#define ORDER_FIELD_01 0x000001
|
||||
#define ORDER_FIELD_02 0x000002
|
||||
#define ORDER_FIELD_03 0x000004
|
||||
#define ORDER_FIELD_04 0x000008
|
||||
#define ORDER_FIELD_05 0x000010
|
||||
#define ORDER_FIELD_06 0x000020
|
||||
#define ORDER_FIELD_07 0x000040
|
||||
#define ORDER_FIELD_08 0x000080
|
||||
#define ORDER_FIELD_09 0x000100
|
||||
#define ORDER_FIELD_10 0x000200
|
||||
#define ORDER_FIELD_11 0x000400
|
||||
#define ORDER_FIELD_12 0x000800
|
||||
#define ORDER_FIELD_13 0x001000
|
||||
#define ORDER_FIELD_14 0x002000
|
||||
#define ORDER_FIELD_15 0x004000
|
||||
#define ORDER_FIELD_16 0x008000
|
||||
#define ORDER_FIELD_17 0x010000
|
||||
#define ORDER_FIELD_18 0x020000
|
||||
#define ORDER_FIELD_19 0x040000
|
||||
#define ORDER_FIELD_20 0x080000
|
||||
#define ORDER_FIELD_21 0x100000
|
||||
#define ORDER_FIELD_22 0x200000
|
||||
#define ORDER_FIELD_23 0x400000
|
||||
|
||||
/* Bitmap Cache Flags */
|
||||
#define CBR2_8BPP 0x3
|
||||
#define CBR2_16BPP 0x4
|
||||
#define CBR2_24BPP 0x5
|
||||
#define CBR2_32BPP 0x6
|
||||
|
||||
#define CBR23_8BPP 0x3
|
||||
#define CBR23_16BPP 0x4
|
||||
#define CBR23_24BPP 0x5
|
||||
#define CBR23_32BPP 0x6
|
||||
|
||||
#define CBR3_IGNORABLE_FLAG 0x08
|
||||
#define CBR3_DO_NOT_CACHE 0x10
|
||||
|
||||
/* Primary Drawing Orders */
|
||||
#define ORDER_TYPE_DSTBLT 0x00
|
||||
#define ORDER_TYPE_PATBLT 0x01
|
||||
#define ORDER_TYPE_SCRBLT 0x02
|
||||
#define ORDER_TYPE_DRAW_NINE_GRID 0x07
|
||||
#define ORDER_TYPE_MULTI_DRAW_NINE_GRID 0x08
|
||||
#define ORDER_TYPE_LINE_TO 0x09
|
||||
#define ORDER_TYPE_OPAQUE_RECT 0x0A
|
||||
#define ORDER_TYPE_SAVE_BITMAP 0x0B
|
||||
#define ORDER_TYPE_MEMBLT 0x0D
|
||||
#define ORDER_TYPE_MEM3BLT 0x0E
|
||||
#define ORDER_TYPE_MULTI_DSTBLT 0x0F
|
||||
#define ORDER_TYPE_MULTI_PATBLT 0x10
|
||||
#define ORDER_TYPE_MULTI_SCRBLT 0x11
|
||||
#define ORDER_TYPE_MULTI_OPAQUE_RECT 0x12
|
||||
#define ORDER_TYPE_FAST_INDEX 0x13
|
||||
#define ORDER_TYPE_POLYGON_SC 0x14
|
||||
#define ORDER_TYPE_POLYGON_CB 0x15
|
||||
#define ORDER_TYPE_POLYLINE 0x16
|
||||
#define ORDER_TYPE_FAST_GLYPH 0x18
|
||||
#define ORDER_TYPE_ELLIPSE_SC 0x19
|
||||
#define ORDER_TYPE_ELLIPSE_CB 0x1A
|
||||
#define ORDER_TYPE_GLYPH_INDEX 0x1B
|
||||
|
||||
/* Primary Drawing Orders Fields */
|
||||
#define DSTBLT_ORDER_FIELDS 5
|
||||
#define PATBLT_ORDER_FIELDS 12
|
||||
#define SCRBLT_ORDER_FIELDS 7
|
||||
#define DRAW_NINE_GRID_ORDER_FIELDS 5
|
||||
#define MULTI_DRAW_NINE_GRID_ORDER_FIELDS 7
|
||||
#define LINE_TO_ORDER_FIELDS 10
|
||||
#define OPAQUE_RECT_ORDER_FIELDS 7
|
||||
#define SAVE_BITMAP_ORDER_FIELDS 6
|
||||
#define MEMBLT_ORDER_FIELDS 9
|
||||
#define MEM3BLT_ORDER_FIELDS 16
|
||||
#define MULTI_DSTBLT_ORDER_FIELDS 7
|
||||
#define MULTI_PATBLT_ORDER_FIELDS 14
|
||||
#define MULTI_SCRBLT_ORDER_FIELDS 9
|
||||
#define MULTI_OPAQUE_RECT_ORDER_FIELDS 9
|
||||
#define FAST_INDEX_ORDER_FIELDS 15
|
||||
#define POLYGON_SC_ORDER_FIELDS 7
|
||||
#define POLYGON_CB_ORDER_FIELDS 13
|
||||
#define POLYLINE_ORDER_FIELDS 7
|
||||
#define FAST_GLYPH_ORDER_FIELDS 15
|
||||
#define ELLIPSE_SC_ORDER_FIELDS 7
|
||||
#define ELLIPSE_CB_ORDER_FIELDS 13
|
||||
#define GLYPH_INDEX_ORDER_FIELDS 22
|
||||
|
||||
/* Primary Drawing Orders Field Bytes */
|
||||
#define DSTBLT_ORDER_FIELD_BYTES 1
|
||||
#define PATBLT_ORDER_FIELD_BYTES 2
|
||||
#define SCRBLT_ORDER_FIELD_BYTES 1
|
||||
#define DRAW_NINE_GRID_ORDER_FIELD_BYTES 1
|
||||
#define MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES 1
|
||||
#define LINE_TO_ORDER_FIELD_BYTES 2
|
||||
#define OPAQUE_RECT_ORDER_FIELD_BYTES 1
|
||||
#define SAVE_BITMAP_ORDER_FIELD_BYTES 1
|
||||
#define MEMBLT_ORDER_FIELD_BYTES 2
|
||||
#define MEM3BLT_ORDER_FIELD_BYTES 3
|
||||
#define MULTI_DSTBLT_ORDER_FIELD_BYTES 1
|
||||
#define MULTI_PATBLT_ORDER_FIELD_BYTES 2
|
||||
#define MULTI_SCRBLT_ORDER_FIELD_BYTES 2
|
||||
#define MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES 2
|
||||
#define FAST_INDEX_ORDER_FIELD_BYTES 2
|
||||
#define POLYGON_SC_ORDER_FIELD_BYTES 1
|
||||
#define POLYGON_CB_ORDER_FIELD_BYTES 2
|
||||
#define POLYLINE_ORDER_FIELD_BYTES 1
|
||||
#define FAST_GLYPH_ORDER_FIELD_BYTES 2
|
||||
#define ELLIPSE_SC_ORDER_FIELD_BYTES 1
|
||||
#define ELLIPSE_CB_ORDER_FIELD_BYTES 2
|
||||
#define GLYPH_INDEX_ORDER_FIELD_BYTES 3
|
||||
|
||||
/* Secondary Drawing Orders */
|
||||
#define ORDER_TYPE_BITMAP_UNCOMPRESSED 0x00
|
||||
#define ORDER_TYPE_CACHE_COLOR_TABLE 0x01
|
||||
#define ORDER_TYPE_CACHE_BITMAP_COMPRESSED 0x02
|
||||
#define ORDER_TYPE_CACHE_GLYPH 0x03
|
||||
#define ORDER_TYPE_BITMAP_UNCOMPRESSED_V2 0x04
|
||||
#define ORDER_TYPE_BITMAP_COMPRESSED_V2 0x05
|
||||
#define ORDER_TYPE_CACHE_BRUSH 0x07
|
||||
#define ORDER_TYPE_BITMAP_COMPRESSED_V3 0x08
|
||||
|
||||
/* Alternate Secondary Drawing Orders */
|
||||
#define ORDER_TYPE_SWITCH_SURFACE 0x00
|
||||
#define ORDER_TYPE_CREATE_OFFSCREEN_BITMAP 0x01
|
||||
#define ORDER_TYPE_STREAM_BITMAP_FIRST 0x02
|
||||
#define ORDER_TYPE_STREAM_BITMAP_NEXT 0x03
|
||||
#define ORDER_TYPE_CREATE_NINE_GRID_BITMAP 0x04
|
||||
#define ORDER_TYPE_GDIPLUS_FIRST 0x05
|
||||
#define ORDER_TYPE_GDIPLUS_NEXT 0x06
|
||||
#define ORDER_TYPE_GDIPLUS_END 0x07
|
||||
#define ORDER_TYPE_GDIPLUS_CACHE_FIRST 0x08
|
||||
#define ORDER_TYPE_GDIPLUS_CACHE_NEXT 0x09
|
||||
#define ORDER_TYPE_GDIPLUS_CACHE_END 0x0A
|
||||
#define ORDER_TYPE_WINDOW 0x0B
|
||||
#define ORDER_TYPE_COMPDESK_FIRST 0x0C
|
||||
#define ORDER_TYPE_FRAME_MARKER 0x0D
|
||||
|
||||
#define CG_GLYPH_UNICODE_PRESENT 0x0010
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_recv_order(rdpUpdate* update, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_field_flags(wStream* s, UINT32 fieldFlags, BYTE flags,
|
||||
BYTE fieldBytes);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_bounds(wStream* s, const ORDER_INFO* orderInfo);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_dstblt_order(ORDER_INFO* orderInfo,
|
||||
const DSTBLT_ORDER* dstblt);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_dstblt_order(wStream* s, ORDER_INFO* orderInfo,
|
||||
const DSTBLT_ORDER* dstblt);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_patblt_order(ORDER_INFO* orderInfo, PATBLT_ORDER* patblt);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_patblt_order(wStream* s, ORDER_INFO* orderInfo,
|
||||
PATBLT_ORDER* patblt);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_scrblt_order(ORDER_INFO* orderInfo,
|
||||
const SCRBLT_ORDER* scrblt);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_scrblt_order(wStream* s, ORDER_INFO* orderInfo,
|
||||
const SCRBLT_ORDER* scrblt);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_opaque_rect_order(ORDER_INFO* orderInfo,
|
||||
const OPAQUE_RECT_ORDER* opaque_rect);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_opaque_rect_order(wStream* s, ORDER_INFO* orderInfo,
|
||||
const OPAQUE_RECT_ORDER* opaque_rect);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_line_to_order(ORDER_INFO* orderInfo,
|
||||
const LINE_TO_ORDER* line_to);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_line_to_order(wStream* s, ORDER_INFO* orderInfo,
|
||||
const LINE_TO_ORDER* line_to);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_memblt_order(ORDER_INFO* orderInfo,
|
||||
const MEMBLT_ORDER* memblt);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_memblt_order(wStream* s, ORDER_INFO* orderInfo,
|
||||
const MEMBLT_ORDER* memblt);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_glyph_index_order(ORDER_INFO* orderInfo,
|
||||
const GLYPH_INDEX_ORDER* glyph_index);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_glyph_index_order(wStream* s, ORDER_INFO* orderInfo,
|
||||
GLYPH_INDEX_ORDER* glyph_index);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_cache_bitmap_order(const CACHE_BITMAP_ORDER* cache_bitmap,
|
||||
BOOL compressed, const UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_cache_bitmap_order(wStream* s,
|
||||
const CACHE_BITMAP_ORDER* cache_bitmap_order,
|
||||
BOOL compressed, UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_cache_bitmap_v2_order(
|
||||
CACHE_BITMAP_V2_ORDER* cache_bitmap_v2, BOOL compressed, const UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_cache_bitmap_v2_order(wStream* s,
|
||||
CACHE_BITMAP_V2_ORDER* cache_bitmap_v2_order,
|
||||
BOOL compressed, UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t
|
||||
update_approximate_cache_bitmap_v3_order(CACHE_BITMAP_V3_ORDER* cache_bitmap_v3, UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_cache_bitmap_v3_order(wStream* s,
|
||||
CACHE_BITMAP_V3_ORDER* cache_bitmap_v3_order,
|
||||
UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_cache_color_table_order(
|
||||
const CACHE_COLOR_TABLE_ORDER* cache_color_table, const UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_cache_color_table_order(
|
||||
wStream* s, const CACHE_COLOR_TABLE_ORDER* cache_color_table_order, UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_cache_glyph_order(const CACHE_GLYPH_ORDER* cache_glyph,
|
||||
const UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_cache_glyph_order(wStream* s,
|
||||
const CACHE_GLYPH_ORDER* cache_glyph_order,
|
||||
UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_cache_glyph_v2_order(
|
||||
const CACHE_GLYPH_V2_ORDER* cache_glyph_v2, const UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_cache_glyph_v2_order(wStream* s,
|
||||
const CACHE_GLYPH_V2_ORDER* cache_glyph_v2,
|
||||
UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_cache_brush_order(const CACHE_BRUSH_ORDER* cache_brush,
|
||||
const UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_cache_brush_order(wStream* s,
|
||||
const CACHE_BRUSH_ORDER* cache_brush_order,
|
||||
UINT16* flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t update_approximate_create_offscreen_bitmap_order(
|
||||
const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_create_offscreen_bitmap_order(
|
||||
wStream* s, const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t
|
||||
update_approximate_switch_surface_order(const SWITCH_SURFACE_ORDER* switch_surface);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL update_write_switch_surface_order(wStream* s,
|
||||
const SWITCH_SURFACE_ORDER* switch_surface);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_ORDERS_H */
|
||||
1618
third_party/FreeRDP/libfreerdp/core/peer.c
vendored
Normal file
1618
third_party/FreeRDP/libfreerdp/core/peer.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
32
third_party/FreeRDP/libfreerdp/core/peer.h
vendored
Normal file
32
third_party/FreeRDP/libfreerdp/core/peer.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Server Peer
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_PEER_H
|
||||
#define FREERDP_LIB_CORE_PEER_H
|
||||
|
||||
#include "rdp.h"
|
||||
#include "mcs.h"
|
||||
#include "server.h"
|
||||
|
||||
#include <freerdp/peer.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t rdp_peer_handle_state_demand_active(freerdp_peer* client);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_PEER_H */
|
||||
995
third_party/FreeRDP/libfreerdp/core/proxy.c
vendored
Normal file
995
third_party/FreeRDP/libfreerdp/core/proxy.c
vendored
Normal file
@@ -0,0 +1,995 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* HTTP Proxy support
|
||||
*
|
||||
* Copyright 2016 Christian Plattner <ccpp@gmx.at>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "settings.h"
|
||||
#include "proxy.h"
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/utils/proxy_utils.h>
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
#include "tcp.h"
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
#include <winpr/environment.h> /* For GetEnvironmentVariableA */
|
||||
|
||||
#define CRLF "\r\n"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#define TAG FREERDP_TAG("core.proxy")
|
||||
|
||||
/* SOCKS Proxy auth methods by rfc1928 */
|
||||
enum
|
||||
{
|
||||
AUTH_M_NO_AUTH = 0,
|
||||
AUTH_M_GSSAPI = 1,
|
||||
AUTH_M_USR_PASS = 2
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SOCKS_CMD_CONNECT = 1,
|
||||
SOCKS_CMD_BIND = 2,
|
||||
SOCKS_CMD_UDP_ASSOCIATE = 3
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SOCKS_ADDR_IPV4 = 1,
|
||||
SOCKS_ADDR_FQDN = 3,
|
||||
SOCKS_ADDR_IPV6 = 4,
|
||||
};
|
||||
|
||||
static const char logprefix[] = "SOCKS Proxy:";
|
||||
|
||||
/* CONN REQ replies in enum. order */
|
||||
static const char* rplstat[] = { "succeeded",
|
||||
"general SOCKS server failure",
|
||||
"connection not allowed by ruleset",
|
||||
"Network unreachable",
|
||||
"Host unreachable",
|
||||
"Connection refused",
|
||||
"TTL expired",
|
||||
"Command not supported",
|
||||
"Address type not supported" };
|
||||
|
||||
static BOOL http_proxy_connect(rdpContext* context, BIO* bufferedBio, const char* proxyUsername,
|
||||
const char* proxyPassword, const char* hostname, UINT16 port);
|
||||
static BOOL socks_proxy_connect(rdpContext* context, BIO* bufferedBio, const char* proxyUsername,
|
||||
const char* proxyPassword, const char* hostname, UINT16 port);
|
||||
static void proxy_read_environment(rdpSettings* settings, char* envname);
|
||||
|
||||
BOOL proxy_prepare(rdpSettings* settings, const char** lpPeerHostname, UINT16* lpPeerPort,
|
||||
const char** lpProxyUsername, const char** lpProxyPassword)
|
||||
{
|
||||
if (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType) == PROXY_TYPE_IGNORE)
|
||||
return FALSE;
|
||||
|
||||
/* For TSGateway, find the system HTTPS proxy automatically */
|
||||
if (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType) == PROXY_TYPE_NONE)
|
||||
proxy_read_environment(settings, "https_proxy");
|
||||
|
||||
if (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType) == PROXY_TYPE_NONE)
|
||||
proxy_read_environment(settings, "HTTPS_PROXY");
|
||||
|
||||
if (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType) != PROXY_TYPE_NONE)
|
||||
proxy_read_environment(settings, "no_proxy");
|
||||
|
||||
if (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType) != PROXY_TYPE_NONE)
|
||||
proxy_read_environment(settings, "NO_PROXY");
|
||||
|
||||
if (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType) != PROXY_TYPE_NONE)
|
||||
{
|
||||
*lpPeerHostname = freerdp_settings_get_string(settings, FreeRDP_ProxyHostname);
|
||||
*lpPeerPort = freerdp_settings_get_uint16(settings, FreeRDP_ProxyPort);
|
||||
*lpProxyUsername = freerdp_settings_get_string(settings, FreeRDP_ProxyUsername);
|
||||
*lpProxyPassword = freerdp_settings_get_string(settings, FreeRDP_ProxyPassword);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL value_to_int(const char* value, LONGLONG* result, LONGLONG min, LONGLONG max)
|
||||
{
|
||||
long long rc = 0;
|
||||
|
||||
if (!value || !result)
|
||||
return FALSE;
|
||||
|
||||
errno = 0;
|
||||
rc = _strtoi64(value, nullptr, 0);
|
||||
|
||||
if (errno != 0)
|
||||
return FALSE;
|
||||
|
||||
if ((rc < min) || (rc > max))
|
||||
return FALSE;
|
||||
|
||||
*result = rc;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL cidr4_match(const struct in_addr* addr, const struct in_addr* net, BYTE bits)
|
||||
{
|
||||
if (bits == 0)
|
||||
return TRUE;
|
||||
|
||||
const uint32_t mask = htonl(0xFFFFFFFFu << (32 - bits));
|
||||
const uint32_t amask = addr->s_addr & mask;
|
||||
const uint32_t nmask = net->s_addr & mask;
|
||||
return amask == nmask;
|
||||
}
|
||||
|
||||
static BOOL cidr6_match(const struct in6_addr* address, const struct in6_addr* network,
|
||||
uint8_t bits)
|
||||
{
|
||||
const uint32_t* a = (const uint32_t*)address;
|
||||
const uint32_t* n = (const uint32_t*)network;
|
||||
const size_t bits_whole = bits >> 5;
|
||||
const size_t bits_incomplete = bits & 0x1F;
|
||||
|
||||
if (bits_whole)
|
||||
{
|
||||
if (memcmp(a, n, bits_whole << 2) != 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (bits_incomplete)
|
||||
{
|
||||
uint32_t mask = htonl((0xFFFFFFFFu) << (32 - bits_incomplete));
|
||||
|
||||
if ((a[bits_whole] ^ n[bits_whole]) & mask)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL option_ends_with(const char* str, const char* ext)
|
||||
{
|
||||
WINPR_ASSERT(str);
|
||||
WINPR_ASSERT(ext);
|
||||
const size_t strLen = strlen(str);
|
||||
const size_t extLen = strlen(ext);
|
||||
|
||||
if (strLen < extLen)
|
||||
return FALSE;
|
||||
|
||||
return _strnicmp(&str[strLen - extLen], ext, extLen) == 0;
|
||||
}
|
||||
|
||||
/* no_proxy has no proper definition, so use curl as reference:
|
||||
* https://about.gitlab.com/blog/2021/01/27/we-need-to-talk-no-proxy/
|
||||
*/
|
||||
static BOOL no_proxy_match_host(const char* val, const char* hostname)
|
||||
{
|
||||
WINPR_ASSERT(val);
|
||||
WINPR_ASSERT(hostname);
|
||||
|
||||
/* match all */
|
||||
if (_stricmp("*", val) == 0)
|
||||
return TRUE;
|
||||
|
||||
/* Strip leading . */
|
||||
if (val[0] == '.')
|
||||
val++;
|
||||
|
||||
/* Match suffix */
|
||||
return option_ends_with(hostname, val);
|
||||
}
|
||||
|
||||
static BOOL starts_with(const char* val, const char* prefix)
|
||||
{
|
||||
const size_t plen = strlen(prefix);
|
||||
const size_t vlen = strlen(val);
|
||||
if (vlen < plen)
|
||||
return FALSE;
|
||||
return _strnicmp(val, prefix, plen) == 0;
|
||||
}
|
||||
|
||||
static BOOL no_proxy_match_ip(const char* val, const char* hostname)
|
||||
{
|
||||
WINPR_ASSERT(val);
|
||||
WINPR_ASSERT(hostname);
|
||||
|
||||
struct sockaddr_in sa4 = WINPR_C_ARRAY_INIT;
|
||||
struct sockaddr_in6 sa6 = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (inet_pton(AF_INET, hostname, &sa4.sin_addr) == 1)
|
||||
{
|
||||
/* Prefix match */
|
||||
if (starts_with(hostname, val))
|
||||
return TRUE;
|
||||
|
||||
char* sub = strchr(val, '/');
|
||||
if (sub)
|
||||
*sub++ = '\0';
|
||||
|
||||
struct sockaddr_in mask = WINPR_C_ARRAY_INIT;
|
||||
if (inet_pton(AF_INET, val, &mask.sin_addr) == 0)
|
||||
return FALSE;
|
||||
|
||||
/* IP address match */
|
||||
if (memcmp(&mask, &sa4, sizeof(mask)) == 0)
|
||||
return TRUE;
|
||||
|
||||
if (sub)
|
||||
{
|
||||
const unsigned long usub = strtoul(sub, nullptr, 0);
|
||||
if ((errno == 0) && (usub <= UINT8_MAX))
|
||||
return cidr4_match(&sa4.sin_addr, &mask.sin_addr, (UINT8)usub);
|
||||
}
|
||||
}
|
||||
else if (inet_pton(AF_INET6, hostname, &sa6.sin6_addr) == 1)
|
||||
{
|
||||
if (val[0] == '[')
|
||||
val++;
|
||||
|
||||
char str[INET6_ADDRSTRLEN + 1] = WINPR_C_ARRAY_INIT;
|
||||
strncpy(str, val, INET6_ADDRSTRLEN);
|
||||
|
||||
const size_t len = strnlen(str, INET6_ADDRSTRLEN);
|
||||
if (len > 0)
|
||||
{
|
||||
if (str[len - 1] == ']')
|
||||
str[len - 1] = '\0';
|
||||
}
|
||||
|
||||
/* Prefix match */
|
||||
if (starts_with(hostname, str))
|
||||
return TRUE;
|
||||
|
||||
char* sub = strchr(str, '/');
|
||||
if (sub)
|
||||
*sub++ = '\0';
|
||||
|
||||
struct sockaddr_in6 mask = WINPR_C_ARRAY_INIT;
|
||||
if (inet_pton(AF_INET6, str, &mask.sin6_addr) == 0)
|
||||
return FALSE;
|
||||
|
||||
/* Address match */
|
||||
if (memcmp(&mask, &sa6, sizeof(mask)) == 0)
|
||||
return TRUE;
|
||||
|
||||
if (sub)
|
||||
{
|
||||
const unsigned long usub = strtoul(sub, nullptr, 0);
|
||||
if ((errno == 0) && (usub <= UINT8_MAX))
|
||||
return cidr6_match(&sa6.sin6_addr, &mask.sin6_addr, (UINT8)usub);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy)
|
||||
{
|
||||
const char* delimiter = ", ";
|
||||
BOOL result = FALSE;
|
||||
char* context = nullptr;
|
||||
|
||||
if (!no_proxy || !settings)
|
||||
return FALSE;
|
||||
|
||||
char* copy = _strdup(no_proxy);
|
||||
|
||||
if (!copy)
|
||||
return FALSE;
|
||||
|
||||
char* current = strtok_s(copy, delimiter, &context);
|
||||
|
||||
while (current && !result)
|
||||
{
|
||||
const size_t currentlen = strlen(current);
|
||||
|
||||
if (currentlen > 0)
|
||||
{
|
||||
WLog_DBG(TAG, "%s => %s (%" PRIuz ")", settings->ServerHostname, current, currentlen);
|
||||
|
||||
if (no_proxy_match_host(current, settings->ServerHostname))
|
||||
result = TRUE;
|
||||
else if (no_proxy_match_ip(current, settings->ServerHostname))
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
current = strtok_s(nullptr, delimiter, &context);
|
||||
}
|
||||
|
||||
free(copy);
|
||||
return result;
|
||||
}
|
||||
|
||||
void proxy_read_environment(rdpSettings* settings, char* envname)
|
||||
{
|
||||
const DWORD envlen = GetEnvironmentVariableA(envname, nullptr, 0);
|
||||
|
||||
if (!envlen || (envlen <= 1))
|
||||
return;
|
||||
|
||||
char* env = calloc(1, envlen);
|
||||
|
||||
if (!env)
|
||||
{
|
||||
WLog_ERR(TAG, "Not enough memory");
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetEnvironmentVariableA(envname, env, envlen) == envlen - 1)
|
||||
{
|
||||
if (_strnicmp("NO_PROXY", envname, 9) == 0)
|
||||
{
|
||||
if (check_no_proxy(settings, env))
|
||||
{
|
||||
WLog_INFO(TAG, "deactivating proxy: %s [%s=%s]",
|
||||
freerdp_settings_get_string(settings, FreeRDP_ServerHostname), envname,
|
||||
env);
|
||||
if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_NONE))
|
||||
WLog_WARN(TAG, "failed to set FreeRDP_ProxyType=PROXY_TYPE_NONE");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!proxy_parse_uri(settings, env))
|
||||
{
|
||||
WLog_WARN(
|
||||
TAG, "Error while parsing proxy URI from environment variable; ignoring proxy");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(env);
|
||||
}
|
||||
|
||||
BOOL proxy_parse_uri(rdpSettings* settings, const char* uri_in)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
const char* protocol = "";
|
||||
UINT16 port = 0;
|
||||
|
||||
if (!settings || !uri_in)
|
||||
return FALSE;
|
||||
|
||||
char* uri_copy = _strdup(uri_in);
|
||||
char* uri = uri_copy;
|
||||
if (!uri)
|
||||
goto fail;
|
||||
|
||||
{
|
||||
char* p = strstr(uri, "://");
|
||||
if (p)
|
||||
{
|
||||
*p = '\0';
|
||||
|
||||
if (_stricmp("no_proxy", uri) == 0)
|
||||
{
|
||||
if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_IGNORE))
|
||||
goto fail;
|
||||
}
|
||||
if (_stricmp("http", uri) == 0)
|
||||
{
|
||||
if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_HTTP))
|
||||
goto fail;
|
||||
protocol = "http";
|
||||
}
|
||||
else if (_stricmp("socks5", uri) == 0)
|
||||
{
|
||||
if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_SOCKS))
|
||||
goto fail;
|
||||
protocol = "socks5";
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "Only HTTP and SOCKS5 proxies supported by now");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uri = p + 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* default proxy protocol is http */
|
||||
if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_HTTP))
|
||||
goto fail;
|
||||
protocol = "http";
|
||||
}
|
||||
}
|
||||
|
||||
/* uri is now [user:password@]hostname:port */
|
||||
{
|
||||
char* atPtr = strrchr(uri, '@');
|
||||
|
||||
if (atPtr)
|
||||
{
|
||||
/* got a login / password,
|
||||
* atPtr
|
||||
* v
|
||||
* [user:password@]hostname:port
|
||||
* ^
|
||||
* colonPtr
|
||||
*/
|
||||
char* colonPtr = strchr(uri, ':');
|
||||
|
||||
if (!colonPtr || (colonPtr > atPtr))
|
||||
{
|
||||
WLog_ERR(TAG, "invalid syntax for proxy (contains no password)");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*colonPtr = '\0';
|
||||
if (!freerdp_settings_set_string(settings, FreeRDP_ProxyUsername, uri))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to allocate proxy username");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*atPtr = '\0';
|
||||
|
||||
if (!freerdp_settings_set_string(settings, FreeRDP_ProxyPassword, colonPtr + 1))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to allocate proxy password");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uri = atPtr + 1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
char* p = strchr(uri, ':');
|
||||
|
||||
if (p)
|
||||
{
|
||||
LONGLONG val = 0;
|
||||
|
||||
if (!value_to_int(&p[1], &val, 0, UINT16_MAX))
|
||||
{
|
||||
WLog_ERR(TAG, "invalid syntax for proxy (invalid port)");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (val == 0)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid syntax for proxy (port missing)");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
port = (UINT16)val;
|
||||
*p = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_stricmp("http", protocol) == 0)
|
||||
{
|
||||
/* The default is 80. Also for Proxies. */
|
||||
port = 80;
|
||||
}
|
||||
else
|
||||
{
|
||||
port = 1080;
|
||||
}
|
||||
|
||||
WLog_DBG(TAG, "setting default proxy port: %" PRIu16, port);
|
||||
}
|
||||
|
||||
if (!freerdp_settings_set_uint16(settings, FreeRDP_ProxyPort, port))
|
||||
goto fail;
|
||||
}
|
||||
{
|
||||
char* p = strchr(uri, '/');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
if (!freerdp_settings_set_string(settings, FreeRDP_ProxyHostname, uri))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (_stricmp("", uri) == 0)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid syntax for proxy (hostname missing)");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (freerdp_settings_get_string(settings, FreeRDP_ProxyUsername))
|
||||
{
|
||||
WLog_INFO(TAG, "Parsed proxy configuration: %s://%s:%s@%s:%" PRIu16, protocol,
|
||||
freerdp_settings_get_string(settings, FreeRDP_ProxyUsername), "******",
|
||||
freerdp_settings_get_string(settings, FreeRDP_ProxyHostname),
|
||||
freerdp_settings_get_uint16(settings, FreeRDP_ProxyPort));
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_INFO(TAG, "Parsed proxy configuration: %s://%s:%" PRIu16, protocol,
|
||||
freerdp_settings_get_string(settings, FreeRDP_ProxyHostname),
|
||||
freerdp_settings_get_uint16(settings, FreeRDP_ProxyPort));
|
||||
}
|
||||
rc = TRUE;
|
||||
|
||||
fail:
|
||||
if (!rc)
|
||||
WLog_WARN(TAG, "Failed to parse proxy configuration: %s://%s:%" PRIu16, protocol, uri,
|
||||
port);
|
||||
free(uri_copy);
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL proxy_connect(rdpContext* context, BIO* bufferedBio, const char* proxyUsername,
|
||||
const char* proxyPassword, const char* hostname, UINT16 port)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
rdpSettings* settings = context->settings;
|
||||
|
||||
switch (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType))
|
||||
{
|
||||
case PROXY_TYPE_NONE:
|
||||
case PROXY_TYPE_IGNORE:
|
||||
return TRUE;
|
||||
|
||||
case PROXY_TYPE_HTTP:
|
||||
return http_proxy_connect(context, bufferedBio, proxyUsername, proxyPassword, hostname,
|
||||
port);
|
||||
|
||||
case PROXY_TYPE_SOCKS:
|
||||
return socks_proxy_connect(context, bufferedBio, proxyUsername, proxyPassword, hostname,
|
||||
port);
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Invalid internal proxy configuration");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* get_response_header(char* response)
|
||||
{
|
||||
char* current_pos = strchr(response, '\r');
|
||||
if (!current_pos)
|
||||
current_pos = strchr(response, '\n');
|
||||
|
||||
if (current_pos)
|
||||
*current_pos = '\0';
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
static BOOL http_proxy_connect(rdpContext* context, BIO* bufferedBio, const char* proxyUsername,
|
||||
const char* proxyPassword, const char* hostname, UINT16 port)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
int status = 0;
|
||||
wStream* s = nullptr;
|
||||
char port_str[10] = WINPR_C_ARRAY_INIT;
|
||||
char recv_buf[256] = WINPR_C_ARRAY_INIT;
|
||||
char* eol = nullptr;
|
||||
size_t resultsize = 0;
|
||||
size_t reserveSize = 0;
|
||||
size_t portLen = 0;
|
||||
size_t hostLen = 0;
|
||||
const char connect[] = "CONNECT ";
|
||||
const char httpheader[] = " HTTP/1.1" CRLF "Host: ";
|
||||
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(bufferedBio);
|
||||
WINPR_ASSERT(hostname);
|
||||
const UINT32 timeout =
|
||||
freerdp_settings_get_uint32(context->settings, FreeRDP_TcpConnectTimeout);
|
||||
|
||||
_itoa_s(port, port_str, sizeof(port_str), 10);
|
||||
|
||||
hostLen = strlen(hostname);
|
||||
portLen = strnlen(port_str, sizeof(port_str));
|
||||
reserveSize = strlen(connect) + (hostLen + 1ull + portLen) * 2ull + strlen(httpheader);
|
||||
s = Stream_New(nullptr, reserveSize);
|
||||
if (!s)
|
||||
goto fail;
|
||||
|
||||
Stream_Write(s, connect, strlen(connect));
|
||||
Stream_Write(s, hostname, hostLen);
|
||||
Stream_Write_UINT8(s, ':');
|
||||
Stream_Write(s, port_str, portLen);
|
||||
Stream_Write(s, httpheader, strlen(httpheader));
|
||||
Stream_Write(s, hostname, hostLen);
|
||||
Stream_Write_UINT8(s, ':');
|
||||
Stream_Write(s, port_str, portLen);
|
||||
|
||||
if (proxyUsername && proxyPassword)
|
||||
{
|
||||
const int length = _scprintf("%s:%s", proxyUsername, proxyPassword);
|
||||
if (length > 0)
|
||||
{
|
||||
const size_t size = (size_t)length + 1ull;
|
||||
char* creds = (char*)malloc(size);
|
||||
|
||||
if (!creds)
|
||||
goto fail;
|
||||
else
|
||||
{
|
||||
const char basic[] = CRLF "Proxy-Authorization: Basic ";
|
||||
char* base64 = nullptr;
|
||||
|
||||
(void)sprintf_s(creds, size, "%s:%s", proxyUsername, proxyPassword);
|
||||
base64 = crypto_base64_encode((const BYTE*)creds, size - 1);
|
||||
|
||||
if (!base64 || !Stream_EnsureRemainingCapacity(s, strlen(basic) + strlen(base64)))
|
||||
{
|
||||
free(base64);
|
||||
free(creds);
|
||||
goto fail;
|
||||
}
|
||||
Stream_Write(s, basic, strlen(basic));
|
||||
Stream_Write(s, base64, strlen(base64));
|
||||
|
||||
free(base64);
|
||||
}
|
||||
free(creds);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, 4))
|
||||
goto fail;
|
||||
|
||||
Stream_Write(s, CRLF CRLF, 4);
|
||||
ERR_clear_error();
|
||||
|
||||
{
|
||||
const size_t pos = Stream_GetPosition(s);
|
||||
if (pos > INT32_MAX)
|
||||
goto fail;
|
||||
|
||||
status = BIO_write(bufferedBio, Stream_Buffer(s), WINPR_ASSERTING_INT_CAST(int, pos));
|
||||
}
|
||||
|
||||
if ((status < 0) || ((size_t)status != Stream_GetPosition(s)))
|
||||
{
|
||||
WLog_ERR(TAG, "HTTP proxy: failed to write CONNECT request");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Read result until CR-LF-CR-LF.
|
||||
* Keep recv_buf a null-terminated string. */
|
||||
{
|
||||
const UINT64 start = GetTickCount64();
|
||||
while (strstr(recv_buf, CRLF CRLF) == nullptr)
|
||||
{
|
||||
if (resultsize >= sizeof(recv_buf) - 1)
|
||||
{
|
||||
WLog_ERR(TAG, "HTTP Reply headers too long: %s", get_response_header(recv_buf));
|
||||
goto fail;
|
||||
}
|
||||
const size_t rdsize = sizeof(recv_buf) - resultsize - 1ULL;
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
WINPR_ASSERT(rdsize <= INT32_MAX);
|
||||
status = BIO_read(bufferedBio, (BYTE*)recv_buf + resultsize, (int)rdsize);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
/* Error? */
|
||||
if (!freerdp_shall_disconnect_context(context) && BIO_should_retry(bufferedBio))
|
||||
{
|
||||
USleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "Failed reading reply from HTTP proxy (Status %d)", status);
|
||||
goto fail;
|
||||
}
|
||||
else if (status == 0)
|
||||
{
|
||||
const UINT64 now = GetTickCount64();
|
||||
const UINT64 diff = now - start;
|
||||
if (freerdp_shall_disconnect_context(context) || (now < start) || (diff > timeout))
|
||||
{
|
||||
/* Error? */
|
||||
WLog_ERR(TAG, "Failed reading reply from HTTP proxy (BIO_read returned zero)");
|
||||
goto fail;
|
||||
}
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
resultsize += WINPR_ASSERTING_INT_CAST(size_t, status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract HTTP status line */
|
||||
eol = strchr(recv_buf, '\r');
|
||||
|
||||
if (!eol)
|
||||
{
|
||||
/* should never happen */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*eol = '\0';
|
||||
WLog_INFO(TAG, "HTTP Proxy: %s", recv_buf);
|
||||
|
||||
if (strnlen(recv_buf, sizeof(recv_buf)) < 12)
|
||||
goto fail;
|
||||
|
||||
recv_buf[7] = 'X';
|
||||
|
||||
if (strncmp(recv_buf, "HTTP/1.X 200", 12) != 0)
|
||||
goto fail;
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
Stream_Free(s, TRUE);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int recv_socks_reply(rdpContext* context, BIO* bufferedBio, BYTE* buf, int len, char* reason,
|
||||
BYTE checkVer)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
const UINT32 timeout =
|
||||
freerdp_settings_get_uint32(context->settings, FreeRDP_TcpConnectTimeout);
|
||||
const UINT64 start = GetTickCount64();
|
||||
for (;;)
|
||||
{
|
||||
ERR_clear_error();
|
||||
status = BIO_read(bufferedBio, buf, len);
|
||||
|
||||
if (status > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (status < 0)
|
||||
{
|
||||
/* Error? */
|
||||
if (!freerdp_shall_disconnect_context(context) && BIO_should_retry(bufferedBio))
|
||||
{
|
||||
USleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "Failed reading %s reply from SOCKS proxy (Status %d)", reason, status);
|
||||
return -1;
|
||||
}
|
||||
else if (status == 0)
|
||||
{
|
||||
const UINT64 now = GetTickCount64();
|
||||
const UINT64 diff = now - start;
|
||||
if (freerdp_shall_disconnect_context(context) || (now < start) || (diff > timeout))
|
||||
{
|
||||
/* Error? */
|
||||
WLog_ERR(TAG, "Failed reading %s reply from SOCKS proxy (BIO_read returned zero)",
|
||||
reason);
|
||||
return status;
|
||||
}
|
||||
Sleep(10);
|
||||
}
|
||||
else // if (status == 0)
|
||||
{
|
||||
/* Error? */
|
||||
WLog_ERR(TAG, "Failed reading %s reply from SOCKS proxy (BIO_read returned zero)",
|
||||
reason);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (status < 2)
|
||||
{
|
||||
WLog_ERR(TAG, "SOCKS Proxy reply packet too short (%s)", reason);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buf[0] != checkVer)
|
||||
{
|
||||
WLog_ERR(TAG, "SOCKS Proxy version is not 5 (%s)", reason);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static BOOL socks_proxy_userpass(rdpContext* context, BIO* bufferedBio, const char* proxyUsername,
|
||||
const char* proxyPassword)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(bufferedBio);
|
||||
|
||||
if (!proxyUsername || !proxyPassword)
|
||||
{
|
||||
WLog_ERR(TAG, "%s invalid username (%p) or password (%p)", logprefix,
|
||||
WINPR_CXX_COMPAT_CAST(const void*, proxyUsername),
|
||||
WINPR_CXX_COMPAT_CAST(const void*, proxyPassword));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const size_t usernameLen = (BYTE)strnlen(proxyUsername, 256);
|
||||
if (usernameLen > 255)
|
||||
{
|
||||
WLog_ERR(TAG, "%s username too long (%" PRIuz ", max=255)", logprefix, usernameLen);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const size_t userpassLen = (BYTE)strnlen(proxyPassword, 256);
|
||||
if (userpassLen > 255)
|
||||
{
|
||||
WLog_ERR(TAG, "%s password too long (%" PRIuz ", max=255)", logprefix, userpassLen);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* user/password v1 method */
|
||||
{
|
||||
BYTE buf[2 * 255 + 3] = WINPR_C_ARRAY_INIT;
|
||||
size_t offset = 0;
|
||||
buf[offset++] = 1;
|
||||
|
||||
buf[offset++] = WINPR_ASSERTING_INT_CAST(uint8_t, usernameLen);
|
||||
memcpy(&buf[offset], proxyUsername, usernameLen);
|
||||
offset += usernameLen;
|
||||
|
||||
buf[offset++] = WINPR_ASSERTING_INT_CAST(uint8_t, userpassLen);
|
||||
memcpy(&buf[offset], proxyPassword, userpassLen);
|
||||
offset += userpassLen;
|
||||
|
||||
ERR_clear_error();
|
||||
const int ioffset = WINPR_ASSERTING_INT_CAST(int, offset);
|
||||
const int status = BIO_write(bufferedBio, buf, ioffset);
|
||||
|
||||
if (status != ioffset)
|
||||
{
|
||||
WLog_ERR(TAG, "%s error writing user/password request", logprefix);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BYTE buf[2] = WINPR_C_ARRAY_INIT;
|
||||
const int status = recv_socks_reply(context, bufferedBio, buf, sizeof(buf), "AUTH REQ", 1);
|
||||
|
||||
if (status < 2)
|
||||
return FALSE;
|
||||
|
||||
if (buf[1] != 0x00)
|
||||
{
|
||||
WLog_ERR(TAG, "%s invalid user/password", logprefix);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL socks_proxy_connect(rdpContext* context, BIO* bufferedBio, const char* proxyUsername,
|
||||
const char* proxyPassword, const char* hostname, UINT16 port)
|
||||
{
|
||||
BYTE nauthMethods = 1;
|
||||
const size_t hostnlen = strnlen(hostname, 255);
|
||||
|
||||
if (proxyUsername || proxyPassword)
|
||||
nauthMethods++;
|
||||
|
||||
/* select auth. method */
|
||||
{
|
||||
const BYTE buf[] = { 5, /* SOCKS version */
|
||||
nauthMethods, /* #of methods offered */
|
||||
AUTH_M_NO_AUTH, AUTH_M_USR_PASS };
|
||||
|
||||
size_t writeLen = sizeof(buf);
|
||||
if (nauthMethods <= 1)
|
||||
writeLen--;
|
||||
|
||||
ERR_clear_error();
|
||||
const int iwriteLen = WINPR_ASSERTING_INT_CAST(int, writeLen);
|
||||
const int status = BIO_write(bufferedBio, buf, iwriteLen);
|
||||
|
||||
if (status != iwriteLen)
|
||||
{
|
||||
WLog_ERR(TAG, "%s SOCKS proxy: failed to write AUTH METHOD request", logprefix);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
BYTE buf[2] = WINPR_C_ARRAY_INIT;
|
||||
const int status = recv_socks_reply(context, bufferedBio, buf, sizeof(buf), "AUTH REQ", 5);
|
||||
|
||||
if (status <= 0)
|
||||
return FALSE;
|
||||
|
||||
switch (buf[1])
|
||||
{
|
||||
case AUTH_M_NO_AUTH:
|
||||
WLog_DBG(TAG, "%s (NO AUTH) method was selected", logprefix);
|
||||
break;
|
||||
|
||||
case AUTH_M_USR_PASS:
|
||||
if (nauthMethods < 2)
|
||||
{
|
||||
WLog_ERR(TAG, "%s USER/PASS method was not proposed to server", logprefix);
|
||||
return FALSE;
|
||||
}
|
||||
if (!socks_proxy_userpass(context, bufferedBio, proxyUsername, proxyPassword))
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "%s unknown method 0x%x was selected by proxy", logprefix, buf[1]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
/* CONN request */
|
||||
{
|
||||
BYTE buf[262] = WINPR_C_ARRAY_INIT;
|
||||
size_t offset = 0;
|
||||
buf[offset++] = 5; /* SOCKS version */
|
||||
buf[offset++] = SOCKS_CMD_CONNECT; /* command */
|
||||
buf[offset++] = 0; /* 3rd octet is reserved x00 */
|
||||
|
||||
if (inet_pton(AF_INET6, hostname, &buf[offset + 1]) == 1)
|
||||
{
|
||||
buf[offset++] = SOCKS_ADDR_IPV6;
|
||||
offset += 16;
|
||||
}
|
||||
else if (inet_pton(AF_INET, hostname, &buf[offset + 1]) == 1)
|
||||
{
|
||||
buf[offset++] = SOCKS_ADDR_IPV4;
|
||||
offset += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[offset++] = SOCKS_ADDR_FQDN;
|
||||
buf[offset++] = WINPR_ASSERTING_INT_CAST(uint8_t, hostnlen);
|
||||
memcpy(&buf[offset], hostname, hostnlen);
|
||||
offset += hostnlen;
|
||||
}
|
||||
|
||||
if (offset > sizeof(buf) - 2)
|
||||
return FALSE;
|
||||
|
||||
/* follows DST.PORT in netw. format */
|
||||
buf[offset++] = (port >> 8) & 0xff;
|
||||
buf[offset++] = port & 0xff;
|
||||
|
||||
ERR_clear_error();
|
||||
const int ioffset = WINPR_ASSERTING_INT_CAST(int, offset);
|
||||
const int status = BIO_write(bufferedBio, buf, ioffset);
|
||||
|
||||
if ((status < 0) || (status != ioffset))
|
||||
{
|
||||
WLog_ERR(TAG, "%s SOCKS proxy: failed to write CONN REQ", logprefix);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BYTE buf[255] = WINPR_C_ARRAY_INIT;
|
||||
const int status = recv_socks_reply(context, bufferedBio, buf, sizeof(buf), "CONN REQ", 5);
|
||||
|
||||
if (status < 4)
|
||||
return FALSE;
|
||||
|
||||
if (buf[1] == 0)
|
||||
{
|
||||
WLog_INFO(TAG, "Successfully connected to %s:%" PRIu16, hostname, port);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((buf[1] > 0) && (buf[1] < 9))
|
||||
WLog_INFO(TAG, "SOCKS Proxy replied: %s", rplstat[buf[1]]);
|
||||
else
|
||||
WLog_INFO(TAG, "SOCKS Proxy replied: %" PRIu8 " status not listed in rfc1928", buf[1]);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
35
third_party/FreeRDP/libfreerdp/core/proxy.h
vendored
Normal file
35
third_party/FreeRDP/libfreerdp/core/proxy.h
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* HTTP proxy support
|
||||
*
|
||||
* Copyright 2014 Christian Plattner <ccpp@gmx.at>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_HTTP_PROXY_H
|
||||
#define FREERDP_LIB_CORE_HTTP_PROXY_H
|
||||
|
||||
#include "freerdp/settings.h"
|
||||
#include <openssl/bio.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL proxy_prepare(rdpSettings* settings, const char** lpPeerHostname,
|
||||
UINT16* lpPeerPort, const char** lpProxyUsername,
|
||||
const char** lpProxyPassword);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL proxy_connect(rdpContext* context, BIO* bio, const char* proxyUsername,
|
||||
const char* proxyPassword, const char* hostname, UINT16 port);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_HTTP_PROXY_H */
|
||||
3155
third_party/FreeRDP/libfreerdp/core/rdp.c
vendored
Normal file
3155
third_party/FreeRDP/libfreerdp/core/rdp.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
367
third_party/FreeRDP/libfreerdp/core/rdp.h
vendored
Normal file
367
third_party/FreeRDP/libfreerdp/core/rdp.h
vendored
Normal file
@@ -0,0 +1,367 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Core
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_RDP_H
|
||||
#define FREERDP_LIB_CORE_RDP_H
|
||||
|
||||
#include <winpr/json.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#include <freerdp/config.h>
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/license.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "nla.h"
|
||||
#include "aad.h"
|
||||
#include "mcs.h"
|
||||
#include "tpkt.h"
|
||||
#include "../codec/bulk.h"
|
||||
#include "fastpath.h"
|
||||
#include "tpdu.h"
|
||||
#include "nego.h"
|
||||
#include "input.h"
|
||||
#include "update.h"
|
||||
#include "license.h"
|
||||
#include "errinfo.h"
|
||||
#include "autodetect.h"
|
||||
#include "heartbeat.h"
|
||||
#include "multitransport.h"
|
||||
#include "security.h"
|
||||
#include "transport.h"
|
||||
#include "connection.h"
|
||||
#include "redirection.h"
|
||||
#include "capabilities.h"
|
||||
#include "channels.h"
|
||||
#include "timer.h"
|
||||
|
||||
/* Security Header Flags */
|
||||
#define SEC_EXCHANGE_PKT 0x0001
|
||||
#define SEC_TRANSPORT_REQ 0x0002
|
||||
#define SEC_TRANSPORT_RSP 0x0004
|
||||
#define SEC_ENCRYPT 0x0008
|
||||
#define SEC_RESET_SEQNO 0x0010
|
||||
#define SEC_IGNORE_SEQNO 0x0020
|
||||
#define SEC_INFO_PKT 0x0040
|
||||
#define SEC_LICENSE_PKT 0x0080
|
||||
#define SEC_LICENSE_ENCRYPT_CS 0x0200
|
||||
#define SEC_LICENSE_ENCRYPT_SC 0x0200
|
||||
#define SEC_REDIRECTION_PKT 0x0400
|
||||
#define SEC_SECURE_CHECKSUM 0x0800
|
||||
#define SEC_AUTODETECT_REQ 0x1000
|
||||
#define SEC_AUTODETECT_RSP 0x2000
|
||||
#define SEC_HEARTBEAT 0x4000
|
||||
#define SEC_FLAGSHI_VALID 0x8000
|
||||
|
||||
#define SEC_PKT_CS_MASK (SEC_EXCHANGE_PKT | SEC_INFO_PKT)
|
||||
#define SEC_PKT_SC_MASK (SEC_LICENSE_PKT | SEC_REDIRECTION_PKT)
|
||||
#define SEC_PKT_MASK (SEC_PKT_CS_MASK | SEC_PKT_SC_MASK)
|
||||
|
||||
#define RDP_SECURITY_HEADER_LENGTH 4
|
||||
#define RDP_SHARE_CONTROL_HEADER_LENGTH 6
|
||||
#define RDP_SHARE_DATA_HEADER_LENGTH 12
|
||||
#define RDP_PACKET_HEADER_MAX_LENGTH (TPDU_DATA_LENGTH + MCS_SEND_DATA_HEADER_MAX_LENGTH)
|
||||
|
||||
#define PDU_TYPE_DEMAND_ACTIVE 0x1
|
||||
#define PDU_TYPE_CONFIRM_ACTIVE 0x3
|
||||
#define PDU_TYPE_DEACTIVATE_ALL 0x6
|
||||
#define PDU_TYPE_DATA 0x7
|
||||
#define PDU_TYPE_SERVER_REDIRECTION 0xA
|
||||
|
||||
#define PDU_TYPE_FLOW_TEST 0x41
|
||||
#define PDU_TYPE_FLOW_RESPONSE 0x42
|
||||
#define PDU_TYPE_FLOW_STOP 0x43
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FINALIZE_SC_SYNCHRONIZE_PDU = 0x01,
|
||||
FINALIZE_SC_CONTROL_COOPERATE_PDU = 0x02,
|
||||
FINALIZE_SC_CONTROL_GRANTED_PDU = 0x04,
|
||||
FINALIZE_SC_FONT_MAP_PDU = 0x08,
|
||||
|
||||
FINALIZE_CS_SYNCHRONIZE_PDU = 0x10,
|
||||
FINALIZE_CS_CONTROL_COOPERATE_PDU = 0x20,
|
||||
FINALIZE_CS_CONTROL_REQUEST_PDU = 0x40,
|
||||
FINALIZE_CS_PERSISTENT_KEY_LIST_PDU = 0x80,
|
||||
FINALIZE_CS_FONT_LIST_PDU = 0x100,
|
||||
|
||||
FINALIZE_DEACTIVATE_REACTIVATE = 0x200
|
||||
} rdpFinalizePduType;
|
||||
|
||||
/* Data PDU Types */
|
||||
typedef enum
|
||||
{
|
||||
DATA_PDU_TYPE_UPDATE = 0x02,
|
||||
DATA_PDU_TYPE_CONTROL = 0x14,
|
||||
DATA_PDU_TYPE_POINTER = 0x1B,
|
||||
DATA_PDU_TYPE_INPUT = 0x1C,
|
||||
DATA_PDU_TYPE_SYNCHRONIZE = 0x1F,
|
||||
DATA_PDU_TYPE_REFRESH_RECT = 0x21,
|
||||
DATA_PDU_TYPE_PLAY_SOUND = 0x22,
|
||||
DATA_PDU_TYPE_SUPPRESS_OUTPUT = 0x23,
|
||||
DATA_PDU_TYPE_SHUTDOWN_REQUEST = 0x24,
|
||||
DATA_PDU_TYPE_SHUTDOWN_DENIED = 0x25,
|
||||
DATA_PDU_TYPE_SAVE_SESSION_INFO = 0x26,
|
||||
DATA_PDU_TYPE_FONT_LIST = 0x27,
|
||||
DATA_PDU_TYPE_FONT_MAP = 0x28,
|
||||
DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS = 0x29,
|
||||
DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST = 0x2B,
|
||||
DATA_PDU_TYPE_BITMAP_CACHE_ERROR = 0x2C,
|
||||
DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS = 0x2D,
|
||||
DATA_PDU_TYPE_OFFSCREEN_CACHE_ERROR = 0x2E,
|
||||
DATA_PDU_TYPE_SET_ERROR_INFO = 0x2F,
|
||||
DATA_PDU_TYPE_DRAW_NINEGRID_ERROR = 0x30,
|
||||
DATA_PDU_TYPE_DRAW_GDIPLUS_ERROR = 0x31,
|
||||
DATA_PDU_TYPE_ARC_STATUS = 0x32,
|
||||
DATA_PDU_TYPE_STATUS_INFO = 0x36,
|
||||
DATA_PDU_TYPE_MONITOR_LAYOUT = 0x37,
|
||||
DATA_PDU_TYPE_FRAME_ACKNOWLEDGE = 0x38
|
||||
} rdpPduType;
|
||||
|
||||
/* Stream Identifiers */
|
||||
#define STREAM_UNDEFINED 0x00
|
||||
#define STREAM_LOW 0x01
|
||||
#define STREAM_MED 0x02
|
||||
#define STREAM_HI 0x04
|
||||
|
||||
struct rdp_rdp
|
||||
{
|
||||
CONNECTION_STATE state;
|
||||
rdpContext* context;
|
||||
rdpNla* nla;
|
||||
rdpAad* aad;
|
||||
rdpMcs* mcs;
|
||||
rdpNego* nego;
|
||||
rdpBulk* bulk;
|
||||
rdpInput* input;
|
||||
rdpUpdate* update;
|
||||
rdpFastPath* fastpath;
|
||||
rdpLicense* license;
|
||||
rdpRedirection* redirection;
|
||||
rdpSettings* settings;
|
||||
rdpSettings* originalSettings;
|
||||
rdpSettings* remoteSettings;
|
||||
rdpTransport* transport;
|
||||
rdpAutoDetect* autodetect;
|
||||
rdpHeartbeat* heartbeat;
|
||||
rdpMultitransport* multitransport;
|
||||
WINPR_RC4_CTX* rc4_decrypt_key;
|
||||
UINT32 decrypt_use_count;
|
||||
UINT32 decrypt_checksum_use_count;
|
||||
WINPR_RC4_CTX* rc4_encrypt_key;
|
||||
UINT32 encrypt_use_count;
|
||||
UINT32 encrypt_checksum_use_count;
|
||||
WINPR_CIPHER_CTX* fips_encrypt;
|
||||
WINPR_CIPHER_CTX* fips_decrypt;
|
||||
BOOL do_crypt;
|
||||
BOOL do_crypt_license;
|
||||
BOOL do_secure_checksum;
|
||||
BYTE sign_key[16];
|
||||
BYTE decrypt_key[16];
|
||||
BYTE encrypt_key[16];
|
||||
BYTE decrypt_update_key[16];
|
||||
BYTE encrypt_update_key[16];
|
||||
size_t rc4_key_len;
|
||||
BYTE fips_sign_key[20];
|
||||
BYTE fips_encrypt_key[24];
|
||||
BYTE fips_decrypt_key[24];
|
||||
UINT32 errorInfo;
|
||||
UINT32 finalize_sc_pdus;
|
||||
BOOL resendFocus;
|
||||
|
||||
UINT64 inBytes;
|
||||
UINT64 inPackets;
|
||||
UINT64 outBytes;
|
||||
UINT64 outPackets;
|
||||
CRITICAL_SECTION critical;
|
||||
rdpTransportIo* io;
|
||||
void* ioContext;
|
||||
HANDLE abortEvent;
|
||||
|
||||
wPubSub* pubSub;
|
||||
|
||||
BOOL monitor_layout_pdu;
|
||||
BOOL was_deactivated;
|
||||
UINT32 deactivated_width;
|
||||
UINT32 deactivated_height;
|
||||
|
||||
wLog* log;
|
||||
char log_context[64];
|
||||
WINPR_JSON* wellknown;
|
||||
FreeRDPTimer* timer;
|
||||
WINPR_ATTR_NODISCARD pGetCommonAccessToken GetCommonAccessToken;
|
||||
};
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_read_security_header(rdpRdp* rdp, wStream* s, UINT16* flags, UINT16* length);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_write_security_header(rdpRdp* rdp, wStream* s, UINT16 flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_read_share_control_header(rdpRdp* rdp, wStream* s, UINT16* tpktLength,
|
||||
UINT16* remainingLength, UINT16* type,
|
||||
UINT16* channel_id);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_read_share_data_header(rdpRdp* rdp, wStream* s, UINT16* length, BYTE* type,
|
||||
UINT32* shareId, BYTE* compressedType,
|
||||
UINT16* compressedLength);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channelId, UINT16 sec_flags);
|
||||
|
||||
WINPR_ATTR_MALLOC(rdp_send, 2)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL wStream* rdp_send_stream_init(rdpRdp* rdp, UINT16* sec_flags);
|
||||
|
||||
WINPR_ATTR_MALLOC(Stream_Release, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL wStream* rdp_send_stream_pdu_init(rdpRdp* rdp, UINT16* sec_flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_write_header(rdpRdp* rdp, wStream* s, size_t length, UINT16 channelId,
|
||||
UINT16 sec_flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type, UINT16 channel_id,
|
||||
UINT16 sec_flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id,
|
||||
UINT16 sec_flags);
|
||||
|
||||
WINPR_ATTR_MALLOC(rdp_send_data_pdu, 2)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL wStream* rdp_data_pdu_init(rdpRdp* rdp, UINT16* sec_flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t rdp_recv_data_pdu(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_channel_data(rdpRdp* rdp, UINT16 channelId, const BYTE* data,
|
||||
size_t size);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_channel_send_packet(rdpRdp* rdp, UINT16 channelId, size_t totalSize,
|
||||
UINT32 flags, const BYTE* data, size_t chunkSize);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags);
|
||||
|
||||
WINPR_ATTR_MALLOC(rdp_send_message_channel_pdu, 2)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL wStream* rdp_message_channel_pdu_init(rdpRdp* rdp, UINT16* sec_flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s,
|
||||
UINT16 securityFlags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s, UINT16 pduType,
|
||||
UINT16 length);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int rdp_check_fds(rdpRdp* rdp);
|
||||
|
||||
FREERDP_LOCAL void rdp_free(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_MALLOC(rdp_free, 1)
|
||||
FREERDP_LOCAL rdpRdp* rdp_new(rdpContext* context);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_reset(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_io_callback_set_event(rdpRdp* rdp, BOOL reset);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const rdpTransportIo* rdp_get_io_callbacks(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_set_io_callbacks(rdpRdp* rdp, const rdpTransportIo* io_callbacks);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_set_io_callback_context(rdpRdp* rdp, void* usercontext);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL void* rdp_get_io_callback_context(rdpRdp* rdp);
|
||||
|
||||
#define RDP_TAG FREERDP_TAG("core.rdp")
|
||||
#ifdef WITH_DEBUG_RDP
|
||||
#define DEBUG_RDP(rdp, ...) WLog_Print(rdp->log, WLOG_DEBUG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_RDP(rdp, ...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL const char* data_pdu_type_to_string(UINT8 type);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL const char* pdu_type_to_str(UINT16 pduType, char* buffer,
|
||||
size_t length);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL rdp_finalize_reset_flags(rdpRdp* rdp, BOOL clearAll);
|
||||
|
||||
FREERDP_LOCAL BOOL rdp_finalize_set_flag(rdpRdp* rdp, UINT32 flag);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL rdp_finalize_is_flag_set(rdpRdp* rdp, UINT32 flag);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL const char* rdp_finalize_flags_to_str(UINT32 flags, char* buffer,
|
||||
size_t size);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength,
|
||||
UINT16 securityFlags);
|
||||
|
||||
FREERDP_LOCAL BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL rdp_send_error_info(rdpRdp* rdp);
|
||||
|
||||
void rdp_free_rc4_encrypt_keys(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL rdp_reset_rc4_encrypt_keys(rdpRdp* rdp);
|
||||
|
||||
void rdp_free_rc4_decrypt_keys(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL rdp_reset_rc4_decrypt_keys(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL const char* rdp_security_flag_string(UINT32 securityFlags,
|
||||
char* buffer, size_t size);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL rdp_set_backup_settings(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL rdp_reset_runtime_settings(rdpRdp* rdp);
|
||||
|
||||
FREERDP_LOCAL void rdp_log_build_warnings(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL size_t rdp_get_event_handles(rdpRdp* rdp, HANDLE* handles, uint32_t count);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_RDP_H */
|
||||
1082
third_party/FreeRDP/libfreerdp/core/rdstls.c
vendored
Normal file
1082
third_party/FreeRDP/libfreerdp/core/rdstls.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
39
third_party/FreeRDP/libfreerdp/core/rdstls.h
vendored
Normal file
39
third_party/FreeRDP/libfreerdp/core/rdstls.h
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDSTLS Security protocol
|
||||
*
|
||||
* Copyright 2023 Joan Torres <joan.torres@suse.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_RDSTLS_H
|
||||
#define FREERDP_LIB_CORE_RDSTLS_H
|
||||
|
||||
typedef struct rdp_rdstls rdpRdstls;
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL SSIZE_T rdstls_parse_pdu(wLog* log, wStream* s);
|
||||
|
||||
FREERDP_LOCAL void rdstls_free(rdpRdstls* rdstls);
|
||||
|
||||
WINPR_ATTR_MALLOC(rdstls_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpRdstls* rdstls_new(rdpContext* context, rdpTransport* transport);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int rdstls_authenticate(rdpRdstls* rdstls);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_RDSTLS_H */
|
||||
1283
third_party/FreeRDP/libfreerdp/core/redirection.c
vendored
Normal file
1283
third_party/FreeRDP/libfreerdp/core/redirection.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
66
third_party/FreeRDP/libfreerdp/core/redirection.h
vendored
Normal file
66
third_party/FreeRDP/libfreerdp/core/redirection.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Server Redirection
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_REDIRECTION_H
|
||||
#define FREERDP_LIB_CORE_REDIRECTION_H
|
||||
|
||||
typedef struct rdp_redirection rdpRedirection;
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#define CERT_cert_file_element 32
|
||||
#define CERT_crl_file_element 33
|
||||
#define CERT_ctl_file_element 34
|
||||
#define CERT_keyid_file_element 35
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int rdp_redirection_apply_settings(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL state_run_t rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL
|
||||
rdp_write_enhanced_security_redirection_packet(wStream* s, const rdpRedirection* redirection);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_redirection_read_target_cert(rdpCertificate** ptargetCertificate,
|
||||
const BYTE* data, size_t length);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rdp_set_target_certificate(rdpSettings* settings, const rdpCertificate* tcert);
|
||||
|
||||
#define REDIR_TAG FREERDP_TAG("core.redirection")
|
||||
#ifdef WITH_DEBUG_REDIR
|
||||
#define DEBUG_REDIR(...) WLog_DBG(REDIR_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_REDIR(...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_REDIRECTION_H */
|
||||
1004
third_party/FreeRDP/libfreerdp/core/security.c
vendored
Normal file
1004
third_party/FreeRDP/libfreerdp/core/security.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
95
third_party/FreeRDP/libfreerdp/core/security.h
vendored
Normal file
95
third_party/FreeRDP/libfreerdp/core/security.h
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Security
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_SECURITY_H
|
||||
#define FREERDP_LIB_CORE_SECURITY_H
|
||||
|
||||
#include "rdp.h"
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_master_secret(const BYTE* premaster_secret, size_t pre_len,
|
||||
const BYTE* client_random, size_t client_len,
|
||||
const BYTE* server_random, size_t server_len,
|
||||
BYTE* output, size_t out_len);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_session_key_blob(const BYTE* master_secret, size_t master_len,
|
||||
const BYTE* client_random, size_t client_len,
|
||||
const BYTE* server_random, size_t server_len,
|
||||
BYTE* output, size_t out_len);
|
||||
|
||||
FREERDP_LOCAL void security_mac_salt_key(const BYTE* session_key_blob, size_t session_len,
|
||||
const BYTE* client_random, size_t client_len,
|
||||
const BYTE* server_random, size_t server_len, BYTE* output,
|
||||
size_t out_len);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_licensing_encryption_key(const BYTE* session_key_blob,
|
||||
size_t session_len, const BYTE* client_random,
|
||||
size_t client_len, const BYTE* server_random,
|
||||
size_t server_len, BYTE* output,
|
||||
size_t out_len);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_mac_data(const BYTE* mac_salt_key, size_t mac_salt_key_length,
|
||||
const BYTE* data, size_t length, BYTE* output,
|
||||
size_t output_length);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length,
|
||||
BYTE* output, size_t out_len);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_salted_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length,
|
||||
BOOL encryption, BYTE* output, size_t out_len);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_establish_keys(rdpRdp* rdp);
|
||||
|
||||
FREERDP_LOCAL void security_lock(rdpRdp* rdp);
|
||||
|
||||
FREERDP_LOCAL void security_unlock(rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_encrypt(BYTE* data, size_t length, rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_decrypt(BYTE* data, size_t length, rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_hmac_signature(const BYTE* data, size_t length, BYTE* output,
|
||||
size_t out_len, rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_fips_encrypt(BYTE* data, size_t length, rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_fips_decrypt(BYTE* data, size_t length, rdpRdp* rdp);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL security_fips_check_signature(const BYTE* data, size_t length, const BYTE* sig,
|
||||
size_t sig_len, rdpRdp* rdp);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_SECURITY_H */
|
||||
2128
third_party/FreeRDP/libfreerdp/core/server.c
vendored
Normal file
2128
third_party/FreeRDP/libfreerdp/core/server.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
404
third_party/FreeRDP/libfreerdp/core/server.h
vendored
Normal file
404
third_party/FreeRDP/libfreerdp/core/server.h
vendored
Normal file
@@ -0,0 +1,404 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Server Channels
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2015 Copyright 2015 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_SERVER_H
|
||||
#define FREERDP_LIB_CORE_SERVER_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
typedef struct rdp_peer_channel rdpPeerChannel;
|
||||
typedef struct WTSVirtualChannelManager WTSVirtualChannelManager;
|
||||
|
||||
#include "rdp.h"
|
||||
#include "mcs.h"
|
||||
|
||||
enum
|
||||
{
|
||||
RDP_PEER_CHANNEL_TYPE_SVC = 0,
|
||||
RDP_PEER_CHANNEL_TYPE_DVC = 1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DVC_OPEN_STATE_NONE = 0,
|
||||
DVC_OPEN_STATE_SUCCEEDED = 1,
|
||||
DVC_OPEN_STATE_FAILED = 2,
|
||||
DVC_OPEN_STATE_CLOSED = 3
|
||||
};
|
||||
|
||||
struct rdp_peer_channel
|
||||
{
|
||||
WTSVirtualChannelManager* vcm;
|
||||
freerdp_peer* client;
|
||||
|
||||
void* extra;
|
||||
UINT16 index;
|
||||
UINT32 channelId;
|
||||
UINT16 channelType;
|
||||
UINT32 channelFlags;
|
||||
|
||||
wStream* receiveData;
|
||||
wMessageQueue* queue;
|
||||
|
||||
BYTE dvc_open_state;
|
||||
INT32 creationStatus;
|
||||
UINT32 dvc_total_length;
|
||||
rdpMcsChannel* mcsChannel;
|
||||
|
||||
char channelName[128];
|
||||
CRITICAL_SECTION writeLock;
|
||||
};
|
||||
|
||||
struct WTSVirtualChannelManager
|
||||
{
|
||||
rdpRdp* rdp;
|
||||
freerdp_peer* client;
|
||||
|
||||
DWORD SessionId;
|
||||
wMessageQueue* queue;
|
||||
|
||||
rdpPeerChannel* drdynvc_channel;
|
||||
BYTE drdynvc_state;
|
||||
LONG dvc_channel_id_seq;
|
||||
UINT16 dvc_spoken_version;
|
||||
|
||||
WINPR_ATTR_NODISCARD psDVCCreationStatusCallback dvc_creation_status;
|
||||
void* dvc_creation_status_userdata;
|
||||
|
||||
wHashTable* dynamicVirtualChannels;
|
||||
};
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionW(LPWSTR pTargetServerName,
|
||||
ULONG TargetLogonId, BYTE HotkeyVk,
|
||||
USHORT HotkeyModifiers);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionA(LPSTR pTargetServerName,
|
||||
ULONG TargetLogonId, BYTE HotkeyVk,
|
||||
USHORT HotkeyModifiers);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExW(LPWSTR pTargetServerName,
|
||||
ULONG TargetLogonId,
|
||||
BYTE HotkeyVk,
|
||||
USHORT HotkeyModifiers,
|
||||
DWORD flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExA(LPSTR pTargetServerName,
|
||||
ULONG TargetLogonId,
|
||||
BYTE HotkeyVk,
|
||||
USHORT HotkeyModifiers,
|
||||
DWORD flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSStopRemoteControlSession(ULONG LogonId);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId,
|
||||
PWSTR pPassword, BOOL bWait);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId,
|
||||
PSTR pPassword, BOOL bWait);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved,
|
||||
DWORD Version,
|
||||
PWTS_SERVER_INFOW* ppServerInfo,
|
||||
DWORD* pCount);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved,
|
||||
DWORD Version,
|
||||
PWTS_SERVER_INFOA* ppServerInfo,
|
||||
DWORD* pCount);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL HANDLE WINAPI FreeRDP_WTSOpenServerW(LPWSTR pServerName);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL HANDLE WINAPI FreeRDP_WTSOpenServerA(LPSTR pServerName);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL HANDLE WINAPI FreeRDP_WTSOpenServerExW(LPWSTR pServerName);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL HANDLE WINAPI FreeRDP_WTSOpenServerExA(LPSTR pServerName);
|
||||
|
||||
FREERDP_LOCAL VOID WINAPI FreeRDP_WTSCloseServer(HANDLE hServer);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved,
|
||||
DWORD Version,
|
||||
PWTS_SESSION_INFOW* ppSessionInfo,
|
||||
DWORD* pCount);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved,
|
||||
DWORD Version,
|
||||
PWTS_SESSION_INFOA* ppSessionInfo,
|
||||
DWORD* pCount);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel,
|
||||
DWORD Filter,
|
||||
PWTS_SESSION_INFO_1W* ppSessionInfo,
|
||||
DWORD* pCount);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel,
|
||||
DWORD Filter,
|
||||
PWTS_SESSION_INFO_1A* ppSessionInfo,
|
||||
DWORD* pCount);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved,
|
||||
DWORD Version,
|
||||
PWTS_PROCESS_INFOW* ppProcessInfo,
|
||||
DWORD* pCount);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved,
|
||||
DWORD Version,
|
||||
PWTS_PROCESS_INFOA* ppProcessInfo,
|
||||
DWORD* pCount);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSTerminateProcess(HANDLE hServer, DWORD ProcessId,
|
||||
DWORD ExitCode);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId,
|
||||
WTS_INFO_CLASS WTSInfoClass,
|
||||
LPWSTR* ppBuffer,
|
||||
DWORD* pBytesReturned);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId,
|
||||
WTS_INFO_CLASS WTSInfoClass,
|
||||
LPSTR* ppBuffer,
|
||||
DWORD* pBytesReturned);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName,
|
||||
WTS_CONFIG_CLASS WTSConfigClass,
|
||||
LPWSTR* ppBuffer, DWORD* pBytesReturned);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName,
|
||||
WTS_CONFIG_CLASS WTSConfigClass,
|
||||
LPSTR* ppBuffer, DWORD* pBytesReturned);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName,
|
||||
WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer,
|
||||
DWORD DataLength);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName,
|
||||
WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer,
|
||||
DWORD DataLength);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle,
|
||||
DWORD TitleLength, LPWSTR pMessage,
|
||||
DWORD MessageLength, DWORD Style, DWORD Timeout,
|
||||
DWORD* pResponse, BOOL bWait);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle,
|
||||
DWORD TitleLength, LPSTR pMessage,
|
||||
DWORD MessageLength, DWORD Style, DWORD Timeout,
|
||||
DWORD* pResponse, BOOL bWait);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask,
|
||||
DWORD* pEventFlags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL HANDLE WINAPI FreeRDP_WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId,
|
||||
LPSTR pVirtualName);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName,
|
||||
DWORD flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut,
|
||||
PCHAR Buffer, ULONG BufferSize,
|
||||
PULONG pBytesRead);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer,
|
||||
ULONG Length, PULONG pBytesWritten);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeInput(HANDLE hChannelHandle);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSVirtualChannelQuery(HANDLE hChannelHandle,
|
||||
WTS_VIRTUAL_CLASS WtsVirtualClass,
|
||||
PVOID* ppBuffer, DWORD* pBytesReturned);
|
||||
|
||||
FREERDP_LOCAL VOID WINAPI FreeRDP_WTSFreeMemory(PVOID pMemory);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory,
|
||||
ULONG NumberOfEntries);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory,
|
||||
ULONG NumberOfEntries);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotification(HWND hWnd);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd,
|
||||
DWORD dwFlags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSQueryUserToken(ULONG SessionId, PHANDLE phToken);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel,
|
||||
DWORD SessionId, LPWSTR* ppProcessInfo,
|
||||
DWORD* pCount);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel,
|
||||
DWORD SessionId, LPSTR* ppProcessInfo,
|
||||
DWORD* pCount);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved,
|
||||
DWORD Reserved,
|
||||
PWTSLISTENERNAMEW pListeners,
|
||||
DWORD* pCount);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved,
|
||||
DWORD Reserved,
|
||||
PWTSLISTENERNAMEA pListeners,
|
||||
DWORD* pCount);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved,
|
||||
DWORD Reserved, LPWSTR pListenerName,
|
||||
PWTSLISTENERCONFIGW pBuffer);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved,
|
||||
DWORD Reserved, LPSTR pListenerName,
|
||||
PWTSLISTENERCONFIGA pBuffer);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSCreateListenerW(HANDLE hServer, PVOID pReserved,
|
||||
DWORD Reserved, LPWSTR pListenerName,
|
||||
PWTSLISTENERCONFIGW pBuffer, DWORD flag);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSCreateListenerA(HANDLE hServer, PVOID pReserved,
|
||||
DWORD Reserved, LPSTR pListenerName,
|
||||
PWTSLISTENERCONFIGA pBuffer, DWORD flag);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved,
|
||||
DWORD Reserved, LPWSTR pListenerName,
|
||||
SECURITY_INFORMATION SecurityInformation,
|
||||
PSECURITY_DESCRIPTOR pSecurityDescriptor);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved,
|
||||
DWORD Reserved, LPSTR pListenerName,
|
||||
SECURITY_INFORMATION SecurityInformation,
|
||||
PSECURITY_DESCRIPTOR pSecurityDescriptor);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved,
|
||||
DWORD Reserved, LPWSTR pListenerName,
|
||||
SECURITY_INFORMATION SecurityInformation,
|
||||
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
||||
DWORD nLength, LPDWORD lpnLengthNeeded);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved,
|
||||
DWORD Reserved, LPSTR pListenerName,
|
||||
SECURITY_INFORMATION SecurityInformation,
|
||||
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
||||
DWORD nLength, LPDWORD lpnLengthNeeded);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL CDECL FreeRDP_WTSEnableChildSessions(BOOL bEnable);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL CDECL FreeRDP_WTSIsChildSessionsEnabled(PBOOL pbEnabled);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL CDECL FreeRDP_WTSGetChildSessionId(PULONG pSessionId);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL DWORD WINAPI FreeRDP_WTSGetActiveConsoleSessionId(void);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSLogoffUser(HANDLE hServer);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR password,
|
||||
LPCSTR domain);
|
||||
|
||||
FREERDP_LOCAL void server_channel_common_free(rdpPeerChannel*);
|
||||
|
||||
WINPR_ATTR_MALLOC(server_channel_common_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpPeerChannel* server_channel_common_new(freerdp_peer* client, UINT16 index,
|
||||
UINT32 channelId, size_t chunkSize,
|
||||
const wObject* callback, const char* name);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_SERVER_H */
|
||||
1808
third_party/FreeRDP/libfreerdp/core/settings.c
vendored
Normal file
1808
third_party/FreeRDP/libfreerdp/core/settings.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
108
third_party/FreeRDP/libfreerdp/core/settings.h
vendored
Normal file
108
third_party/FreeRDP/libfreerdp/core/settings.h
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Internal settings header for functions not exported
|
||||
*
|
||||
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2018 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_LIB_CORE_SETTINGS_H
|
||||
#define FREERDP_LIB_CORE_SETTINGS_H
|
||||
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/sspi.h>
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#define FREERDP_SETTINGS_INTERNAL_USE
|
||||
#include <freerdp/settings_types_private.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_settings_enforce_consistency(rdpSettings* settings);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_settings_enforce_monitor_exists(rdpSettings* settings);
|
||||
|
||||
FREERDP_LOCAL void freerdp_settings_print_warnings(const rdpSettings* settings);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_settings_check_client_after_preconnect(const rdpSettings* settings);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_settings_set_default_order_support(rdpSettings* settings);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_settings_clone_keys(rdpSettings* dst, const rdpSettings* src);
|
||||
|
||||
FREERDP_LOCAL void freerdp_settings_free_keys(rdpSettings* dst, BOOL cleanup);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_settings_set_string_(rdpSettings* settings,
|
||||
FreeRDP_Settings_Keys_String id, const char* val,
|
||||
size_t len);
|
||||
|
||||
FREERDP_LOCAL BOOL freerdp_settings_set_string_copy_(rdpSettings* settings,
|
||||
FreeRDP_Settings_Keys_String id,
|
||||
const char* val, size_t len, BOOL cleanup);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_capability_buffer_resize(rdpSettings* settings, size_t count,
|
||||
BOOL force);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL identity_set_from_settings_with_pwd(SEC_WINNT_AUTH_IDENTITY_W* identity,
|
||||
const rdpSettings* settings,
|
||||
FreeRDP_Settings_Keys_String UserId,
|
||||
FreeRDP_Settings_Keys_String DomainId,
|
||||
const WCHAR* Password, size_t pwdLen);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL identity_set_from_settings(SEC_WINNT_AUTH_IDENTITY_W* identity,
|
||||
const rdpSettings* settings,
|
||||
FreeRDP_Settings_Keys_String UserId,
|
||||
FreeRDP_Settings_Keys_String DomainId,
|
||||
FreeRDP_Settings_Keys_String PwdId);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL identity_set_from_smartcard_hash(SEC_WINNT_AUTH_IDENTITY_W* identity,
|
||||
const rdpSettings* settings,
|
||||
FreeRDP_Settings_Keys_String userId,
|
||||
FreeRDP_Settings_Keys_String domainId,
|
||||
FreeRDP_Settings_Keys_String pwdId,
|
||||
const BYTE* certSha1, size_t sha1len);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* freerdp_settings_glyph_level_string(UINT32 level, char* buffer,
|
||||
size_t size);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_settings_set_pointer_len_(rdpSettings* settings,
|
||||
FreeRDP_Settings_Keys_Pointer id,
|
||||
FreeRDP_Settings_Keys_UInt32 lenId,
|
||||
const void* data, size_t len, size_t size);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_target_net_adresses_reset(rdpSettings* settings, size_t size);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_target_net_addresses_resize(rdpSettings* settings, size_t count);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_SETTINGS_H */
|
||||
43
third_party/FreeRDP/libfreerdp/core/simd.h
vendored
Normal file
43
third_party/FreeRDP/libfreerdp/core/simd.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* SIMD support detection header
|
||||
*
|
||||
* Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2024 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <freerdp/config.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#define PRIM_TAG FREERDP_TAG("primitives")
|
||||
|
||||
/* https://sourceforge.net/p/predef/wiki/Architectures/
|
||||
*
|
||||
* contains a list of defined symbols for each compiler
|
||||
*/
|
||||
#if defined(WITH_SIMD)
|
||||
#if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) || defined(_M_IX86_AMD64) || \
|
||||
defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \
|
||||
defined(__i686__) || defined(__ia64__)
|
||||
#define SSE_AVX_INTRINSICS_ENABLED
|
||||
#endif
|
||||
|
||||
// Inspired by llvm arm_neon.h header checks
|
||||
#if defined(__ARM_NEON) && defined(__ARM_FP)
|
||||
#define NEON_INTRINSICS_ENABLED
|
||||
#endif
|
||||
#endif
|
||||
959
third_party/FreeRDP/libfreerdp/core/smartcardlogon.c
vendored
Normal file
959
third_party/FreeRDP/libfreerdp/core/smartcardlogon.c
vendored
Normal file
@@ -0,0 +1,959 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Logging in with smartcards
|
||||
*
|
||||
* Copyright 2022 David Fort <contact@hardening-consulting.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/error.h>
|
||||
#include <winpr/ncrypt.h>
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/path.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <freerdp/utils/smartcardlogon.h>
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
#include <freerdp/utils/helpers.h>
|
||||
|
||||
#include <openssl/obj_mac.h>
|
||||
|
||||
#define TAG FREERDP_TAG("smartcardlogon")
|
||||
|
||||
struct SmartcardKeyInfo_st
|
||||
{
|
||||
char* certPath;
|
||||
char* keyPath;
|
||||
};
|
||||
|
||||
static void delete_file(char* path)
|
||||
{
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
/* Overwrite data in files before deletion */
|
||||
{
|
||||
FILE* fp = winpr_fopen(path, "r+");
|
||||
if (fp)
|
||||
{
|
||||
const char buffer[8192] = WINPR_C_ARRAY_INIT;
|
||||
INT64 size = 0;
|
||||
int rs = _fseeki64(fp, 0, SEEK_END);
|
||||
if (rs == 0)
|
||||
size = _ftelli64(fp);
|
||||
(void)_fseeki64(fp, 0, SEEK_SET);
|
||||
|
||||
for (INT64 x = 0; x < size; x += sizeof(buffer))
|
||||
{
|
||||
const size_t dnmemb = (size_t)(size - x);
|
||||
const size_t nmemb = MIN(sizeof(buffer), dnmemb);
|
||||
const size_t count = fwrite(buffer, nmemb, 1, fp);
|
||||
if (count != 1)
|
||||
break;
|
||||
}
|
||||
|
||||
(void)fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
winpr_DeleteFile(path);
|
||||
free(path);
|
||||
}
|
||||
|
||||
static void smartcardKeyInfo_Free(SmartcardKeyInfo* key_info)
|
||||
{
|
||||
if (!key_info)
|
||||
return;
|
||||
|
||||
delete_file(key_info->certPath);
|
||||
delete_file(key_info->keyPath);
|
||||
|
||||
free(key_info);
|
||||
}
|
||||
|
||||
void smartcardCertInfo_Free(SmartcardCertInfo* scCert)
|
||||
{
|
||||
if (!scCert)
|
||||
return;
|
||||
|
||||
free(scCert->csp);
|
||||
free(scCert->reader);
|
||||
freerdp_certificate_free(scCert->certificate);
|
||||
free(scCert->pkinitArgs);
|
||||
free(scCert->keyName);
|
||||
free(scCert->containerName);
|
||||
free(scCert->upn);
|
||||
free(scCert->userHint);
|
||||
free(scCert->domainHint);
|
||||
free(scCert->subject);
|
||||
free(scCert->issuer);
|
||||
smartcardKeyInfo_Free(scCert->key_info);
|
||||
|
||||
free(scCert);
|
||||
}
|
||||
|
||||
void smartcardCertList_Free(SmartcardCertInfo** pscCert, size_t count)
|
||||
{
|
||||
if (!pscCert)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
SmartcardCertInfo* cert = pscCert[i];
|
||||
smartcardCertInfo_Free(cert);
|
||||
}
|
||||
|
||||
free((void*)pscCert);
|
||||
}
|
||||
|
||||
static BOOL add_cert_to_list(SmartcardCertInfo*** certInfoList, size_t* count,
|
||||
SmartcardCertInfo* certInfo)
|
||||
{
|
||||
size_t curCount = *count;
|
||||
SmartcardCertInfo** curInfoList = *certInfoList;
|
||||
|
||||
/* Check if the certificate is already in the list */
|
||||
for (size_t i = 0; i < curCount; ++i)
|
||||
{
|
||||
if (_wcscmp(curInfoList[i]->containerName, certInfo->containerName) == 0)
|
||||
{
|
||||
smartcardCertInfo_Free(certInfo);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
SmartcardCertInfo** tmpInfoList = (SmartcardCertInfo**)realloc(
|
||||
(void*)curInfoList, sizeof(SmartcardCertInfo*) * (curCount + 1));
|
||||
if (!tmpInfoList)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to reallocate certs");
|
||||
return FALSE;
|
||||
}
|
||||
curInfoList = tmpInfoList;
|
||||
}
|
||||
|
||||
curInfoList[curCount++] = certInfo;
|
||||
*certInfoList = curInfoList;
|
||||
*count = curCount;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL treat_sc_cert(SmartcardCertInfo* scCert)
|
||||
{
|
||||
WINPR_ASSERT(scCert);
|
||||
|
||||
scCert->upn = freerdp_certificate_get_upn(scCert->certificate);
|
||||
if (!scCert->upn)
|
||||
{
|
||||
WLog_DBG(TAG, "%s has no UPN, trying emailAddress", scCert->keyName);
|
||||
scCert->upn = freerdp_certificate_get_email(scCert->certificate);
|
||||
}
|
||||
|
||||
if (scCert->upn)
|
||||
{
|
||||
size_t userLen = 0;
|
||||
const char* atPos = strchr(scCert->upn, '@');
|
||||
|
||||
if (!atPos)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid UPN, for key %s (no @)", scCert->keyName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
userLen = (size_t)(atPos - scCert->upn);
|
||||
scCert->userHint = malloc(userLen + 1);
|
||||
scCert->domainHint = _strdup(atPos + 1);
|
||||
|
||||
if (!scCert->userHint || !scCert->domainHint)
|
||||
{
|
||||
WLog_ERR(TAG, "error allocating userHint or domainHint, for key %s", scCert->keyName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(scCert->userHint, scCert->upn, userLen);
|
||||
scCert->userHint[userLen] = 0;
|
||||
}
|
||||
|
||||
scCert->subject = freerdp_certificate_get_subject(scCert->certificate);
|
||||
scCert->issuer = freerdp_certificate_get_issuer(scCert->certificate);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL set_info_certificate(SmartcardCertInfo* cert, BYTE* certBytes, DWORD cbCertBytes,
|
||||
const char* userFilter, const char* domainFilter)
|
||||
{
|
||||
if (!winpr_Digest(WINPR_MD_SHA1, certBytes, cbCertBytes, cert->sha1Hash,
|
||||
sizeof(cert->sha1Hash)))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to compute certificate sha1 for key %s", cert->keyName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cert->certificate = freerdp_certificate_new_from_der(certBytes, cbCertBytes);
|
||||
if (!cert->certificate)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to parse X509 certificate for key %s", cert->keyName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!freerdp_certificate_check_eku(cert->certificate, NID_ms_smartcard_login))
|
||||
{
|
||||
WLog_DBG(TAG, "discarding certificate without Smartcard Login EKU for key %s",
|
||||
cert->keyName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!treat_sc_cert(cert))
|
||||
{
|
||||
WLog_DBG(TAG, "error treating cert");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (userFilter && (!cert->upn || (strcmp(cert->upn, userFilter) != 0)))
|
||||
{
|
||||
if (cert->userHint && strcmp(cert->userHint, userFilter) != 0)
|
||||
{
|
||||
WLog_DBG(TAG, "discarding non matching cert by user %s@%s", cert->userHint,
|
||||
cert->domainHint);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (domainFilter && cert->domainHint && strcmp(cert->domainHint, domainFilter) != 0)
|
||||
{
|
||||
WLog_DBG(TAG, "discarding non matching cert by domain(%s) %s@%s", domainFilter,
|
||||
cert->userHint, cert->domainHint);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static BOOL build_pkinit_args(NCRYPT_PROV_HANDLE provider, SmartcardCertInfo* scCert)
|
||||
{
|
||||
/* pkinit args only under windows
|
||||
* PKCS11:module_name=opensc-pkcs11.so
|
||||
*/
|
||||
const char* pkModule = winpr_NCryptGetModulePath(provider);
|
||||
size_t size = 0;
|
||||
|
||||
return (winpr_asprintf(&scCert->pkinitArgs, &size, "PKCS11:module_name=%s:slotid=%" PRIu16,
|
||||
pkModule, (UINT16)scCert->slotId) > 0);
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef _WIN32
|
||||
static BOOL list_capi_provider_keys(const rdpSettings* settings, LPCWSTR csp, LPCWSTR scope,
|
||||
const char* userFilter, const char* domainFilter,
|
||||
SmartcardCertInfo*** pcerts, size_t* pcount)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
HCRYPTKEY hKey = 0;
|
||||
HCRYPTPROV hProvider = 0;
|
||||
SmartcardCertInfo* cert = nullptr;
|
||||
BYTE* certBytes = nullptr;
|
||||
CHAR* readerName = nullptr;
|
||||
|
||||
if (!CryptAcquireContextW(&hProvider, scope, csp, PROV_RSA_FULL, CRYPT_SILENT))
|
||||
{
|
||||
WLog_DBG(TAG, "Unable to acquire context: %d", GetLastError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
cert = calloc(1, sizeof(SmartcardCertInfo));
|
||||
if (!cert)
|
||||
goto out;
|
||||
|
||||
cert->csp = _wcsdup(csp);
|
||||
if (!cert->csp)
|
||||
goto out;
|
||||
|
||||
/* ====== retrieve key's reader ====== */
|
||||
DWORD dwDataLen = 0;
|
||||
if (!CryptGetProvParam(hProvider, PP_SMARTCARD_READER, nullptr, &dwDataLen, 0))
|
||||
{
|
||||
WLog_DBG(TAG, "Unable to get provider param: %d", GetLastError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
readerName = malloc(dwDataLen);
|
||||
if (!readerName)
|
||||
goto out;
|
||||
|
||||
if (!CryptGetProvParam(hProvider, PP_SMARTCARD_READER, readerName, &dwDataLen, 0))
|
||||
{
|
||||
WLog_DBG(TAG, "Unable to get reader name: %d", GetLastError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
cert->reader = ConvertUtf8ToWCharAlloc(readerName, nullptr);
|
||||
if (!cert->reader)
|
||||
goto out;
|
||||
|
||||
/* ====== retrieve key container name ====== */
|
||||
dwDataLen = 0;
|
||||
if (!CryptGetProvParam(hProvider, PP_CONTAINER, nullptr, &dwDataLen, 0))
|
||||
{
|
||||
WLog_DBG(TAG, "Unable to get provider param: %d", GetLastError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
cert->keyName = malloc(dwDataLen);
|
||||
if (!cert->keyName)
|
||||
goto out;
|
||||
|
||||
if (!CryptGetProvParam(hProvider, PP_CONTAINER, cert->keyName, &dwDataLen, 0))
|
||||
{
|
||||
WLog_DBG(TAG, "Unable to get container name: %d", GetLastError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
cert->containerName = ConvertUtf8ToWCharAlloc(cert->keyName, nullptr);
|
||||
if (!cert->containerName)
|
||||
goto out;
|
||||
|
||||
/* ========= retrieve the certificate ===============*/
|
||||
if (!CryptGetUserKey(hProvider, AT_KEYEXCHANGE, &hKey))
|
||||
{
|
||||
WLog_DBG(TAG, "Unable to get user key for %s: %d", cert->keyName, GetLastError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
dwDataLen = 0;
|
||||
if (!CryptGetKeyParam(hKey, KP_CERTIFICATE, nullptr, &dwDataLen, 0))
|
||||
{
|
||||
WLog_DBG(TAG, "Unable to get key param for key %s: %d", cert->keyName, GetLastError());
|
||||
goto out;
|
||||
}
|
||||
|
||||
certBytes = malloc(dwDataLen);
|
||||
if (!certBytes)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to allocate %" PRIu32 " certBytes for key %s", dwDataLen,
|
||||
cert->keyName);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!CryptGetKeyParam(hKey, KP_CERTIFICATE, certBytes, &dwDataLen, 0))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to retrieve certificate for key %s", cert->keyName);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!set_info_certificate(cert, certBytes, dwDataLen, userFilter, domainFilter))
|
||||
goto out;
|
||||
|
||||
if (!add_cert_to_list(pcerts, pcount, cert))
|
||||
goto out;
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
free(readerName);
|
||||
free(certBytes);
|
||||
if (hKey)
|
||||
CryptDestroyKey(hKey);
|
||||
if (hProvider)
|
||||
CryptReleaseContext(hProvider, 0);
|
||||
if (!ret)
|
||||
smartcardCertInfo_Free(cert);
|
||||
return ret;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
static BOOL list_provider_keys(WINPR_ATTR_UNUSED const rdpSettings* settings,
|
||||
NCRYPT_PROV_HANDLE provider, LPCWSTR csp, LPCWSTR scope,
|
||||
const char* userFilter, const char* domainFilter,
|
||||
SmartcardCertInfo*** pcerts, size_t* pcount)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
NCryptKeyName* keyName = nullptr;
|
||||
PVOID enumState = nullptr;
|
||||
SmartcardCertInfo** cert_list = *pcerts;
|
||||
size_t count = *pcount;
|
||||
|
||||
while (NCryptEnumKeys(provider, scope, &keyName, &enumState, NCRYPT_SILENT_FLAG) ==
|
||||
ERROR_SUCCESS)
|
||||
{
|
||||
NCRYPT_KEY_HANDLE phKey = 0;
|
||||
PBYTE certBytes = nullptr;
|
||||
DWORD dwFlags = NCRYPT_SILENT_FLAG;
|
||||
DWORD cbOutput = 0;
|
||||
SmartcardCertInfo* cert = nullptr;
|
||||
BOOL haveError = TRUE;
|
||||
SECURITY_STATUS status = 0;
|
||||
|
||||
cert = calloc(1, sizeof(SmartcardCertInfo));
|
||||
if (!cert)
|
||||
goto out;
|
||||
|
||||
cert->keyName = ConvertWCharToUtf8Alloc(keyName->pszName, nullptr);
|
||||
if (!cert->keyName)
|
||||
goto endofloop;
|
||||
|
||||
WLog_DBG(TAG, "opening key %s", cert->keyName);
|
||||
|
||||
status =
|
||||
NCryptOpenKey(provider, &phKey, keyName->pszName, keyName->dwLegacyKeySpec, dwFlags);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_DBG(TAG,
|
||||
"unable to NCryptOpenKey(dwLegacyKeySpec=0x%08" PRIx32 " dwFlags=0x%08" PRIx32
|
||||
"), status=%s, skipping",
|
||||
keyName->dwLegacyKeySpec, keyName->dwFlags,
|
||||
winpr_NCryptSecurityStatusError(status));
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
cert->csp = _wcsdup(csp);
|
||||
if (!cert->csp)
|
||||
goto endofloop;
|
||||
|
||||
#ifndef _WIN32
|
||||
status = NCryptGetProperty(phKey, NCRYPT_WINPR_SLOTID, (PBYTE)&cert->slotId, 4, &cbOutput,
|
||||
dwFlags);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to retrieve slotId for key %s, status=%s", cert->keyName,
|
||||
winpr_NCryptSecurityStatusError(status));
|
||||
goto endofloop;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* ====== retrieve key's reader ====== */
|
||||
cbOutput = 0;
|
||||
status = NCryptGetProperty(phKey, NCRYPT_READER_PROPERTY, nullptr, 0, &cbOutput, dwFlags);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_DBG(TAG, "unable to retrieve reader's name length for key %s", cert->keyName);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
cert->reader = calloc(1, cbOutput + 2);
|
||||
if (!cert->reader)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to allocate reader's name for key %s", cert->keyName);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
status = NCryptGetProperty(phKey, NCRYPT_READER_PROPERTY, (PBYTE)cert->reader, cbOutput + 2,
|
||||
&cbOutput, dwFlags);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to retrieve reader's name for key %s", cert->keyName);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
/* ====== retrieve key container name ====== */
|
||||
/* When using PKCS11, this will try to return what Windows would use for the key's name */
|
||||
cbOutput = 0;
|
||||
status = NCryptGetProperty(phKey, NCRYPT_NAME_PROPERTY, nullptr, 0, &cbOutput, dwFlags);
|
||||
if (status == ERROR_SUCCESS)
|
||||
{
|
||||
cert->containerName = calloc(1, cbOutput + sizeof(WCHAR));
|
||||
if (!cert->containerName)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to allocate key container name for key %s", cert->keyName);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
status = NCryptGetProperty(phKey, NCRYPT_NAME_PROPERTY, (BYTE*)cert->containerName,
|
||||
cbOutput, &cbOutput, dwFlags);
|
||||
}
|
||||
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to retrieve key container name for key %s", cert->keyName);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
/* ========= retrieve the certificate ===============*/
|
||||
cbOutput = 0;
|
||||
status =
|
||||
NCryptGetProperty(phKey, NCRYPT_CERTIFICATE_PROPERTY, nullptr, 0, &cbOutput, dwFlags);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
/* can happen that key don't have certificates */
|
||||
WLog_DBG(TAG, "unable to retrieve certificate property len, status=%s, skipping",
|
||||
winpr_NCryptSecurityStatusError(status));
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
certBytes = calloc(1, cbOutput);
|
||||
if (!certBytes)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to allocate %" PRIu32 " certBytes for key %s", cbOutput,
|
||||
cert->keyName);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
status = NCryptGetProperty(phKey, NCRYPT_CERTIFICATE_PROPERTY, certBytes, cbOutput,
|
||||
&cbOutput, dwFlags);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to retrieve certificate for key %s", cert->keyName);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
if (!set_info_certificate(cert, certBytes, cbOutput, userFilter, domainFilter))
|
||||
goto endofloop;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (!build_pkinit_args(provider, cert))
|
||||
{
|
||||
WLog_ERR(TAG, "error build pkinit args");
|
||||
goto endofloop;
|
||||
}
|
||||
#endif
|
||||
haveError = FALSE;
|
||||
|
||||
endofloop:
|
||||
free(certBytes);
|
||||
NCryptFreeBuffer(keyName);
|
||||
if (phKey)
|
||||
NCryptFreeObject((NCRYPT_HANDLE)phKey);
|
||||
|
||||
if (haveError)
|
||||
smartcardCertInfo_Free(cert);
|
||||
else
|
||||
{
|
||||
if (!add_cert_to_list(&cert_list, &count, cert))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (count == 0)
|
||||
{
|
||||
char cspa[128] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
(void)ConvertWCharToUtf8(csp, cspa, sizeof(cspa));
|
||||
char scopea[128] = WINPR_C_ARRAY_INIT;
|
||||
(void)ConvertWCharToUtf8(scope, scopea, sizeof(scopea));
|
||||
WLog_WARN(TAG, "%s [%s] no certificates found", cspa, scopea);
|
||||
}
|
||||
*pcount = count;
|
||||
*pcerts = cert_list;
|
||||
NCryptFreeBuffer(enumState);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL smartcard_hw_enumerateCerts(const rdpSettings* settings, LPCWSTR csp,
|
||||
const char* reader, const char* userFilter,
|
||||
const char* domainFilter, SmartcardCertInfo*** scCerts,
|
||||
size_t* retCount)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
LPWSTR scope = nullptr;
|
||||
NCRYPT_PROV_HANDLE provider = 0;
|
||||
SECURITY_STATUS status = 0;
|
||||
size_t count = 0;
|
||||
SmartcardCertInfo** cert_list = nullptr;
|
||||
const char* Pkcs11Module = freerdp_settings_get_string(settings, FreeRDP_Pkcs11Module);
|
||||
|
||||
WINPR_ASSERT(scCerts);
|
||||
WINPR_ASSERT(retCount);
|
||||
|
||||
if (reader)
|
||||
{
|
||||
size_t readerSz = strlen(reader);
|
||||
char* scopeStr = malloc(4 + readerSz + 1 + 1);
|
||||
if (!scopeStr)
|
||||
goto out;
|
||||
|
||||
(void)_snprintf(scopeStr, readerSz + 6, "\\\\.\\%s\\", reader);
|
||||
scope = ConvertUtf8NToWCharAlloc(scopeStr, readerSz + 6, nullptr);
|
||||
free(scopeStr);
|
||||
|
||||
if (!scope)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (Pkcs11Module)
|
||||
{
|
||||
/* load a unique CSP by pkcs11 module path */
|
||||
LPCSTR paths[] = { Pkcs11Module, nullptr };
|
||||
|
||||
if (!csp)
|
||||
csp = MS_SCARD_PROV;
|
||||
|
||||
status = winpr_NCryptOpenStorageProviderEx(&provider, csp, 0, paths);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to open provider given by pkcs11 module");
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = list_provider_keys(settings, provider, csp, scope, userFilter, domainFilter,
|
||||
&cert_list, &count);
|
||||
NCryptFreeObject((NCRYPT_HANDLE)provider);
|
||||
if (!status)
|
||||
{
|
||||
WLog_ERR(TAG, "error listing keys from CSP loaded from %s", Pkcs11Module);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NCryptProviderName* names = nullptr;
|
||||
DWORD nproviders = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* On Windows, mstsc first enumerates the legacy CAPI providers for usable certificates. */
|
||||
DWORD provType, cbProvName = 0;
|
||||
for (DWORD i = 0; CryptEnumProvidersW(i, nullptr, 0, &provType, nullptr, &cbProvName); ++i)
|
||||
{
|
||||
char providerNameStr[256] = WINPR_C_ARRAY_INIT;
|
||||
LPWSTR szProvName = malloc(cbProvName * sizeof(WCHAR));
|
||||
if (!CryptEnumProvidersW(i, nullptr, 0, &provType, szProvName, &cbProvName))
|
||||
{
|
||||
free(szProvName);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ConvertWCharToUtf8(szProvName, providerNameStr, ARRAYSIZE(providerNameStr)) < 0)
|
||||
{
|
||||
_snprintf(providerNameStr, sizeof(providerNameStr), "<unknown>");
|
||||
WLog_ERR(TAG, "unable to convert provider name to char*, will show it as '%s'",
|
||||
providerNameStr);
|
||||
}
|
||||
|
||||
WLog_DBG(TAG, "exploring CSP '%s'", providerNameStr);
|
||||
if (provType != PROV_RSA_FULL || (csp && _wcscmp(szProvName, csp) != 0))
|
||||
{
|
||||
WLog_DBG(TAG, "CSP '%s' filtered out", providerNameStr);
|
||||
goto end_of_loop;
|
||||
}
|
||||
|
||||
if (!list_capi_provider_keys(settings, szProvName, scope, userFilter, domainFilter,
|
||||
&cert_list, &count))
|
||||
WLog_INFO(TAG, "error when retrieving keys in CSP '%s'", providerNameStr);
|
||||
|
||||
end_of_loop:
|
||||
free(szProvName);
|
||||
}
|
||||
#endif
|
||||
|
||||
status = NCryptEnumStorageProviders(&nproviders, &names, NCRYPT_SILENT_FLAG);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_ERR(TAG, "error listing providers");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (DWORD i = 0; i < nproviders; i++)
|
||||
{
|
||||
char providerNameStr[256] = WINPR_C_ARRAY_INIT;
|
||||
const NCryptProviderName* name = &names[i];
|
||||
|
||||
if (ConvertWCharToUtf8(name->pszName, providerNameStr, ARRAYSIZE(providerNameStr)) < 0)
|
||||
{
|
||||
(void)_snprintf(providerNameStr, sizeof(providerNameStr), "<unknown>");
|
||||
WLog_ERR(TAG, "unable to convert provider name to char*, will show it as '%s'",
|
||||
providerNameStr);
|
||||
}
|
||||
|
||||
WLog_DBG(TAG, "exploring CSP '%s'", providerNameStr);
|
||||
if (csp && _wcscmp(name->pszName, csp) != 0)
|
||||
{
|
||||
WLog_DBG(TAG, "CSP '%s' filtered out", providerNameStr);
|
||||
continue;
|
||||
}
|
||||
|
||||
status = NCryptOpenStorageProvider(&provider, name->pszName, 0);
|
||||
if (status != ERROR_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (!list_provider_keys(settings, provider, name->pszName, scope, userFilter,
|
||||
domainFilter, &cert_list, &count))
|
||||
WLog_INFO(TAG, "error when retrieving keys in CSP '%s'", providerNameStr);
|
||||
|
||||
NCryptFreeObject((NCRYPT_HANDLE)provider);
|
||||
}
|
||||
|
||||
NCryptFreeBuffer(names);
|
||||
}
|
||||
|
||||
*scCerts = cert_list;
|
||||
*retCount = count;
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
if (!ret)
|
||||
smartcardCertList_Free(cert_list, count);
|
||||
free(scope);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char* create_temporary_file(void)
|
||||
{
|
||||
BYTE buffer[32] = WINPR_C_ARRAY_INIT;
|
||||
char* path = nullptr;
|
||||
|
||||
if (winpr_RAND(buffer, sizeof(buffer)) < 0)
|
||||
return nullptr;
|
||||
|
||||
char* hex = winpr_BinToHexString(buffer, sizeof(buffer), FALSE);
|
||||
if (hex)
|
||||
path = GetKnownSubPath(KNOWN_PATH_TEMP, hex);
|
||||
free(hex);
|
||||
return path;
|
||||
}
|
||||
|
||||
static SmartcardCertInfo* smartcardCertInfo_New(const char* privKeyPEM, const char* certPEM)
|
||||
{
|
||||
size_t size = 0;
|
||||
|
||||
WINPR_ASSERT(privKeyPEM);
|
||||
WINPR_ASSERT(certPEM);
|
||||
|
||||
SmartcardCertInfo* cert = calloc(1, sizeof(SmartcardCertInfo));
|
||||
if (!cert)
|
||||
goto fail;
|
||||
|
||||
{
|
||||
SmartcardKeyInfo* info = cert->key_info = calloc(1, sizeof(SmartcardKeyInfo));
|
||||
if (!info)
|
||||
goto fail;
|
||||
|
||||
cert->certificate = freerdp_certificate_new_from_pem(certPEM);
|
||||
if (!cert->certificate)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to read smartcard certificate");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!treat_sc_cert(cert))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to treat smartcard certificate");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
{
|
||||
char* str = nullptr;
|
||||
size_t len = 0;
|
||||
(void)winpr_asprintf(&str, &len, "%s Emulator", freerdp_getApplicationDetailsString());
|
||||
if (str)
|
||||
cert->reader = ConvertUtf8NToWCharAlloc(str, len, nullptr);
|
||||
free(str);
|
||||
}
|
||||
if (!cert->reader)
|
||||
goto fail;
|
||||
|
||||
cert->containerName = ConvertUtf8ToWCharAlloc("Private Key 00", nullptr);
|
||||
if (!cert->containerName)
|
||||
goto fail;
|
||||
|
||||
/* compute PKINIT args FILE:<cert file>,<key file>
|
||||
*
|
||||
* We need files for PKINIT to read, so write the certificate to some
|
||||
* temporary location and use that.
|
||||
*/
|
||||
info->keyPath = create_temporary_file();
|
||||
WLog_DBG(TAG, "writing PKINIT key to %s", info->keyPath);
|
||||
if (!crypto_write_pem(info->keyPath, privKeyPEM, strlen(privKeyPEM)))
|
||||
goto fail;
|
||||
|
||||
info->certPath = create_temporary_file();
|
||||
WLog_DBG(TAG, "writing PKINIT cert to %s", info->certPath);
|
||||
if (!crypto_write_pem(info->certPath, certPEM, strlen(certPEM)))
|
||||
goto fail;
|
||||
|
||||
{
|
||||
const int res = winpr_asprintf(&cert->pkinitArgs, &size, "FILE:%s,%s", info->certPath,
|
||||
info->keyPath);
|
||||
if (res <= 0)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return cert;
|
||||
fail:
|
||||
smartcardCertInfo_Free(cert);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static BOOL smartcard_sw_enumerateCerts(const rdpSettings* settings, SmartcardCertInfo*** scCerts,
|
||||
size_t* retCount)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
SmartcardCertInfo** cert_list = nullptr;
|
||||
|
||||
WINPR_ASSERT(settings);
|
||||
WINPR_ASSERT(scCerts);
|
||||
WINPR_ASSERT(retCount);
|
||||
|
||||
const char* privKeyPEM = freerdp_settings_get_string(settings, FreeRDP_SmartcardPrivateKey);
|
||||
const char* certPEM = freerdp_settings_get_string(settings, FreeRDP_SmartcardCertificate);
|
||||
if (!privKeyPEM)
|
||||
{
|
||||
WLog_ERR(TAG, "Invalid smartcard private key PEM, aborting");
|
||||
goto out_error;
|
||||
}
|
||||
if (!certPEM)
|
||||
{
|
||||
WLog_ERR(TAG, "Invalid smartcard certificate PEM, aborting");
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
cert_list = (SmartcardCertInfo**)calloc(1, sizeof(SmartcardCertInfo*));
|
||||
if (!cert_list)
|
||||
goto out_error;
|
||||
|
||||
{
|
||||
SmartcardCertInfo* cert = smartcardCertInfo_New(privKeyPEM, certPEM);
|
||||
if (!cert)
|
||||
goto out_error;
|
||||
cert_list[0] = cert;
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
*scCerts = cert_list;
|
||||
*retCount = 1;
|
||||
|
||||
out_error:
|
||||
if (!rc)
|
||||
smartcardCertList_Free(cert_list, 1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL smartcard_enumerateCerts(const rdpSettings* settings, SmartcardCertInfo*** scCerts,
|
||||
size_t* retCount, BOOL gateway)
|
||||
{
|
||||
BOOL ret = 0;
|
||||
LPWSTR csp = nullptr;
|
||||
const char* ReaderName = freerdp_settings_get_string(settings, FreeRDP_ReaderName);
|
||||
const char* CspName = freerdp_settings_get_string(settings, FreeRDP_CspName);
|
||||
const char* Username = nullptr;
|
||||
const char* Domain = nullptr;
|
||||
|
||||
if (gateway)
|
||||
{
|
||||
Username = freerdp_settings_get_string(settings, FreeRDP_GatewayUsername);
|
||||
Domain = freerdp_settings_get_string(settings, FreeRDP_GatewayDomain);
|
||||
}
|
||||
else
|
||||
{
|
||||
Username = freerdp_settings_get_string(settings, FreeRDP_Username);
|
||||
Domain = freerdp_settings_get_string(settings, FreeRDP_Domain);
|
||||
}
|
||||
|
||||
WINPR_ASSERT(settings);
|
||||
WINPR_ASSERT(scCerts);
|
||||
WINPR_ASSERT(retCount);
|
||||
|
||||
if (Domain && !strlen(Domain))
|
||||
Domain = nullptr;
|
||||
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_SmartcardEmulation))
|
||||
return smartcard_sw_enumerateCerts(settings, scCerts, retCount);
|
||||
|
||||
if (CspName && (!(csp = ConvertUtf8ToWCharAlloc(CspName, nullptr))))
|
||||
{
|
||||
WLog_ERR(TAG, "error while converting CSP to WCHAR");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret =
|
||||
smartcard_hw_enumerateCerts(settings, csp, ReaderName, Username, Domain, scCerts, retCount);
|
||||
free(csp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL set_settings_from_smartcard(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
|
||||
const char* value)
|
||||
{
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
if (!freerdp_settings_get_string(settings, id) && value)
|
||||
if (!freerdp_settings_set_string(settings, id, value))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL smartcard_getCert(const rdpContext* context, SmartcardCertInfo** cert, BOOL gateway)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
const freerdp* instance = context->instance;
|
||||
rdpSettings* settings = context->settings;
|
||||
SmartcardCertInfo** cert_list = nullptr;
|
||||
size_t count = 0;
|
||||
|
||||
WINPR_ASSERT(instance);
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
if (!smartcard_enumerateCerts(settings, &cert_list, &count, gateway))
|
||||
return FALSE;
|
||||
|
||||
if (count < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "no suitable smartcard certificates were found");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (count > UINT32_MAX)
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard certificate count %" PRIuz " exceeds UINT32_MAX", count);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (count > 1)
|
||||
{
|
||||
DWORD index = 0;
|
||||
|
||||
if (!instance->ChooseSmartcard ||
|
||||
!instance->ChooseSmartcard(context->instance, cert_list, (UINT32)count, &index,
|
||||
gateway))
|
||||
{
|
||||
WLog_ERR(TAG, "more than one suitable smartcard certificate was found");
|
||||
smartcardCertList_Free(cert_list, count);
|
||||
return FALSE;
|
||||
}
|
||||
*cert = cert_list[index];
|
||||
|
||||
for (DWORD i = 0; i < index; i++)
|
||||
smartcardCertInfo_Free(cert_list[i]);
|
||||
for (DWORD i = index + 1; i < count; i++)
|
||||
smartcardCertInfo_Free(cert_list[i]);
|
||||
}
|
||||
else
|
||||
*cert = cert_list[0];
|
||||
|
||||
FreeRDP_Settings_Keys_String username_setting =
|
||||
gateway ? FreeRDP_GatewayUsername : FreeRDP_Username;
|
||||
FreeRDP_Settings_Keys_String domain_setting = gateway ? FreeRDP_GatewayDomain : FreeRDP_Domain;
|
||||
|
||||
free((void*)cert_list);
|
||||
|
||||
if (!set_settings_from_smartcard(settings, username_setting, (*cert)->userHint) ||
|
||||
!set_settings_from_smartcard(settings, domain_setting, (*cert)->domainHint))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to set settings from smartcard!");
|
||||
smartcardCertInfo_Free(*cert);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user