summaryrefslogtreecommitdiff
path: root/libcli
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2017-09-11 16:48:27 -0700
committerVolker Lendecke <vl@samba.org>2017-09-25 09:43:12 +0200
commit3e72a12dafde9f437e3b57836b7fc0960a65a049 (patch)
tree5e6da2173f0103d32bbba13e3d3557dc250519ef /libcli
parent4b97de8adb2977aaec21940241dbc4d615307f4f (diff)
downloadsamba-3e72a12dafde9f437e3b57836b7fc0960a65a049.tar.gz
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 <vl@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'libcli')
-rw-r--r--libcli/auth/netlogon_creds_cli.c143
-rw-r--r--libcli/auth/netlogon_creds_cli.h20
2 files changed, 163 insertions, 0 deletions
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,