BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings) { int i; UINT16 MCSChannelId; UINT16 channelCount; UINT16 channelId; if(Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */ Stream_Read_UINT16(s, channelCount); /* channelCount */ if (channelCount != settings->ChannelCount) { fprintf(stderr, "requested %d channels, got %d instead\n", settings->ChannelCount, channelCount); } if(Stream_GetRemainingLength(s) < channelCount * 2) return FALSE; for (i = 0; i < channelCount; i++) { Stream_Read_UINT16(s, channelId); /* channelId */ settings->ChannelDefArray[i].ChannelId = channelId; } if (channelCount % 2 == 1) return Stream_SafeSeek(s, 2); /* padding */ return TRUE; }
int rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s) { int status = 0; if (!Stream_SafeSeek(s, 2)) /* pad2Octets (2 bytes) */ return -1; status = rdp_recv_server_redirection_pdu(rdp, s); if (status < 0) return status; if (!Stream_SafeSeek(s, 1)) /* pad2Octets (1 byte) */ return -1; return status; }
BOOL ber_read_integer(wStream* s, UINT32* value) { int length; if (!ber_read_universal_tag(s, BER_TAG_INTEGER, FALSE) || !ber_read_length(s, &length) || ((int) Stream_GetRemainingLength(s)) < length) return FALSE; if (value == NULL) { // even if we don't care the integer value, check the announced size return Stream_SafeSeek(s, length); } if (length == 1) { Stream_Read_UINT8(s, *value); } else if (length == 2) { Stream_Read_UINT16_BE(s, *value); } else if (length == 3) { BYTE byte; Stream_Read_UINT8(s, byte); Stream_Read_UINT16_BE(s, *value); *value += (byte << 16); } else if (length == 4) { Stream_Read_UINT32_BE(s, *value); } else if (length == 8) { WLog_ERR(TAG, "should implement reading an 8 bytes integer"); return FALSE; } else { WLog_ERR(TAG, "should implement reading an integer with length=%d", length); return FALSE; } return TRUE; }
int rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s) { int status = 0; if (!Stream_SafeSeek(s, 2)) /* pad2Octets (2 bytes) */ return -1; status = rdp_recv_server_redirection_pdu(rdp, s); if (status < 0) return status; if (Stream_GetRemainingLength(s) >= 1) { /* this field is optional, and its absence is not an error */ Stream_Seek(s, 1); /* pad2Octets (1 byte) */ } return status; }
BOOL gcc_read_server_network_data(wStream* s, rdpMcs* mcs) { int i; UINT16 channelId; UINT16 MCSChannelId; UINT16 channelCount; UINT16 parsedChannelCount; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */ Stream_Read_UINT16(s, channelCount); /* channelCount */ parsedChannelCount = channelCount; if (channelCount != mcs->channelCount) { WLog_ERR(TAG, "requested %d channels, got %d instead", mcs->channelCount, channelCount); /* we ensure that the response is not bigger than the request */ if (channelCount > mcs->channelCount) parsedChannelCount = mcs->channelCount; } if (Stream_GetRemainingLength(s) < (size_t) channelCount * 2) return FALSE; for (i = 0; i < parsedChannelCount; i++) { Stream_Read_UINT16(s, channelId); /* channelId */ mcs->channels[i].ChannelId = channelId; } if (channelCount % 2 == 1) return Stream_SafeSeek(s, 2); /* padding */ return TRUE; }
BOOL tpdu_read_header(wStream* s, BYTE* code, BYTE* li) { if (Stream_GetRemainingLength(s) < 3) return FALSE; Stream_Read_UINT8(s, *li); /* LI */ Stream_Read_UINT8(s, *code); /* Code */ if (*code == X224_TPDU_DATA) { /* EOT (1 byte) */ Stream_Seek(s, 1); } else { /* DST-REF (2 bytes) */ /* SRC-REF (2 bytes) */ /* Class 0 (1 byte) */ return Stream_SafeSeek(s, 5); } return TRUE; }
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; if (!cert || !info) return FALSE; memset(info, 0, sizeof(rdpCertInfo)); 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: WLog_ERR(TAG, "error reading when reading certificate: part=%s error=%d", certificate_read_errors[error], error); Stream_Free(s, FALSE); return FALSE; }
BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) { UINT16 flags; UINT16 length; rdpRedirection* redirection = rdp->redirection; if (Stream_GetRemainingLength(s) < 12) return -1; 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) */ WLog_Print(redirection->log, WLOG_DEBUG, "flags: 0x%04X, redirFlags: 0x%04X length: %d, sessionID: 0x%08X", flags, redirection->flags, length, redirection->sessionID); #ifdef WITH_DEBUG_REDIR rdp_print_redirection_flags(redirection->flags); #endif if (redirection->flags & LB_TARGET_NET_ADDRESS) { if (!rdp_redirection_read_string(s, &(redirection->TargetNetAddress))) return -1; } if (redirection->flags & LB_LOAD_BALANCE_INFO) { if (Stream_GetRemainingLength(s) < 4) return -1; Stream_Read_UINT32(s, redirection->LoadBalanceInfoLength); if (Stream_GetRemainingLength(s) < redirection->LoadBalanceInfoLength) return -1; 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 (!rdp_redirection_read_string(s, &(redirection->Username))) return -1; WLog_Print(redirection->log, WLOG_DEBUG, "Username: %s", redirection->Username); } if (redirection->flags & LB_DOMAIN) { if (!rdp_redirection_read_string(s, &(redirection->Domain))) return FALSE; WLog_Print(redirection->log, WLOG_DEBUG, "Domain: %s", redirection->Domain); } if (redirection->flags & LB_PASSWORD) { /* Note: length (hopefully) includes double zero termination */ if (Stream_GetRemainingLength(s) < 4) return -1; Stream_Read_UINT32(s, redirection->PasswordLength); redirection->Password = (BYTE*) malloc(redirection->PasswordLength); Stream_Read(s, redirection->Password, redirection->PasswordLength); #ifdef WITH_DEBUG_REDIR DEBUG_REDIR("PasswordCookie:"); winpr_HexDump(redirection->Password, redirection->PasswordLength); #endif } if (redirection->flags & LB_TARGET_FQDN) { if (!rdp_redirection_read_string(s, &(redirection->TargetFQDN))) return -1; WLog_Print(redirection->log, WLOG_DEBUG, "TargetFQDN: %s", redirection->TargetFQDN); } if (redirection->flags & LB_TARGET_NETBIOS_NAME) { if (!rdp_redirection_read_string(s, &(redirection->TargetNetBiosName))) return -1; WLog_Print(redirection->log, WLOG_DEBUG, "TargetNetBiosName: %s", redirection->TargetNetBiosName); } if (redirection->flags & LB_CLIENT_TSV_URL) { if (Stream_GetRemainingLength(s) < 4) return -1; Stream_Read_UINT32(s, redirection->TsvUrlLength); if (Stream_GetRemainingLength(s) < redirection->TsvUrlLength) return -1; redirection->TsvUrl = (BYTE*) malloc(redirection->TsvUrlLength); Stream_Read(s, redirection->TsvUrl, redirection->TsvUrlLength); #ifdef WITH_DEBUG_REDIR DEBUG_REDIR("TsvUrl:"); winpr_HexDump(redirection->TsvUrl, redirection->TsvUrlLength); #endif } if (redirection->flags & LB_TARGET_NET_ADDRESSES) { int i; UINT32 count; UINT32 targetNetAddressesLength; if (Stream_GetRemainingLength(s) < 8) return -1; Stream_Read_UINT32(s, targetNetAddressesLength); Stream_Read_UINT32(s, redirection->TargetNetAddressesCount); count = redirection->TargetNetAddressesCount; redirection->TargetNetAddresses = (char**) malloc(count * sizeof(char*)); ZeroMemory(redirection->TargetNetAddresses, count * sizeof(char*)); WLog_Print(redirection->log, WLOG_DEBUG, "TargetNetAddressesCount: %d", redirection->TargetNetAddressesCount); for (i = 0; i < (int) count; i++) { if (!rdp_redirection_read_string(s, &(redirection->TargetNetAddresses[i]))) return FALSE; WLog_Print(redirection->log, WLOG_DEBUG, "TargetNetAddresses[%d]: %s", i, redirection->TargetNetAddresses[i]); } } if (!Stream_SafeSeek(s, 8)) /* pad (8 bytes) */ return -1; if (redirection->flags & LB_NOREDIRECT) return 0; return 1; }
static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s) { int i, num_known_format = 0; UINT32 flags, vol, pitch; UINT16 udpPort, version; BYTE lastblock; if (Stream_GetRemainingLength(s) < 20) return FALSE; Stream_Read_UINT32(s, flags); /* dwFlags */ Stream_Read_UINT32(s, vol); /* dwVolume */ Stream_Read_UINT32(s, pitch); /* dwPitch */ Stream_Read_UINT16(s, udpPort); /* wDGramPort */ Stream_Read_UINT16(s, context->num_client_formats); /* wNumberOfFormats */ Stream_Read_UINT8(s, lastblock); /* cLastBlockConfirmed */ Stream_Read_UINT16(s, version); /* wVersion */ Stream_Seek_UINT8(s); /* bPad */ /* this check is only a guess as cbSize can influence the size of a format record */ if (Stream_GetRemainingLength(s) < context->num_client_formats * 18) return FALSE; if (!context->num_client_formats) { fprintf(stderr, "%s: client doesn't support any format!\n", __FUNCTION__); return FALSE; } context->client_formats = (AUDIO_FORMAT *)calloc(context->num_client_formats, sizeof(AUDIO_FORMAT)); if (!context->client_formats) return FALSE; for (i = 0; i < context->num_client_formats; i++) { if (Stream_GetRemainingLength(s) < 18) goto out_free; Stream_Read_UINT16(s, context->client_formats[i].wFormatTag); Stream_Read_UINT16(s, context->client_formats[i].nChannels); Stream_Read_UINT32(s, context->client_formats[i].nSamplesPerSec); Stream_Read_UINT32(s, context->client_formats[i].nAvgBytesPerSec); Stream_Read_UINT16(s, context->client_formats[i].nBlockAlign); Stream_Read_UINT16(s, context->client_formats[i].wBitsPerSample); Stream_Read_UINT16(s, context->client_formats[i].cbSize); if (context->client_formats[i].cbSize > 0) { if (!Stream_SafeSeek(s, context->client_formats[i].cbSize)) goto out_free; } if (context->client_formats[i].wFormatTag != 0) { //lets call this a known format //TODO: actually look through our own list of known formats num_known_format++; } } if (!context->num_client_formats) { fprintf(stderr, "%s: client doesn't support any known format!\n", __FUNCTION__); goto out_free; } return TRUE; out_free: free(context->client_formats); return FALSE; }
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; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s) { int i, num_known_format = 0; UINT32 flags, vol, pitch; UINT16 udpPort; BYTE lastblock; UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 20) { WLog_ERR(TAG, "not enought data in stream!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, flags); /* dwFlags */ Stream_Read_UINT32(s, vol); /* dwVolume */ Stream_Read_UINT32(s, pitch); /* dwPitch */ Stream_Read_UINT16(s, udpPort); /* wDGramPort */ Stream_Read_UINT16(s, context->num_client_formats); /* wNumberOfFormats */ Stream_Read_UINT8(s, lastblock); /* cLastBlockConfirmed */ Stream_Read_UINT16(s, context->clientVersion); /* wVersion */ Stream_Seek_UINT8(s); /* bPad */ /* this check is only a guess as cbSize can influence the size of a format record */ if (Stream_GetRemainingLength(s) < context->num_client_formats * 18) { WLog_ERR(TAG, "not enought data in stream!"); return ERROR_INVALID_DATA; } if (!context->num_client_formats) { WLog_ERR(TAG, "client doesn't support any format!"); return ERROR_INTERNAL_ERROR; } context->client_formats = (AUDIO_FORMAT *)calloc(context->num_client_formats, sizeof(AUDIO_FORMAT)); if (!context->client_formats) { WLog_ERR(TAG, "calloc failed!"); return CHANNEL_RC_NO_MEMORY; } for (i = 0; i < context->num_client_formats; i++) { if (Stream_GetRemainingLength(s) < 18) { WLog_ERR(TAG, "not enought data in stream!"); error = ERROR_INVALID_DATA; goto out_free; } Stream_Read_UINT16(s, context->client_formats[i].wFormatTag); Stream_Read_UINT16(s, context->client_formats[i].nChannels); Stream_Read_UINT32(s, context->client_formats[i].nSamplesPerSec); Stream_Read_UINT32(s, context->client_formats[i].nAvgBytesPerSec); Stream_Read_UINT16(s, context->client_formats[i].nBlockAlign); Stream_Read_UINT16(s, context->client_formats[i].wBitsPerSample); Stream_Read_UINT16(s, context->client_formats[i].cbSize); if (context->client_formats[i].cbSize > 0) { if (!Stream_SafeSeek(s, context->client_formats[i].cbSize)) { WLog_ERR(TAG, "Stream_SafeSeek failed!"); error = ERROR_INTERNAL_ERROR; goto out_free; } } if (context->client_formats[i].wFormatTag != 0) { //lets call this a known format //TODO: actually look through our own list of known formats num_known_format++; } } if (!context->num_client_formats) { WLog_ERR(TAG, "client doesn't support any known format!"); goto out_free; } return CHANNEL_RC_OK; out_free: free(context->client_formats); return error; }