mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
netlogon_creds_cli: Protect netlogon_creds_cli_check by _lck
netlogon_creds_cli_lck provides the locking around the operation Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
d61545a5b3
commit
f6e39450f5
@ -1525,14 +1525,13 @@ struct netlogon_creds_cli_check_state {
|
|||||||
union netr_Capabilities caps;
|
union netr_Capabilities caps;
|
||||||
|
|
||||||
struct netlogon_creds_CredentialState *creds;
|
struct netlogon_creds_CredentialState *creds;
|
||||||
struct netlogon_creds_CredentialState tmp_creds;
|
|
||||||
struct netr_Authenticator req_auth;
|
struct netr_Authenticator req_auth;
|
||||||
struct netr_Authenticator rep_auth;
|
struct netr_Authenticator rep_auth;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
|
static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
|
||||||
NTSTATUS status);
|
NTSTATUS status);
|
||||||
static void netlogon_creds_cli_check_locked(struct tevent_req *subreq);
|
static void netlogon_creds_cli_check_caps(struct tevent_req *subreq);
|
||||||
|
|
||||||
struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx,
|
struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx,
|
||||||
struct tevent_context *ev,
|
struct tevent_context *ev,
|
||||||
@ -1544,6 +1543,7 @@ struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx,
|
|||||||
struct tevent_req *subreq;
|
struct tevent_req *subreq;
|
||||||
enum dcerpc_AuthType auth_type;
|
enum dcerpc_AuthType auth_type;
|
||||||
enum dcerpc_AuthLevel auth_level;
|
enum dcerpc_AuthLevel auth_level;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
req = tevent_req_create(mem_ctx, &state,
|
req = tevent_req_create(mem_ctx, &state,
|
||||||
struct netlogon_creds_cli_check_state);
|
struct netlogon_creds_cli_check_state);
|
||||||
@ -1555,6 +1555,17 @@ struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx,
|
|||||||
state->context = context;
|
state->context = context;
|
||||||
state->binding_handle = b;
|
state->binding_handle = b;
|
||||||
|
|
||||||
|
if (context->db.lock != NETLOGON_CREDS_CLI_LCK_EXCLUSIVE) {
|
||||||
|
tevent_req_nterror(req, NT_STATUS_NOT_LOCKED);
|
||||||
|
return tevent_req_post(req, ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = netlogon_creds_cli_get_internal(context, state,
|
||||||
|
&state->creds);
|
||||||
|
if (tevent_req_nterror(req, status)) {
|
||||||
|
return tevent_req_post(req, ev);
|
||||||
|
}
|
||||||
|
|
||||||
state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
|
state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
|
||||||
context->server.computer);
|
context->server.computer);
|
||||||
if (tevent_req_nomem(state->srv_name_slash, req)) {
|
if (tevent_req_nomem(state->srv_name_slash, req)) {
|
||||||
@ -1578,14 +1589,29 @@ struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx,
|
|||||||
return tevent_req_post(req, ev);
|
return tevent_req_post(req, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
subreq = netlogon_creds_cli_lock_send(state, state->ev,
|
/*
|
||||||
state->context);
|
* we defer all callbacks in order to cleanup
|
||||||
|
* the database record.
|
||||||
|
*/
|
||||||
|
tevent_req_defer_callback(req, state->ev);
|
||||||
|
|
||||||
|
netlogon_creds_client_authenticator(state->creds, &state->req_auth);
|
||||||
|
ZERO_STRUCT(state->rep_auth);
|
||||||
|
|
||||||
|
subreq = dcerpc_netr_LogonGetCapabilities_send(state, state->ev,
|
||||||
|
state->binding_handle,
|
||||||
|
state->srv_name_slash,
|
||||||
|
state->context->client.computer,
|
||||||
|
&state->req_auth,
|
||||||
|
&state->rep_auth,
|
||||||
|
1,
|
||||||
|
&state->caps);
|
||||||
if (tevent_req_nomem(subreq, req)) {
|
if (tevent_req_nomem(subreq, req)) {
|
||||||
return tevent_req_post(req, ev);
|
return tevent_req_post(req, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
tevent_req_set_callback(subreq,
|
tevent_req_set_callback(subreq,
|
||||||
netlogon_creds_cli_check_locked,
|
netlogon_creds_cli_check_caps,
|
||||||
req);
|
req);
|
||||||
|
|
||||||
return req;
|
return req;
|
||||||
@ -1611,58 +1637,10 @@ static void netlogon_creds_cli_check_cleanup(struct tevent_req *req,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
netlogon_creds_cli_delete(state->context, state->creds);
|
netlogon_creds_cli_delete_lck(state->context);
|
||||||
TALLOC_FREE(state->creds);
|
TALLOC_FREE(state->creds);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netlogon_creds_cli_check_caps(struct tevent_req *subreq);
|
|
||||||
|
|
||||||
static void netlogon_creds_cli_check_locked(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;
|
|
||||||
|
|
||||||
status = netlogon_creds_cli_lock_recv(subreq, state,
|
|
||||||
&state->creds);
|
|
||||||
TALLOC_FREE(subreq);
|
|
||||||
if (tevent_req_nterror(req, status)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* we defer all callbacks in order to cleanup
|
|
||||||
* the database record.
|
|
||||||
*/
|
|
||||||
tevent_req_defer_callback(req, state->ev);
|
|
||||||
|
|
||||||
state->tmp_creds = *state->creds;
|
|
||||||
netlogon_creds_client_authenticator(&state->tmp_creds,
|
|
||||||
&state->req_auth);
|
|
||||||
ZERO_STRUCT(state->rep_auth);
|
|
||||||
|
|
||||||
subreq = dcerpc_netr_LogonGetCapabilities_send(state, state->ev,
|
|
||||||
state->binding_handle,
|
|
||||||
state->srv_name_slash,
|
|
||||||
state->context->client.computer,
|
|
||||||
&state->req_auth,
|
|
||||||
&state->rep_auth,
|
|
||||||
1,
|
|
||||||
&state->caps);
|
|
||||||
if (tevent_req_nomem(subreq, req)) {
|
|
||||||
status = NT_STATUS_NO_MEMORY;
|
|
||||||
netlogon_creds_cli_check_cleanup(req, status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tevent_req_set_callback(subreq,
|
|
||||||
netlogon_creds_cli_check_caps,
|
|
||||||
req);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
|
static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
|
||||||
{
|
{
|
||||||
struct tevent_req *req =
|
struct tevent_req *req =
|
||||||
@ -1683,7 +1661,7 @@ static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
|
|||||||
* Note that the negotiated flags are already checked
|
* Note that the negotiated flags are already checked
|
||||||
* for our required flags after the ServerAuthenticate3/2 call.
|
* for our required flags after the ServerAuthenticate3/2 call.
|
||||||
*/
|
*/
|
||||||
uint32_t negotiated = state->tmp_creds.negotiate_flags;
|
uint32_t negotiated = state->creds->negotiate_flags;
|
||||||
|
|
||||||
if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
|
if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
|
||||||
/*
|
/*
|
||||||
@ -1738,7 +1716,7 @@ static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
|
|||||||
* Note that the negotiated flags are already checked
|
* Note that the negotiated flags are already checked
|
||||||
* for our required flags after the ServerAuthenticate3/2 call.
|
* for our required flags after the ServerAuthenticate3/2 call.
|
||||||
*/
|
*/
|
||||||
uint32_t negotiated = state->tmp_creds.negotiate_flags;
|
uint32_t negotiated = state->creds->negotiate_flags;
|
||||||
|
|
||||||
if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
|
if (negotiated & NETLOGON_NEG_SUPPORTS_AES) {
|
||||||
/*
|
/*
|
||||||
@ -1764,8 +1742,7 @@ static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = netlogon_creds_client_check(&state->tmp_creds,
|
ok = netlogon_creds_client_check(state->creds, &state->rep_auth.cred);
|
||||||
&state->rep_auth.cred);
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
status = NT_STATUS_ACCESS_DENIED;
|
status = NT_STATUS_ACCESS_DENIED;
|
||||||
tevent_req_nterror(req, status);
|
tevent_req_nterror(req, status);
|
||||||
@ -1778,7 +1755,7 @@ static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->caps.server_capabilities != state->tmp_creds.negotiate_flags) {
|
if (state->caps.server_capabilities != state->creds->negotiate_flags) {
|
||||||
status = NT_STATUS_DOWNGRADE_DETECTED;
|
status = NT_STATUS_DOWNGRADE_DETECTED;
|
||||||
tevent_req_nterror(req, status);
|
tevent_req_nterror(req, status);
|
||||||
netlogon_creds_cli_check_cleanup(req, status);
|
netlogon_creds_cli_check_cleanup(req, status);
|
||||||
@ -1800,10 +1777,8 @@ static void netlogon_creds_cli_check_caps(struct tevent_req *subreq)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*state->creds = state->tmp_creds;
|
status = netlogon_creds_cli_store_internal(state->context,
|
||||||
status = netlogon_creds_cli_store(state->context,
|
state->creds);
|
||||||
state->creds);
|
|
||||||
TALLOC_FREE(state->creds);
|
|
||||||
if (tevent_req_nterror(req, status)) {
|
if (tevent_req_nterror(req, status)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3281,21 +3281,23 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
|
|||||||
struct rpc_pipe_client *rpccli;
|
struct rpc_pipe_client *rpccli;
|
||||||
struct pipe_auth_data *rpcauth;
|
struct pipe_auth_data *rpcauth;
|
||||||
const char *target_service = table->authservices->names[0];
|
const char *target_service = table->authservices->names[0];
|
||||||
struct netlogon_creds_CredentialState *ncreds = NULL;
|
|
||||||
struct cli_credentials *cli_creds;
|
struct cli_credentials *cli_creds;
|
||||||
enum dcerpc_AuthLevel auth_level;
|
enum dcerpc_AuthLevel auth_level;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
int rpc_pipe_bind_dbglvl = 0;
|
int rpc_pipe_bind_dbglvl = 0;
|
||||||
|
struct netlogon_creds_cli_lck *lck;
|
||||||
|
|
||||||
status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
|
status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &ncreds);
|
status = netlogon_creds_cli_lck(
|
||||||
|
netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
|
||||||
|
rpccli, &lck);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
DEBUG(0, ("netlogon_creds_cli_lock returned %s\n",
|
DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
|
||||||
nt_errstr(status)));
|
nt_errstr(status));
|
||||||
TALLOC_FREE(rpccli);
|
TALLOC_FREE(rpccli);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -3333,8 +3335,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
|
|||||||
|
|
||||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
|
if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
|
||||||
rpc_pipe_bind_dbglvl = 1;
|
rpc_pipe_bind_dbglvl = 1;
|
||||||
netlogon_creds_cli_delete(netlogon_creds, ncreds);
|
netlogon_creds_cli_delete_lck(netlogon_creds);
|
||||||
TALLOC_FREE(ncreds);
|
|
||||||
}
|
}
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
DEBUG(rpc_pipe_bind_dbglvl,
|
DEBUG(rpc_pipe_bind_dbglvl,
|
||||||
@ -3344,8 +3345,6 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
TALLOC_FREE(ncreds);
|
|
||||||
|
|
||||||
if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
|
if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -3359,13 +3358,14 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
DEBUG(10,("%s: opened pipe %s to machine %s "
|
DEBUG(10,("%s: opened pipe %s to machine %s "
|
||||||
"for domain %s and bound using schannel.\n",
|
"for domain %s and bound using schannel.\n",
|
||||||
__func__, table->name,
|
__func__, table->name,
|
||||||
rpccli->desthost, cli_credentials_get_domain(cli_creds)));
|
rpccli->desthost, cli_credentials_get_domain(cli_creds)));
|
||||||
|
|
||||||
|
TALLOC_FREE(lck);
|
||||||
|
|
||||||
*_rpccli = rpccli;
|
*_rpccli = rpccli;
|
||||||
return NT_STATUS_OK;
|
return NT_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user