static void* drdynvc_server_thread(void* arg) { #if 0 wStream* s; DWORD status; DWORD nCount; void* buffer; HANDLE events[8]; HANDLE ChannelEvent; DWORD BytesReturned; DrdynvcServerContext* context; UINT error = ERROR_INTERNAL_ERROR; context = (DrdynvcServerContext*) arg; buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; s = Stream_New(NULL, 4096); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); ExitThread((DWORD) CHANNEL_RC_NO_MEMORY); return NULL; } if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); } nCount = 0; events[nCount++] = ChannelEvent; events[nCount++] = context->priv->StopEvent; while (1) { status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) { error = CHANNEL_RC_OK; break; } if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); break; } if (BytesReturned < 1) continue; if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); break; } if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); break; } } Stream_Free(s, TRUE); ExitThread((DWORD) error); #endif // WTF ... this code only reads data into the stream until there is no more memory ExitThread(0); return NULL; }
static void* remdesk_server_thread(void* arg) { wStream* s; DWORD status; DWORD nCount; void* buffer; UINT32* pHeader; UINT32 PduLength; HANDLE events[8]; HANDLE ChannelEvent; DWORD BytesReturned; RemdeskServerContext* context; UINT error; context = (RemdeskServerContext*) arg; freerdp_channel_init_thread_context(context->rdpcontext); buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; s = Stream_New(NULL, 4096); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); error = CHANNEL_RC_NO_MEMORY; goto out; } if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); } else { WLog_ERR(TAG, "WTSVirtualChannelQuery failed!"); error = ERROR_INTERNAL_ERROR; goto out; } nCount = 0; events[nCount++] = ChannelEvent; events[nCount++] = context->priv->StopEvent; if ((error = remdesk_send_ctl_version_info_pdu(context))) { WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %lu!", error); goto out; } while (1) { status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error); break; } status = WaitForSingleObject(context->priv->StopEvent, 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error); break; } if (status == WAIT_OBJECT_0) { break; } if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { if (BytesReturned) Stream_Seek(s, BytesReturned); } else { if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); error = CHANNEL_RC_NO_MEMORY; break; } } if (Stream_GetPosition(s) >= 8) { pHeader = (UINT32*) Stream_Buffer(s); PduLength = pHeader[0] + pHeader[1] + 8; if (PduLength >= Stream_GetPosition(s)) { Stream_SealLength(s); Stream_SetPosition(s, 0); if ((error = remdesk_server_receive_pdu(context, s))) { WLog_ERR(TAG, "remdesk_server_receive_pdu failed with error %lu!", error); break; } Stream_SetPosition(s, 0); } } } Stream_Free(s, TRUE); out: if (error && context->rdpcontext) setChannelError(context->rdpcontext, error, "remdesk_server_thread reported an error"); ExitThread((DWORD)error); return NULL; }
DWORD TsProxySendToServer(handle_t IDL_handle, byte pRpcMessage[], UINT32 count, UINT32* lengths) { wStream* s; int status; rdpTsg* tsg; BYTE* buffer; UINT32 length; byte* buffer1 = NULL; byte* buffer2 = NULL; byte* buffer3 = NULL; UINT32 buffer1Length; UINT32 buffer2Length; UINT32 buffer3Length; UINT32 numBuffers = 0; UINT32 totalDataBytes = 0; tsg = (rdpTsg*) IDL_handle; buffer1Length = buffer2Length = buffer3Length = 0; if (count > 0) { numBuffers++; buffer1 = &pRpcMessage[0]; buffer1Length = lengths[0]; totalDataBytes += lengths[0] + 4; } if (count > 1) { numBuffers++; buffer2 = &pRpcMessage[1]; buffer2Length = lengths[1]; totalDataBytes += lengths[1] + 4; } if (count > 2) { numBuffers++; buffer3 = &pRpcMessage[2]; buffer3Length = lengths[2]; totalDataBytes += lengths[2] + 4; } length = 28 + totalDataBytes; buffer = (BYTE*) malloc(length); s = Stream_New(buffer, length); /* PCHANNEL_CONTEXT_HANDLE_NOSERIALIZE_NR (20 bytes) */ Stream_Write(s, &tsg->ChannelContext.ContextType, 4); /* ContextType (4 bytes) */ Stream_Write(s, tsg->ChannelContext.ContextUuid, 16); /* ContextUuid (16 bytes) */ Stream_Write_UINT32_BE(s, totalDataBytes); /* totalDataBytes (4 bytes) */ Stream_Write_UINT32_BE(s, numBuffers); /* numBuffers (4 bytes) */ if (buffer1Length > 0) Stream_Write_UINT32_BE(s, buffer1Length); /* buffer1Length (4 bytes) */ if (buffer2Length > 0) Stream_Write_UINT32_BE(s, buffer2Length); /* buffer2Length (4 bytes) */ if (buffer3Length > 0) Stream_Write_UINT32_BE(s, buffer3Length); /* buffer3Length (4 bytes) */ if (buffer1Length > 0) Stream_Write(s, buffer1, buffer1Length); /* buffer1 (variable) */ if (buffer2Length > 0) Stream_Write(s, buffer2, buffer2Length); /* buffer2 (variable) */ if (buffer3Length > 0) Stream_Write(s, buffer3, buffer3Length); /* buffer3 (variable) */ Stream_Length(s) = Stream_GetPosition(s); status = rpc_write(tsg->rpc, Stream_Buffer(s), Stream_Length(s), TsProxySendToServerOpnum); Stream_Free(s, TRUE); if (status <= 0) { fprintf(stderr, "rpc_write failed!\n"); return -1; } return length; }
BOOL nego_send_negotiation_request(rdpNego* nego) { wStream* s; int length; int bm, em; int cookie_length; s = Stream_New(NULL, 512); length = TPDU_CONNECTION_REQUEST_LENGTH; bm = Stream_GetPosition(s); Stream_Seek(s, length); if (nego->RoutingToken) { Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength); Stream_Write_UINT8(s, 0x0D); /* CR */ Stream_Write_UINT8(s, 0x0A); /* LF */ length += nego->RoutingTokenLength + 2; } else if (nego->cookie) { cookie_length = strlen(nego->cookie); if (cookie_length > (int) nego->cookie_max_length) cookie_length = nego->cookie_max_length; Stream_Write(s, "Cookie: mstshash=", 17); Stream_Write(s, (BYTE*) nego->cookie, cookie_length); Stream_Write_UINT8(s, 0x0D); /* CR */ Stream_Write_UINT8(s, 0x0A); /* LF */ length += cookie_length + 19; } DEBUG_NEGO("requested_protocols: %d", nego->requested_protocols); if ((nego->requested_protocols > PROTOCOL_RDP) || (nego->sendNegoData)) { /* RDP_NEG_DATA must be present for TLS and NLA */ Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ); Stream_Write_UINT8(s, 0); /* flags, must be set to zero */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ Stream_Write_UINT32(s, nego->requested_protocols); /* requestedProtocols */ length += 8; } em = Stream_GetPosition(s); Stream_SetPosition(s, bm); tpkt_write_header(s, length); tpdu_write_connection_request(s, length - 5); Stream_SetPosition(s, em); Stream_SealLength(s); if (transport_write(nego->transport, s) < 0) { Stream_Free(s, TRUE); return FALSE; } Stream_Free(s, TRUE); return TRUE; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors) { UINT status; wStream* s; UINT32 type; UINT32 index; UINT32 length; DISP_PLUGIN* disp; UINT32 MonitorLayoutSize; disp = (DISP_PLUGIN*) callback->plugin; MonitorLayoutSize = 40; length = 8 + 8 + (NumMonitors * MonitorLayoutSize); type = DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT; s = Stream_New(NULL, length); if(!s) { WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT32(s, type); /* Type (4 bytes) */ Stream_Write_UINT32(s, length); /* Length (4 bytes) */ if (NumMonitors > disp->MaxNumMonitors) NumMonitors = disp->MaxNumMonitors; Stream_Write_UINT32(s, MonitorLayoutSize); /* MonitorLayoutSize (4 bytes) */ Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */ //WLog_ERR(TAG, "NumMonitors: %d", NumMonitors); for (index = 0; index < NumMonitors; index++) { Monitors[index].Width -= (Monitors[index].Width % 2); if (Monitors[index].Width < 200) Monitors[index].Width = 200; if (Monitors[index].Width > 8192) Monitors[index].Width = 8192; if (Monitors[index].Width % 2) Monitors[index].Width++; if (Monitors[index].Height < 200) Monitors[index].Height = 200; if (Monitors[index].Height > 8192) Monitors[index].Height = 8192; Stream_Write_UINT32(s, Monitors[index].Flags); /* Flags (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].Left); /* Left (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].Top); /* Top (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].Width); /* Width (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].Height); /* Height (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].PhysicalWidth); /* PhysicalWidth (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].PhysicalHeight); /* PhysicalHeight (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].Orientation); /* Orientation (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */ #if 0 WLog_DBG(TAG, "\t: Flags: 0x%04X", Monitors[index].Flags); WLog_DBG(TAG, "\t: Left: %d", Monitors[index].Left); WLog_DBG(TAG, "\t: Top: %d", Monitors[index].Top); WLog_DBG(TAG, "\t: Width: %d", Monitors[index].Width); WLog_DBG(TAG, "\t: Height: %d", Monitors[index].Height); WLog_DBG(TAG, "\t: PhysicalWidth: %d", Monitors[index].PhysicalWidth); WLog_DBG(TAG, "\t: PhysicalHeight: %d", Monitors[index].PhysicalHeight); WLog_DBG(TAG, "\t: Orientation: %d", Monitors[index].Orientation); #endif } Stream_SealLength(s); status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); Stream_Free(s, TRUE); return status; }
BOOL nego_send_negotiation_response(rdpNego* nego) { int length; int bm, em; BOOL status; wStream* s; BYTE flags; rdpSettings* settings; status = TRUE; settings = nego->transport->settings; s = Stream_New(NULL, 512); if (!s) return FALSE; length = TPDU_CONNECTION_CONFIRM_LENGTH; bm = Stream_GetPosition(s); Stream_Seek(s, length); if ((nego->selected_protocol == PROTOCOL_RDP) && !settings->RdpSecurity) { flags = 0; Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE); Stream_Write_UINT8(s, flags); /* flags */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ /* * TODO: Check for other possibilities, * like SSL_NOT_ALLOWED_BY_SERVER. */ WLog_ERR(TAG, "client supports only Standard RDP Security"); Stream_Write_UINT32(s, SSL_REQUIRED_BY_SERVER); length += 8; status = FALSE; } else { flags = EXTENDED_CLIENT_DATA_SUPPORTED; if (settings->SupportGraphicsPipeline) flags |= DYNVC_GFX_PROTOCOL_SUPPORTED; /* RDP_NEG_DATA must be present for TLS, NLA, and RDP */ Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP); Stream_Write_UINT8(s, flags); /* flags */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ Stream_Write_UINT32(s, nego->selected_protocol); /* selectedProtocol */ length += 8; } em = Stream_GetPosition(s); Stream_SetPosition(s, bm); tpkt_write_header(s, length); tpdu_write_connection_confirm(s, length - 5); Stream_SetPosition(s, em); Stream_SealLength(s); if (transport_write(nego->transport, s) < 0) { Stream_Free(s, TRUE); return FALSE; } Stream_Free(s, TRUE); if (status) { /* update settings with negotiated protocol security */ settings->RequestedProtocols = nego->requested_protocols; settings->SelectedProtocol = nego->selected_protocol; if (settings->SelectedProtocol == PROTOCOL_RDP) { settings->TlsSecurity = FALSE; settings->NlaSecurity = FALSE; settings->RdpSecurity = TRUE; settings->UseRdpSecurityLayer = TRUE; if (settings->EncryptionLevel == ENCRYPTION_LEVEL_NONE) { /** * If the server implementation did not explicitely set a * encryption level we default to client compatible */ settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; } if (settings->LocalConnection) { /** * Note: This hack was firstly introduced in commit 95f5e115 to * disable the unnecessary encryption with peers connecting to * 127.0.0.1 or local unix sockets. * This also affects connections via port tunnels! (e.g. ssh -L) */ WLog_INFO(TAG, "Turning off encryption for local peer with standard rdp security"); settings->UseRdpSecurityLayer = FALSE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } if (!settings->RdpServerRsaKey && !settings->RdpKeyFile) { WLog_ERR(TAG, "Missing server certificate"); return FALSE; } } else if (settings->SelectedProtocol == PROTOCOL_TLS) { settings->TlsSecurity = TRUE; settings->NlaSecurity = FALSE; settings->RdpSecurity = FALSE; settings->UseRdpSecurityLayer = FALSE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } else if (settings->SelectedProtocol == PROTOCOL_NLA) { settings->TlsSecurity = TRUE; settings->NlaSecurity = TRUE; settings->RdpSecurity = FALSE; settings->UseRdpSecurityLayer = FALSE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } } return status; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { unsigned long pos; UINT status; UINT32 ChannelId; wStream* data_out; UINT channel_status; if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES) { /** * For some reason the server does not always send the * capabilities pdu as it should. When this happens, * send a capabilities response. */ drdynvc->version = 3; if ((status = drdynvc_send_capability_response(drdynvc))) { WLog_ERR(TAG, "drdynvc_send_capability_response failed!"); return status; } drdynvc->state = DRDYNVC_STATE_READY; } ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = Stream_GetPosition(s); WLog_DBG(TAG, "process_create_request: ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s)); channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s)); data_out = Stream_New(NULL, pos + 4); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT8(data_out, 0x10 | cbChId); Stream_SetPosition(s, 1); Stream_Copy(s, data_out, pos - 1); if (channel_status == CHANNEL_RC_OK) { WLog_DBG(TAG, "channel created"); Stream_Write_UINT32(data_out, 0); } else { WLog_DBG(TAG, "no listener"); Stream_Write_UINT32(data_out, (UINT32) 0xC0000001); /* same code used by mstsc */ } status = drdynvc_send(drdynvc, data_out); if (status != CHANNEL_RC_OK) { WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]", WTSErrorToString(status), status); return status; } if (channel_status == CHANNEL_RC_OK) { if ((status = dvcman_open_channel(drdynvc->channel_mgr, ChannelId))) { WLog_ERR(TAG, "dvcman_open_channel failed with error %lu!", status); return status; } } else { if ((status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId))) WLog_ERR(TAG, "dvcman_close_channel failed with error %lu!", status); } return status; }
RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, BYTE* data, UINT32 length) { int pos; UINT32 blockLen; UINT32 blockType; RFX_MESSAGE* message = NULL; wStream* s = NULL; BOOL ok = TRUE; UINT16 expectedDataBlockType = WBT_FRAME_BEGIN; if (!context || !data || !length) goto fail; if (!(s = Stream_New(data, length))) goto fail; if (!(message = (RFX_MESSAGE*) calloc(1, sizeof(RFX_MESSAGE)))) goto fail; message->freeRects = TRUE; while (ok && Stream_GetRemainingLength(s) > 6) { /* RFX_BLOCKT */ Stream_Read_UINT16(s, blockType); /* blockType (2 bytes) */ Stream_Read_UINT32(s, blockLen); /* blockLen (4 bytes) */ WLog_Print(context->priv->log, WLOG_DEBUG, "blockType 0x%X blockLen %d", blockType, blockLen); if (blockLen == 0) { WLog_ERR(TAG, "zero blockLen"); goto fail; } if (Stream_GetRemainingLength(s) < blockLen - 6) { WLog_ERR(TAG, "%s: packet too small for blocklen=%d", __FUNCTION__, blockLen); goto fail; } pos = Stream_GetPosition(s) - 6 + blockLen; if (blockType > WBT_CONTEXT && context->decodedHeaderBlocks != _RFX_DECODED_HEADERS) { WLog_ERR(TAG, "%s: incomplete header blocks processing", __FUNCTION__); goto fail; } if (blockType >= WBT_CONTEXT && blockType <= WBT_EXTENSION) { /* RFX_CODEC_CHANNELT */ UINT8 codecId; UINT8 channelId; if (Stream_GetRemainingLength(s) < 2) goto fail; Stream_Read_UINT8(s, codecId); /* codecId (1 byte) must be set to 0x01 */ Stream_Read_UINT8(s, channelId); /* channelId (1 byte) 0xFF or 0x00, see below */ if (codecId != 0x01) { WLog_ERR(TAG, "%s: invalid codecId 0x%02X", __FUNCTION__, codecId); goto fail; } if (blockType == WBT_CONTEXT) { /* If the blockType is set to WBT_CONTEXT, then channelId MUST be set to 0xFF.*/ if (channelId != 0xFF) { WLog_ERR(TAG, "%s: invalid channelId 0x%02X for blockType 0x%04X", __FUNCTION__, channelId, blockType); goto fail; } } else { /* For all other values of blockType, channelId MUST be set to 0x00. */ if (channelId != 0x00) { WLog_ERR(TAG, "%s: invalid channelId 0x%02X for blockType WBT_CONTEXT", __FUNCTION__, channelId); goto fail; } } } switch (blockType) { /* Header messages: * The stream MUST start with the header messages and any of these headers can appear * in the stream at a later stage. The header messages can be repeated. */ case WBT_SYNC: ok = rfx_process_message_sync(context, s); break; case WBT_CONTEXT: ok = rfx_process_message_context(context, s); break; case WBT_CODEC_VERSIONS: ok = rfx_process_message_codec_versions(context, s); break; case WBT_CHANNELS: ok = rfx_process_message_channels(context, s); break; /* Data messages: * The data associated with each encoded frame or image is always bracketed by the * TS_RFX_FRAME_BEGIN (section 2.2.2.3.1) and TS_RFX_FRAME_END (section 2.2.2.3.2) messages. * There MUST only be one TS_RFX_REGION (section 2.2.2.3.3) message per frame and one TS_RFX_TILESET * (section 2.2.2.3.4) message per TS_RFX_REGION. */ case WBT_FRAME_BEGIN: ok = rfx_process_message_frame_begin(context, message, s, &expectedDataBlockType); break; case WBT_REGION: ok = rfx_process_message_region(context, message, s, &expectedDataBlockType); break; case WBT_EXTENSION: ok = rfx_process_message_tileset(context, message, s, &expectedDataBlockType); break; case WBT_FRAME_END: ok = rfx_process_message_frame_end(context, message, s, &expectedDataBlockType); break; default: WLog_ERR(TAG, "%s: unknown blockType 0x%X", __FUNCTION__, blockType); goto fail; } Stream_SetPosition(s, pos); } if (ok) { Stream_Free(s, FALSE); return message; } fail: Stream_Free(s, FALSE); rfx_message_free(context, message); return NULL; }
static void* remdesk_server_thread(void* arg) { wStream* s; DWORD status; DWORD nCount; void* buffer; HANDLE events[8]; HANDLE ChannelEvent; DWORD BytesReturned; RemdeskServerContext* context; context = (RemdeskServerContext*) arg; buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; s = Stream_New(NULL, 4096); if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); } nCount = 0; events[nCount++] = ChannelEvent; events[nCount++] = context->priv->StopEvent; while (1) { status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) { break; } if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { if (BytesReturned) Stream_Seek(s, BytesReturned); } else { Stream_EnsureRemainingCapacity(s, BytesReturned); } if (0) { remdesk_server_receive_pdu(context, s); } } Stream_Free(s, TRUE); return NULL; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) { UINT error; wStream* s; UINT16 index; RDPGFX_PLUGIN* gfx; RDPGFX_HEADER header; RDPGFX_CAPSET* capsSet; RDPGFX_CAPSET capsSets[2]; RDPGFX_CAPS_ADVERTISE_PDU pdu; gfx = (RDPGFX_PLUGIN*) callback->plugin; header.flags = 0; header.cmdId = RDPGFX_CMDID_CAPSADVERTISE; pdu.capsSetCount = 0; pdu.capsSets = (RDPGFX_CAPSET*) capsSets; capsSet = &capsSets[pdu.capsSetCount++]; capsSet->version = RDPGFX_CAPVERSION_8; capsSet->flags = 0; if (gfx->ThinClient) capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; if (gfx->SmallCache) capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; capsSet = &capsSets[pdu.capsSetCount++]; capsSet->version = RDPGFX_CAPVERSION_81; capsSet->flags = 0; if (gfx->ThinClient) capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; if (gfx->SmallCache) capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; if (gfx->H264) capsSet->flags |= RDPGFX_CAPS_FLAG_H264ENABLED; header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE); WLog_DBG(TAG, "SendCapsAdvertisePdu"); s = Stream_New(NULL, header.pduLength); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } if ((error = rdpgfx_write_header(s, &header))) { WLog_ERR(TAG, "rdpgfx_write_header failed with error %lu!", error); return error; } /* RDPGFX_CAPS_ADVERTISE_PDU */ Stream_Write_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */ for (index = 0; index < pdu.capsSetCount; index++) { capsSet = &(pdu.capsSets[index]); Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */ Stream_Write_UINT32(s, 4); /* capsDataLength (4 bytes) */ Stream_Write_UINT32(s, capsSet->flags); /* capsData (4 bytes) */ } Stream_SealLength(s); error = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); Stream_Free(s, TRUE); return error; }
static PresentationContext *PresentationContext_new(VideoClientContext *video, BYTE PresentationId, UINT32 x, UINT32 y, UINT32 width, UINT32 height) { VideoClientContextPriv *priv = video->priv; PresentationContext *ret = calloc(1, sizeof(*ret)); if (!ret) return NULL; ret->video = video; ret->PresentationId = PresentationId; ret->h264 = h264_context_new(FALSE); if (!ret->h264) { WLog_ERR(TAG, "unable to create a h264 context"); goto error_h264; } h264_context_reset(ret->h264, width, height); ret->currentSample = Stream_New(NULL, 4096); if (!ret->currentSample) { WLog_ERR(TAG, "unable to create current packet stream"); goto error_currentSample; } ret->surfaceData = BufferPool_Take(priv->surfacePool, width * height * 4); if (!ret->surfaceData) { WLog_ERR(TAG, "unable to allocate surfaceData"); goto error_surfaceData; } ret->surface = video->createSurface(video, ret->surfaceData, x, y, width, height); if (!ret->surface) { WLog_ERR(TAG, "unable to create surface"); goto error_surface; } ret->yuv = yuv_context_new(FALSE); if (!ret->yuv) { WLog_ERR(TAG, "unable to create YUV decoder"); goto error_yuv; } yuv_context_reset(ret->yuv, width, height); ret->refCounter = 1; return ret; error_yuv: video->deleteSurface(video, ret->surface); error_surface: BufferPool_Return(priv->surfacePool, ret->surfaceData); error_surfaceData: Stream_Free(ret->currentSample, TRUE); error_currentSample: h264_context_free(ret->h264); error_h264: free(ret); return NULL; }
BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) { wStream* s; int length; BYTE padding; UINT32 version; int modulus_length; int exponent_length; int error = 0; s = Stream_New(cert->data, cert->length); if (!s) return FALSE; info->Modulus = 0; if (!ber_read_sequence_tag(s, &length)) /* Certificate (SEQUENCE) */ goto error1; error++; if (!ber_read_sequence_tag(s, &length)) /* TBSCertificate (SEQUENCE) */ goto error1; error++; if (!ber_read_contextual_tag(s, 0, &length, TRUE)) /* Explicit Contextual Tag [0] */ goto error1; error++; if (!ber_read_integer(s, &version)) /* version (INTEGER) */ goto error1; error++; version++; /* serialNumber */ if (!ber_read_integer(s, NULL)) /* CertificateSerialNumber (INTEGER) */ goto error1; error++; /* signature */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ goto error1; error++; /* issuer */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */ goto error1; error++; /* validity */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Validity (SEQUENCE) */ goto error1; error++; /* subject */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */ goto error1; error++; /* subjectPublicKeyInfo */ if (!ber_read_sequence_tag(s, &length)) /* SubjectPublicKeyInfo (SEQUENCE) */ goto error1; error++; /* subjectPublicKeyInfo::AlgorithmIdentifier */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ goto error1; error++; /* subjectPublicKeyInfo::subjectPublicKey */ if (!ber_read_bit_string(s, &length, &padding)) /* BIT_STRING */ goto error1; error++; /* RSAPublicKey (SEQUENCE) */ if (!ber_read_sequence_tag(s, &length)) /* SEQUENCE */ goto error1; error++; if (!ber_read_integer_length(s, &modulus_length)) /* modulus (INTEGER) */ goto error1; error++; /* skip zero padding, if any */ do { if (Stream_GetRemainingLength(s) < 1) goto error1; Stream_Peek_UINT8(s, padding); if (padding == 0) { if (!Stream_SafeSeek(s, 1)) goto error1; modulus_length--; } } while (padding == 0); error++; if (((int) Stream_GetRemainingLength(s)) < modulus_length) goto error1; info->ModulusLength = modulus_length; info->Modulus = (BYTE*) malloc(info->ModulusLength); if (!info->Modulus) goto error1; Stream_Read(s, info->Modulus, info->ModulusLength); error++; if (!ber_read_integer_length(s, &exponent_length)) /* publicExponent (INTEGER) */ goto error2; error++; if ((((int) Stream_GetRemainingLength(s)) < exponent_length) || (exponent_length > 4)) goto error2; Stream_Read(s, &info->exponent[4 - exponent_length], exponent_length); crypto_reverse(info->Modulus, info->ModulusLength); crypto_reverse(info->exponent, 4); Stream_Free(s, FALSE); return TRUE; error2: free(info->Modulus); info->Modulus = 0; error1: fprintf(stderr, "error reading when reading certificate: part=%s error=%d\n", certificate_read_errors[error], error); Stream_Free(s, FALSE); return FALSE; }
int credssp_recv(rdpCredssp* credssp) { wStream* s; int length; int status; UINT32 version; s = Stream_New(NULL, 4096); status = transport_read(credssp->transport, s); Stream_Length(s) = status; if (status < 0) { fprintf(stderr, "credssp_recv() error: %d\n", status); Stream_Free(s, TRUE); return -1; } /* TSRequest */ if(!ber_read_sequence_tag(s, &length) || !ber_read_contextual_tag(s, 0, &length, TRUE) || !ber_read_integer(s, &version)) return -1; /* [1] negoTokens (NegoData) */ if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE) { if (!ber_read_sequence_tag(s, &length) || /* SEQUENCE OF NegoDataItem */ !ber_read_sequence_tag(s, &length) || /* NegoDataItem */ !ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */ !ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ Stream_GetRemainingLength(s) < length) return -1; sspi_SecBufferAlloc(&credssp->negoToken, length); Stream_Read(s, credssp->negoToken.pvBuffer, length); credssp->negoToken.cbBuffer = length; } /* [2] authInfo (OCTET STRING) */ if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE) { if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ Stream_GetRemainingLength(s) < length) return -1; sspi_SecBufferAlloc(&credssp->authInfo, length); Stream_Read(s, credssp->authInfo.pvBuffer, length); credssp->authInfo.cbBuffer = length; } /* [3] pubKeyAuth (OCTET STRING) */ if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE) { if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ Stream_GetRemainingLength(s) < length) return -1; sspi_SecBufferAlloc(&credssp->pubKeyAuth, length); Stream_Read(s, credssp->pubKeyAuth.pvBuffer, length); credssp->pubKeyAuth.cbBuffer = length; } Stream_Free(s, TRUE); return 0; }
void credssp_send(rdpCredssp* credssp) { wStream* s; int length; int ts_request_length; int nego_tokens_length; int pub_key_auth_length; int auth_info_length; nego_tokens_length = (credssp->negoToken.cbBuffer > 0) ? credssp_sizeof_nego_tokens(credssp->negoToken.cbBuffer) : 0; pub_key_auth_length = (credssp->pubKeyAuth.cbBuffer > 0) ? credssp_sizeof_pub_key_auth(credssp->pubKeyAuth.cbBuffer) : 0; auth_info_length = (credssp->authInfo.cbBuffer > 0) ? credssp_sizeof_auth_info(credssp->authInfo.cbBuffer) : 0; length = nego_tokens_length + pub_key_auth_length + auth_info_length; ts_request_length = credssp_sizeof_ts_request(length); s = Stream_New(NULL, ber_sizeof_sequence(ts_request_length)); /* TSRequest */ ber_write_sequence_tag(s, ts_request_length); /* SEQUENCE */ /* [0] version */ ber_write_contextual_tag(s, 0, 3, TRUE); ber_write_integer(s, 2); /* INTEGER */ /* [1] negoTokens (NegoData) */ if (nego_tokens_length > 0) { length = nego_tokens_length; length -= ber_write_contextual_tag(s, 1, ber_sizeof_sequence(ber_sizeof_sequence(ber_sizeof_sequence_octet_string(credssp->negoToken.cbBuffer))), TRUE); /* NegoData */ length -= ber_write_sequence_tag(s, ber_sizeof_sequence(ber_sizeof_sequence_octet_string(credssp->negoToken.cbBuffer))); /* SEQUENCE OF NegoDataItem */ length -= ber_write_sequence_tag(s, ber_sizeof_sequence_octet_string(credssp->negoToken.cbBuffer)); /* NegoDataItem */ length -= ber_write_sequence_octet_string(s, 0, (BYTE*) credssp->negoToken.pvBuffer, credssp->negoToken.cbBuffer); /* OCTET STRING */ // assert length == 0 } /* [2] authInfo (OCTET STRING) */ if (auth_info_length > 0) { length = auth_info_length; length -= ber_write_sequence_octet_string(s, 2, credssp->authInfo.pvBuffer, credssp->authInfo.cbBuffer); // assert length == 0 } /* [3] pubKeyAuth (OCTET STRING) */ if (pub_key_auth_length > 0) { length = pub_key_auth_length; length -= ber_write_sequence_octet_string(s, 3, credssp->pubKeyAuth.pvBuffer, credssp->pubKeyAuth.cbBuffer); // assert length == 0 } Stream_SealLength(s); transport_write(credssp->transport, s); Stream_Free(s, TRUE); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* printer) { char* port; UINT32 Flags; int DriverNameLen; WCHAR* DriverName = NULL; int PrintNameLen; WCHAR* PrintName = NULL; UINT32 CachedFieldsLen; BYTE* CachedPrinterConfigData; PRINTER_DEVICE* printer_dev; UINT error; port = malloc(10); if (!port) { WLog_ERR(TAG, "malloc failed!"); return CHANNEL_RC_NO_MEMORY; } sprintf_s(port, 10, "PRN%d", printer->id); printer_dev = (PRINTER_DEVICE*) calloc(1, sizeof(PRINTER_DEVICE)); if (!printer_dev) { WLog_ERR(TAG, "calloc failed!"); free(port); return CHANNEL_RC_NO_MEMORY; } printer_dev->device.type = RDPDR_DTYP_PRINT; printer_dev->device.name = port; printer_dev->device.IRPRequest = printer_irp_request; printer_dev->device.Free = printer_free; printer_dev->rdpcontext = pEntryPoints->rdpcontext; printer_dev->printer = printer; CachedFieldsLen = 0; CachedPrinterConfigData = NULL; Flags = 0; if (printer->is_default) Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER; DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName, 0) * 2; PrintNameLen = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &PrintName, 0) * 2; printer_dev->device.data = Stream_New(NULL, 28 + DriverNameLen + PrintNameLen + CachedFieldsLen); if (!printer_dev->device.data) { WLog_ERR(TAG, "calloc failed!"); error = CHANNEL_RC_NO_MEMORY; free(DriverName); free(PrintName); goto error_out; } Stream_Write_UINT32(printer_dev->device.data, Flags); Stream_Write_UINT32(printer_dev->device.data, 0); /* CodePage, reserved */ Stream_Write_UINT32(printer_dev->device.data, 0); /* PnPNameLen */ Stream_Write_UINT32(printer_dev->device.data, DriverNameLen + 2); Stream_Write_UINT32(printer_dev->device.data, PrintNameLen + 2); Stream_Write_UINT32(printer_dev->device.data, CachedFieldsLen); Stream_Write(printer_dev->device.data, DriverName, DriverNameLen); Stream_Write_UINT16(printer_dev->device.data, 0); Stream_Write(printer_dev->device.data, PrintName, PrintNameLen); Stream_Write_UINT16(printer_dev->device.data, 0); if (CachedFieldsLen > 0) { Stream_Write(printer_dev->device.data, CachedPrinterConfigData, CachedFieldsLen); } free(DriverName); free(PrintName); printer_dev->pIrpList = (WINPR_PSLIST_HEADER) _aligned_malloc(sizeof( WINPR_SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT); if (!printer_dev->pIrpList) { WLog_ERR(TAG, "_aligned_malloc failed!"); error = CHANNEL_RC_NO_MEMORY; goto error_out; } InitializeSListHead(printer_dev->pIrpList); if (!(printer_dev->event = CreateEvent(NULL, TRUE, FALSE, NULL))) { WLog_ERR(TAG, "CreateEvent failed!"); error = ERROR_INTERNAL_ERROR; goto error_out; } if (!(printer_dev->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { WLog_ERR(TAG, "CreateEvent failed!"); error = ERROR_INTERNAL_ERROR; goto error_out; } if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) printer_dev))) { WLog_ERR(TAG, "RegisterDevice failed with error %"PRIu32"!", error); goto error_out; } if (!(printer_dev->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) printer_thread_func, (void*) printer_dev, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); error = ERROR_INTERNAL_ERROR; goto error_out; } return CHANNEL_RC_OK; error_out: CloseHandle(printer_dev->stopEvent); CloseHandle(printer_dev->event); _aligned_free(printer_dev->pIrpList); Stream_Free(printer_dev->device.data, TRUE); free(printer_dev); free(port); return error; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpsnd_server_start(RdpsndServerContext* context) { void *buffer = NULL; DWORD bytesReturned; RdpsndServerPrivate *priv = context->priv; UINT error = ERROR_INTERNAL_ERROR; priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpsnd"); if (!priv->ChannelHandle) { WLog_ERR(TAG, "WTSVirtualChannelOpen failed!"); return ERROR_INTERNAL_ERROR; } if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE))) { WLog_ERR(TAG, "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)", bytesReturned); if (buffer) WTSFreeMemory(buffer); goto out_close; } CopyMemory(&priv->channelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); priv->rdpsnd_pdu = Stream_New(NULL, 4096); if (!priv->rdpsnd_pdu) { WLog_ERR(TAG, "Stream_New failed!"); error = CHANNEL_RC_NO_MEMORY; goto out_close; } if (!InitializeCriticalSectionEx(&context->priv->lock, 0, 0)) { WLog_ERR(TAG, "InitializeCriticalSectionEx failed!"); goto out_pdu; } if (priv->ownThread) { context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!context->priv->StopEvent) { WLog_ERR(TAG, "CreateEvent failed!"); goto out_lock; } context->priv->Thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL); if (!context->priv->Thread) { WLog_ERR(TAG, "CreateThread failed!"); goto out_stopEvent; } } return CHANNEL_RC_OK; out_stopEvent: CloseHandle(context->priv->StopEvent); context->priv->StopEvent = NULL; out_lock: DeleteCriticalSection(&context->priv->lock); out_pdu: Stream_Free(context->priv->rdpsnd_pdu, TRUE); context->priv->rdpsnd_pdu = NULL; out_close: WTSVirtualChannelClose(context->priv->ChannelHandle); context->priv->ChannelHandle = NULL; return error; }
BOOL nego_send_negotiation_request(rdpNego* nego) { wStream* s; int length; int bm, em; BYTE flags = 0; int cookie_length; s = Stream_New(NULL, 512); length = TPDU_CONNECTION_REQUEST_LENGTH; bm = Stream_GetPosition(s); Stream_Seek(s, length); if (nego->RoutingToken) { Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength); /* Ensure Routing Token is correctly terminated - may already be present in string */ if (nego->RoutingTokenLength>2 && (nego->RoutingToken[nego->RoutingTokenLength-2]==0x0D && nego->RoutingToken[nego->RoutingTokenLength-1]==0x0A)) { DEBUG_NEGO("Routing token looks correctly terminated - use verbatim"); length +=nego->RoutingTokenLength; } else { DEBUG_NEGO("Adding terminating CRLF to routing token"); Stream_Write_UINT8(s, 0x0D); /* CR */ Stream_Write_UINT8(s, 0x0A); /* LF */ length += nego->RoutingTokenLength + 2; } } else if (nego->cookie) { cookie_length = strlen(nego->cookie); if (cookie_length > (int) nego->cookie_max_length) cookie_length = nego->cookie_max_length; Stream_Write(s, "Cookie: mstshash=", 17); Stream_Write(s, (BYTE*) nego->cookie, cookie_length); Stream_Write_UINT8(s, 0x0D); /* CR */ Stream_Write_UINT8(s, 0x0A); /* LF */ length += cookie_length + 19; } DEBUG_NEGO("requested_protocols: %d", nego->requested_protocols); if ((nego->requested_protocols > PROTOCOL_RDP) || (nego->sendNegoData)) { /* RDP_NEG_DATA must be present for TLS and NLA */ if (nego->RestrictedAdminModeRequired) flags |= RESTRICTED_ADMIN_MODE_REQUIRED; Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ); Stream_Write_UINT8(s, flags); Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ Stream_Write_UINT32(s, nego->requested_protocols); /* requestedProtocols */ length += 8; } em = Stream_GetPosition(s); Stream_SetPosition(s, bm); tpkt_write_header(s, length); tpdu_write_connection_request(s, length - 5); Stream_SetPosition(s, em); Stream_SealLength(s); if (transport_write(nego->transport, s) < 0) { Stream_Free(s, TRUE); return FALSE; } Stream_Free(s, TRUE); return TRUE; }
int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) { char* name; char* path; int length, ck; RDPDR_SMARTCARD* device; SMARTCARD_DEVICE* smartcard; device = (RDPDR_SMARTCARD*) pEntryPoints->device; name = device->Name; path = device->Path; smartcard = (SMARTCARD_DEVICE*) calloc(1, sizeof(SMARTCARD_DEVICE)); if (!smartcard) return -1; smartcard->device.type = RDPDR_DTYP_SMARTCARD; smartcard->device.name = "SCARD"; smartcard->device.IRPRequest = smartcard_irp_request; smartcard->device.Init = smartcard_init; smartcard->device.Free = smartcard_free; length = strlen(smartcard->device.name); smartcard->device.data = Stream_New(NULL, length + 1); Stream_Write(smartcard->device.data, "SCARD", 6); smartcard->name = NULL; smartcard->path = NULL; if (path) { smartcard->path = path; smartcard->name = name; } else if (name) { if (1 == sscanf(name, "%d", &ck)) smartcard->path = name; else smartcard->name = name; } smartcard->log = WLog_Get("com.freerdp.channel.smartcard.client"); //WLog_SetLogLevel(smartcard->log, WLOG_DEBUG); smartcard->IrpQueue = MessageQueue_New(NULL); smartcard->rgSCardContextList = ListDictionary_New(TRUE); smartcard->rgOutstandingMessages = ListDictionary_New(TRUE); smartcard->CompletedIrpQueue = Queue_New(TRUE, -1, -1); smartcard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_thread_func, smartcard, CREATE_SUSPENDED, NULL); pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) smartcard); ResumeThread(smartcard->thread); return 0; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const BYTE* data, UINT32 dataSize) { wStream* data_out; unsigned long pos; UINT32 cbChId; UINT32 cbLen; unsigned long chunkLength; UINT status; WLog_DBG(TAG, "write_data: ChannelId=%d size=%d", ChannelId, dataSize); data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH); if (!data_out) { WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_SetPosition(data_out, 1); cbChId = drdynvc_write_variable_uint(data_out, ChannelId); pos = Stream_GetPosition(data_out); if (dataSize == 0) { Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x40 | cbChId); Stream_SetPosition(data_out, pos); status = drdynvc_send(drdynvc, data_out); } else if (dataSize <= CHANNEL_CHUNK_LENGTH - pos) { Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x30 | cbChId); Stream_SetPosition(data_out, pos); Stream_Write(data_out, data, dataSize); status = drdynvc_send(drdynvc, data_out); } else { /* Fragment the data */ cbLen = drdynvc_write_variable_uint(data_out, dataSize); pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x20 | cbChId | (cbLen << 2)); Stream_SetPosition(data_out, pos); chunkLength = CHANNEL_CHUNK_LENGTH - pos; Stream_Write(data_out, data, chunkLength); data += chunkLength; dataSize -= chunkLength; status = drdynvc_send(drdynvc, data_out); while (status == CHANNEL_RC_OK && dataSize > 0) { data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH); if (!data_out) { WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_SetPosition(data_out, 1); cbChId = drdynvc_write_variable_uint(data_out, ChannelId); pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x30 | cbChId); Stream_SetPosition(data_out, pos); chunkLength = dataSize; if (chunkLength > CHANNEL_CHUNK_LENGTH - pos) chunkLength = CHANNEL_CHUNK_LENGTH - pos; Stream_Write(data_out, data, chunkLength); data += chunkLength; dataSize -= chunkLength; status = drdynvc_send(drdynvc, data_out); } } if (status != CHANNEL_RC_OK) { WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]", WTSErrorToString(status), status); return status; } return CHANNEL_RC_OK; }
RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, BYTE* data, UINT32 length) { int pos; wStream* s; UINT32 blockLen; UINT32 blockType; RFX_MESSAGE* message; message = (RFX_MESSAGE*) malloc(sizeof(RFX_MESSAGE)); ZeroMemory(message, sizeof(RFX_MESSAGE)); s = Stream_New(data, length); while (Stream_GetRemainingLength(s) > 6) { /* RFX_BLOCKT */ Stream_Read_UINT16(s, blockType); /* blockType (2 bytes) */ Stream_Read_UINT32(s, blockLen); /* blockLen (4 bytes) */ DEBUG_RFX("blockType 0x%X blockLen %d", blockType, blockLen); if (blockLen == 0) { DEBUG_WARN("zero blockLen"); break; } if (Stream_GetRemainingLength(s) < blockLen - 6) { DEBUG_WARN("rfx_process_message: packet too small for blocklen=%d", blockLen); break; } pos = Stream_GetPosition(s) - 6 + blockLen; if (blockType >= WBT_CONTEXT && blockType <= WBT_EXTENSION) { /* RFX_CODEC_CHANNELT */ /* codecId (1 byte) must be set to 0x01 */ /* channelId (1 byte) must be set to 0x00 */ if (!Stream_SafeSeek(s, 2)) { DEBUG_WARN("rfx_process_message: unable to skip RFX_CODEC_CHANNELT"); break; } } switch (blockType) { case WBT_SYNC: rfx_process_message_sync(context, s); break; case WBT_CODEC_VERSIONS: rfx_process_message_codec_versions(context, s); break; case WBT_CHANNELS: rfx_process_message_channels(context, s); break; case WBT_CONTEXT: rfx_process_message_context(context, s); break; case WBT_FRAME_BEGIN: rfx_process_message_frame_begin(context, message, s); break; case WBT_FRAME_END: rfx_process_message_frame_end(context, message, s); break; case WBT_REGION: rfx_process_message_region(context, message, s); break; case WBT_EXTENSION: rfx_process_message_tileset(context, message, s); break; default: DEBUG_WARN("unknown blockType 0x%X", blockType); break; } Stream_SetPosition(s, pos); } Stream_Free(s, FALSE); return message; }
int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UINT32 data_size) { wStream* data_out; UINT32 pos = 0; UINT32 cbChId; UINT32 cbLen; UINT32 chunk_len; int error; DEBUG_DVC("ChannelId=%d size=%d", ChannelId, data_size); if (drdynvc->channel_error != CHANNEL_RC_OK) return 1; data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH); Stream_SetPosition(data_out, 1); cbChId = drdynvc_write_variable_uint(data_out, ChannelId); if (data_size == 0) { pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x40 | cbChId); Stream_SetPosition(data_out, pos); error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); } else if (data_size <= CHANNEL_CHUNK_LENGTH - pos) { pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x30 | cbChId); Stream_SetPosition(data_out, pos); Stream_Write(data_out, data, data_size); error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); } else { /* Fragment the data */ cbLen = drdynvc_write_variable_uint(data_out, data_size); pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x20 | cbChId | (cbLen << 2)); Stream_SetPosition(data_out, pos); chunk_len = CHANNEL_CHUNK_LENGTH - pos; Stream_Write(data_out, data, chunk_len); data += chunk_len; data_size -= chunk_len; error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); while (error == CHANNEL_RC_OK && data_size > 0) { data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH); Stream_SetPosition(data_out, 1); cbChId = drdynvc_write_variable_uint(data_out, ChannelId); pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x30 | cbChId); Stream_SetPosition(data_out, pos); chunk_len = data_size; if (chunk_len > CHANNEL_CHUNK_LENGTH - pos) chunk_len = CHANNEL_CHUNK_LENGTH - pos; Stream_Write(data_out, data, chunk_len); data += chunk_len; data_size -= chunk_len; error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); } } if (error != CHANNEL_RC_OK) { drdynvc->channel_error = error; DEBUG_WARN("VirtualChannelWrite failed %d", error); return 1; } return 0; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk) { int status; UINT error; wStream* s = NULL; int cbExpertBlobW = 0; WCHAR* expertBlobW = NULL; int cbRaConnectionStringW = 0; WCHAR* raConnectionStringW = NULL; REMDESK_CTL_AUTHENTICATE_PDU pdu; if ((error = remdesk_generate_expert_blob(remdesk))) { WLog_ERR(TAG, "remdesk_generate_expert_blob failed with error %u", error); return error; } pdu.expertBlob = remdesk->ExpertBlob; pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket; status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1, &raConnectionStringW, 0); if (status <= 0) { WLog_ERR(TAG, "ConvertToUnicode failed!"); return ERROR_INTERNAL_ERROR; } cbRaConnectionStringW = status * 2; status = ConvertToUnicode(CP_UTF8, 0, pdu.expertBlob, -1, &expertBlobW, 0); if (status <= 0) { WLog_ERR(TAG, "ConvertToUnicode failed!"); error = ERROR_INTERNAL_ERROR; goto out; } cbExpertBlobW = status * 2; remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_AUTHENTICATE, cbRaConnectionStringW + cbExpertBlobW); s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); error = CHANNEL_RC_NO_MEMORY; goto out; } remdesk_write_ctl_header(s, &(pdu.ctlHeader)); Stream_Write(s, (BYTE*) raConnectionStringW, cbRaConnectionStringW); Stream_Write(s, (BYTE*) expertBlobW, cbExpertBlobW); Stream_SealLength(s); if ((error = remdesk_virtual_channel_write(remdesk, s))) WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %u!", error); out: free(raConnectionStringW); free(expertBlobW); if (error != CHANNEL_RC_OK) Stream_Free(s, TRUE); return error; }
BOOL nego_send_negotiation_response(rdpNego* nego) { int length; int bm, em; BOOL status; wStream* s; rdpSettings* settings; status = TRUE; settings = nego->transport->settings; s = Stream_New(NULL, 512); length = TPDU_CONNECTION_CONFIRM_LENGTH; bm = Stream_GetPosition(s); Stream_Seek(s, length); if (nego->selected_protocol > PROTOCOL_RDP) { /* RDP_NEG_DATA must be present for TLS and NLA */ Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP); Stream_Write_UINT8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ Stream_Write_UINT32(s, nego->selected_protocol); /* selectedProtocol */ length += 8; } else if (!settings->RdpSecurity) { Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE); Stream_Write_UINT8(s, 0); /* flags */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ /* * TODO: Check for other possibilities, * like SSL_NOT_ALLOWED_BY_SERVER. */ fprintf(stderr, "nego_send_negotiation_response: client supports only Standard RDP Security\n"); Stream_Write_UINT32(s, SSL_REQUIRED_BY_SERVER); length += 8; status = FALSE; } em = Stream_GetPosition(s); Stream_SetPosition(s, bm); tpkt_write_header(s, length); tpdu_write_connection_confirm(s, length - 5); Stream_SetPosition(s, em); Stream_SealLength(s); if (transport_write(nego->transport, s) < 0) { Stream_Free(s, TRUE); return FALSE; } Stream_Free(s, TRUE); if (status) { /* update settings with negotiated protocol security */ settings->RequestedProtocols = nego->requested_protocols; settings->SelectedProtocol = nego->selected_protocol; if (settings->SelectedProtocol == PROTOCOL_RDP) { settings->TlsSecurity = FALSE; settings->NlaSecurity = FALSE; settings->RdpSecurity = TRUE; if (!settings->LocalConnection) { settings->DisableEncryption = TRUE; settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; } if (settings->DisableEncryption && settings->RdpServerRsaKey == NULL && settings->RdpKeyFile == NULL) return FALSE; } else if (settings->SelectedProtocol == PROTOCOL_TLS) { settings->TlsSecurity = TRUE; settings->NlaSecurity = FALSE; settings->RdpSecurity = FALSE; settings->DisableEncryption = FALSE; settings->EncryptionMethods = ENCRYPTION_METHOD_NONE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } else if (settings->SelectedProtocol == PROTOCOL_NLA) { settings->TlsSecurity = TRUE; settings->NlaSecurity = TRUE; settings->RdpSecurity = FALSE; settings->DisableEncryption = FALSE; settings->EncryptionMethods = ENCRYPTION_METHOD_NONE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } } return status; }
static void* encomsp_server_thread(void* arg) { wStream* s; DWORD nCount; void* buffer; HANDLE events[8]; HANDLE ChannelEvent; DWORD BytesReturned; ENCOMSP_ORDER_HEADER* header; EncomspServerContext* context; UINT error = CHANNEL_RC_OK; DWORD status; context = (EncomspServerContext*) arg; buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; s = Stream_New(NULL, 4096); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); error = CHANNEL_RC_NO_MEMORY; goto out; } if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); } nCount = 0; events[nCount++] = ChannelEvent; events[nCount++] = context->priv->StopEvent; while (1) { status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"", error); break; } status = WaitForSingleObject(context->priv->StopEvent, 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); break; } if (status == WAIT_OBJECT_0) { break; } WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned); if (BytesReturned < 1) continue; if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); error = CHANNEL_RC_NO_MEMORY; break; } if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); error = ERROR_INTERNAL_ERROR; break; } if (Stream_GetPosition(s) >= ENCOMSP_ORDER_HEADER_SIZE) { header = (ENCOMSP_ORDER_HEADER*) Stream_Buffer(s); if (header->Length >= Stream_GetPosition(s)) { Stream_SealLength(s); Stream_SetPosition(s, 0); if ((error = encomsp_server_receive_pdu(context, s))) { WLog_ERR(TAG, "encomsp_server_receive_pdu failed with error %"PRIu32"!", error); break; } Stream_SetPosition(s, 0); } } } Stream_Free(s, TRUE); out: if (error && context->rdpcontext) setChannelError(context->rdpcontext, error, "encomsp_server_thread reported an error"); ExitThread((DWORD)error); return NULL; }