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); } }
void cliprdr_process_long_format_names(cliprdrPlugin* cliprdr, STREAM* s, uint32 length, uint16 flags) { int num_formats; uint8* start_mark; uint8* end_mark; CLIPRDR_FORMAT_NAME* format_name; num_formats = 0; stream_get_mark(s, start_mark); stream_get_mark(s, end_mark); end_mark += length; while (s->p < end_mark) { stream_seek_uint32(s); stream_seek(s, 32); num_formats++; } stream_set_mark(s, start_mark); cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) xmalloc(sizeof(CLIPRDR_FORMAT_NAME) * num_formats); cliprdr->num_format_names = num_formats; num_formats = 0; while (s->p < end_mark) { format_name = &cliprdr->format_names[num_formats++]; stream_read_uint32(s, format_name->id); format_name->name = freerdp_uniconv_in(cliprdr->uniconv, s->p, 32); format_name->length = strlen(format_name->name); stream_seek(s, 32); } }
void update_read_bitmap_data(STREAM* s, BITMAP_DATA* bitmap_data) { uint8* srcData; uint16 dstSize; boolean status; uint16 bytesPerPixel; stream_read_uint16(s, bitmap_data->left); stream_read_uint16(s, bitmap_data->top); stream_read_uint16(s, bitmap_data->right); stream_read_uint16(s, bitmap_data->bottom); stream_read_uint16(s, bitmap_data->width); stream_read_uint16(s, bitmap_data->height); stream_read_uint16(s, bitmap_data->bpp); stream_read_uint16(s, bitmap_data->flags); stream_read_uint16(s, bitmap_data->length); bytesPerPixel = (bitmap_data->bpp + 7) / 8; if (bitmap_data->flags & BITMAP_COMPRESSION) { uint16 cbCompMainBodySize; uint16 cbUncompressedSize; stream_seek_uint16(s); /* cbCompFirstRowSize (2 bytes) */ stream_read_uint16(s, cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */ stream_seek_uint16(s); /* cbScanWidth (2 bytes) */ stream_read_uint16(s, cbUncompressedSize); /* cbUncompressedSize (2 bytes) */ dstSize = cbUncompressedSize; bitmap_data->length = cbCompMainBodySize; bitmap_data->data = (uint8*) xzalloc(dstSize); stream_get_mark(s, srcData); stream_seek(s, bitmap_data->length); status = bitmap_decompress(srcData, bitmap_data->data, bitmap_data->width, bitmap_data->height, bitmap_data->length, bitmap_data->bpp, bitmap_data->bpp); if (status != True) printf("bitmap decompression failed, bpp:%d\n", bitmap_data->bpp); } else { int y; int offset; int scanline; stream_get_mark(s, srcData); dstSize = bitmap_data->length; bitmap_data->data = (uint8*) xzalloc(dstSize); scanline = bitmap_data->width * (bitmap_data->bpp / 8); for (y = 0; y < bitmap_data->height; y++) { offset = (bitmap_data->height - y - 1) * scanline; stream_read(s, &bitmap_data->data[offset], scanline); } } }
BOOL nego_send_negotiation_request(rdpNego* nego) { STREAM* s; int length; BYTE *bm, *em; int cookie_length; s = transport_send_stream_init(nego->transport, 256); length = TPDU_CONNECTION_REQUEST_LENGTH; stream_get_mark(s, bm); stream_seek(s, length); if (nego->RoutingToken != NULL) { stream_write(s, nego->RoutingToken, nego->RoutingTokenLength); length += nego->RoutingTokenLength; } else if (nego->cookie != NULL) { cookie_length = strlen(nego->cookie); if (cookie_length > (int) nego->cookie_max_length) cookie_length = nego->cookie_max_length; stream_write(s, "Cookie: mstshash=", 17); stream_write(s, (BYTE*) nego->cookie, cookie_length); stream_write_BYTE(s, 0x0D); /* CR */ stream_write_BYTE(s, 0x0A); /* LF */ length += cookie_length + 19; } DEBUG_NEGO("requested_protocols: %d", nego->requested_protocols); if (nego->requested_protocols > PROTOCOL_RDP) { /* RDP_NEG_DATA must be present for TLS and NLA */ stream_write_BYTE(s, TYPE_RDP_NEG_REQ); stream_write_BYTE(s, 0); /* flags, must be set to zero */ stream_write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ stream_write_UINT32(s, nego->requested_protocols); /* requestedProtocols */ length += 8; } stream_get_mark(s, em); stream_set_mark(s, bm); tpkt_write_header(s, length); tpdu_write_connection_request(s, length - 5); stream_set_mark(s, em); if (transport_write(nego->transport, s) < 0) return FALSE; return TRUE; }
boolean nego_send_negotiation_request(rdpNego* nego) { STREAM* s; int length; uint8 *bm, *em; s = transport_send_stream_init(nego->transport, 256); length = TPDU_CONNECTION_REQUEST_LENGTH; stream_get_mark(s, bm); stream_seek(s, length); if (nego->routing_token != NULL) { stream_write(s, nego->routing_token->data, nego->routing_token->length); length += nego->routing_token->length; } else if (nego->cookie != NULL) { int cookie_length = strlen(nego->cookie); stream_write(s, "Cookie: mstshash=", 17); stream_write(s, (uint8*) nego->cookie, cookie_length); stream_write_uint8(s, 0x0D); /* CR */ stream_write_uint8(s, 0x0A); /* LF */ length += cookie_length + 19; } DEBUG_NEGO("requested_protocols: %d", nego->requested_protocols); if (nego->requested_protocols > PROTOCOL_RDP) { /* RDP_NEG_DATA must be present for TLS and NLA */ stream_write_uint8(s, TYPE_RDP_NEG_REQ); stream_write_uint8(s, 0); /* flags, must be set to zero */ stream_write_uint16(s, 8); /* RDP_NEG_DATA length (8) */ stream_write_uint32(s, nego->requested_protocols); /* requestedProtocols */ length += 8; } stream_get_mark(s, em); stream_set_mark(s, bm); tpkt_write_header(s, length); tpdu_write_connection_request(s, length - 5); stream_set_mark(s, em); if (transport_write(nego->transport, s) < 0) return false; return true; }
uint8* rdp_capability_set_start(STREAM* s) { uint8* header; stream_get_mark(s, header); stream_seek(s, CAPSET_HEADER_LENGTH); return header; }
boolean rdp_client_connect_demand_active(rdpRdp* rdp, STREAM* s) { uint8* mark; uint16 width; uint16 height; width = rdp->settings->width; height = rdp->settings->height; stream_get_mark(s, mark); if (!rdp_recv_demand_active(rdp, s)) { stream_set_mark(s, mark); stream_seek(s, RDP_PACKET_HEADER_LENGTH); if (rdp_recv_out_of_sequence_pdu(rdp, s) != True) return False; return True; } if (!rdp_send_confirm_active(rdp)) return False; /** * The server may request a different desktop size during Deactivation-Reactivation sequence. * In this case, the UI should be informed and do actual window resizing at this point. */ if (width != rdp->settings->width || height != rdp->settings->height) { IFCALL(rdp->update->DesktopResize, rdp->update); } /** * [MS-RDPBCGR] 1.3.1.1 - 8. * The client-to-server PDUs sent during this phase have no dependencies on any of the server-to- * client PDUs; they may be sent as a single batch, provided that sequencing is maintained. */ if (!rdp_send_client_synchronize_pdu(rdp)) return False; if (!rdp_send_client_control_pdu(rdp, CTRLACTION_COOPERATE)) return False; if (!rdp_send_client_control_pdu(rdp, CTRLACTION_REQUEST_CONTROL)) return False; if (!rdp_send_client_persistent_key_list_pdu(rdp)) return False; if (!rdp_send_client_font_list_pdu(rdp, FONTLIST_FIRST | FONTLIST_LAST)) return False; rdp->state = CONNECTION_STATE_ACTIVE; update_reset_state(rdp->update); return True; }
static void wts_write_drdynvc_header(STREAM *s, uint8 Cmd, uint32 ChannelId) { uint8* bm; int cbChId; stream_get_mark(s, bm); stream_seek_uint8(s); cbChId = wts_write_variable_uint(s, ChannelId); *bm = ((Cmd & 0x0F) << 4) | cbChId; }
static void wts_write_drdynvc_header(wStream *s, BYTE Cmd, UINT32 ChannelId) { BYTE* bm; int cbChId; stream_get_mark(s, bm); stream_seek_BYTE(s); cbChId = wts_write_variable_uint(s, ChannelId); *bm = ((Cmd & 0x0F) << 4) | cbChId; }
boolean tsmf_codec_check_media_type(STREAM* s) { uint8* m; boolean ret; TS_AM_MEDIA_TYPE mediatype; stream_get_mark(s, m); ret = tsmf_codec_parse_media_type(&mediatype, s); stream_set_mark(s, m); return ret; }
tbool rdp_client_connect_demand_active(rdpRdp* rdp, STREAM* s) { uint8* mark; uint16 width; uint16 height; uint16 channelId; width = rdp->settings->width; height = rdp->settings->height; stream_get_mark(s, mark); if (!rdp_recv_demand_active(rdp, s)) { stream_set_mark(s, mark); rdp_recv_get_active_header(rdp, s, &channelId); /* Was stream_seek(s, RDP_PACKET_HEADER_MAX_LENGTH); * but the headers aren't always that length, * so that could result in a bad offset. */ if (rdp_recv_out_of_sequence_pdu(rdp, s) == false) return false; return true; } if (rdp->disconnect) return true; if (!rdp_send_confirm_active(rdp)) return false; input_register_client_callbacks(rdp->input); /** * The server may request a different desktop size during Deactivation-Reactivation sequence. * In this case, the UI should be informed and do actual window resizing at this point. */ if (width != rdp->settings->width || height != rdp->settings->height) { IFCALL(rdp->update->DesktopResize, rdp->update->context); } rdp->state = CONNECTION_STATE_FINALIZATION; update_reset_state(rdp->update); rdp_client_connect_finalize(rdp); return true; }
void update_read_bitmap_data(STREAM* s, BITMAP_DATA* bitmap_data) { uint8* srcData; uint16 dstSize; boolean status; uint16 bytesPerPixel; stream_read_uint16(s, bitmap_data->left); stream_read_uint16(s, bitmap_data->top); stream_read_uint16(s, bitmap_data->right); stream_read_uint16(s, bitmap_data->bottom); stream_read_uint16(s, bitmap_data->width); stream_read_uint16(s, bitmap_data->height); stream_read_uint16(s, bitmap_data->bpp); stream_read_uint16(s, bitmap_data->flags); stream_read_uint16(s, bitmap_data->length); bytesPerPixel = (bitmap_data->bpp + 7) / 8; if (bitmap_data->flags & BITMAP_COMPRESSION) { uint16 cbCompMainBodySize; uint16 cbUncompressedSize; stream_seek_uint16(s); /* cbCompFirstRowSize (2 bytes) */ stream_read_uint16(s, cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */ stream_seek_uint16(s); /* cbScanWidth (2 bytes) */ stream_read_uint16(s, cbUncompressedSize); /* cbUncompressedSize (2 bytes) */ dstSize = cbUncompressedSize; bitmap_data->length = cbCompMainBodySize; } else { dstSize = bitmap_data->width * bitmap_data->height * bytesPerPixel; } stream_get_mark(s, srcData); stream_seek(s, bitmap_data->length); bitmap_data->data = (uint8*) xzalloc(dstSize); //printf("bytesPerPixel:%d, width:%d, height:%d dstSize:%d flags:0x%04X\n", // bytesPerPixel, bitmap_data->width, bitmap_data->height, dstSize, bitmap_data->flags); status = bitmap_decompress(srcData, bitmap_data->data, bitmap_data->width, bitmap_data->height, bitmap_data->length, bitmap_data->bpp, bitmap_data->bpp); if (status != True) printf("bitmap decompression failed\n"); }
boolean nego_send_negotiation_response(rdpNego* nego) { STREAM* s; int length; uint8 *bm, *em; s = transport_send_stream_init(nego->transport, 256); length = TPDU_CONNECTION_CONFIRM_LENGTH; stream_get_mark(s, bm); stream_seek(s, length); if (nego->selected_protocol > PROTOCOL_RDP) { /* RDP_NEG_DATA must be present for TLS and NLA */ stream_write_uint8(s, TYPE_RDP_NEG_RSP); stream_write_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */ stream_write_uint16(s, 8); /* RDP_NEG_DATA length (8) */ stream_write_uint32(s, nego->selected_protocol); /* selectedProtocol */ length += 8; } stream_get_mark(s, em); stream_set_mark(s, bm); tpkt_write_header(s, length); tpdu_write_connection_confirm(s, length - 5); stream_set_mark(s, em); if (transport_write(nego->transport, s) < 0) return false; /* update settings with negotiated protocol security */ nego->transport->settings->requested_protocols = nego->requested_protocols; nego->transport->settings->selected_protocol = nego->selected_protocol; 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; }
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); } }
void cliprdr_process_short_format_names(cliprdrPlugin* cliprdr, STREAM* s, uint32 length, uint16 flags) { boolean ascii; int num_formats; uint8* end_mark; CLIPRDR_FORMAT_NAME* format_name; num_formats = length / 36; if (num_formats * 36 != length) DEBUG_WARN("dataLen %d not divided by 36!", length); ascii = (flags & CB_ASCII_NAMES) ? True : False; stream_get_mark(s, end_mark); end_mark += length; cliprdr->format_names = (CLIPRDR_FORMAT_NAME*) xmalloc(sizeof(CLIPRDR_FORMAT_NAME) * num_formats); cliprdr->num_format_names = num_formats; format_name = cliprdr->format_names; while (s->p < end_mark) { stream_read_uint32(s, format_name->id); if (ascii) { format_name->name = xstrdup((char*) s->p); format_name->length = strlen(format_name->name); } else { format_name->name = freerdp_uniconv_in(cliprdr->uniconv, s->p, 32); format_name->length = strlen(format_name->name); } stream_seek(s, 32); format_name++; } }
boolean update_recv_surfcmds(rdpUpdate* update, uint32 size, STREAM* s) { uint8* 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: cmdLength = update_recv_surfcmd_surface_bits(update, s); break; case CMDTYPE_FRAME_MARKER: cmdLength = update_recv_surfcmd_frame_marker(update, s); break; default: DEBUG_WARN("unknown cmdType 0x%X", cmdType); return false; } size -= cmdLength; if (update->dump_rfx) { pcap_add_record(update->pcap_rfx, mark, cmdLength + 2); pcap_flush(update->pcap_rfx); } } return true; }
/* receives a list of server supported formats and returns a list of client supported formats */ static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in) { uint16 wNumberOfFormats; uint16 nFormat; uint16 wVersion; STREAM* data_out; rdpsndFormat* out_formats; uint16 n_out_formats; rdpsndFormat* format; uint8* format_mark; uint8* data_mark; int pos; rdpsnd_free_supported_formats(rdpsnd); stream_seek_uint32(data_in); /* dwFlags */ stream_seek_uint32(data_in); /* dwVolume */ stream_seek_uint32(data_in); /* dwPitch */ stream_seek_uint16(data_in); /* wDGramPort */ stream_read_uint16(data_in, wNumberOfFormats); stream_read_uint8(data_in, rdpsnd->cBlockNo); /* cLastBlockConfirmed */ stream_read_uint16(data_in, wVersion); stream_seek_uint8(data_in); /* bPad */ DEBUG_SVC("wNumberOfFormats %d wVersion %d", wNumberOfFormats, wVersion); if (wNumberOfFormats < 1) { DEBUG_WARN("wNumberOfFormats is 0"); return; } out_formats = (rdpsndFormat*)xzalloc(wNumberOfFormats * sizeof(rdpsndFormat)); n_out_formats = 0; data_out = stream_new(24); stream_write_uint8(data_out, SNDC_FORMATS); /* msgType */ stream_write_uint8(data_out, 0); /* bPad */ stream_seek_uint16(data_out); /* BodySize */ stream_write_uint32(data_out, TSSNDCAPS_ALIVE | TSSNDCAPS_VOLUME); /* dwFlags */ stream_write_uint32(data_out, 0xFFFFFFFF); /* dwVolume */ stream_write_uint32(data_out, 0); /* dwPitch */ stream_write_uint16_be(data_out, 0); /* wDGramPort */ stream_seek_uint16(data_out); /* wNumberOfFormats */ stream_write_uint8(data_out, 0); /* cLastBlockConfirmed */ stream_write_uint16(data_out, 6); /* wVersion */ stream_write_uint8(data_out, 0); /* bPad */ for (nFormat = 0; nFormat < wNumberOfFormats; nFormat++) { stream_get_mark(data_in, format_mark); format = &out_formats[n_out_formats]; stream_read_uint16(data_in, format->wFormatTag); stream_read_uint16(data_in, format->nChannels); stream_read_uint32(data_in, format->nSamplesPerSec); stream_seek_uint32(data_in); /* nAvgBytesPerSec */ stream_read_uint16(data_in, format->nBlockAlign); stream_read_uint16(data_in, format->wBitsPerSample); stream_read_uint16(data_in, format->cbSize); stream_get_mark(data_in, data_mark); stream_seek(data_in, format->cbSize); format->data = NULL; DEBUG_SVC("wFormatTag=%d nChannels=%d nSamplesPerSec=%d nBlockAlign=%d wBitsPerSample=%d", format->wFormatTag, format->nChannels, format->nSamplesPerSec, format->nBlockAlign, format->wBitsPerSample); if (rdpsnd->fixed_format > 0 && rdpsnd->fixed_format != format->wFormatTag) continue; if (rdpsnd->fixed_channel > 0 && rdpsnd->fixed_channel != format->nChannels) continue; if (rdpsnd->fixed_rate > 0 && rdpsnd->fixed_rate != format->nSamplesPerSec) continue; if (rdpsnd->device && rdpsnd->device->FormatSupported(rdpsnd->device, format)) { DEBUG_SVC("format supported."); stream_check_size(data_out, 18 + format->cbSize); stream_write(data_out, format_mark, 18 + format->cbSize); if (format->cbSize > 0) { format->data = xmalloc(format->cbSize); memcpy(format->data, data_mark, format->cbSize); } n_out_formats++; } } rdpsnd->n_supported_formats = n_out_formats; if (n_out_formats > 0) { rdpsnd->supported_formats = out_formats; } else { xfree(out_formats); DEBUG_WARN("no formats supported"); } pos = stream_get_pos(data_out); stream_set_pos(data_out, 2); stream_write_uint16(data_out, pos - 4); stream_set_pos(data_out, 18); stream_write_uint16(data_out, n_out_formats); stream_set_pos(data_out, pos); svc_plugin_send((rdpSvcPlugin*)rdpsnd, data_out); if (wVersion >= 6) { data_out = stream_new(8); stream_write_uint8(data_out, SNDC_QUALITYMODE); /* msgType */ stream_write_uint8(data_out, 0); /* bPad */ stream_write_uint16(data_out, 4); /* BodySize */ stream_write_uint16(data_out, HIGH_QUALITY); /* wQualityMode */ stream_write_uint16(data_out, 0); /* Reserved */ svc_plugin_send((rdpSvcPlugin*)rdpsnd, data_out); } }
void krb_tgsreq_send(KRB_CONTEXT* krb_ctx, uint8 errcode) { KrbTGSREQ* krb_tgsreq; KrbAPREQ* krb_apreq; PAData** pa_data; Authenticator* krb_auth; STREAM* s; STREAM* sapreq; rdpBlob msg; uint32 curlen, totlen, tmp; uint8 *bm; bm = NULL; totlen = tmp = 0; krb_tgsreq = krb_tgsreq_new(krb_ctx, errcode); krb_auth = xnew(Authenticator); pa_data = krb_tgsreq->padata; s = stream_new(4096); sapreq = stream_new(2048); //Begin write asn1 data reversely into stream stream_seek(s, 4095); stream_seek(sapreq, 2047); /* KDC-REQ-BODY (TAG 4) */ totlen += krb_encode_req_body(s, &(krb_tgsreq->req_body), krb_tgsreq->type); stream_get_mark(s, bm); tmp = totlen; totlen += krb_encode_contextual_tag(s, 4, totlen); msg.data = bm; msg.length = tmp; /* Authenticator */ krb_auth->avno = KRB_VERSION; krb_auth->cname = krb_ctx->cname; krb_auth->crealm = krb_ctx->realm; krb_auth->cksumtype = get_cksum_type(krb_ctx->enctype); krb_auth->cksum = crypto_kdcmsg_cksum(&msg, krb_ctx->askey, 6); //RFC4757 section 3 for msgtype (T=6) krb_auth->ctime = krb_tgsreq->req_body.from; krb_auth->cusec = 0; crypto_nonce((uint8*)&(krb_auth->seqno), 4); /* PA-TGS-REQ */ krb_apreq = krb_apreq_new(krb_ctx, &(krb_ctx->asticket), krb_auth); curlen = krb_encode_apreq(sapreq, krb_apreq); msg.data = sapreq->p; msg.length = curlen; (*pa_data)->type = 1; (*pa_data)->value = msg; /* PA-DATA (TAG 3) */ curlen = krb_encode_padata(s, pa_data); totlen += curlen + krb_encode_contextual_tag(s, 3, curlen); /* MSGTYPE (TAG 2) */ totlen += krb_encode_uint8(s, 2, krb_tgsreq->type); /* VERSION NO (TAG 1) */ totlen += krb_encode_uint8(s, 1, krb_tgsreq->pvno); totlen += krb_encode_sequence_tag(s, totlen); totlen += krb_encode_application_tag(s, krb_tgsreq->type, totlen); totlen += krb_encode_recordmark(s, totlen); /* READY SEND */ krb_tcp_send(krb_ctx, s->p, totlen); /* save stuff */ krb_ctx->nonce = krb_tgsreq->req_body.nonce; xfree(krb_ctx->sname); krb_ctx->sname = xstrdup(krb_tgsreq->req_body.sname); krb_ctx->ctime = get_local_time(krb_tgsreq->req_body.from); krb_ctx->state = KRB_TGSREQ_OK; /* clean up */ freerdp_blob_free(krb_auth->cksum); xfree(krb_auth->cksum); xfree(krb_auth); krb_free_tgsreq(krb_tgsreq); xfree(krb_tgsreq); stream_free(sapreq); stream_free(s); }
BOOL nego_send_negotiation_response(rdpNego* nego) { STREAM* s; BYTE* bm; BYTE* em; int length; BOOL status; rdpSettings* settings; status = TRUE; settings = nego->transport->settings; s = transport_send_stream_init(nego->transport, 256); length = TPDU_CONNECTION_CONFIRM_LENGTH; stream_get_mark(s, bm); stream_seek(s, length); if (nego->selected_protocol > PROTOCOL_RDP) { /* RDP_NEG_DATA must be present for TLS and NLA */ stream_write_BYTE(s, TYPE_RDP_NEG_RSP); stream_write_BYTE(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */ stream_write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ stream_write_UINT32(s, nego->selected_protocol); /* selectedProtocol */ length += 8; } else if (!settings->RdpSecurity) { stream_write_BYTE(s, TYPE_RDP_NEG_FAILURE); stream_write_BYTE(s, 0); /* flags */ stream_write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ /* * TODO: Check for other possibilities, * like SSL_NOT_ALLOWED_BY_SERVER. */ printf("nego_send_negotiation_response: client supports only Standard RDP Security\n"); stream_write_UINT32(s, SSL_REQUIRED_BY_SERVER); length += 8; status = FALSE; } stream_get_mark(s, em); stream_set_mark(s, bm); tpkt_write_header(s, length); tpdu_write_connection_confirm(s, length - 5); stream_set_mark(s, em); if (transport_write(nego->transport, s) < 0) return FALSE; if (status) { /* update settings with negotiated protocol security */ settings->RequestedProtocols = nego->requested_protocols; settings->SelectedProtocol = nego->selected_protocol; if (settings->SelectedProtocol == PROTOCOL_RDP) { settings->TlsSecurity = FALSE; settings->NlaSecurity = FALSE; settings->RdpSecurity = TRUE; if (!settings->LocalConnection) { settings->DisableEncryption = TRUE; settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; } if (settings->DisableEncryption && settings->RdpServerRsaKey == NULL && settings->RdpKeyFile == NULL) return FALSE; } else if (settings->SelectedProtocol == PROTOCOL_TLS) { settings->TlsSecurity = TRUE; settings->NlaSecurity = FALSE; settings->RdpSecurity = FALSE; settings->DisableEncryption = FALSE; settings->EncryptionMethods = ENCRYPTION_METHOD_NONE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } else if (settings->SelectedProtocol == PROTOCOL_NLA) { settings->TlsSecurity = TRUE; settings->NlaSecurity = TRUE; settings->RdpSecurity = FALSE; settings->DisableEncryption = FALSE; settings->EncryptionMethods = ENCRYPTION_METHOD_NONE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } } return status; }
void rdp_read_demand_active(STREAM* s, rdpSettings* settings) { uint16 type; uint16 length; uint8 *bm, *em; uint16 numberCapabilities; uint16 lengthSourceDescriptor; uint16 lengthCombinedCapabilities; printf("Demand Active PDU\n"); stream_read_uint32(s, settings->share_id); /* shareId (4 bytes) */ stream_read_uint16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */ stream_read_uint16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */ stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor */ stream_read_uint16(s, numberCapabilities); /* numberCapabilities (2 bytes) */ stream_seek(s, 2); /* pad2Octets (2 bytes) */ /* capabilitySets */ while (numberCapabilities > 0) { stream_get_mark(s, bm); rdp_read_capability_set_header(s, &length, &type); printf("%s Capability Set (0x%02X), length:%d\n", CAPSET_TYPE_STRINGS[type], type, length); settings->received_caps[type] = True; em = bm + length; switch (type) { case CAPSET_TYPE_GENERAL: rdp_read_general_capability_set(s, settings); break; case CAPSET_TYPE_BITMAP: rdp_read_bitmap_capability_set(s, settings); break; case CAPSET_TYPE_ORDER: rdp_read_order_capability_set(s, settings); break; case CAPSET_TYPE_BITMAP_CACHE: rdp_read_bitmap_cache_capability_set(s, settings); break; case CAPSET_TYPE_CONTROL: rdp_read_control_capability_set(s, settings); break; case CAPSET_TYPE_ACTIVATION: rdp_read_window_activation_capability_set(s, settings); break; case CAPSET_TYPE_POINTER: rdp_read_pointer_capability_set(s, settings); break; case CAPSET_TYPE_SHARE: rdp_read_share_capability_set(s, settings); break; case CAPSET_TYPE_COLOR_CACHE: rdp_read_color_cache_capability_set(s, settings); break; case CAPSET_TYPE_SOUND: rdp_read_sound_capability_set(s, settings); break; case CAPSET_TYPE_INPUT: rdp_read_input_capability_set(s, settings); break; case CAPSET_TYPE_FONT: rdp_read_font_capability_set(s, settings); break; case CAPSET_TYPE_BRUSH: rdp_read_brush_capability_set(s, settings); break; case CAPSET_TYPE_GLYPH_CACHE: rdp_read_glyph_cache_capability_set(s, settings); break; case CAPSET_TYPE_OFFSCREEN_CACHE: rdp_read_offscreen_bitmap_cache_capability_set(s, settings); break; case CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT: rdp_read_bitmap_cache_host_support_capability_set(s, settings); break; case CAPSET_TYPE_BITMAP_CACHE_V2: rdp_read_bitmap_cache_v2_capability_set(s, settings); break; case CAPSET_TYPE_VIRTUAL_CHANNEL: rdp_read_virtual_channel_capability_set(s, settings); break; case CAPSET_TYPE_DRAW_NINE_GRID_CACHE: rdp_read_draw_nine_grid_cache_capability_set(s, settings); break; case CAPSET_TYPE_DRAW_GDI_PLUS: rdp_read_draw_gdiplus_cache_capability_set(s, settings); break; case CAPSET_TYPE_RAIL: rdp_read_remote_programs_capability_set(s, settings); break; case CAPSET_TYPE_WINDOW: rdp_read_window_list_capability_set(s, settings); break; case CAPSET_TYPE_COMP_DESK: rdp_read_desktop_composition_capability_set(s, settings); break; case CAPSET_TYPE_MULTI_FRAGMENT_UPDATE: rdp_read_multifragment_update_capability_set(s, settings); break; case CAPSET_TYPE_LARGE_POINTER: rdp_read_large_pointer_capability_set(s, settings); break; case CAPSET_TYPE_SURFACE_COMMANDS: rdp_read_surface_commands_capability_set(s, settings); break; case CAPSET_TYPE_BITMAP_CODECS: rdp_read_bitmap_codecs_capability_set(s, settings); break; case CAPSET_TYPE_FRAME_ACKNOWLEDGE: rdp_read_frame_acknowledge_capability_set(s, settings); break; default: break; } if (s->p != em) printf("incorrect offset, actual:%d expected:%d\n", (int) (s->p - bm), (int) (em - bm)); stream_set_mark(s, em); numberCapabilities--; } }
void rdp_write_confirm_active(STREAM* s, rdpSettings* settings) { uint8 *bm, *em, *lm; uint16 numberCapabilities; uint16 lengthSourceDescriptor; uint16 lengthCombinedCapabilities; lengthSourceDescriptor = sizeof(SOURCE_DESCRIPTOR); stream_write_uint32(s, settings->share_id); /* shareId (4 bytes) */ stream_write_uint16(s, 0x03EA); /* originatorId (2 bytes) */ stream_write_uint16(s, lengthSourceDescriptor);/* lengthSourceDescriptor (2 bytes) */ stream_get_mark(s, lm); stream_seek_uint16(s); /* lengthCombinedCapabilities (2 bytes) */ stream_write(s, SOURCE_DESCRIPTOR, lengthSourceDescriptor); /* sourceDescriptor */ stream_get_mark(s, bm); stream_seek_uint16(s); /* numberCapabilities (2 bytes) */ stream_write_uint16(s, 0); /* pad2Octets (2 bytes) */ /* Capability Sets */ numberCapabilities = 15; rdp_write_general_capability_set(s, settings); rdp_write_bitmap_capability_set(s, settings); rdp_write_order_capability_set(s, settings); rdp_write_bitmap_cache_capability_set(s, settings); rdp_write_pointer_capability_set(s, settings); rdp_write_input_capability_set(s, settings); rdp_write_brush_capability_set(s, settings); rdp_write_glyph_cache_capability_set(s, settings); rdp_write_offscreen_bitmap_cache_capability_set(s, settings); rdp_write_virtual_channel_capability_set(s, settings); rdp_write_sound_capability_set(s, settings); rdp_write_share_capability_set(s, settings); rdp_write_control_capability_set(s, settings); rdp_write_color_cache_capability_set(s, settings); rdp_write_window_activation_capability_set(s, settings); if (settings->offscreen_bitmap_cache) { numberCapabilities++; rdp_write_offscreen_bitmap_cache_capability_set(s, settings); } if (settings->received_caps[CAPSET_TYPE_MULTI_FRAGMENT_UPDATE]) { numberCapabilities++; rdp_write_multifragment_update_capability_set(s, settings); } if (settings->received_caps[CAPSET_TYPE_LARGE_POINTER]) { numberCapabilities++; rdp_write_large_pointer_capability_set(s, settings); } if (settings->received_caps[CAPSET_TYPE_SURFACE_COMMANDS]) { numberCapabilities++; rdp_write_surface_commands_capability_set(s, settings); } #if 0 if (settings->received_caps[CAPSET_TYPE_BITMAP_CODECS]) { numberCapabilities++; rdp_write_bitmap_codecs_capability_set(s, settings); } #endif if (settings->received_caps[CAPSET_TYPE_FRAME_ACKNOWLEDGE]) { if (settings->frame_acknowledge) { numberCapabilities++; rdp_write_frame_acknowledge_capability_set(s, settings); } } stream_get_mark(s, em); stream_set_mark(s, lm); /* go back to lengthCombinedCapabilities */ lengthCombinedCapabilities = (em - bm); stream_write_uint16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */ stream_set_mark(s, bm); /* go back to numberCapabilities */ stream_write_uint16(s, numberCapabilities); /* numberCapabilities (2 bytes) */ stream_set_mark(s, em); }
boolean nego_send_negotiation_response(rdpNego* nego) { STREAM* s; uint8* bm; uint8* em; int length; boolean status; rdpSettings* settings; status = true; settings = nego->transport->settings; s = transport_send_stream_init(nego->transport, 256); length = TPDU_CONNECTION_CONFIRM_LENGTH; stream_get_mark(s, bm); stream_seek(s, length); if (nego->selected_protocol > PROTOCOL_RDP) { /* RDP_NEG_DATA must be present for TLS and NLA */ stream_write_uint8(s, TYPE_RDP_NEG_RSP); stream_write_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */ stream_write_uint16(s, 8); /* RDP_NEG_DATA length (8) */ stream_write_uint32(s, nego->selected_protocol); /* selectedProtocol */ length += 8; } else if (!settings->rdp_security) { stream_write_uint8(s, TYPE_RDP_NEG_FAILURE); stream_write_uint8(s, 0); /* flags */ stream_write_uint16(s, 8); /* RDP_NEG_DATA length (8) */ /* * TODO: Check for other possibilities, * like SSL_NOT_ALLOWED_BY_SERVER. */ printf("nego_send_negotiation_response: client supports only Standard RDP Security\n"); stream_write_uint32(s, SSL_REQUIRED_BY_SERVER); length += 8; status = false; } stream_get_mark(s, em); stream_set_mark(s, bm); tpkt_write_header(s, length); tpdu_write_connection_confirm(s, length - 5); stream_set_mark(s, em); if (transport_write(nego->transport, s) < 0) return false; if (status) { /* update settings with negotiated protocol security */ settings->requested_protocols = nego->requested_protocols; settings->selected_protocol = nego->selected_protocol; if (settings->selected_protocol == PROTOCOL_RDP) { settings->tls_security = false; settings->nla_security = false; settings->rdp_security = true; if (!settings->local) { settings->encryption = true; settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; } if (settings->encryption && settings->server_key == NULL && settings->rdp_key_file == NULL) return false; } else if (settings->selected_protocol == PROTOCOL_TLS) { settings->tls_security = true; settings->nla_security = false; settings->rdp_security = false; settings->encryption = false; settings->encryption_method = ENCRYPTION_METHOD_NONE; settings->encryption_level = ENCRYPTION_LEVEL_NONE; } else if (settings->selected_protocol == PROTOCOL_NLA) { settings->tls_security = true; settings->nla_security = true; settings->rdp_security = false; settings->encryption = false; settings->encryption_method = ENCRYPTION_METHOD_NONE; settings->encryption_level = ENCRYPTION_LEVEL_NONE; } } return status; }
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; }