Fix server-side protocol negociation
Before this patch, RDP security was (wrongly) the fallback when negociating a security protocol between the client and the server. For example when a client was claiming TLS-only when connecting to a FreeRDP based-server with RDP security only, the result of the negociation was that the server started to do RDP security. The expected behaviour is to send a nego failure packet with error code SSL_NOT_ALLOWED_BY_SERVER. This patch fixes this. We also try to handle all cases of failed negociation and return the corresponding error code.
This commit is contained in:
parent
5becf70fe9
commit
6a8d21cab9
@ -1011,20 +1011,48 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
nego->SelectedProtocol = PROTOCOL_TLS;
|
||||
}
|
||||
else if ((settings->RdpSecurity) && (nego->SelectedProtocol == PROTOCOL_RDP))
|
||||
else if ((settings->RdpSecurity) && (nego->RequestedProtocols == PROTOCOL_RDP))
|
||||
{
|
||||
nego->SelectedProtocol = PROTOCOL_RDP;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* when here client and server aren't compatible, we select the right
|
||||
* error message to return to the client in the nego failure packet
|
||||
*/
|
||||
nego->SelectedProtocol = PROTOCOL_FAILED_NEGO;
|
||||
|
||||
if (settings->RdpSecurity)
|
||||
{
|
||||
WLog_ERR(TAG, "server supports only Standard RDP Security");
|
||||
nego->SelectedProtocol |= SSL_NOT_ALLOWED_BY_SERVER;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings->NlaSecurity && !settings->TlsSecurity)
|
||||
{
|
||||
WLog_ERR(TAG, "server supports only NLA Security");
|
||||
nego->SelectedProtocol |= HYBRID_REQUIRED_BY_SERVER;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "server supports only a SSL based Security (TLS or NLA)");
|
||||
nego->SelectedProtocol |= SSL_REQUIRED_BY_SERVER;
|
||||
}
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "Protocol security negotiation failure");
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "Negotiated Security: NLA:%d TLS:%d RDP:%d",
|
||||
(nego->SelectedProtocol & PROTOCOL_NLA) ? 1 : 0,
|
||||
(nego->SelectedProtocol & PROTOCOL_TLS) ? 1 : 0,
|
||||
(nego->SelectedProtocol == PROTOCOL_RDP) ? 1: 0
|
||||
);
|
||||
if (!(nego->SelectedProtocol & PROTOCOL_FAILED_NEGO))
|
||||
{
|
||||
WLog_INFO(TAG, "Negotiated Security: NLA:%d TLS:%d RDP:%d",
|
||||
(nego->SelectedProtocol & PROTOCOL_NLA) ? 1 : 0,
|
||||
(nego->SelectedProtocol & PROTOCOL_TLS) ? 1 : 0,
|
||||
(nego->SelectedProtocol == PROTOCOL_RDP) ? 1: 0
|
||||
);
|
||||
}
|
||||
|
||||
if (!nego_send_negotiation_response(nego))
|
||||
return FALSE;
|
||||
|
@ -918,20 +918,16 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
|
||||
bm = Stream_GetPosition(s);
|
||||
Stream_Seek(s, length);
|
||||
|
||||
if ((nego->SelectedProtocol == PROTOCOL_RDP) && !settings->RdpSecurity)
|
||||
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) */
|
||||
|
||||
/*
|
||||
* TODO: Check for other possibilities,
|
||||
* like SSL_NOT_ALLOWED_BY_SERVER.
|
||||
*/
|
||||
WLog_ERR(TAG, "client supports only Standard RDP Security");
|
||||
Stream_Write_UINT32(s, SSL_REQUIRED_BY_SERVER);
|
||||
Stream_Write_UINT32(s, errorCode);
|
||||
length += 8;
|
||||
status = FALSE;
|
||||
}
|
||||
|
@ -34,7 +34,9 @@ enum RDP_NEG_PROTOCOLS
|
||||
PROTOCOL_RDP = 0x00000000,
|
||||
PROTOCOL_TLS = 0x00000001,
|
||||
PROTOCOL_NLA = 0x00000002,
|
||||
PROTOCOL_EXT = 0x00000008
|
||||
PROTOCOL_EXT = 0x00000008,
|
||||
|
||||
PROTOCOL_FAILED_NEGO = 0x80000000 /* only used internally, not on the wire */
|
||||
};
|
||||
|
||||
/* Protocol Security Negotiation Failure Codes */
|
||||
|
Loading…
Reference in New Issue
Block a user