BOOL license_read_error_alert_packet(rdpLicense* license, STREAM* s) { UINT32 dwErrorCode; UINT32 dwStateTransition; if(stream_get_left(s) < 8) return FALSE; stream_read_UINT32(s, dwErrorCode); /* dwErrorCode (4 bytes) */ stream_read_UINT32(s, dwStateTransition); /* dwStateTransition (4 bytes) */ if(!license_read_binary_blob(s, license->error_info)) /* bbErrorInfo */ return FALSE; #ifdef WITH_DEBUG_LICENSE printf("dwErrorCode: %s, dwStateTransition: %s\n", error_codes[dwErrorCode], state_transitions[dwStateTransition]); #endif if (dwErrorCode == STATUS_VALID_CLIENT) { license->state = LICENSE_STATE_COMPLETED; return TRUE; } switch (dwStateTransition) { case ST_TOTAL_ABORT: license->state = LICENSE_STATE_ABORTED; break; case ST_NO_TRANSITION: license->state = LICENSE_STATE_COMPLETED; break; case ST_RESET_PHASE_TO_START: license->state = LICENSE_STATE_AWAIT; break; case ST_RESEND_LAST_MESSAGE: break; default: break; } return TRUE; }
tbool rdp_read_share_data_header(STREAM* s, uint16* length, uint8* type, uint32* share_id, uint8 *compressed_type, uint16 *compressed_len) { if (stream_get_left(s) < 12) return false; /* Share Data Header */ stream_read_uint32(s, *share_id); /* shareId (4 bytes) */ stream_seek_uint8(s); /* pad1 (1 byte) */ stream_seek_uint8(s); /* streamId (1 byte) */ stream_read_uint16(s, *length); /* uncompressedLength (2 bytes) */ stream_read_uint8(s, *type); /* pduType2, Data PDU Type (1 byte) */ stream_read_uint8(s, *compressed_type); /* compressedType (1 byte) */ stream_read_uint16(s, *compressed_len); /* compressedLength (2 bytes) */ return true; }
boolean rdp_read_header(rdpRdp* rdp, STREAM* s, uint16* length, uint16* channel_id) { uint16 initiator; enum DomainMCSPDU MCSPDU; MCSPDU = (rdp->settings->server_mode) ? DomainMCSPDU_SendDataRequest : DomainMCSPDU_SendDataIndication; mcs_read_domain_mcspdu_header(s, &MCSPDU, length); per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ per_read_integer16(s, channel_id, 0); /* channelId */ stream_seek(s, 1); /* dataPriority + Segmentation (0x70) */ per_read_length(s, length); /* userData (OCTET_STRING) */ if (*length > stream_get_left(s)) return false; return true; }
boolean rdp_read_share_control_header(STREAM* s, uint16* length, uint16* type, uint16* channel_id) { /* Share Control Header */ stream_read_uint16(s, *length); /* totalLength */ if (*length - 2 > stream_get_left(s)) return false; stream_read_uint16(s, *type); /* pduType */ *type &= 0x0F; /* type is in the 4 least significant bits */ if (*length > 4) stream_read_uint16(s, *channel_id); /* pduSource */ else /* Windows XP can send such short DEACTIVATE_ALL PDUs. */ *channel_id = 0; return true; }
BOOL update_recv_altsec_window_order(rdpUpdate* update, wStream* s) { UINT16 orderSize; rdpWindowUpdate* window = update->window; if(stream_get_left(s) < 6) return FALSE; stream_read_UINT16(s, orderSize); /* orderSize (2 bytes) */ stream_read_UINT32(s, window->orderInfo.fieldFlags); /* FieldsPresentFlags (4 bytes) */ if (window->orderInfo.fieldFlags & WINDOW_ORDER_TYPE_WINDOW) return update_recv_window_info_order(update, s, &window->orderInfo); else if (window->orderInfo.fieldFlags & WINDOW_ORDER_TYPE_NOTIFY) return update_recv_notification_icon_info_order(update, s, &window->orderInfo); else if (window->orderInfo.fieldFlags & WINDOW_ORDER_TYPE_DESKTOP) return update_recv_desktop_info_order(update, s, &window->orderInfo); return TRUE; }
static int drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* s) { int error; UINT32 Length; UINT32 ChannelId; ChannelId = drdynvc_read_variable_uint(s, cbChId); Length = drdynvc_read_variable_uint(s, Sp); DEBUG_DVC("ChannelId=%d Length=%d", ChannelId, Length); error = dvcman_receive_channel_data_first(drdynvc->channel_mgr, ChannelId, Length); if (error) return error; return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, stream_get_tail(s), stream_get_left(s)); }
static BOOL rfx_process_message_context(RFX_CONTEXT* context, STREAM* s) { BYTE ctxId; UINT16 tileSize; UINT16 properties; if (stream_get_left(s) < 5) { DEBUG_WARN("RfxMessageContext packet too small"); return FALSE; } stream_read_BYTE(s, ctxId); /* ctxId (1 byte), must be set to 0x00 */ stream_read_UINT16(s, tileSize); /* tileSize (2 bytes), must be set to CT_TILE_64x64 (0x0040) */ stream_read_UINT16(s, properties); /* properties (2 bytes) */ DEBUG_RFX("ctxId %d tileSize %d properties 0x%X.", ctxId, tileSize, properties); context->properties = properties; context->flags = (properties & 0x0007); if (context->flags == CODEC_MODE) DEBUG_RFX("codec is in image mode."); else DEBUG_RFX("codec is in video mode."); switch ((properties & 0x1E00) >> 9) { case CLW_ENTROPY_RLGR1: context->mode = RLGR1; DEBUG_RFX("RLGR1."); break; case CLW_ENTROPY_RLGR3: context->mode = RLGR3; DEBUG_RFX("RLGR3."); break; default: DEBUG_WARN("unknown RLGR algorithm."); break; } return TRUE; }
boolean rdp_recv_client_synchronize_pdu(rdpRdp* rdp, STREAM* s) { uint16 messageType; rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU; if (stream_get_left(s) < 4) return false; stream_read_uint16(s, messageType); /* messageType (2 bytes) */ if (messageType != SYNCMSGTYPE_SYNC) return false; /* targetUser (2 bytes) */ stream_seek_uint16(s); return true; }
BOOL license_read_platform_challenge_packet(rdpLicense* license, STREAM* s) { DEBUG_LICENSE("Receiving Platform Challenge Packet"); if(stream_get_left(s) < 4) return FALSE; stream_seek(s, 4); /* ConnectFlags, Reserved (4 bytes) */ /* EncryptedPlatformChallenge */ license->encrypted_platform_challenge->type = BB_ANY_BLOB; license_read_binary_blob(s, license->encrypted_platform_challenge); license->encrypted_platform_challenge->type = BB_ENCRYPTED_DATA_BLOB; /* MACData (16 bytes) */ if(!stream_skip(s, 16)) return FALSE; license_decrypt_platform_challenge(license); return TRUE; }
static boolean rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s) { uint16 length; length = fastpath_read_header_rdp(rdp->fastpath, s); if (length == 0 || length > stream_get_left(s)) { printf("incorrect FastPath PDU header length %d\n", length); return False; } if (rdp->fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED) { rdp_decrypt(rdp, s, length); } return fastpath_recv_updates(rdp->fastpath, s); }
BOOL ber_read_enumerated(wStream* s, BYTE* enumerated, BYTE count) { int length; if(!ber_read_universal_tag(s, BER_TAG_ENUMERATED, FALSE) || !ber_read_length(s, &length)) return FALSE; if (length != 1 || stream_get_left(s) < 1) return FALSE; stream_read_BYTE(s, *enumerated); /* check that enumerated value falls within expected range */ if (*enumerated + 1 > count) return FALSE; return TRUE; }
BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp, STREAM* s) { UINT16 messageType; rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU; if (stream_get_left(s) < 4) return FALSE; stream_read_UINT16(s, messageType); /* messageType (2 bytes) */ if (messageType != SYNCMSGTYPE_SYNC) return FALSE; /* targetUser (2 bytes) */ stream_seek_UINT16(s); return TRUE; }
BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_INFO* orderInfo) { rdpContext* context = update->context; rdpWindowUpdate* window = update->window; if(stream_get_left(s) < 4) return FALSE; stream_read_UINT32(s, orderInfo->windowId); /* windowId (4 bytes) */ if (orderInfo->fieldFlags & WINDOW_ORDER_ICON) { DEBUG_WND("Window Icon Order"); if(!update_read_window_icon_order(s, orderInfo, &window->window_icon)) return FALSE; IFCALL(window->WindowIcon, context, orderInfo, &window->window_icon); } else if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) { DEBUG_WND("Window Cached Icon Order"); if(!update_read_window_cached_icon_order(s, orderInfo, &window->window_cached_icon)) return FALSE; IFCALL(window->WindowCachedIcon, context, orderInfo, &window->window_cached_icon); } else if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_DELETED) { DEBUG_WND("Window Deleted Order"); update_read_window_delete_order(s, orderInfo); IFCALL(window->WindowDelete, context, orderInfo); } else { DEBUG_WND("Window State Order"); if(!update_read_window_state_order(s, orderInfo, &window->window_state)) return FALSE; if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW) IFCALL(window->WindowCreate, context, orderInfo, &window->window_state); else IFCALL(window->WindowUpdate, context, orderInfo, &window->window_state); } return TRUE; }
void cliprdr_process_long_format_names(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) { int allocated_formats = 8; BYTE* end_mark; CLIPRDR_FORMAT_NAME* format_name; stream_get_mark(s, end_mark); end_mark += length; cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) malloc(sizeof(CLIPRDR_FORMAT_NAME) * allocated_formats); cliprdr->num_format_names = 0; while (stream_get_left(s) >= 6) { BYTE* p; int name_len; if (cliprdr->num_format_names >= allocated_formats) { allocated_formats *= 2; cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) realloc(cliprdr->format_names, sizeof(CLIPRDR_FORMAT_NAME) * allocated_formats); } format_name = &cliprdr->format_names[cliprdr->num_format_names++]; stream_read_UINT32(s, format_name->id); format_name->name = NULL; format_name->length = 0; for (p = stream_get_tail(s), name_len = 0; p + 1 < end_mark; p += 2, name_len += 2) { if (*((unsigned short*) p) == 0) break; } format_name->length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(s), name_len / 2, &format_name->name, 0, NULL, NULL); stream_seek(s, name_len + 2); } }
void cliprdr_process_long_format_names(cliprdrPlugin* cliprdr, STREAM* s, uint32 length, uint16 flags) { int allocated_formats = 8; uint8* end_mark; CLIPRDR_FORMAT_NAME* format_name; stream_get_mark(s, end_mark); end_mark += length; cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) xmalloc(sizeof(CLIPRDR_FORMAT_NAME) * allocated_formats); cliprdr->num_format_names = 0; while (stream_get_left(s) >= 6) { uint8* p; int name_len; if (cliprdr->num_format_names >= allocated_formats) { allocated_formats *= 2; cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) xrealloc(cliprdr->format_names, sizeof(CLIPRDR_FORMAT_NAME) * allocated_formats); } format_name = &cliprdr->format_names[cliprdr->num_format_names++]; stream_read_uint32(s, format_name->id); format_name->name = NULL; format_name->length = 0; for (p = stream_get_tail(s), name_len = 0; p + 1 < end_mark; p += 2, name_len += 2) { if (*((unsigned short*) p) == 0) break; } format_name->name = freerdp_uniconv_in(cliprdr->uniconv, stream_get_tail(s), name_len); format_name->length = strlen(format_name->name); stream_seek(s, name_len + 2); } }
static tbool rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s) { uint16 length; rdpFastPath* fastpath; fastpath = rdp->fastpath; length = fastpath_read_header_rdp(fastpath, s); if (length == 0 || length > stream_get_left(s)) { printf("incorrect FastPath PDU header length %d\n", length); return false; } if (fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED) { rdp_decrypt(rdp, s, length, (fastpath->encryptionFlags & FASTPATH_OUTPUT_SECURE_CHECKSUM) ? SEC_SECURE_CHECKSUM : 0); } return fastpath_recv_updates(rdp->fastpath, s); }
BOOL license_read_scope_list(STREAM* s, SCOPE_LIST* scopeList) { UINT32 i; UINT32 scopeCount; if(stream_get_left(s) < 4) return FALSE; stream_read_UINT32(s, scopeCount); /* ScopeCount (4 bytes) */ scopeList->count = scopeCount; scopeList->array = (LICENSE_BLOB*) malloc(sizeof(LICENSE_BLOB) * scopeCount); /* ScopeArray */ for (i = 0; i < scopeCount; i++) { scopeList->array[i].type = BB_SCOPE_BLOB; if(!license_read_binary_blob(s, &scopeList->array[i])) return FALSE; } return TRUE; }
static BOOL rfx_process_message_tile(RFX_CONTEXT* context, RFX_TILE* tile, STREAM* s) { BYTE quantIdxY; BYTE quantIdxCb; BYTE quantIdxCr; UINT16 xIdx, yIdx; UINT16 YLen, CbLen, CrLen; if (stream_get_left(s) < 13) { DEBUG_WARN("RfxMessageTile packet too small"); return FALSE; } /* RFX_TILE */ stream_read_BYTE(s, quantIdxY); /* quantIdxY (1 byte) */ stream_read_BYTE(s, quantIdxCb); /* quantIdxCb (1 byte) */ stream_read_BYTE(s, quantIdxCr); /* quantIdxCr (1 byte) */ stream_read_UINT16(s, xIdx); /* xIdx (2 bytes) */ stream_read_UINT16(s, yIdx); /* yIdx (2 bytes) */ stream_read_UINT16(s, YLen); /* YLen (2 bytes) */ stream_read_UINT16(s, CbLen); /* CbLen (2 bytes) */ stream_read_UINT16(s, CrLen); /* CrLen (2 bytes) */ DEBUG_RFX("quantIdxY:%d quantIdxCb:%d quantIdxCr:%d xIdx:%d yIdx:%d YLen:%d CbLen:%d CrLen:%d", quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx, YLen, CbLen, CrLen); tile->x = xIdx * 64; tile->y = yIdx * 64; return rfx_decode_rgb(context, s, YLen, context->quants + (quantIdxY * 10), CbLen, context->quants + (quantIdxCb * 10), CrLen, context->quants + (quantIdxCr * 10), tile->data, 64 * 4); }
void update_read_pointer_color(STREAM* s, POINTER_COLOR_UPDATE* pointer_color) { stream_read_UINT16(s, pointer_color->cacheIndex); /* cacheIndex (2 bytes) */ stream_read_UINT16(s, pointer_color->xPos); /* xPos (2 bytes) */ stream_read_UINT16(s, pointer_color->yPos); /* yPos (2 bytes) */ stream_read_UINT16(s, pointer_color->width); /* width (2 bytes) */ stream_read_UINT16(s, pointer_color->height); /* height (2 bytes) */ stream_read_UINT16(s, pointer_color->lengthAndMask); /* lengthAndMask (2 bytes) */ stream_read_UINT16(s, pointer_color->lengthXorMask); /* lengthXorMask (2 bytes) */ /** * There does not seem to be any documentation on why * xPos / yPos can be larger than width / height * so it is missing in documentation or a bug in implementation * 2.2.9.1.1.4.4 Color Pointer Update (TS_COLORPOINTERATTRIBUTE) */ if (pointer_color->xPos >= pointer_color->width) pointer_color->xPos = 0; if (pointer_color->yPos >= pointer_color->height) pointer_color->yPos = 0; if (pointer_color->lengthXorMask > 0) { pointer_color->xorMaskData = (BYTE*) malloc(pointer_color->lengthXorMask); stream_read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask); } if (pointer_color->lengthAndMask > 0) { pointer_color->andMaskData = (BYTE*) malloc(pointer_color->lengthAndMask); stream_read(s, pointer_color->andMaskData, pointer_color->lengthAndMask); } if (stream_get_left(s) > 0) stream_seek_BYTE(s); /* pad (1 byte) */ }
int rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s) { BYTE type; UINT16 length; UINT32 share_id; BYTE compressed_type; UINT16 compressed_len; UINT32 roff; UINT32 rlen; STREAM* comp_stream; if (!rdp_read_share_data_header(s, &length, &type, &share_id, &compressed_type, &compressed_len)) return -1; comp_stream = s; if (compressed_type & PACKET_COMPRESSED) { if (stream_get_left(s) < compressed_len - 18) { printf("decompress_rdp: not enough bytes for compressed_len=%d\n", compressed_len); return -1; } if (decompress_rdp(rdp->mppc_dec, s->p, compressed_len - 18, compressed_type, &roff, &rlen)) { comp_stream = stream_new(0); comp_stream->data = rdp->mppc_dec->history_buf + roff; comp_stream->p = comp_stream->data; comp_stream->size = rlen; } else { printf("decompress_rdp() failed\n"); return -1; } stream_seek(s, compressed_len - 18); } #ifdef WITH_DEBUG_RDP /* if (type != DATA_PDU_TYPE_UPDATE) */ DEBUG_RDP("recv %s Data PDU (0x%02X), length:%d", type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length); #endif switch (type) { case DATA_PDU_TYPE_UPDATE: if (!update_recv(rdp->update, comp_stream)) return -1; break; case DATA_PDU_TYPE_CONTROL: if (!rdp_recv_server_control_pdu(rdp, comp_stream)) return -1; break; case DATA_PDU_TYPE_POINTER: if (!update_recv_pointer(rdp->update, comp_stream)) return -1; break; case DATA_PDU_TYPE_INPUT: break; case DATA_PDU_TYPE_SYNCHRONIZE: if (!rdp_recv_synchronize_pdu(rdp, comp_stream)) return -1; break; case DATA_PDU_TYPE_REFRESH_RECT: break; case DATA_PDU_TYPE_PLAY_SOUND: if (!update_recv_play_sound(rdp->update, comp_stream)) return -1; break; case DATA_PDU_TYPE_SUPPRESS_OUTPUT: break; case DATA_PDU_TYPE_SHUTDOWN_REQUEST: break; case DATA_PDU_TYPE_SHUTDOWN_DENIED: break; case DATA_PDU_TYPE_SAVE_SESSION_INFO: if(!rdp_recv_save_session_info(rdp, comp_stream)) return -1; break; case DATA_PDU_TYPE_FONT_LIST: break; case DATA_PDU_TYPE_FONT_MAP: if(!rdp_recv_font_map_pdu(rdp, comp_stream)) return -1; break; case DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS: break; case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST: break; case DATA_PDU_TYPE_BITMAP_CACHE_ERROR: break; case DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS: break; case DATA_PDU_TYPE_OFFSCREEN_CACHE_ERROR: break; case DATA_PDU_TYPE_SET_ERROR_INFO: if (!rdp_recv_set_error_info_data_pdu(rdp, comp_stream)) return -1; break; case DATA_PDU_TYPE_DRAW_NINEGRID_ERROR: break; case DATA_PDU_TYPE_DRAW_GDIPLUS_ERROR: break; case DATA_PDU_TYPE_ARC_STATUS: break; case DATA_PDU_TYPE_STATUS_INFO: break; case DATA_PDU_TYPE_MONITOR_LAYOUT: break; default: break; } if (comp_stream != s) { stream_detach(comp_stream); stream_free(comp_stream); } return 0; }
BOOL rdp_decrypt(rdpRdp* rdp, STREAM* s, int length, UINT16 securityFlags) { BYTE cmac[8]; BYTE wmac[8]; if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { UINT16 len; BYTE version, pad; BYTE* sig; if (stream_get_left(s) < 12) return FALSE; stream_read_UINT16(s, len); /* 0x10 */ stream_read_BYTE(s, version); /* 0x1 */ stream_read_BYTE(s, pad); sig = s->p; stream_seek(s, 8); /* signature */ length -= 12; if (!security_fips_decrypt(s->p, length, rdp)) { printf("FATAL: cannot decrypt\n"); return FALSE; /* TODO */ } if (!security_fips_check_signature(s->p, length - pad, sig, rdp)) { printf("FATAL: invalid packet signature\n"); return FALSE; /* TODO */ } /* is this what needs adjusting? */ s->size -= pad; return TRUE; } if (stream_get_left(s) < 8) return FALSE; stream_read(s, wmac, sizeof(wmac)); length -= sizeof(wmac); security_decrypt(s->p, length, rdp); if (securityFlags & SEC_SECURE_CHECKSUM) security_salted_mac_signature(rdp, s->p, length, FALSE, cmac); else security_mac_signature(rdp, s->p, length, cmac); if (memcmp(wmac, cmac, sizeof(wmac)) != 0) { printf("WARNING: invalid packet signature\n"); /* * Because Standard RDP Security is totally broken, * and cannot protect against MITM, don't treat signature * verification failure as critical. This at least enables * us to work with broken RDP clients and servers that * generate invalid signatures. */ //return FALSE; } return TRUE; }
BOOL WTSVirtualChannelWrite( /* __in */ void* hChannelHandle, /* __in */ BYTE* Buffer, /* __in */ UINT32 Length, /* __out */ UINT32* pBytesWritten) { rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; wts_data_item* item; wStream* s; int cbLen; int cbChId; int first; UINT32 written; if (channel == NULL) return FALSE; if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) { item = (wts_data_item*) malloc(sizeof(wts_data_item)); ZeroMemory(item, sizeof(wts_data_item)); item->buffer = malloc(Length); item->length = Length; CopyMemory(item->buffer, Buffer, Length); wts_queue_send_item(channel, item); } else if (channel->vcm->drdynvc_channel == NULL || channel->vcm->drdynvc_state != DRDYNVC_STATE_READY) { DEBUG_DVC("drdynvc not ready"); return FALSE; } else { s = stream_new(0); first = TRUE; while (Length > 0) { item = (wts_data_item*) malloc(sizeof(wts_data_item)); ZeroMemory(item, sizeof(wts_data_item)); item->buffer = malloc(channel->client->settings->VirtualChannelChunkSize); stream_attach(s, item->buffer, channel->client->settings->VirtualChannelChunkSize); stream_seek_BYTE(s); cbChId = wts_write_variable_uint(s, channel->channel_id); if (first && (Length > (UINT32) stream_get_left(s))) { cbLen = wts_write_variable_uint(s, Length); item->buffer[0] = (DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId; } else { item->buffer[0] = (DATA_PDU << 4) | cbChId; } first = FALSE; written = stream_get_left(s); if (written > Length) written = Length; stream_write(s, Buffer, written); item->length = stream_get_length(s); stream_detach(s); Length -= written; Buffer += written; wts_queue_send_item(channel->vcm->drdynvc_channel, item); } stream_free(s); } if (pBytesWritten != NULL) *pBytesWritten = Length; return TRUE; }
static tbool rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s) { uint16 length; uint16 pduType; uint16 pduLength; uint16 pduSource; uint16 channelId; uint16 securityFlags; uint8* nextp; if (!rdp_read_header(rdp, s, &length, &channelId)) { printf("Incorrect RDP header.\n"); return false; } if (rdp->settings->encryption) { rdp_read_security_header(s, &securityFlags); if (securityFlags & (SEC_ENCRYPT|SEC_REDIRECTION_PKT)) { if (!rdp_decrypt(rdp, s, length - 4, securityFlags)) { printf("rdp_decrypt failed\n"); return false; } } if (securityFlags & SEC_REDIRECTION_PKT) { /* * [MS-RDPBCGR] 2.2.13.2.1 * - no share control header, nor the 2 byte pad */ s->p -= 2; rdp_recv_enhanced_security_redirection_packet(rdp, s); return true; } } if (channelId != MCS_GLOBAL_CHANNEL_ID) { freerdp_channel_process(rdp->instance, s, channelId); } else { while (stream_get_left(s) > 3) { stream_get_mark(s, nextp); rdp_read_share_control_header(s, &pduLength, &pduType, &pduSource); nextp += pduLength; rdp->settings->pdu_source = pduSource; switch (pduType) { case PDU_TYPE_DATA: if (!rdp_recv_data_pdu(rdp, s)) { printf("rdp_recv_data_pdu failed\n"); return false; } break; case PDU_TYPE_DEACTIVATE_ALL: if (!rdp_recv_deactivate_all(rdp, s)) return false; break; case PDU_TYPE_SERVER_REDIRECTION: rdp_recv_enhanced_security_redirection_packet(rdp, s); break; default: printf("incorrect PDU type: 0x%04X\n", pduType); break; } stream_set_mark(s, nextp); } } return true; }
boolean rdp_read_info_packet(STREAM* s, rdpSettings* settings) { uint32 flags; uint16 cbDomain; uint16 cbUserName; uint16 cbPassword; uint16 cbAlternateShell; uint16 cbWorkingDir; stream_seek_uint32(s); /* CodePage */ stream_read_uint32(s, flags); /* flags */ settings->autologon = ((flags & INFO_AUTOLOGON) ? true : false); settings->remote_app = ((flags & INFO_RAIL) ? true : false); settings->console_audio = ((flags & INFO_REMOTECONSOLEAUDIO) ? true : false); settings->compression = ((flags & INFO_COMPRESSION) ? true : false); stream_read_uint16(s, cbDomain); /* cbDomain */ stream_read_uint16(s, cbUserName); /* cbUserName */ stream_read_uint16(s, cbPassword); /* cbPassword */ stream_read_uint16(s, cbAlternateShell); /* cbAlternateShell */ stream_read_uint16(s, cbWorkingDir); /* cbWorkingDir */ if (stream_get_left(s) < cbDomain + 2) return false; if (cbDomain > 0) { settings->domain = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), cbDomain); stream_seek(s, cbDomain); } stream_seek(s, 2); if (stream_get_left(s) < cbUserName + 2) return false; if (cbUserName > 0) { settings->username = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), cbUserName); stream_seek(s, cbUserName); } stream_seek(s, 2); if (stream_get_left(s) < cbPassword + 2) return false; if (cbPassword > 0) { settings->password = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), cbPassword); stream_seek(s, cbPassword); } stream_seek(s, 2); if (stream_get_left(s) < cbAlternateShell + 2) return false; if (cbAlternateShell > 0) { settings->shell = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), cbAlternateShell); stream_seek(s, cbAlternateShell); } stream_seek(s, 2); if (stream_get_left(s) < cbWorkingDir + 2) return false; if (cbWorkingDir > 0) { settings->directory = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), cbWorkingDir); stream_seek(s, cbWorkingDir); } stream_seek(s, 2); if (settings->rdp_version >= 5) return rdp_read_extended_info_packet(s, settings); /* extraInfo */ return true; }
static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { int i; int pos; BYTE quant; UINT32* quants; UINT16 subtype; UINT32 blockLen; UINT32 blockType; UINT32 tilesDataSize; PTP_WORK* work_objects = NULL; RFX_TILE_WORK_PARAM* params = NULL; if (stream_get_left(s) < 14) { DEBUG_WARN("RfxMessageTileSet packet too small"); return FALSE; } stream_read_UINT16(s, subtype); /* subtype (2 bytes) must be set to CBT_TILESET (0xCAC2) */ if (subtype != CBT_TILESET) { DEBUG_WARN("invalid subtype, expected CBT_TILESET."); return FALSE; } stream_seek_UINT16(s); /* idx (2 bytes), must be set to 0x0000 */ stream_seek_UINT16(s); /* properties (2 bytes) */ stream_read_BYTE(s, context->num_quants); /* numQuant (1 byte) */ stream_seek_BYTE(s); /* tileSize (1 byte), must be set to 0x40 */ if (context->num_quants < 1) { DEBUG_WARN("no quantization value."); return TRUE; } stream_read_UINT16(s, message->num_tiles); /* numTiles (2 bytes) */ if (message->num_tiles < 1) { DEBUG_WARN("no tiles."); return TRUE; } stream_read_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */ if (context->quants != NULL) context->quants = (UINT32*) realloc((void*) context->quants, context->num_quants * 10 * sizeof(UINT32)); else context->quants = (UINT32*) malloc(context->num_quants * 10 * sizeof(UINT32)); quants = context->quants; /* quantVals */ if (stream_get_left(s) < context->num_quants * 5) { DEBUG_WARN("RfxMessageTileSet packet too small for num_quants=%d", context->num_quants); return FALSE; } for (i = 0; i < context->num_quants; i++) { /* RFX_CODEC_QUANT */ stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); stream_read_BYTE(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); DEBUG_RFX("quant %d (%d %d %d %d %d %d %d %d %d %d).", i, context->quants[i * 10], context->quants[i * 10 + 1], context->quants[i * 10 + 2], context->quants[i * 10 + 3], context->quants[i * 10 + 4], context->quants[i * 10 + 5], context->quants[i * 10 + 6], context->quants[i * 10 + 7], context->quants[i * 10 + 8], context->quants[i * 10 + 9]); } message->tiles = (RFX_TILE**) malloc(sizeof(RFX_TILE*) * message->num_tiles); ZeroMemory(message->tiles, sizeof(RFX_TILE*) * message->num_tiles); if (context->priv->UseThreads) { work_objects = (PTP_WORK*) malloc(sizeof(PTP_WORK) * message->num_tiles); params = (RFX_TILE_WORK_PARAM*) malloc(sizeof(RFX_TILE_WORK_PARAM) * message->num_tiles); } /* tiles */ for (i = 0; i < message->num_tiles; i++) { /* RFX_TILE */ if (stream_get_left(s) < 6) { DEBUG_WARN("RfxMessageTileSet packet too small to read tile %d/%d", i, message->num_tiles); return FALSE; } stream_read_UINT16(s, blockType); /* blockType (2 bytes), must be set to CBT_TILE (0xCAC3) */ stream_read_UINT32(s, blockLen); /* blockLen (4 bytes) */ if (stream_get_left(s) < blockLen - 6) { DEBUG_WARN("RfxMessageTileSet not enough bytes to read tile %d/%d with blocklen=%d", i, message->num_tiles, blockLen); return FALSE; } pos = stream_get_pos(s) - 6 + blockLen; if (blockType != CBT_TILE) { DEBUG_WARN("unknown block type 0x%X, expected CBT_TILE (0xCAC3).", blockType); break; } message->tiles[i] = rfx_tile_pool_take(context); if (context->priv->UseThreads) { params[i].context = context; params[i].tile = message->tiles[i]; CopyMemory(&(params[i].s), s, sizeof(STREAM)); work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_process_message_tile_work_callback, (void*) ¶ms[i], &context->priv->ThreadPoolEnv); SubmitThreadpoolWork(work_objects[i]); } else { rfx_process_message_tile(context, message->tiles[i], s); } stream_set_pos(s, pos); } if (context->priv->UseThreads) { for (i = 0; i < message->num_tiles; i++) WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); free(work_objects); free(params); } return TRUE; }
static BOOL peer_recv_data_pdu(freerdp_peer* client, wStream* s) { BYTE type; UINT16 length; UINT32 share_id; BYTE compressed_type; UINT16 compressed_len; if (!rdp_read_share_data_header(s, &length, &type, &share_id, &compressed_type, &compressed_len)) return FALSE; switch (type) { case DATA_PDU_TYPE_SYNCHRONIZE: if (!rdp_recv_client_synchronize_pdu(client->context->rdp, s)) return FALSE; break; case DATA_PDU_TYPE_CONTROL: if (!rdp_server_accept_client_control_pdu(client->context->rdp, s)) return FALSE; break; case DATA_PDU_TYPE_INPUT: if (!input_recv(client->context->rdp->input, s)) return FALSE; break; case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST: /* TODO: notify server bitmap cache data */ break; case DATA_PDU_TYPE_FONT_LIST: if (!rdp_server_accept_client_font_list_pdu(client->context->rdp, s)) return FALSE; if (!client->connected) { /** * PostConnect should only be called once and should not be called * after a reactivation sequence. */ IFCALLRET(client->PostConnect, client->connected, client); if (!client->connected) return FALSE; } if (!client->activated) { /* Activate will be called everytime after the client is activated/reactivated. */ IFCALLRET(client->Activate, client->activated, client); if (!client->activated) return FALSE; } break; case DATA_PDU_TYPE_SHUTDOWN_REQUEST: mcs_send_disconnect_provider_ultimatum(client->context->rdp->mcs); return FALSE; case DATA_PDU_TYPE_FRAME_ACKNOWLEDGE: if(stream_get_left(s) < 4) return FALSE; stream_read_UINT32(s, client->ack_frame_id); break; case DATA_PDU_TYPE_REFRESH_RECT: if (!update_read_refresh_rect(client->update, s)) return FALSE; break; case DATA_PDU_TYPE_SUPPRESS_OUTPUT: if (!update_read_suppress_output(client->update, s)) return FALSE; break; default: fprintf(stderr, "Data PDU type %d\n", type); break; } return TRUE; }
boolean WTSVirtualChannelWrite( /* __in */ void* hChannelHandle, /* __in */ uint8* Buffer, /* __in */ uint32 Length, /* __out */ uint32* pBytesWritten) { rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; wts_data_item* item; STREAM* s; int cbLen; int cbChId; int first; uint32 written; if (channel == NULL) return false; if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC) { item = xnew(wts_data_item); item->buffer = xmalloc(Length); item->length = Length; memcpy(item->buffer, Buffer, Length); wts_queue_send_item(channel, item); } else if (channel->vcm->drdynvc_channel == NULL || channel->vcm->drdynvc_state != DRDYNVC_STATE_READY) { DEBUG_DVC("drdynvc not ready"); return false; } else { s = stream_new(0); first = true; while (Length > 0) { item = xnew(wts_data_item); item->buffer = xmalloc(channel->client->settings->vc_chunk_size); stream_attach(s, item->buffer, channel->client->settings->vc_chunk_size); stream_seek_uint8(s); cbChId = wts_write_variable_uint(s, channel->channel_id); if (first && (Length > (uint32) stream_get_left(s))) { cbLen = wts_write_variable_uint(s, Length); item->buffer[0] = (DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId; } else { item->buffer[0] = (DATA_PDU << 4) | cbChId; } first = false; written = stream_get_left(s); if (written > Length) written = Length; stream_write(s, Buffer, written); item->length = stream_get_length(s); stream_detach(s); Length -= written; Buffer += written; wts_queue_send_item(channel->vcm->drdynvc_channel, item); } stream_free(s); } if (pBytesWritten != NULL) *pBytesWritten = Length; return true; }
BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate, wStream* s) { UINT32 dwSigAlgId; UINT32 dwKeyAlgId; UINT32 wPublicKeyBlobType; UINT32 wPublicKeyBlobLen; UINT32 wSignatureBlobType; UINT32 wSignatureBlobLen; BYTE* sigdata; int sigdatalen; if(stream_get_left(s) < 12) return FALSE; /* -4, because we need to include dwVersion */ sigdata = stream_get_tail(s) - 4; stream_read_UINT32(s, dwSigAlgId); stream_read_UINT32(s, dwKeyAlgId); if (!(dwSigAlgId == SIGNATURE_ALG_RSA && dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)) { fprintf(stderr, "certificate_read_server_proprietary_certificate: parse error 1\n"); return FALSE; } stream_read_UINT16(s, wPublicKeyBlobType); if (wPublicKeyBlobType != BB_RSA_KEY_BLOB) { fprintf(stderr, "certificate_read_server_proprietary_certificate: parse error 2\n"); return FALSE; } stream_read_UINT16(s, wPublicKeyBlobLen); if(stream_get_left(s) < wPublicKeyBlobLen) return FALSE; if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen)) { fprintf(stderr, "certificate_read_server_proprietary_certificate: parse error 3\n"); return FALSE; } if(stream_get_left(s) < 4) return FALSE; sigdatalen = stream_get_tail(s) - sigdata; stream_read_UINT16(s, wSignatureBlobType); if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB) { fprintf(stderr, "certificate_read_server_proprietary_certificate: parse error 4\n"); return FALSE; } stream_read_UINT16(s, wSignatureBlobLen); if(stream_get_left(s) < wSignatureBlobLen) return FALSE; if (wSignatureBlobLen != 72) { fprintf(stderr, "certificate_process_server_public_signature: invalid signature length (got %d, expected %d)\n", wSignatureBlobLen, 64); return FALSE; } if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s, wSignatureBlobLen)) { fprintf(stderr, "certificate_read_server_proprietary_certificate: parse error 5\n"); return FALSE; } return TRUE; }
RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, BYTE* data, UINT32 length) { int pos; STREAM* s; UINT32 blockLen; UINT32 blockType; RFX_MESSAGE* message; message = (RFX_MESSAGE*) malloc(sizeof(RFX_MESSAGE)); ZeroMemory(message, sizeof(RFX_MESSAGE)); s = stream_new(0); stream_attach(s, data, length); while (stream_get_left(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_get_left(s) < blockLen - 6) { DEBUG_WARN("rfx_process_message: packet too small for blocklen=%d", blockLen); break; } pos = stream_get_pos(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_skip(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_set_pos(s, pos); } stream_detach(s); stream_free(s); return message; }
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(0); stream_attach(s, cert->data, cert->length); 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_skip(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ goto error1; error++; /* issuer */ if(!ber_read_sequence_tag(s, &length) || !stream_skip(s, length)) /* Name (SEQUENCE) */ goto error1; error++; /* validity */ if(!ber_read_sequence_tag(s, &length) || !stream_skip(s, length)) /* Validity (SEQUENCE) */ goto error1; error++; /* subject */ if(!ber_read_sequence_tag(s, &length) || !stream_skip(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_skip(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_get_left(s) < 1) goto error1; stream_peek_BYTE(s, padding); if (padding == 0) { if(!stream_skip(s, 1)) goto error1; modulus_length--; } } while (padding == 0); error++; if(stream_get_left(s) < modulus_length) goto error1; info->ModulusLength = modulus_length; info->Modulus = (BYTE*) malloc(info->ModulusLength); stream_read(s, info->Modulus, info->ModulusLength); error++; if(!ber_read_integer_length(s, &exponent_length)) /* publicExponent (INTEGER) */ goto error2; error++; if(stream_get_left(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_detach(s); stream_free(s); 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_detach(s); stream_free(s); return FALSE; }