BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channel_id) { UINT16 initiator; enum DomainMCSPDU MCSPDU; MCSPDU = (rdp->settings->ServerMode) ? DomainMCSPDU_SendDataRequest : DomainMCSPDU_SendDataIndication; if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, length)) { if (MCSPDU != DomainMCSPDU_DisconnectProviderUltimatum) return FALSE; } if (*length - 8 > Stream_GetRemainingLength(s)) return FALSE; if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum) { BYTE reason; (void) per_read_enumerated(s, &reason, 0); DEBUG_RDP("DisconnectProviderUltimatum from server, reason code 0x%02x\n", reason); rdp->disconnect = TRUE; return TRUE; } if (Stream_GetRemainingLength(s) < 5) return FALSE; 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) */ if (!per_read_length(s, length)) /* userData (OCTET_STRING) */ return FALSE; if (*length > Stream_GetRemainingLength(s)) return FALSE; return TRUE; }
int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s) { BYTE type; UINT32 roff; UINT32 rlen; wStream* cs; BYTE* buffer; 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 -1; cs = s; if (compressed_type & PACKET_COMPRESSED) { if (Stream_GetRemainingLength(s) < compressed_len - 18) { fprintf(stderr, "decompress_rdp: not enough bytes for compressed_len=%d\n", compressed_len); return -1; } if (decompress_rdp(rdp->mppc_dec, Stream_Pointer(s), compressed_len - 18, compressed_type, &roff, &rlen)) { buffer = rdp->mppc_dec->history_buf + roff; cs = StreamPool_Take(rdp->transport->ReceivePool, rlen); Stream_SetPosition(cs, 0); Stream_Write(cs, buffer, rlen); Stream_SealLength(cs); Stream_SetPosition(cs, 0); } else { fprintf(stderr, "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, cs)) return -1; break; case DATA_PDU_TYPE_CONTROL: if (!rdp_recv_server_control_pdu(rdp, cs)) return -1; break; case DATA_PDU_TYPE_POINTER: if (!update_recv_pointer(rdp->update, cs)) return -1; break; case DATA_PDU_TYPE_INPUT: break; case DATA_PDU_TYPE_SYNCHRONIZE: if (!rdp_recv_synchronize_pdu(rdp, cs)) return -1; break; case DATA_PDU_TYPE_REFRESH_RECT: break; case DATA_PDU_TYPE_PLAY_SOUND: if (!update_recv_play_sound(rdp->update, cs)) 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, cs)) return -1; break; case DATA_PDU_TYPE_FONT_LIST: break; case DATA_PDU_TYPE_FONT_MAP: if (!rdp_recv_font_map_pdu(rdp, cs)) 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, cs)) 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 (cs != s) Stream_Release(cs); return 0; }
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; }