static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s) { int i, num_known_format = 0; UINT32 flags, vol, pitch; UINT16 udpPort; 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, 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) return FALSE; if (!context->num_client_formats) { WLog_ERR(TAG, "client doesn't support any format!"); 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) { WLog_ERR(TAG, "client doesn't support any known format!"); goto out_free; } return TRUE; out_free: free(context->client_formats); return FALSE; }
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_GetRemainingLength(s) < 12) return FALSE; /* -4, because we need to include dwVersion */ sigdata = Stream_Pointer(s) - 4; Stream_Read_UINT32(s, dwSigAlgId); Stream_Read_UINT32(s, dwKeyAlgId); if (!(dwSigAlgId == SIGNATURE_ALG_RSA && dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)) { fprintf(stderr, "%s: unsupported signature or key algorithm, dwSigAlgId=%d dwKeyAlgId=%d\n", __FUNCTION__, dwSigAlgId, dwKeyAlgId); return FALSE; } Stream_Read_UINT16(s, wPublicKeyBlobType); if (wPublicKeyBlobType != BB_RSA_KEY_BLOB) { fprintf(stderr, "%s: unsupported public key blob type %d\n", __FUNCTION__, wPublicKeyBlobType); return FALSE; } Stream_Read_UINT16(s, wPublicKeyBlobLen); if (Stream_GetRemainingLength(s) < wPublicKeyBlobLen) return FALSE; if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen)) { fprintf(stderr, "%s: error in server public key\n", __FUNCTION__); return FALSE; } if (Stream_GetRemainingLength(s) < 4) return FALSE; sigdatalen = Stream_Pointer(s) - sigdata; Stream_Read_UINT16(s, wSignatureBlobType); if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB) { fprintf(stderr, "%s: unsupported blob signature %d\n", __FUNCTION__, wSignatureBlobType); return FALSE; } Stream_Read_UINT16(s, wSignatureBlobLen); if (Stream_GetRemainingLength(s) < wSignatureBlobLen) { fprintf(stderr, "%s: not enought bytes for signature(len=%d)\n", __FUNCTION__, wSignatureBlobLen); return FALSE; } if (wSignatureBlobLen != 72) { fprintf(stderr, "%s: invalid signature length (got %d, expected %d)\n", __FUNCTION__, wSignatureBlobLen, 64); return FALSE; } if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s, wSignatureBlobLen)) { fprintf(stderr, "%s: unable to parse server public signature\n", __FUNCTION__); return FALSE; } return TRUE; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s) { UINT16 msgType; UINT16 msgFlags; UINT32 dataLen; UINT error; Stream_Read_UINT16(s, msgType); /* msgType (2 bytes) */ Stream_Read_UINT16(s, msgFlags); /* msgFlags (2 bytes) */ Stream_Read_UINT32(s, dataLen); /* dataLen (4 bytes) */ #ifdef WITH_DEBUG_CLIPRDR WLog_DBG(TAG, "msgType: %s (%d), msgFlags: %d dataLen: %d", CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), dataLen + 8); #endif switch (msgType) { case CB_CLIP_CAPS: if ((error = cliprdr_process_clip_caps(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_clip_caps failed with error %lu!", error); break; case CB_MONITOR_READY: if ((error = cliprdr_process_monitor_ready(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_monitor_ready failed with error %lu!", error); break; case CB_FORMAT_LIST: if ((error = cliprdr_process_format_list(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_format_list failed with error %lu!", error); break; case CB_FORMAT_LIST_RESPONSE: if ((error = cliprdr_process_format_list_response(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_format_list_response failed with error %lu!", error); break; case CB_FORMAT_DATA_REQUEST: if ((error = cliprdr_process_format_data_request(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_format_data_request failed with error %lu!", error); break; case CB_FORMAT_DATA_RESPONSE: if ((error = cliprdr_process_format_data_response(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_format_data_response failed with error %lu!", error); break; case CB_FILECONTENTS_REQUEST: if ((error = cliprdr_process_filecontents_request(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_filecontents_request failed with error %lu!", error); break; case CB_FILECONTENTS_RESPONSE: if ((error = cliprdr_process_filecontents_response(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_filecontents_response failed with error %lu!", error); break; case CB_LOCK_CLIPDATA: if ((error = cliprdr_process_lock_clipdata(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_lock_clipdata failed with error %lu!", error); break; case CB_UNLOCK_CLIPDATA: if ((error = cliprdr_process_unlock_clipdata(cliprdr, s, dataLen, msgFlags))) WLog_ERR(TAG, "cliprdr_process_lock_clipdata failed with error %lu!", error); break; default: error = CHANNEL_RC_BAD_PROC; WLog_ERR(TAG, "unknown msgType %d", msgType); break; } Stream_Free(s, TRUE); return error; }
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)); message->freeRects = TRUE; 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) */ WLog_Print(context->priv->log, WLOG_DEBUG, "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; }
static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s) { BOOL rc; int i, close_cnt; int pos; BYTE quant; RFX_TILE* tile; UINT32* quants; UINT16 subtype; UINT32 blockLen; UINT32 blockType; UINT32 tilesDataSize; PTP_WORK* work_objects = NULL; RFX_TILE_PROCESS_WORK_PARAM* params = NULL; if (Stream_GetRemainingLength(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_UINT8(s, context->numQuant); /* numQuant (1 byte) */ Stream_Seek_UINT8(s); /* tileSize (1 byte), must be set to 0x40 */ if (context->numQuant < 1) { DEBUG_WARN("no quantization value."); return TRUE; } Stream_Read_UINT16(s, message->numTiles); /* numTiles (2 bytes) */ if (message->numTiles < 1) { DEBUG_WARN("no tiles."); return TRUE; } Stream_Read_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */ context->quants = (UINT32 *)realloc((void*) context->quants, context->numQuant * 10 * sizeof(UINT32)); quants = context->quants; /* quantVals */ if (Stream_GetRemainingLength(s) < (size_t) (context->numQuant * 5)) { DEBUG_WARN("RfxMessageTileSet packet too small for num_quants=%d", context->numQuant); return FALSE; } for (i = 0; i < context->numQuant; i++) { /* RFX_CODEC_QUANT */ Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); WLog_Print(context->priv->log, WLOG_DEBUG, "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->numTiles); ZeroMemory(message->tiles, sizeof(RFX_TILE*) * message->numTiles); if (context->priv->UseThreads) { work_objects = (PTP_WORK*) malloc(sizeof(PTP_WORK) * message->numTiles); params = (RFX_TILE_PROCESS_WORK_PARAM*) malloc(sizeof(RFX_TILE_PROCESS_WORK_PARAM) * message->numTiles); if (!work_objects) { if (params) free(params); return FALSE; } if (!params) { if (work_objects) free(work_objects); return FALSE; } ZeroMemory(work_objects, sizeof(PTP_WORK) * message->numTiles); ZeroMemory(params, sizeof(RFX_TILE_PROCESS_WORK_PARAM) * message->numTiles); } /* tiles */ close_cnt = 0; rc = TRUE; for (i = 0; i < message->numTiles; i++) { tile = message->tiles[i] = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool); /* RFX_TILE */ if (Stream_GetRemainingLength(s) < 6) { DEBUG_WARN("RfxMessageTileSet packet too small to read tile %d/%d", i, message->numTiles); rc = FALSE; break; } 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_GetRemainingLength(s) < blockLen - 6) { DEBUG_WARN("RfxMessageTileSet not enough bytes to read tile %d/%d with blocklen=%d", i, message->numTiles, blockLen); rc = FALSE; break; } pos = Stream_GetPosition(s) - 6 + blockLen; if (blockType != CBT_TILE) { DEBUG_WARN("unknown block type 0x%X, expected CBT_TILE (0xCAC3).", blockType); break; } Stream_Read_UINT8(s, tile->quantIdxY); /* quantIdxY (1 byte) */ Stream_Read_UINT8(s, tile->quantIdxCb); /* quantIdxCb (1 byte) */ Stream_Read_UINT8(s, tile->quantIdxCr); /* quantIdxCr (1 byte) */ Stream_Read_UINT16(s, tile->xIdx); /* xIdx (2 bytes) */ Stream_Read_UINT16(s, tile->yIdx); /* yIdx (2 bytes) */ Stream_Read_UINT16(s, tile->YLen); /* YLen (2 bytes) */ Stream_Read_UINT16(s, tile->CbLen); /* CbLen (2 bytes) */ Stream_Read_UINT16(s, tile->CrLen); /* CrLen (2 bytes) */ Stream_GetPointer(s, tile->YData); Stream_Seek(s, tile->YLen); Stream_GetPointer(s, tile->CbData); Stream_Seek(s, tile->CbLen); Stream_GetPointer(s, tile->CrData); Stream_Seek(s, tile->CrLen); tile->x = tile->xIdx * 64; tile->y = tile->yIdx * 64; if (context->priv->UseThreads) { assert(params); params[i].context = context; params[i].tile = message->tiles[i]; work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_process_message_tile_work_callback, (void*) ¶ms[i], &context->priv->ThreadPoolEnv); SubmitThreadpoolWork(work_objects[i]); close_cnt = i + 1; } else { rfx_decode_rgb(context, tile, tile->data, 64 * 4); } Stream_SetPosition(s, pos); } if (context->priv->UseThreads) { for (i = 0; i < close_cnt; i++) { WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); CloseThreadpoolWork(work_objects[i]); } } if (work_objects) free(work_objects); if (params) free(params); for (i = 0; i < message->numTiles; i++) { tile = message->tiles[i]; tile->YLen = tile->CbLen = tile->CrLen = 0; tile->YData = tile->CbData = tile->CrData = NULL; } return rc; }
int rdpei_server_handle_messages(RdpeiServerContext *context) { DWORD bytesReturned; RdpeiServerPrivate *priv = context->priv; wStream *s = priv->inputStream; if (!WTSVirtualChannelRead(priv->channelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned)) { if (GetLastError() == ERROR_NO_DATA) return -1; fprintf(stderr, "%s: channel connection closed\n", __FUNCTION__); return 0; } priv->expectedBytes -= bytesReturned; Stream_Seek(s, bytesReturned); if (priv->expectedBytes) return 1; Stream_SealLength(s); Stream_SetPosition(s, 0); if (priv->waitingHeaders) { UINT32 pduLen; /* header case */ Stream_Read_UINT16(s, priv->currentMsgType); Stream_Read_UINT16(s, pduLen); if (pduLen < RDPINPUT_HEADER_LENGTH) { fprintf(stderr, "%s: invalid pduLength %d\n", __FUNCTION__, pduLen); return -1; } priv->expectedBytes = pduLen - RDPINPUT_HEADER_LENGTH; priv->waitingHeaders = FALSE; Stream_SetPosition(s, 0); if (priv->expectedBytes) { Stream_EnsureCapacity(s, priv->expectedBytes); return 1; } } /* when here we have the header + the body */ switch (priv->currentMsgType) { case EVENTID_CS_READY: if (priv->automataState != STATE_WAITING_CLIENT_READY) { fprintf(stderr, "%s: not expecting a CS_READY packet in this state(%d)\n", __FUNCTION__, (int)priv->automataState); return 0; } if (read_cs_ready_message(context, s) < 0) return 0; break; case EVENTID_TOUCH: if (read_touch_event(context, s) < 0) { fprintf(stderr, "%s: error in touch event packet\n", __FUNCTION__); return 0; } break; case EVENTID_DISMISS_HOVERING_CONTACT: if (read_dismiss_hovering_contact(context, s) < 0) { fprintf(stderr, "%s: error reading read_dismiss_hovering_contact\n", __FUNCTION__); return 0; } break; default: fprintf(stderr, "%s: unexpected message type 0x%x\n", __FUNCTION__, priv->currentMsgType); } Stream_SetPosition(s, 0); priv->waitingHeaders = TRUE; priv->expectedBytes = RDPINPUT_HEADER_LENGTH; return 1; }