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_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) { int length; int bm, em; BOOL status; wStream* s; BYTE flags; rdpSettings* settings; status = TRUE; settings = nego->transport->settings; s = Stream_New(NULL, 512); if (!s) return FALSE; length = TPDU_CONNECTION_CONFIRM_LENGTH; bm = Stream_GetPosition(s); Stream_Seek(s, length); if (nego->SelectedProtocol & PROTOCOL_FAILED_NEGO) { UINT32 errorCode = (nego->SelectedProtocol & ~PROTOCOL_FAILED_NEGO); flags = 0; Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE); Stream_Write_UINT8(s, flags); /* flags */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ Stream_Write_UINT32(s, errorCode); length += 8; status = FALSE; } else { flags = EXTENDED_CLIENT_DATA_SUPPORTED; if (settings->SupportGraphicsPipeline) flags |= DYNVC_GFX_PROTOCOL_SUPPORTED; /* RDP_NEG_DATA must be present for TLS, NLA, and RDP */ Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP); Stream_Write_UINT8(s, flags); /* flags */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ Stream_Write_UINT32(s, nego->SelectedProtocol); /* selectedProtocol */ length += 8; } em = Stream_GetPosition(s); Stream_SetPosition(s, bm); tpkt_write_header(s, length); tpdu_write_connection_confirm(s, length - 5); Stream_SetPosition(s, em); Stream_SealLength(s); if (transport_write(nego->transport, s) < 0) { Stream_Free(s, TRUE); return FALSE; } Stream_Free(s, TRUE); if (status) { /* update settings with negotiated protocol security */ settings->RequestedProtocols = nego->RequestedProtocols; settings->SelectedProtocol = nego->SelectedProtocol; if (settings->SelectedProtocol == PROTOCOL_RDP) { settings->TlsSecurity = FALSE; settings->NlaSecurity = FALSE; settings->RdpSecurity = TRUE; settings->UseRdpSecurityLayer = TRUE; if (settings->EncryptionLevel == ENCRYPTION_LEVEL_NONE) { /** * If the server implementation did not explicitely set a * encryption level we default to client compatible */ settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; } if (settings->LocalConnection) { /** * Note: This hack was firstly introduced in commit 95f5e115 to * disable the unnecessary encryption with peers connecting to * 127.0.0.1 or local unix sockets. * This also affects connections via port tunnels! (e.g. ssh -L) */ WLog_INFO(TAG, "Turning off encryption for local peer with standard rdp security"); settings->UseRdpSecurityLayer = FALSE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } if (!settings->RdpServerRsaKey && !settings->RdpKeyFile) { WLog_ERR(TAG, "Missing server certificate"); return FALSE; } } else if (settings->SelectedProtocol == PROTOCOL_TLS) { settings->TlsSecurity = TRUE; settings->NlaSecurity = FALSE; settings->RdpSecurity = FALSE; settings->UseRdpSecurityLayer = FALSE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } else if (settings->SelectedProtocol == PROTOCOL_NLA) { settings->TlsSecurity = TRUE; settings->NlaSecurity = TRUE; settings->RdpSecurity = FALSE; settings->UseRdpSecurityLayer = FALSE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } } return status; }
BOOL nego_send_negotiation_request(rdpNego* nego) { wStream* s; int length; int bm, em; BYTE flags = 0; int cookie_length; s = Stream_New(NULL, 512); length = TPDU_CONNECTION_REQUEST_LENGTH; bm = Stream_GetPosition(s); Stream_Seek(s, length); if (nego->RoutingToken) { Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength); /* Ensure Routing Token is correctly terminated - may already be present in string */ if ((nego->RoutingTokenLength > 2) && (nego->RoutingToken[nego->RoutingTokenLength - 2] == 0x0D) && (nego->RoutingToken[nego->RoutingTokenLength - 1] == 0x0A)) { WLog_DBG(TAG, "Routing token looks correctly terminated - use verbatim"); length +=nego->RoutingTokenLength; } else { WLog_DBG(TAG, "Adding terminating CRLF to routing token"); Stream_Write_UINT8(s, 0x0D); /* CR */ Stream_Write_UINT8(s, 0x0A); /* LF */ length += nego->RoutingTokenLength + 2; } } else if (nego->cookie) { cookie_length = strlen(nego->cookie); if (cookie_length > (int) nego->CookieMaxLength) cookie_length = nego->CookieMaxLength; Stream_Write(s, "Cookie: mstshash=", 17); Stream_Write(s, (BYTE*) nego->cookie, cookie_length); Stream_Write_UINT8(s, 0x0D); /* CR */ Stream_Write_UINT8(s, 0x0A); /* LF */ length += cookie_length + 19; } WLog_DBG(TAG, "RequestedProtocols: %d", nego->RequestedProtocols); if ((nego->RequestedProtocols > PROTOCOL_RDP) || (nego->sendNegoData)) { /* RDP_NEG_DATA must be present for TLS and NLA */ if (nego->RestrictedAdminModeRequired) flags |= RESTRICTED_ADMIN_MODE_REQUIRED; Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ); Stream_Write_UINT8(s, flags); Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ Stream_Write_UINT32(s, nego->RequestedProtocols); /* requestedProtocols */ length += 8; } em = Stream_GetPosition(s); Stream_SetPosition(s, bm); tpkt_write_header(s, length); tpdu_write_connection_request(s, length - 5); Stream_SetPosition(s, em); Stream_SealLength(s); if (transport_write(nego->transport, s) < 0) { Stream_Free(s, TRUE); return FALSE; } Stream_Free(s, TRUE); return TRUE; }
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; }
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; }
BOOL nego_send_negotiation_request(rdpNego* nego) { wStream* s; int length; int bm, em; int cookie_length; s = Stream_New(NULL, 512); length = TPDU_CONNECTION_REQUEST_LENGTH; bm = Stream_GetPosition(s); Stream_Seek(s, length); if (nego->RoutingToken) { Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength); Stream_Write_UINT8(s, 0x0D); /* CR */ Stream_Write_UINT8(s, 0x0A); /* LF */ length += nego->RoutingTokenLength + 2; } else if (nego->cookie) { 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_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) || (nego->sendNegoData)) { /* 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; } em = Stream_GetPosition(s); Stream_SetPosition(s, bm); tpkt_write_header(s, length); tpdu_write_connection_request(s, length - 5); Stream_SetPosition(s, em); Stream_SealLength(s); if (transport_write(nego->transport, s) < 0) return FALSE; Stream_Free(s, TRUE); return TRUE; }