Made nego self contained.
This commit is contained in:
parent
a1c2033226
commit
5ca8eca18e
@ -197,6 +197,7 @@ static BOOL rdp_client_reset_codecs(rdpContext* context)
|
||||
|
||||
BOOL rdp_client_connect(rdpRdp* rdp)
|
||||
{
|
||||
UINT32 SelectedProtocol;
|
||||
BOOL status;
|
||||
rdpSettings* settings = rdp->settings;
|
||||
/* make sure SSL is initialize for earlier enough for crypto, by taking advantage of winpr SSL FIPS flag for openssl initialization */
|
||||
@ -306,7 +307,9 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((rdp->nego->SelectedProtocol & PROTOCOL_TLS) || (rdp->nego->SelectedProtocol == PROTOCOL_RDP))
|
||||
SelectedProtocol = nego_get_selected_protocol(rdp->nego);
|
||||
|
||||
if ((SelectedProtocol & PROTOCOL_TLS) || (SelectedProtocol == PROTOCOL_RDP))
|
||||
{
|
||||
if ((settings->Username != NULL) && ((settings->Password != NULL) ||
|
||||
(settings->RedirectionPassword != NULL && settings->RedirectionPasswordLength > 0)))
|
||||
@ -1169,6 +1172,8 @@ int rdp_client_transition_to_state(rdpRdp* rdp, int state)
|
||||
|
||||
BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
UINT32 SelectedProtocol = 0;
|
||||
UINT32 RequestedProtocols;
|
||||
BOOL status;
|
||||
rdpSettings* settings = rdp->settings;
|
||||
rdpNego* nego = rdp->nego;
|
||||
@ -1177,26 +1182,26 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
|
||||
if (!nego_read_request(nego, s))
|
||||
return FALSE;
|
||||
|
||||
nego->SelectedProtocol = 0;
|
||||
RequestedProtocols = nego_get_requested_protocols(nego);
|
||||
WLog_INFO(TAG, "Client Security: NLA:%d TLS:%d RDP:%d",
|
||||
(nego->RequestedProtocols & PROTOCOL_NLA) ? 1 : 0,
|
||||
(nego->RequestedProtocols & PROTOCOL_TLS) ? 1 : 0,
|
||||
(nego->RequestedProtocols == PROTOCOL_RDP) ? 1 : 0
|
||||
(RequestedProtocols & PROTOCOL_NLA) ? 1 : 0,
|
||||
(RequestedProtocols & PROTOCOL_TLS) ? 1 : 0,
|
||||
(RequestedProtocols == PROTOCOL_RDP) ? 1 : 0
|
||||
);
|
||||
WLog_INFO(TAG, "Server Security: NLA:%"PRId32" TLS:%"PRId32" RDP:%"PRId32"",
|
||||
settings->NlaSecurity, settings->TlsSecurity, settings->RdpSecurity);
|
||||
|
||||
if ((settings->NlaSecurity) && (nego->RequestedProtocols & PROTOCOL_NLA))
|
||||
if ((settings->NlaSecurity) && (RequestedProtocols & PROTOCOL_NLA))
|
||||
{
|
||||
nego->SelectedProtocol = PROTOCOL_NLA;
|
||||
SelectedProtocol = PROTOCOL_NLA;
|
||||
}
|
||||
else if ((settings->TlsSecurity) && (nego->RequestedProtocols & PROTOCOL_TLS))
|
||||
else if ((settings->TlsSecurity) && (RequestedProtocols & PROTOCOL_TLS))
|
||||
{
|
||||
nego->SelectedProtocol = PROTOCOL_TLS;
|
||||
SelectedProtocol = PROTOCOL_TLS;
|
||||
}
|
||||
else if ((settings->RdpSecurity) && (nego->RequestedProtocols == PROTOCOL_RDP))
|
||||
else if ((settings->RdpSecurity) && (RequestedProtocols == PROTOCOL_RDP))
|
||||
{
|
||||
nego->SelectedProtocol = PROTOCOL_RDP;
|
||||
SelectedProtocol = PROTOCOL_RDP;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1204,49 +1209,53 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
|
||||
* 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;
|
||||
SelectedProtocol = PROTOCOL_FAILED_NEGO;
|
||||
|
||||
if (settings->RdpSecurity)
|
||||
{
|
||||
WLog_ERR(TAG, "server supports only Standard RDP Security");
|
||||
nego->SelectedProtocol |= SSL_NOT_ALLOWED_BY_SERVER;
|
||||
SelectedProtocol |= SSL_NOT_ALLOWED_BY_SERVER;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings->NlaSecurity && !settings->TlsSecurity)
|
||||
{
|
||||
WLog_WARN(TAG, "server supports only NLA Security");
|
||||
nego->SelectedProtocol |= HYBRID_REQUIRED_BY_SERVER;
|
||||
SelectedProtocol |= HYBRID_REQUIRED_BY_SERVER;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_WARN(TAG, "server supports only a SSL based Security (TLS or NLA)");
|
||||
nego->SelectedProtocol |= SSL_REQUIRED_BY_SERVER;
|
||||
SelectedProtocol |= SSL_REQUIRED_BY_SERVER;
|
||||
}
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "Protocol security negotiation failure");
|
||||
}
|
||||
|
||||
if (!(nego->SelectedProtocol & PROTOCOL_FAILED_NEGO))
|
||||
if (!(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
|
||||
(SelectedProtocol & PROTOCOL_NLA) ? 1 : 0,
|
||||
(SelectedProtocol & PROTOCOL_TLS) ? 1 : 0,
|
||||
(SelectedProtocol == PROTOCOL_RDP) ? 1 : 0
|
||||
);
|
||||
}
|
||||
|
||||
if (!nego_set_selected_protocol(nego, SelectedProtocol))
|
||||
return FALSE;
|
||||
|
||||
if (!nego_send_negotiation_response(nego))
|
||||
return FALSE;
|
||||
|
||||
SelectedProtocol = nego_get_selected_protocol(nego);
|
||||
status = FALSE;
|
||||
|
||||
if (nego->SelectedProtocol & PROTOCOL_NLA)
|
||||
if (SelectedProtocol & PROTOCOL_NLA)
|
||||
status = transport_accept_nla(rdp->transport);
|
||||
else if (nego->SelectedProtocol & PROTOCOL_TLS)
|
||||
else if (SelectedProtocol & PROTOCOL_TLS)
|
||||
status = transport_accept_tls(rdp->transport);
|
||||
else if (nego->SelectedProtocol == PROTOCOL_RDP) /* 0 */
|
||||
else if (SelectedProtocol == PROTOCOL_RDP) /* 0 */
|
||||
status = transport_accept_rdp(rdp->transport);
|
||||
|
||||
if (!status)
|
||||
|
@ -36,6 +36,35 @@
|
||||
|
||||
#define TAG FREERDP_TAG("core.nego")
|
||||
|
||||
struct rdp_nego
|
||||
{
|
||||
int port;
|
||||
UINT32 flags;
|
||||
char* hostname;
|
||||
char* cookie;
|
||||
BYTE* RoutingToken;
|
||||
DWORD RoutingTokenLength;
|
||||
BOOL SendPreconnectionPdu;
|
||||
UINT32 PreconnectionId;
|
||||
char* PreconnectionBlob;
|
||||
|
||||
NEGO_STATE state;
|
||||
BOOL TcpConnected;
|
||||
BOOL SecurityConnected;
|
||||
UINT32 CookieMaxLength;
|
||||
|
||||
BOOL sendNegoData;
|
||||
UINT32 SelectedProtocol;
|
||||
UINT32 RequestedProtocols;
|
||||
BOOL NegotiateSecurityLayer;
|
||||
BYTE EnabledProtocols[16];
|
||||
BOOL RestrictedAdminModeRequired;
|
||||
BOOL GatewayEnabled;
|
||||
BOOL GatewayBypassLocal;
|
||||
|
||||
rdpTransport* transport;
|
||||
};
|
||||
|
||||
static const char* const NEGO_STATE_STRINGS[] =
|
||||
{
|
||||
"NEGO_STATE_INITIAL",
|
||||
@ -1339,3 +1368,72 @@ void nego_set_preconnection_blob(rdpNego* nego, char* PreconnectionBlob)
|
||||
{
|
||||
nego->PreconnectionBlob = PreconnectionBlob;
|
||||
}
|
||||
|
||||
UINT32 nego_get_selected_protocol(rdpNego* nego)
|
||||
{
|
||||
if (!nego)
|
||||
return 0;
|
||||
|
||||
return nego->SelectedProtocol;
|
||||
}
|
||||
|
||||
BOOL nego_set_selected_protocol(rdpNego* nego, UINT32 SelectedProtocol)
|
||||
{
|
||||
if (!nego)
|
||||
return FALSE;
|
||||
|
||||
nego->SelectedProtocol = SelectedProtocol;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UINT32 nego_get_requested_protocols(rdpNego* nego)
|
||||
{
|
||||
if (!nego)
|
||||
return 0;
|
||||
|
||||
return nego->RequestedProtocols;
|
||||
}
|
||||
|
||||
|
||||
BOOL nego_set_requested_protocols(rdpNego* nego, UINT32 RequestedProtocols)
|
||||
{
|
||||
if (!nego)
|
||||
return FALSE;
|
||||
|
||||
nego->RequestedProtocols = RequestedProtocols;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
NEGO_STATE nego_get_state(rdpNego* nego)
|
||||
{
|
||||
if (!nego)
|
||||
return NEGO_STATE_FAIL;
|
||||
|
||||
return nego->state;
|
||||
}
|
||||
|
||||
BOOL nego_set_state(rdpNego* nego, NEGO_STATE state)
|
||||
{
|
||||
if (!nego)
|
||||
return FALSE;
|
||||
|
||||
nego->state = state;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SEC_WINNT_AUTH_IDENTITY* nego_get_identity(rdpNego* nego)
|
||||
{
|
||||
if (!nego)
|
||||
return NULL;
|
||||
|
||||
return nego->transport->nla->identity;
|
||||
}
|
||||
|
||||
void nego_free_nla(rdpNego* nego)
|
||||
{
|
||||
if (!nego || !nego->transport)
|
||||
return;
|
||||
|
||||
nla_free(nego->transport->nla);
|
||||
nego->transport->nla = NULL;
|
||||
}
|
||||
|
@ -90,34 +90,6 @@ enum RDP_NEG_MSG
|
||||
#define REDIRECTED_AUTHENTICATION_MODE_REQUIRED 0x02
|
||||
#define CORRELATION_INFO_PRESENT 0x08
|
||||
|
||||
struct rdp_nego
|
||||
{
|
||||
int port;
|
||||
UINT32 flags;
|
||||
char* hostname;
|
||||
char* cookie;
|
||||
BYTE* RoutingToken;
|
||||
DWORD RoutingTokenLength;
|
||||
BOOL SendPreconnectionPdu;
|
||||
UINT32 PreconnectionId;
|
||||
char* PreconnectionBlob;
|
||||
|
||||
NEGO_STATE state;
|
||||
BOOL TcpConnected;
|
||||
BOOL SecurityConnected;
|
||||
UINT32 CookieMaxLength;
|
||||
|
||||
BOOL sendNegoData;
|
||||
UINT32 SelectedProtocol;
|
||||
UINT32 RequestedProtocols;
|
||||
BOOL NegotiateSecurityLayer;
|
||||
BYTE EnabledProtocols[16];
|
||||
BOOL RestrictedAdminModeRequired;
|
||||
BOOL GatewayEnabled;
|
||||
BOOL GatewayBypassLocal;
|
||||
|
||||
rdpTransport* transport;
|
||||
};
|
||||
typedef struct rdp_nego rdpNego;
|
||||
|
||||
FREERDP_LOCAL BOOL nego_connect(rdpNego* nego);
|
||||
@ -157,4 +129,17 @@ FREERDP_LOCAL void nego_set_preconnection_id(rdpNego* nego,
|
||||
FREERDP_LOCAL void nego_set_preconnection_blob(rdpNego* nego,
|
||||
char* PreconnectionBlob);
|
||||
|
||||
FREERDP_LOCAL UINT32 nego_get_selected_protocol(rdpNego* nego);
|
||||
FREERDP_LOCAL BOOL nego_set_selected_protocol(rdpNego* nego, UINT32 SelectedProtocol);
|
||||
|
||||
FREERDP_LOCAL UINT32 nego_get_requested_protocols(rdpNego* nego);
|
||||
FREERDP_LOCAL BOOL nego_set_requested_protocols(rdpNego* nego, UINT32 RequestedProtocols);
|
||||
|
||||
FREERDP_LOCAL BOOL nego_set_state(rdpNego* nego, NEGO_STATE state);
|
||||
FREERDP_LOCAL NEGO_STATE nego_get_state(rdpNego* nego);
|
||||
|
||||
FREERDP_LOCAL SEC_WINNT_AUTH_IDENTITY* nego_get_identity(rdpNego* nego);
|
||||
|
||||
FREERDP_LOCAL void nego_free_nla(rdpNego* nego);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_NEGO_H */
|
||||
|
@ -464,6 +464,7 @@ static int peer_recv_pdu(freerdp_peer* client, wStream* s)
|
||||
|
||||
static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
{
|
||||
UINT32 SelectedProtocol;
|
||||
freerdp_peer* client = (freerdp_peer*) extra;
|
||||
rdpRdp* rdp = client->context->rdp;
|
||||
|
||||
@ -476,16 +477,17 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
return -1;
|
||||
}
|
||||
|
||||
client->settings->NlaSecurity = (rdp->nego->SelectedProtocol & PROTOCOL_NLA) ? TRUE : FALSE;
|
||||
client->settings->TlsSecurity = (rdp->nego->SelectedProtocol & PROTOCOL_TLS) ? TRUE : FALSE;
|
||||
client->settings->RdpSecurity = (rdp->nego->SelectedProtocol == PROTOCOL_RDP) ? TRUE : FALSE;
|
||||
SelectedProtocol = nego_get_selected_protocol(rdp->nego);
|
||||
client->settings->NlaSecurity = (SelectedProtocol & PROTOCOL_NLA) ? TRUE : FALSE;
|
||||
client->settings->TlsSecurity = (SelectedProtocol & PROTOCOL_TLS) ? TRUE : FALSE;
|
||||
client->settings->RdpSecurity = (SelectedProtocol == PROTOCOL_RDP) ? TRUE : FALSE;
|
||||
|
||||
if (rdp->nego->SelectedProtocol & PROTOCOL_NLA)
|
||||
if (SelectedProtocol & PROTOCOL_NLA)
|
||||
{
|
||||
sspi_CopyAuthIdentity(&client->identity, rdp->nego->transport->nla->identity);
|
||||
SEC_WINNT_AUTH_IDENTITY* identity = nego_get_identity(rdp->nego);
|
||||
sspi_CopyAuthIdentity(&client->identity, identity);
|
||||
IFCALLRET(client->Logon, client->authenticated, client, &client->identity, TRUE);
|
||||
nla_free(rdp->nego->transport->nla);
|
||||
rdp->nego->transport->nla = NULL;
|
||||
nego_free_nla(rdp->nego);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -497,7 +499,8 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
case CONNECTION_STATE_NEGO:
|
||||
if (!rdp_server_accept_mcs_connect_initial(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_NEGO - rdp_server_accept_mcs_connect_initial() fail");
|
||||
WLog_ERR(TAG,
|
||||
"peer_recv_callback: CONNECTION_STATE_NEGO - rdp_server_accept_mcs_connect_initial() fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -642,10 +645,13 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
|
||||
static BOOL freerdp_peer_close(freerdp_peer* client)
|
||||
{
|
||||
UINT32 SelectedProtocol;
|
||||
/** if negotiation has failed, we're not MCS connected. So don't
|
||||
* send anything else, or some mstsc will consider that as an error
|
||||
*/
|
||||
if (client->context->rdp->nego->SelectedProtocol & PROTOCOL_FAILED_NEGO)
|
||||
SelectedProtocol = nego_get_selected_protocol(client->context->rdp->nego);
|
||||
|
||||
if (SelectedProtocol & PROTOCOL_FAILED_NEGO)
|
||||
return TRUE;
|
||||
|
||||
/**
|
||||
|
@ -1400,7 +1400,7 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
{
|
||||
nego_recv(rdp->transport, s, (void*) rdp->nego);
|
||||
|
||||
if (rdp->nego->state != NEGO_STATE_FINAL)
|
||||
if (nego_get_state(rdp->nego) != NEGO_STATE_FINAL)
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_recv_callback: CONNECTION_STATE_NLA - nego_recv() fail");
|
||||
return -1;
|
||||
@ -1415,8 +1415,12 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
|
||||
if (rdp->settings->VmConnectMode)
|
||||
{
|
||||
rdp->nego->state = NEGO_STATE_NLA;
|
||||
rdp->nego->RequestedProtocols = PROTOCOL_NLA | PROTOCOL_TLS;
|
||||
if (!nego_set_state(rdp->nego, NEGO_STATE_NLA))
|
||||
return -1;
|
||||
|
||||
if (!nego_set_requested_protocols(rdp->nego, PROTOCOL_NLA | PROTOCOL_TLS))
|
||||
return -1;
|
||||
|
||||
nego_send_negotiation_request(rdp->nego);
|
||||
rdp->nla->state = NLA_STATE_POST_NEGO;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user