peer: Disconnect if Logon() returned FALSE

Returning FALSE implies the client was not authorized, but it does not
have any real impact on the connection, other than setting the
authorized field.

Change this by disconnecting the client if a Logon() callback returned
that a client was not authorized.
This commit is contained in:
Jonas Ådahl
2026-01-27 14:03:53 +01:00
committed by akallabeth
parent dcdfd36990
commit 4ea803134e
2 changed files with 32 additions and 13 deletions

View File

@@ -71,8 +71,21 @@ extern "C"
typedef BOOL (*psPeerCapabilities)(freerdp_peer* peer);
typedef BOOL (*psPeerPostConnect)(freerdp_peer* peer);
typedef BOOL (*psPeerActivate)(freerdp_peer* peer);
/** @brief Callback after the initial RDP authentication (NLA) succeeded or anonymous tunnel was
* established (RDP, TLS, ...)
*
* @param peer A pointer to a peer context to work on
* @param identity A pointer to the identity of the peer
* @param automatic \b TRUE in case the connection is already authenticated, \b FALSE in case
* of \b RDP, \b TLS or similar anonymous tunnels
*
* @return \b TRUE if the connection is allowed, \b FALSE if denied. Defaults to \b TRUE if the
* callback is unused.
*/
typedef BOOL (*psPeerLogon)(freerdp_peer* peer, const SEC_WINNT_AUTH_IDENTITY* identity,
BOOL automatic);
typedef BOOL (*psPeerSendServerRedirection)(freerdp_peer* peer,
const rdpRedirection* redirection);
typedef BOOL (*psPeerAdjustMonitorsLayout)(freerdp_peer* peer);

View File

@@ -789,20 +789,17 @@ static state_run_t rdp_peer_handle_state_active(freerdp_peer* client)
static state_run_t peer_recv_callback_internal(WINPR_ATTR_UNUSED rdpTransport* transport,
wStream* s, void* extra)
{
UINT32 SelectedProtocol = 0;
freerdp_peer* client = (freerdp_peer*)extra;
rdpRdp* rdp = NULL;
state_run_t ret = STATE_RUN_FAILED;
rdpSettings* settings = NULL;
WINPR_ASSERT(transport);
WINPR_ASSERT(client);
WINPR_ASSERT(client->context);
rdp = client->context->rdp;
rdpRdp* rdp = client->context->rdp;
WINPR_ASSERT(rdp);
settings = client->context->settings;
rdpSettings* settings = client->context->settings;
WINPR_ASSERT(settings);
IFCALL(client->ReachedState, client, rdp_get_state(rdp));
@@ -822,28 +819,37 @@ static state_run_t peer_recv_callback_internal(WINPR_ATTR_UNUSED rdpTransport* t
}
else
{
SelectedProtocol = nego_get_selected_protocol(rdp->nego);
const UINT32 SelectedProtocol = nego_get_selected_protocol(rdp->nego);
settings->RdstlsSecurity = (SelectedProtocol & PROTOCOL_RDSTLS) ? TRUE : FALSE;
settings->NlaSecurity = (SelectedProtocol & PROTOCOL_HYBRID) ? TRUE : FALSE;
settings->TlsSecurity = (SelectedProtocol & PROTOCOL_SSL) ? TRUE : FALSE;
settings->RdpSecurity = (SelectedProtocol == PROTOCOL_RDP) ? TRUE : FALSE;
client->authenticated = FALSE;
if (SelectedProtocol & PROTOCOL_HYBRID)
{
SEC_WINNT_AUTH_IDENTITY_INFO* identity =
(SEC_WINNT_AUTH_IDENTITY_INFO*)nego_get_identity(rdp->nego);
sspi_CopyAuthIdentity(&client->identity, identity);
IFCALLRET(client->Logon, client->authenticated, client, &client->identity,
TRUE);
if (sspi_CopyAuthIdentity(&client->identity, identity) >= 0)
{
client->authenticated =
IFCALLRESULT(TRUE, client->Logon, client, &client->identity, TRUE);
}
nego_free_nla(rdp->nego);
}
else
{
IFCALLRET(client->Logon, client->authenticated, client, &client->identity,
FALSE);
client->authenticated =
IFCALLRESULT(TRUE, client->Logon, client, &client->identity, FALSE);
}
if (!client->authenticated)
ret = STATE_RUN_FAILED;
else
{
if (rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_REQUEST))
ret = STATE_RUN_SUCCESS;
}
if (rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_REQUEST))
ret = STATE_RUN_SUCCESS;
}
break;