From 4f597f1e5e567ef592ae65a73c536aefcbdea475 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 11 May 2017 13:28:10 +0200 Subject: [PATCH] auth/gensec: make sure there's only one pending gensec_update_send() per context Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- auth/gensec/gensec.c | 29 ++++++++++++++++++++++++++++- auth/gensec/gensec_internal.h | 6 ++++++ 2 files changed, 34 insertions(+), 1 deletion(-) 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 */ -- 2.11.4.GIT