static UINT32 drdynvc_read_variable_uint(STREAM* stream, int cbLen) { UINT32 val; switch (cbLen) { case 0: stream_read_BYTE(stream, val); break; case 1: stream_read_UINT16(stream, val); break; default: stream_read_UINT32(stream, val); break; } return val; }
BOOL rail_read_unicode_string(wStream* s, RAIL_UNICODE_STRING* unicode_string) { if (stream_get_left(s) < 2) return FALSE; stream_read_UINT16(s, unicode_string->length); /* cbString (2 bytes) */ if (stream_get_left(s) < unicode_string->length) return FALSE; if (unicode_string->string == NULL) unicode_string->string = (BYTE*) malloc(unicode_string->length); else unicode_string->string = (BYTE*) realloc(unicode_string->string, unicode_string->length); stream_read(s, unicode_string->string, unicode_string->length); 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; }
int update_recv_surfcmds(rdpUpdate* update, UINT32 size, STREAM* s) { BYTE* mark; UINT16 cmdType; UINT32 cmdLength; while (size > 2) { stream_get_mark(s, mark); stream_read_UINT16(s, cmdType); size -= 2; switch (cmdType) { case CMDTYPE_SET_SURFACE_BITS: case CMDTYPE_STREAM_SURFACE_BITS: if (!update_recv_surfcmd_surface_bits(update, s, &cmdLength)) return -1; break; case CMDTYPE_FRAME_MARKER: if (!update_recv_surfcmd_frame_marker(update, s, &cmdLength)) return -1; break; default: DEBUG_WARN("unknown cmdType 0x%X", cmdType); return -1; } size -= cmdLength; if (update->dump_rfx) { pcap_add_record(update->pcap_rfx, mark, cmdLength + 2); pcap_flush(update->pcap_rfx); } } return 0; }
BOOL update_read_icon_info(wStream* s, ICON_INFO* icon_info) { if(stream_get_left(s) < 8) return FALSE; stream_read_UINT16(s, icon_info->cacheEntry); /* cacheEntry (2 bytes) */ stream_read_BYTE(s, icon_info->cacheId); /* cacheId (1 byte) */ stream_read_BYTE(s, icon_info->bpp); /* bpp (1 byte) */ stream_read_UINT16(s, icon_info->width); /* width (2 bytes) */ stream_read_UINT16(s, icon_info->height); /* height (2 bytes) */ /* cbColorTable is only present when bpp is 1, 2 or 4 */ if (icon_info->bpp == 1 || icon_info->bpp == 2 || icon_info->bpp == 4) { if(stream_get_left(s) < 2) return FALSE; stream_read_UINT16(s, icon_info->cbColorTable); /* cbColorTable (2 bytes) */ } else { icon_info->cbColorTable = 0; } if(stream_get_left(s) < 4) return FALSE; stream_read_UINT16(s, icon_info->cbBitsMask); /* cbBitsMask (2 bytes) */ stream_read_UINT16(s, icon_info->cbBitsColor); /* cbBitsColor (2 bytes) */ if(stream_get_left(s) < icon_info->cbBitsMask + icon_info->cbBitsColor) return FALSE; /* bitsMask */ if (icon_info->bitsMask == NULL) icon_info->bitsMask = (BYTE*) malloc(icon_info->cbBitsMask); else icon_info->bitsMask = (BYTE*) realloc(icon_info->bitsMask, icon_info->cbBitsMask); stream_read(s, icon_info->bitsMask, icon_info->cbBitsMask); /* colorTable */ if (icon_info->colorTable == NULL) icon_info->colorTable = (BYTE*) malloc(icon_info->cbColorTable); else icon_info->colorTable = (BYTE*) realloc(icon_info->colorTable, icon_info->cbColorTable); stream_read(s, icon_info->colorTable, icon_info->cbColorTable); /* bitsColor */ if (icon_info->bitsColor == NULL) icon_info->bitsColor = (BYTE*) malloc(icon_info->cbBitsColor); else icon_info->bitsColor = (BYTE*) realloc(icon_info->bitsColor, icon_info->cbBitsColor); stream_read(s, icon_info->bitsColor, icon_info->cbBitsColor); return TRUE; }
BOOL update_recv(rdpUpdate* update, STREAM* s) { UINT16 updateType; rdpContext* context = update->context; stream_read_UINT16(s, updateType); /* updateType (2 bytes) */ //printf("%s Update Data PDU\n", UPDATE_TYPE_STRINGS[updateType]); IFCALL(update->BeginPaint, context); switch (updateType) { case UPDATE_TYPE_ORDERS: if (!update_recv_orders(update, s)) { /* XXX: Do we have to call EndPaint? */ return FALSE; } break; case UPDATE_TYPE_BITMAP: update_read_bitmap(update, s, &update->bitmap_update); IFCALL(update->BitmapUpdate, context, &update->bitmap_update); break; case UPDATE_TYPE_PALETTE: update_read_palette(update, s, &update->palette_update); IFCALL(update->Palette, context, &update->palette_update); break; case UPDATE_TYPE_SYNCHRONIZE: update_read_synchronize(update, s); IFCALL(update->Synchronize, context); break; } IFCALL(update->EndPaint, context); return TRUE; }
void update_recv_pointer(rdpUpdate* update, STREAM* s) { UINT16 messageType; rdpContext* context = update->context; rdpPointerUpdate* pointer = update->pointer; stream_read_UINT16(s, messageType); /* messageType (2 bytes) */ stream_seek_UINT16(s); /* pad2Octets (2 bytes) */ switch (messageType) { case PTR_MSG_TYPE_POSITION: update_read_pointer_position(s, &pointer->pointer_position); IFCALL(pointer->PointerPosition, context, &pointer->pointer_position); break; case PTR_MSG_TYPE_SYSTEM: update_read_pointer_system(s, &pointer->pointer_system); IFCALL(pointer->PointerSystem, context, &pointer->pointer_system); break; case PTR_MSG_TYPE_COLOR: update_read_pointer_color(s, &pointer->pointer_color); IFCALL(pointer->PointerColor, context, &pointer->pointer_color); break; case PTR_MSG_TYPE_POINTER: update_read_pointer_new(s, &pointer->pointer_new); IFCALL(pointer->PointerNew, context, &pointer->pointer_new); break; case PTR_MSG_TYPE_CACHED: update_read_pointer_cached(s, &pointer->pointer_cached); IFCALL(pointer->PointerCached, context, &pointer->pointer_cached); break; default: break; } }
static BOOL rdpsnd_server_recv_formats(rdpsnd_server* rdpsnd, STREAM* s) { int i; if (stream_get_left(s) < 20) return FALSE; stream_seek_UINT32(s); /* dwFlags */ stream_seek_UINT32(s); /* dwVolume */ stream_seek_UINT32(s); /* dwPitch */ stream_seek_UINT16(s); /* wDGramPort */ stream_read_UINT16(s, rdpsnd->context.num_client_formats); /* wNumberOfFormats */ stream_seek_BYTE(s); /* cLastBlockConfirmed */ stream_seek_UINT16(s); /* wVersion */ stream_seek_BYTE(s); /* bPad */ if (rdpsnd->context.num_client_formats > 0) { rdpsnd->context.client_formats = (rdpsndFormat*) malloc(rdpsnd->context.num_client_formats * sizeof(rdpsndFormat)); ZeroMemory(rdpsnd->context.client_formats, sizeof(rdpsndFormat)); for (i = 0; i < rdpsnd->context.num_client_formats; i++) { if (stream_get_left(s) < 18) { free(rdpsnd->context.client_formats); rdpsnd->context.client_formats = NULL; return FALSE; } stream_read_UINT16(s, rdpsnd->context.client_formats[i].wFormatTag); stream_read_UINT16(s, rdpsnd->context.client_formats[i].nChannels); stream_read_UINT32(s, rdpsnd->context.client_formats[i].nSamplesPerSec); stream_seek_UINT32(s); /* nAvgBytesPerSec */ stream_read_UINT16(s, rdpsnd->context.client_formats[i].nBlockAlign); stream_read_UINT16(s, rdpsnd->context.client_formats[i].wBitsPerSample); stream_read_UINT16(s, rdpsnd->context.client_formats[i].cbSize); if (rdpsnd->context.client_formats[i].cbSize > 0) { stream_seek(s, rdpsnd->context.client_formats[i].cbSize); } } } return TRUE; }
BOOL input_recv(rdpInput* input, STREAM* s) { UINT16 i, numberEvents; if (stream_get_left(s) < 4) return FALSE; stream_read_UINT16(s, numberEvents); /* numberEvents (2 bytes) */ stream_seek(s, 2); /* pad2Octets (2 bytes) */ /* Each input event uses 6 exactly bytes. */ if (stream_get_left(s) < 6 * numberEvents) return FALSE; for (i = 0; i < numberEvents; i++) { if (!input_recv_event(input, s)) return FALSE; } return TRUE; }
static void xf_cliprdr_process_dib(clipboardContext* cb, BYTE* data, int size) { STREAM* s; UINT16 bpp; UINT32 offset; UINT32 ncolors; /* size should be at least sizeof(BITMAPINFOHEADER) */ if (size < 40) { DEBUG_X11_CLIPRDR("dib size %d too short", size); return; } s = stream_new(0); stream_attach(s, data, size); stream_seek(s, 14); stream_read_UINT16(s, bpp); stream_read_UINT32(s, ncolors); offset = 14 + 40 + (bpp <= 8 ? (ncolors == 0 ? (1 << bpp) : ncolors) * 4 : 0); stream_detach(s); stream_free(s); DEBUG_X11_CLIPRDR("offset=%d bpp=%d ncolors=%d", offset, bpp, ncolors); s = stream_new(14 + size); stream_write_BYTE(s, 'B'); stream_write_BYTE(s, 'M'); stream_write_UINT32(s, 14 + size); stream_write_UINT32(s, 0); stream_write_UINT32(s, offset); stream_write(s, data, size); cb->data = stream_get_head(s); cb->data_length = stream_get_length(s); stream_detach(s); stream_free(s); }
static void rfx_process_message_sync(RFX_CONTEXT* context, STREAM* s) { UINT32 magic; /* RFX_SYNC */ stream_read_UINT32(s, magic); /* magic (4 bytes), 0xCACCACCA */ if (magic != WF_MAGIC) { DEBUG_WARN("invalid magic number 0x%X", magic); return; } stream_read_UINT16(s, context->version); /* version (2 bytes), WF_VERSION_1_0 (0x0100) */ if (context->version != WF_VERSION_1_0) { DEBUG_WARN("unknown version number 0x%X", context->version); return; } DEBUG_RFX("version 0x%X", context->version); }
static int wts_read_variable_uint(wStream* s, int cbLen, UINT32* val) { switch (cbLen) { case 0: if (stream_get_left(s) < 1) return 0; stream_read_BYTE(s, *val); return 1; case 1: if (stream_get_left(s) < 2) return 0; stream_read_UINT16(s, *val); return 2; default: if (stream_get_left(s) < 4) return 0; stream_read_UINT32(s, *val); return 4; } }
void nego_process_negotiation_failure(rdpNego* nego, STREAM* s) { BYTE flags; UINT16 length; UINT32 failureCode; DEBUG_NEGO("RDP_NEG_FAILURE"); stream_read_BYTE(s, flags); stream_read_UINT16(s, length); stream_read_UINT32(s, failureCode); switch (failureCode) { case SSL_REQUIRED_BY_SERVER: DEBUG_NEGO("Error: SSL_REQUIRED_BY_SERVER"); break; case SSL_NOT_ALLOWED_BY_SERVER: DEBUG_NEGO("Error: SSL_NOT_ALLOWED_BY_SERVER"); break; case SSL_CERT_NOT_ON_SERVER: DEBUG_NEGO("Error: SSL_CERT_NOT_ON_SERVER"); break; case INCONSISTENT_FLAGS: DEBUG_NEGO("Error: INCONSISTENT_FLAGS"); break; case HYBRID_REQUIRED_BY_SERVER: DEBUG_NEGO("Error: HYBRID_REQUIRED_BY_SERVER"); break; default: DEBUG_NEGO("Error: Unknown protocol security error %d", failureCode); break; } nego->state = NEGO_STATE_FAIL; }
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) */ }
static int update_recv_surfcmd_surface_bits(rdpUpdate* update, STREAM* s) { int pos; SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command; stream_read_UINT16(s, cmd->destLeft); stream_read_UINT16(s, cmd->destTop); stream_read_UINT16(s, cmd->destRight); stream_read_UINT16(s, cmd->destBottom); stream_read_BYTE(s, cmd->bpp); stream_seek(s, 2); /* reserved1, reserved2 */ stream_read_BYTE(s, cmd->codecID); stream_read_UINT16(s, cmd->width); stream_read_UINT16(s, cmd->height); stream_read_UINT32(s, cmd->bitmapDataLength); pos = stream_get_pos(s) + cmd->bitmapDataLength; cmd->bitmapData = stream_get_tail(s); IFCALL(update->SurfaceBits, update->context, cmd); stream_set_pos(s, pos); return 20 + cmd->bitmapDataLength; }
static void rdpdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) { UINT16 component; UINT16 packetID; UINT32 deviceID; UINT32 status; rdpdrPlugin* rdpdr = (rdpdrPlugin*) plugin; stream_read_UINT16(data_in, component); stream_read_UINT16(data_in, packetID); if (component == RDPDR_CTYP_CORE) { switch (packetID) { case PAKID_CORE_SERVER_ANNOUNCE: DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_SERVER_ANNOUNCE"); rdpdr_process_server_announce_request(rdpdr, data_in); rdpdr_send_client_announce_reply(rdpdr); rdpdr_send_client_name_request(rdpdr); break; case PAKID_CORE_SERVER_CAPABILITY: DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_SERVER_CAPABILITY"); rdpdr_process_capability_request(rdpdr, data_in); rdpdr_send_capability_response(rdpdr); break; case PAKID_CORE_CLIENTID_CONFIRM: DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_CLIENTID_CONFIRM"); rdpdr_process_server_clientid_confirm(rdpdr, data_in); rdpdr_send_device_list_announce_request(rdpdr, FALSE); break; case PAKID_CORE_USER_LOGGEDON: DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_USER_LOGGEDON"); rdpdr_send_device_list_announce_request(rdpdr, TRUE); break; case PAKID_CORE_DEVICE_REPLY: /* connect to a specific resource */ stream_read_UINT32(data_in, deviceID); stream_read_UINT32(data_in, status); DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_DEVICE_REPLY (deviceID=%d status=0x%08X)", deviceID, status); break; case PAKID_CORE_DEVICE_IOREQUEST: DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_DEVICE_IOREQUEST"); if (rdpdr_process_irp(rdpdr, data_in)) data_in = NULL; break; default: DEBUG_WARN("RDPDR_CTYP_CORE / unknown packetID: 0x%02X", packetID); break; } } else if (component == RDPDR_CTYP_PRN) { DEBUG_SVC("RDPDR_CTYP_PRN"); } else { DEBUG_WARN("RDPDR component: 0x%02X packetID: 0x%02X", component, packetID); } stream_free(data_in); }
BOOL gcc_read_client_core_data(STREAM* s, rdpSettings* settings, UINT16 blockLength) { char* str; UINT32 version; UINT32 color_depth; UINT16 colorDepth = 0; UINT16 postBeta2ColorDepth = 0; UINT16 highColorDepth = 0; UINT16 supportedColorDepths = 0; UINT16 earlyCapabilityFlags = 0; UINT32 serverSelectedProtocol = 0; /* Length of all required fields, until imeFileName */ if (blockLength < 128) return FALSE; stream_read_UINT32(s, version); /* version */ settings->RdpVersion = (version == RDP_VERSION_4 ? 4 : 7); stream_read_UINT16(s, settings->DesktopWidth); /* DesktopWidth */ stream_read_UINT16(s, settings->DesktopHeight); /* DesktopHeight */ stream_read_UINT16(s, colorDepth); /* ColorDepth */ stream_seek_UINT16(s); /* SASSequence (Secure Access Sequence) */ stream_read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout */ stream_read_UINT32(s, settings->ClientBuild); /* ClientBuild */ /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */ ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(s), 32 / 2, &str, 0, NULL, NULL); stream_seek(s, 32); sprintf_s(settings->ClientHostname, 31, "%s", str); settings->ClientHostname[31] = 0; free(str); stream_read_UINT32(s, settings->KeyboardType); /* KeyboardType */ stream_read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType */ stream_read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey */ stream_seek(s, 64); /* imeFileName */ blockLength -= 128; /** * The following fields are all optional. If one field is present, all of the preceding * fields MUST also be present. If one field is not present, all of the subsequent fields * MUST NOT be present. * We must check the bytes left before reading each field. */ do { if (blockLength < 2) break; stream_read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */ blockLength -= 2; if (blockLength < 2) break; stream_seek_UINT16(s); /* clientProductID */ blockLength -= 2; if (blockLength < 4) break; stream_seek_UINT32(s); /* serialNumber */ blockLength -= 4; if (blockLength < 2) break; stream_read_UINT16(s, highColorDepth); /* highColorDepth */ blockLength -= 2; if (blockLength < 2) break; stream_read_UINT16(s, supportedColorDepths); /* supportedColorDepths */ blockLength -= 2; if (blockLength < 2) break; stream_read_UINT16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */ blockLength -= 2; if (blockLength < 64) break; ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(s), 64 / 2, &str, 0, NULL, NULL); stream_seek(s, 64); sprintf_s(settings->ClientProductId, 32, "%s", str); free(str); blockLength -= 64; if (blockLength < 1) break; stream_read_BYTE(s, settings->PerformanceFlags); /* connectionType */ blockLength -= 1; if (blockLength < 1) break; stream_seek_BYTE(s); /* pad1octet */ blockLength -= 1; if (blockLength < 4) break; stream_read_UINT32(s, serverSelectedProtocol); /* serverSelectedProtocol */ blockLength -= 4; if (settings->SelectedProtocol != serverSelectedProtocol) return FALSE; } while (0); if (highColorDepth > 0) { color_depth = highColorDepth; } else if (postBeta2ColorDepth > 0) { switch (postBeta2ColorDepth) { case RNS_UD_COLOR_4BPP: color_depth = 4; break; case RNS_UD_COLOR_8BPP: color_depth = 8; break; case RNS_UD_COLOR_16BPP_555: color_depth = 15; break; case RNS_UD_COLOR_16BPP_565: color_depth = 16; break; case RNS_UD_COLOR_24BPP: color_depth = 24; break; default: return FALSE; } } else { switch (colorDepth) { case RNS_UD_COLOR_4BPP: color_depth = 4; break; case RNS_UD_COLOR_8BPP: color_depth = 8; break; default: return FALSE; } } /* * If we are in server mode, accept client's color depth only if * it is smaller than ours. This is what Windows server does. */ if (color_depth < settings->ColorDepth || !settings->ServerMode) settings->ColorDepth = color_depth; 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; }
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 update_read_window_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* window_state) { int i; int size; if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) { if(stream_get_left(s) < 4) return FALSE; stream_read_UINT32(s, window_state->ownerWindowId); /* ownerWindowId (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) { if(stream_get_left(s) < 8) return FALSE; stream_read_UINT32(s, window_state->style); /* style (4 bytes) */ stream_read_UINT32(s, window_state->extendedStyle); /* extendedStyle (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) { if(stream_get_left(s) < 1) return FALSE; stream_read_BYTE(s, window_state->showState); /* showState (1 byte) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) { if(!rail_read_unicode_string(s, &window_state->titleInfo)) /* titleInfo */ return FALSE; } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) { if(stream_get_left(s) < 4) return FALSE; stream_read_UINT32(s, window_state->clientOffsetX); /* clientOffsetX (4 bytes) */ stream_read_UINT32(s, window_state->clientOffsetY); /* clientOffsetY (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) { if(stream_get_left(s) < 4) return FALSE; stream_read_UINT32(s, window_state->clientAreaWidth); /* clientAreaWidth (4 bytes) */ stream_read_UINT32(s, window_state->clientAreaHeight); /* clientAreaHeight (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) { if(stream_get_left(s) < 1) return FALSE; stream_read_BYTE(s, window_state->RPContent); /* RPContent (1 byte) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) { if(stream_get_left(s) < 4) return FALSE; stream_read_UINT32(s, window_state->rootParentHandle);/* rootParentHandle (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) { if(stream_get_left(s) < 8) return FALSE; stream_read_UINT32(s, window_state->windowOffsetX); /* windowOffsetX (4 bytes) */ stream_read_UINT32(s, window_state->windowOffsetY); /* windowOffsetY (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) { if(stream_get_left(s) < 8) return FALSE; stream_read_UINT32(s, window_state->windowClientDeltaX); /* windowClientDeltaX (4 bytes) */ stream_read_UINT32(s, window_state->windowClientDeltaY); /* windowClientDeltaY (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) { if(stream_get_left(s) < 8) return FALSE; stream_read_UINT32(s, window_state->windowWidth); /* windowWidth (4 bytes) */ stream_read_UINT32(s, window_state->windowHeight); /* windowHeight (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) { if(stream_get_left(s) < 2) return FALSE; stream_read_UINT16(s, window_state->numWindowRects); /* numWindowRects (2 bytes) */ size = sizeof(RECTANGLE_16) * window_state->numWindowRects; window_state->windowRects = (RECTANGLE_16*) malloc(size); if(stream_get_left(s) < 8 * window_state->numWindowRects) return FALSE; /* windowRects */ for (i = 0; i < (int) window_state->numWindowRects; i++) { stream_read_UINT16(s, window_state->windowRects[i].left); /* left (2 bytes) */ stream_read_UINT16(s, window_state->windowRects[i].top); /* top (2 bytes) */ stream_read_UINT16(s, window_state->windowRects[i].right); /* right (2 bytes) */ stream_read_UINT16(s, window_state->windowRects[i].bottom); /* bottom (2 bytes) */ } } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) { if(stream_get_left(s) < 4) return FALSE; stream_read_UINT32(s, window_state->visibleOffsetX); /* visibleOffsetX (4 bytes) */ stream_read_UINT32(s, window_state->visibleOffsetY); /* visibleOffsetY (4 bytes) */ } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) { if(stream_get_left(s) < 2) return FALSE; stream_read_UINT16(s, window_state->numVisibilityRects); /* numVisibilityRects (2 bytes) */ size = sizeof(RECTANGLE_16) * window_state->numVisibilityRects; window_state->visibilityRects = (RECTANGLE_16*) malloc(size); if(stream_get_left(s) < window_state->numVisibilityRects * 8) return FALSE; /* visibilityRects */ for (i = 0; i < (int) window_state->numVisibilityRects; i++) { stream_read_UINT16(s, window_state->visibilityRects[i].left); /* left (2 bytes) */ stream_read_UINT16(s, window_state->visibilityRects[i].top); /* top (2 bytes) */ stream_read_UINT16(s, window_state->visibilityRects[i].right); /* right (2 bytes) */ stream_read_UINT16(s, window_state->visibilityRects[i].bottom); /* bottom (2 bytes) */ } } return TRUE; }
void update_read_pointer_position(STREAM* s, POINTER_POSITION_UPDATE* pointer_position) { stream_read_UINT16(s, pointer_position->xPos); /* xPos (2 bytes) */ stream_read_UINT16(s, pointer_position->yPos); /* yPos (2 bytes) */ }
BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, STREAM* s) { UINT16 flags; UINT16 length; rdpRedirection* redirection = rdp->redirection; if(stream_get_left(s) < 12) return FALSE; stream_read_UINT16(s, flags); /* flags (2 bytes) */ stream_read_UINT16(s, length); /* length (2 bytes) */ stream_read_UINT32(s, redirection->sessionID); /* sessionID (4 bytes) */ stream_read_UINT32(s, redirection->flags); /* redirFlags (4 bytes) */ DEBUG_REDIR("flags: 0x%04X, length:%d, sessionID:0x%08X", flags, length, redirection->sessionID); #ifdef WITH_DEBUG_REDIR rdp_print_redirection_flags(redirection->flags); #endif if (redirection->flags & LB_TARGET_NET_ADDRESS) { if(!freerdp_string_read_length32(s, &redirection->targetNetAddress)) return FALSE; DEBUG_REDIR("targetNetAddress: %s", redirection->targetNetAddress.ascii); } if (redirection->flags & LB_LOAD_BALANCE_INFO) { if(stream_get_left(s) < 4) return FALSE; stream_read_UINT32(s, redirection->LoadBalanceInfoLength); if(stream_get_left(s) < redirection->LoadBalanceInfoLength) return FALSE; redirection->LoadBalanceInfo = (BYTE*) malloc(redirection->LoadBalanceInfoLength); stream_read(s, redirection->LoadBalanceInfo, redirection->LoadBalanceInfoLength); #ifdef WITH_DEBUG_REDIR DEBUG_REDIR("loadBalanceInfo:"); winpr_HexDump(redirection->LoadBalanceInfo, redirection->LoadBalanceInfoLength); #endif } if (redirection->flags & LB_USERNAME) { if(!freerdp_string_read_length32(s, &redirection->username)) return FALSE; DEBUG_REDIR("username: %s", redirection->username.ascii); } if (redirection->flags & LB_DOMAIN) { if(!freerdp_string_read_length32(s, &redirection->domain)) return FALSE; DEBUG_REDIR("domain: %s", redirection->domain.ascii); } if (redirection->flags & LB_PASSWORD) { /* Note: length (hopefully) includes double zero termination */ if(stream_get_left(s) < 4) return FALSE; stream_read_UINT32(s, redirection->PasswordCookieLength); redirection->PasswordCookie = (BYTE*) malloc(redirection->PasswordCookieLength); stream_read(s, redirection->PasswordCookie, redirection->PasswordCookieLength); #ifdef WITH_DEBUG_REDIR DEBUG_REDIR("password_cookie:"); winpr_HexDump(redirection->PasswordCookie, redirection->PasswordCookieLength); #endif } if (redirection->flags & LB_TARGET_FQDN) { if(!freerdp_string_read_length32(s, &redirection->targetFQDN)) return FALSE; DEBUG_REDIR("targetFQDN: %s", redirection->targetFQDN.ascii); } if (redirection->flags & LB_TARGET_NETBIOS_NAME) { if(!freerdp_string_read_length32(s, &redirection->targetNetBiosName)) return FALSE; DEBUG_REDIR("targetNetBiosName: %s", redirection->targetNetBiosName.ascii); } if (redirection->flags & LB_CLIENT_TSV_URL) { if(!freerdp_string_read_length32(s, &redirection->tsvUrl)) return FALSE; DEBUG_REDIR("tsvUrl: %s", redirection->tsvUrl.ascii); } if (redirection->flags & LB_TARGET_NET_ADDRESSES) { int i; UINT32 count; UINT32 targetNetAddressesLength; if(stream_get_left(s) < 8) return FALSE; stream_read_UINT32(s, targetNetAddressesLength); stream_read_UINT32(s, redirection->targetNetAddressesCount); count = redirection->targetNetAddressesCount; redirection->targetNetAddresses = (rdpString*) malloc(count * sizeof(rdpString)); ZeroMemory(redirection->targetNetAddresses, count * sizeof(rdpString)); for (i = 0; i < (int) count; i++) { if(!freerdp_string_read_length32(s, &redirection->targetNetAddresses[i])) return FALSE; DEBUG_REDIR("targetNetAddresses: %s", (&redirection->targetNetAddresses[i])->ascii); } } if (!stream_skip(s, 8)) /* pad (8 bytes) */ return FALSE; if (redirection->flags & LB_NOREDIRECT) return TRUE; else return rdp_client_redirect(rdp); }
void rail_read_pdu_header(STREAM* s, UINT16* orderType, UINT16* orderLength) { stream_read_UINT16(s, *orderType); /* orderType (2 bytes) */ stream_read_UINT16(s, *orderLength); /* orderLength (2 bytes) */ }
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; }
void update_read_pointer_new(STREAM* s, POINTER_NEW_UPDATE* pointer_new) { stream_read_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */ update_read_pointer_color(s, &pointer_new->colorPtrAttr); /* colorPtrAttr */ }
void update_read_pointer_cached(STREAM* s, POINTER_CACHED_UPDATE* pointer_cached) { stream_read_UINT16(s, pointer_cached->cacheIndex); /* cacheIndex (2 bytes) */ }
static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* s) { int i; UINT16 subtype; UINT32 blockLen; UINT32 blockType; UINT32 tilesDataSize; UINT32* quants; BYTE quant; int pos; 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; } 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; } stream_read_UINT16(s, message->num_tiles); /* numTiles (2 bytes) */ if (message->num_tiles < 1) { DEBUG_WARN("no tiles."); return; } 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 */ 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_pool_get_tiles(context->priv->pool, message->num_tiles); /* tiles */ for (i = 0; i < message->num_tiles; i++) { /* RFX_TILE */ stream_read_UINT16(s, blockType); /* blockType (2 bytes), must be set to CBT_TILE (0xCAC3) */ stream_read_UINT32(s, blockLen); /* blockLen (4 bytes) */ pos = stream_get_pos(s) - 6 + blockLen; if (blockType != CBT_TILE) { DEBUG_WARN("unknown block type 0x%X, expected CBT_TILE (0xCAC3).", blockType); break; } rfx_process_message_tile(context, message->tiles[i], s); stream_set_pos(s, pos); } }
void rdp_read_security_header(STREAM* s, UINT16* flags) { /* Basic Security Header */ stream_read_UINT16(s, *flags); /* flags */ stream_seek(s, 2); /* flagsHi (unused) */ }
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; }
void update_read_bitmap_data(STREAM* s, BITMAP_DATA* bitmap_data) { stream_read_UINT16(s, bitmap_data->destLeft); stream_read_UINT16(s, bitmap_data->destTop); stream_read_UINT16(s, bitmap_data->destRight); stream_read_UINT16(s, bitmap_data->destBottom); stream_read_UINT16(s, bitmap_data->width); stream_read_UINT16(s, bitmap_data->height); stream_read_UINT16(s, bitmap_data->bitsPerPixel); stream_read_UINT16(s, bitmap_data->flags); stream_read_UINT16(s, bitmap_data->bitmapLength); if (bitmap_data->flags & BITMAP_COMPRESSION) { if (!(bitmap_data->flags & NO_BITMAP_COMPRESSION_HDR)) { stream_read_UINT16(s, bitmap_data->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */ stream_read_UINT16(s, bitmap_data->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */ stream_read_UINT16(s, bitmap_data->cbScanWidth); /* cbScanWidth (2 bytes) */ stream_read_UINT16(s, bitmap_data->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */ bitmap_data->bitmapLength = bitmap_data->cbCompMainBodySize; } bitmap_data->compressed = TRUE; stream_get_mark(s, bitmap_data->bitmapDataStream); stream_seek(s, bitmap_data->bitmapLength); } else { bitmap_data->compressed = FALSE; stream_get_mark(s, bitmap_data->bitmapDataStream); stream_seek(s, bitmap_data->bitmapLength); } }