From 3e72a12dafde9f437e3b57836b7fc0960a65a049 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 11 Sep 2017 16:48:27 -0700 Subject: netlogon_creds_cli: Add netlogon_creds_cli_lck This adds an external locking scheme to protect our netlogon_creds_CredentialState. This is needed because the routines exposed by netlogon_creds_cli.h need a more flexible locking to set up our credentials in a properly protected way. Signed-off-by: Volker Lendecke Reviewed-by: Andrew Bartlett --- libcli/auth/netlogon_creds_cli.c | 143 +++++++++++++++++++++++++++++++++++++++ libcli/auth/netlogon_creds_cli.h | 20 ++++++ 2 files changed, 163 insertions(+) (limited to 'libcli') diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 3209f6cf871..06d7260c8b6 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -68,6 +68,7 @@ struct netlogon_creds_cli_context { struct db_context *ctx; struct g_lock_ctx *g_ctx; struct netlogon_creds_cli_locked_state *locked_state; + enum netlogon_creds_cli_lck_type lock; } db; }; @@ -909,6 +910,148 @@ NTSTATUS netlogon_creds_cli_lock(struct netlogon_creds_cli_context *context, return status; } +struct netlogon_creds_cli_lck { + struct netlogon_creds_cli_context *context; +}; + +struct netlogon_creds_cli_lck_state { + struct netlogon_creds_cli_lck *lck; + enum netlogon_creds_cli_lck_type type; +}; + +static void netlogon_creds_cli_lck_locked(struct tevent_req *subreq); +static int netlogon_creds_cli_lck_destructor( + struct netlogon_creds_cli_lck *lck); + +struct tevent_req *netlogon_creds_cli_lck_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, + struct netlogon_creds_cli_context *context, + enum netlogon_creds_cli_lck_type type) +{ + struct tevent_req *req, *subreq; + struct netlogon_creds_cli_lck_state *state; + enum g_lock_type gtype; + + req = tevent_req_create(mem_ctx, &state, + struct netlogon_creds_cli_lck_state); + if (req == NULL) { + return NULL; + } + + if (context->db.lock != NETLOGON_CREDS_CLI_LCK_NONE) { + DBG_DEBUG("context already locked\n"); + tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE); + return tevent_req_post(req, ev); + } + + switch (type) { + case NETLOGON_CREDS_CLI_LCK_SHARED: + gtype = G_LOCK_READ; + break; + case NETLOGON_CREDS_CLI_LCK_EXCLUSIVE: + gtype = G_LOCK_WRITE; + break; + default: + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + + state->lck = talloc(state, struct netlogon_creds_cli_lck); + if (tevent_req_nomem(state->lck, req)) { + return tevent_req_post(req, ev); + } + state->lck->context = context; + state->type = type; + + subreq = g_lock_lock_send(state, ev, + context->db.g_ctx, + context->db.key_name, + gtype); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, netlogon_creds_cli_lck_locked, req); + + return req; +} + +static void netlogon_creds_cli_lck_locked(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct netlogon_creds_cli_lck_state *state = tevent_req_data( + req, struct netlogon_creds_cli_lck_state); + NTSTATUS status; + + status = g_lock_lock_recv(subreq); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + + state->lck->context->db.lock = state->type; + talloc_set_destructor(state->lck, netlogon_creds_cli_lck_destructor); + + tevent_req_done(req); +} + +static int netlogon_creds_cli_lck_destructor( + struct netlogon_creds_cli_lck *lck) +{ + struct netlogon_creds_cli_context *ctx = lck->context; + NTSTATUS status; + + status = g_lock_unlock(ctx->db.g_ctx, ctx->db.key_name); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("g_lock_unlock failed: %s\n", nt_errstr(status)); + smb_panic("g_lock_unlock failed"); + } + ctx->db.lock = NETLOGON_CREDS_CLI_LCK_NONE; + return 0; +} + +NTSTATUS netlogon_creds_cli_lck_recv( + struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_lck **lck) +{ + struct netlogon_creds_cli_lck_state *state = tevent_req_data( + req, struct netlogon_creds_cli_lck_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *lck = talloc_move(mem_ctx, &state->lck); + return NT_STATUS_OK; +} + +NTSTATUS netlogon_creds_cli_lck( + struct netlogon_creds_cli_context *context, + enum netlogon_creds_cli_lck_type type, + TALLOC_CTX *mem_ctx, struct netlogon_creds_cli_lck **lck) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = netlogon_creds_cli_lck_send(frame, ev, context, type); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = netlogon_creds_cli_lck_recv(req, mem_ctx, lck); + fail: + TALLOC_FREE(frame); + return status; +} + struct netlogon_creds_cli_auth_state { struct tevent_context *ev; struct netlogon_creds_cli_context *context; diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h index 7664387ab95..b3e30eb67bf 100644 --- a/libcli/auth/netlogon_creds_cli.h +++ b/libcli/auth/netlogon_creds_cli.h @@ -76,6 +76,26 @@ NTSTATUS netlogon_creds_cli_lock(struct netlogon_creds_cli_context *context, TALLOC_CTX *mem_ctx, struct netlogon_creds_CredentialState **creds); +struct netlogon_creds_cli_lck; + +enum netlogon_creds_cli_lck_type { + NETLOGON_CREDS_CLI_LCK_NONE, + NETLOGON_CREDS_CLI_LCK_SHARED, + NETLOGON_CREDS_CLI_LCK_EXCLUSIVE, +}; + +struct tevent_req *netlogon_creds_cli_lck_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, + struct netlogon_creds_cli_context *context, + enum netlogon_creds_cli_lck_type type); +NTSTATUS netlogon_creds_cli_lck_recv( + struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_lck **lck); +NTSTATUS netlogon_creds_cli_lck( + struct netlogon_creds_cli_context *context, + enum netlogon_creds_cli_lck_type type, + TALLOC_CTX *mem_ctx, struct netlogon_creds_cli_lck **lck); + struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct netlogon_creds_cli_context *context, -- cgit v1.2.1