1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

libcli/auth: use a LogonControl after a LogonGetCapabilities downgrade

If LogonGetCapabilities was downgraded by an DCERPC Fault, we
rely on the schannel message ordering to detect failures.

Instead of letting any real winbindd request trigger this,
we do it directly in netlogon_creds_cli_check() with
a LogonControl that is also used for 'wbinfo --ping-dc'.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15425

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
This commit is contained in:
Stefan Metzmacher 2024-10-02 14:25:19 +02:00 committed by Douglas Bagnall
parent 3da40f1c68
commit 276137e950

View File

@ -1591,6 +1591,8 @@ struct netlogon_creds_cli_check_state {
struct netlogon_creds_CredentialState *creds;
struct netr_Authenticator req_auth;
struct netr_Authenticator rep_auth;
union netr_CONTROL_QUERY_INFORMATION ctrl_info;
};
static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
@ -1709,6 +1711,8 @@ static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
TALLOC_FREE(state->creds);
}
static void netlogon_creds_cli_check_control_do(struct tevent_req *req);
static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
{
struct tevent_req *req =
@ -1769,9 +1773,10 @@ static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
* we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
* with the next request as the sequence number processing
* gets out of sync.
*
* So we'll do a LogonControl message to check that...
*/
netlogon_creds_cli_check_cleanup(req, status);
tevent_req_done(req);
netlogon_creds_cli_check_control_do(req);
return;
}
if (tevent_req_nterror(req, status)) {
@ -1854,6 +1859,73 @@ static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
tevent_req_done(req);
}
static void netlogon_creds_cli_check_control_done(struct tevent_req *subreq);
static void netlogon_creds_cli_check_control_do(struct tevent_req *req)
{
struct netlogon_creds_cli_check_state *state =
tevent_req_data(req,
struct netlogon_creds_cli_check_state);
struct tevent_req *subreq = NULL;
/*
* In case we got a downgrade based on a FAULT
* we use a LogonControl that is supposed to
* return WERR_NOT_SUPPORTED (without a DCERPC FAULT)
* to verify that the connection is still ok and didn't
* get out of sync.
*/
subreq = dcerpc_netr_LogonControl_send(state,
state->ev,
state->binding_handle,
state->srv_name_slash,
NETLOGON_CONTROL_QUERY,
2,
&state->ctrl_info);
if (tevent_req_nomem(subreq, req)) {
return;
}
tevent_req_set_callback(subreq,
netlogon_creds_cli_check_control_done,
req);
return;
}
static void netlogon_creds_cli_check_control_done(struct tevent_req *subreq)
{
struct tevent_req *req =
tevent_req_callback_data(subreq,
struct tevent_req);
struct netlogon_creds_cli_check_state *state =
tevent_req_data(req,
struct netlogon_creds_cli_check_state);
NTSTATUS status;
WERROR result;
status = dcerpc_netr_LogonControl_recv(subreq, state, &result);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
/*
* We want to delete the creds,
* so we pass NT_STATUS_DOWNGRADE_DETECTED
* to netlogon_creds_cli_check_cleanup()
*/
status = NT_STATUS_DOWNGRADE_DETECTED;
netlogon_creds_cli_check_cleanup(req, status);
return;
}
if (!W_ERROR_EQUAL(result, WERR_NOT_SUPPORTED)) {
status = NT_STATUS_DOWNGRADE_DETECTED;
tevent_req_nterror(req, status);
netlogon_creds_cli_check_cleanup(req, status);
return;
}
tevent_req_done(req);
}
NTSTATUS netlogon_creds_cli_check_recv(struct tevent_req *req,
union netr_Capabilities *capabilities)
{