void rdp_capability_set_finish(STREAM* s, uint8* header, uint16 type) { uint16 length; length = s->p - header; stream_set_mark(s, header); rdp_write_capability_set_header(s, length, type); stream_set_mark(s, header + length); }
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; }
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); } }
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; }
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; }
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; }
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; }
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; }
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); }
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--; } }