summaryrefslogtreecommitdiff
path: root/auth
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2017-05-11 13:28:10 +0200
committerAndrew Bartlett <abartlet@samba.org>2017-05-21 21:05:11 +0200
commit4f597f1e5e567ef592ae65a73c536aefcbdea475 (patch)
treed411da6094d81b4e4beadaa1fe096d08dfbc4821 /auth
parent8a3a1111ed2561a40333ebf644a82314ffde7b15 (diff)
downloadsamba-4f597f1e5e567ef592ae65a73c536aefcbdea475.tar.gz
auth/gensec: make sure there's only one pending gensec_update_send() per context
Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'auth')
-rw-r--r--auth/gensec/gensec.c29
-rw-r--r--auth/gensec/gensec_internal.h6
2 files changed, 34 insertions, 1 deletions
diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c
index cf00a363247..014516f2f6d 100644
--- a/auth/gensec/gensec.c
+++ b/auth/gensec/gensec.c
@@ -403,6 +403,8 @@ struct gensec_update_state {
DATA_BLOB out;
};
+static void gensec_update_cleanup(struct tevent_req *req,
+ enum tevent_req_state req_state);
static void gensec_update_done(struct tevent_req *subreq);
/**
@@ -430,15 +432,22 @@ _PUBLIC_ struct tevent_req *gensec_update_send(TALLOC_CTX *mem_ctx,
if (req == NULL) {
return NULL;
}
-
state->ops = gensec_security->ops;
state->gensec_security = gensec_security;
+ if (gensec_security->update_busy_ptr != NULL) {
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ return tevent_req_post(req, ev);
+ }
+
if (gensec_security->child_security != NULL) {
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
return tevent_req_post(req, ev);
}
+ gensec_security->update_busy_ptr = &state->gensec_security;
+ tevent_req_set_cleanup_fn(req, gensec_update_cleanup);
+
subreq = state->ops->update_send(state, ev, gensec_security, in);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
@@ -448,6 +457,24 @@ _PUBLIC_ struct tevent_req *gensec_update_send(TALLOC_CTX *mem_ctx,
return req;
}
+static void gensec_update_cleanup(struct tevent_req *req,
+ enum tevent_req_state req_state)
+{
+ struct gensec_update_state *state =
+ tevent_req_data(req,
+ struct gensec_update_state);
+
+ if (state->gensec_security == NULL) {
+ return;
+ }
+
+ if (state->gensec_security->update_busy_ptr == &state->gensec_security) {
+ state->gensec_security->update_busy_ptr = NULL;
+ }
+
+ state->gensec_security = NULL;
+}
+
static void gensec_update_done(struct tevent_req *subreq)
{
struct tevent_req *req =
diff --git a/auth/gensec/gensec_internal.h b/auth/gensec/gensec_internal.h
index b3a84344d2d..c73be11ded6 100644
--- a/auth/gensec/gensec_internal.h
+++ b/auth/gensec/gensec_internal.h
@@ -113,6 +113,12 @@ struct gensec_security {
struct gensec_security *parent_security;
struct gensec_security *child_security;
+
+ /*
+ * This is used to mark the context as being
+ * busy in an async gensec_update_send().
+ */
+ struct gensec_security **update_busy_ptr;
};
/* this structure is used by backends to determine the size of some critical types */