diff options
author | Stefan Metzmacher <metze@samba.org> | 2017-05-11 13:28:10 +0200 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2017-05-21 21:05:11 +0200 |
commit | 4f597f1e5e567ef592ae65a73c536aefcbdea475 (patch) | |
tree | d411da6094d81b4e4beadaa1fe096d08dfbc4821 /auth | |
parent | 8a3a1111ed2561a40333ebf644a82314ffde7b15 (diff) | |
download | samba-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.c | 29 | ||||
-rw-r--r-- | auth/gensec/gensec_internal.h | 6 |
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 */ |