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:
David FORT 2015-02-11 21:38:32 +01:00
parent 5becf70fe9
commit 6a8d21cab9
3 changed files with 40 additions and 14 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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 */