wStream* license_send_stream_init(rdpLicense* license) { wStream* s; BOOL do_crypt = license->rdp->do_crypt; license->rdp->sec_flags = SEC_LICENSE_PKT; /** * Encryption of licensing packets is optional even if the rdp security * layer is used. If the peer has not indicated that it is capable of * processing encrypted licensing packets (rdp->do_crypt_license) we turn * off encryption (via rdp->do_crypt) before initializing the rdp stream * and reenable it afterwards. */ if (do_crypt) { license->rdp->sec_flags |= SEC_LICENSE_ENCRYPT_CS; license->rdp->do_crypt = license->rdp->do_crypt_license; } s = transport_send_stream_init(license->rdp->transport, 4096); if (!s) return NULL; rdp_init_stream(license->rdp, s); license->rdp->do_crypt = do_crypt; license->PacketHeaderLength = Stream_GetPosition(s); Stream_Seek(s, LICENSE_PREAMBLE_LENGTH); return s; }
STREAM* rdp_send_stream_init(rdpRdp* rdp) { STREAM* s; s = transport_send_stream_init(rdp->transport, 2048); stream_seek(s, RDP_PACKET_HEADER_LENGTH); return s; }
wStream* rdp_data_pdu_init(rdpRdp* rdp) { wStream* s; s = transport_send_stream_init(rdp->transport, 2048); rdp_init_stream_data_pdu(rdp, s); return s; }
STREAM* license_send_stream_init(rdpLicense* license) { STREAM* s; s = transport_send_stream_init(license->rdp->transport, 4096); stream_seek(s, LICENSE_PACKET_HEADER_MAX_LENGTH); return s; }
wStream* rdp_message_channel_pdu_init(rdpRdp* rdp) { wStream* s; s = transport_send_stream_init(rdp->transport, 2048); Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH); rdp_security_stream_init(rdp, s); return s; }
STREAM* rdp_pdu_init(rdpRdp* rdp) { STREAM* s; s = transport_send_stream_init(rdp->transport, 2048); stream_seek(s, RDP_PACKET_HEADER_MAX_LENGTH); rdp_security_stream_init(rdp, s); stream_seek(s, RDP_SHARE_CONTROL_HEADER_LENGTH); return s; }
STREAM* rdp_data_pdu_init(rdpRdp* rdp) { STREAM* s; s = transport_send_stream_init(rdp->transport, 2048); stream_seek(s, RDP_PACKET_HEADER_LENGTH); stream_seek(s, RDP_SHARE_CONTROL_HEADER_LENGTH); stream_seek(s, RDP_SHARE_DATA_HEADER_LENGTH); return s; }
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; }
boolean nego_send_preconnection_pdu(rdpNego* nego) { STREAM* s; uint32 cbSize; UNICONV* uniconv; uint16 cchPCB_times2 = 0; char* wszPCB = NULL; if (!nego->send_preconnection_pdu) return true; DEBUG_NEGO("Sending preconnection PDU"); if (!nego_tcp_connect(nego)) return false; /* it's easier to always send the version 2 PDU, and it's just 2 bytes overhead */ cbSize = PRECONNECTION_PDU_V2_MIN_SIZE; if (nego->preconnection_blob) { size_t size; uniconv = freerdp_uniconv_new(); wszPCB = freerdp_uniconv_out(uniconv, nego->preconnection_blob, &size); cchPCB_times2 = (uint16) size; freerdp_uniconv_free(uniconv); cchPCB_times2 += 2; /* zero-termination */ cbSize += cchPCB_times2; } s = transport_send_stream_init(nego->transport, cbSize); stream_write_uint32(s, cbSize); /* cbSize */ stream_write_uint32(s, 0); /* Flags */ stream_write_uint32(s, PRECONNECTION_PDU_V2); /* Version */ stream_write_uint32(s, nego->preconnection_id); /* Id */ stream_write_uint16(s, cchPCB_times2 / 2); /* cchPCB */ if (wszPCB) { stream_write(s, wszPCB, cchPCB_times2); /* wszPCB */ xfree(wszPCB); } if (transport_write(nego->transport, s) < 0) return false; return true; }
wStream* license_send_stream_init(rdpLicense* license) { wStream* s; license->rdp->sec_flags = SEC_LICENSE_PKT; if (license->rdp->do_crypt) license->rdp->sec_flags |= SEC_LICENSE_ENCRYPT_CS; s = transport_send_stream_init(license->rdp->transport, 4096); rdp_init_stream(license->rdp, s); license->PacketHeaderLength = Stream_GetPosition(s); Stream_Seek(s, LICENSE_PREAMBLE_LENGTH); return s; }
BOOL nego_send_preconnection_pdu(rdpNego* nego) { STREAM* s; UINT32 cbSize; UINT16 cchPCB = 0; WCHAR* wszPCB = NULL; if (!nego->send_preconnection_pdu) return TRUE; DEBUG_NEGO("Sending preconnection PDU"); if (!nego_tcp_connect(nego)) return FALSE; /* it's easier to always send the version 2 PDU, and it's just 2 bytes overhead */ cbSize = PRECONNECTION_PDU_V2_MIN_SIZE; if (nego->preconnection_blob) { cchPCB = (UINT16) ConvertToUnicode(CP_UTF8, 0, nego->preconnection_blob, -1, &wszPCB, 0); cchPCB += 1; /* zero-termination */ cbSize += cchPCB * 2; } s = transport_send_stream_init(nego->transport, cbSize); stream_write_UINT32(s, cbSize); /* cbSize */ stream_write_UINT32(s, 0); /* Flags */ stream_write_UINT32(s, PRECONNECTION_PDU_V2); /* Version */ stream_write_UINT32(s, nego->preconnection_id); /* Id */ stream_write_UINT16(s, cchPCB); /* cchPCB */ if (wszPCB) { stream_write(s, wszPCB, cchPCB * 2); /* wszPCB */ free(wszPCB); } if (transport_write(nego->transport, s) < 0) return FALSE; 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; }
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 boolean rdp_establish_keys(rdpRdp* rdp) { uint8 client_random[32]; uint8 crypt_client_random[256 + 8]; uint32 key_len; uint8* mod; uint8* exp; uint32 length; STREAM* s; if (rdp->settings->encryption == False) { /* no RDP encryption */ return True; } /* encrypt client random */ memset(crypt_client_random, 0, sizeof(crypt_client_random)); memset(client_random, 0x5e, 32); crypto_nonce(client_random, 32); key_len = rdp->settings->server_cert->cert_info.modulus.length; mod = rdp->settings->server_cert->cert_info.modulus.data; exp = rdp->settings->server_cert->cert_info.exponent; crypto_rsa_encrypt(client_random, 32, key_len, mod, exp, crypt_client_random); /* send crypt client random to server */ length = 7 + 8 + 4 + 4 + key_len + 8; s = transport_send_stream_init(rdp->mcs->transport, length); tpkt_write_header(s, length); tpdu_write_header(s, 2, 0xf0); per_write_choice(s, DomainMCSPDU_SendDataRequest << 2); per_write_integer16(s, rdp->mcs->user_id, MCS_BASE_CHANNEL_ID); per_write_integer16(s, MCS_GLOBAL_CHANNEL_ID, 0); stream_write_uint8(s, 0x70); length = (4 + 4 + key_len + 8) | 0x8000; stream_write_uint16_be(s, length); stream_write_uint32(s, 1); /* SEC_CLIENT_RANDOM */ length = key_len + 8; stream_write_uint32(s, length); memcpy(s->p, crypt_client_random, length); stream_seek(s, length); if (transport_write(rdp->mcs->transport, s) < 0) { return False; } /* now calculate encrypt / decrypt and update keys */ if (!security_establish_keys(client_random, rdp)) { return False; } rdp->do_crypt = True; if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS) { uint8 fips_ivec[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec); rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec); rdp->fips_hmac = crypto_hmac_new(); return True; } rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); 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; }
static boolean rdp_client_establish_keys(rdpRdp* rdp) { uint8 client_random[CLIENT_RANDOM_LENGTH]; uint8 crypt_client_random[256 + 8]; uint32 key_len; uint8* mod; uint8* exp; uint32 length; STREAM* s; if (rdp->settings->encryption == false) { /* no RDP encryption */ return true; } /* encrypt client random */ memset(crypt_client_random, 0, sizeof(crypt_client_random)); crypto_nonce(client_random, sizeof(client_random)); key_len = rdp->settings->server_cert->cert_info.modulus.length; mod = rdp->settings->server_cert->cert_info.modulus.data; exp = rdp->settings->server_cert->cert_info.exponent; crypto_rsa_public_encrypt(client_random, sizeof(client_random), key_len, mod, exp, crypt_client_random); /* send crypt client random to server */ length = RDP_PACKET_HEADER_MAX_LENGTH + RDP_SECURITY_HEADER_LENGTH + 4 + key_len + 8; s = transport_send_stream_init(rdp->mcs->transport, length); rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID); rdp_write_security_header(s, SEC_EXCHANGE_PKT); length = key_len + 8; stream_write_uint32(s, length); stream_write(s, crypt_client_random, length); if (transport_write(rdp->mcs->transport, s) < 0) { return false; } /* now calculate encrypt / decrypt and update keys */ if (!security_establish_keys(client_random, rdp)) { return false; } rdp->do_crypt = true; if (rdp->settings->salted_checksum) rdp->do_secure_checksum = true; if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS) { uint8 fips_ivec[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec); rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec); rdp->fips_hmac = crypto_hmac_new(); return true; } rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); return true; }