From 3bf494645044f858e7e34501d7b39e2677745ede Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 13 Jun 2017 23:43:01 +0200 Subject: auth/spnego: split out gensec_spnego_update_pre/post() functions For now we keep doing sync processing only, in future we'll do some preprocessing before a gensec_update_send() on the subcontext in gensec_spnego_update_pre() and handle the the result of gensec_update_recv() in gensec_spnego_update_post(). Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider --- auth/gensec/spnego.c | 234 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 153 insertions(+), 81 deletions(-) (limited to 'auth') diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c index af554cd3c89..f8ab11493f9 100644 --- a/auth/gensec/spnego.c +++ b/auth/gensec/spnego.c @@ -1166,6 +1166,7 @@ static NTSTATUS gensec_spnego_server_negTokenTarg(struct gensec_security *gensec } struct gensec_spnego_update_state { + struct tevent_context *ev; struct gensec_security *gensec; struct spnego_state *spnego; DATA_BLOB full_in; @@ -1199,6 +1200,8 @@ static void gensec_spnego_update_cleanup(struct tevent_req *req, static NTSTATUS gensec_spnego_update_in(struct gensec_security *gensec_security, const DATA_BLOB in, TALLOC_CTX *mem_ctx, DATA_BLOB *full_in); +static void gensec_spnego_update_pre(struct tevent_req *req); +static void gensec_spnego_update_post(struct tevent_req *req); static NTSTATUS gensec_spnego_update_out(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, DATA_BLOB *_out); @@ -1221,6 +1224,7 @@ static struct tevent_req *gensec_spnego_update_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } + state->ev = ev; state->gensec = gensec_security; state->spnego = spnego_state; tevent_req_set_cleanup_fn(req, gensec_spnego_update_cleanup); @@ -1326,94 +1330,21 @@ static struct tevent_req *gensec_spnego_update_send(TALLOC_CTX *mem_ctx, return NULL; } - /* and switch into the state machine */ - - switch (spnego_state->state_position) { - case SPNEGO_FALLBACK: - status = gensec_update_ev(spnego_state->sub_sec_security, - state, ev, - state->full_in, - &spnego_state->out_frag); - break; - - case SPNEGO_CLIENT_START: - if (state->spnego_in == NULL) { - /* client to produce negTokenInit */ - status = gensec_spnego_create_negTokenInit(gensec_security, - spnego_state, state, ev, - &spnego_state->out_frag); - break; - } - - status = gensec_spnego_client_negTokenInit(gensec_security, - spnego_state, ev, - state->spnego_in, state, - &spnego_state->out_frag); - break; - - case SPNEGO_CLIENT_TARG: - status = gensec_spnego_client_negTokenTarg(gensec_security, - spnego_state, ev, - state->spnego_in, state, - &spnego_state->out_frag); - break; - - case SPNEGO_SERVER_START: - if (state->spnego_in == NULL) { - /* server to produce negTokenInit */ - status = gensec_spnego_create_negTokenInit(gensec_security, - spnego_state, state, ev, - &spnego_state->out_frag); - break; - } - - status = gensec_spnego_server_negTokenInit(gensec_security, - spnego_state, ev, - state->spnego_in, state, - &spnego_state->out_frag); - break; - - case SPNEGO_SERVER_TARG: - status = gensec_spnego_server_negTokenTarg(gensec_security, - spnego_state, ev, - state->spnego_in, state, - &spnego_state->out_frag); - break; - - default: - smb_panic(__location__); - return NULL; - } - - if (GENSEC_UPDATE_IS_NTERROR(status)) { - tevent_req_nterror(req, status); + gensec_spnego_update_pre(req); + if (!tevent_req_is_in_progress(req)) { return tevent_req_post(req, ev); } - if (NT_STATUS_IS_OK(status)) { - bool reset_full = true; - - reset_full = !spnego_state->done_mic_check; - - status = gensec_may_reset_crypto(spnego_state->sub_sec_security, - reset_full); - if (tevent_req_nterror(req, status)) { - return tevent_req_post(req, ev); - } - } - - spnego_state->out_status = status; + /* + * TODO: prepare async processing here in future. + */ - status = gensec_spnego_update_out(gensec_security, - state, &state->out); - if (GENSEC_UPDATE_IS_NTERROR(status)) { - tevent_req_nterror(req, status); + gensec_spnego_update_post(req); + if (!tevent_req_is_in_progress(req)) { return tevent_req_post(req, ev); } - state->status = status; - tevent_req_done(req); - return tevent_req_post(req, ev); + return req; } static NTSTATUS gensec_spnego_update_in(struct gensec_security *gensec_security, @@ -1524,6 +1455,147 @@ static NTSTATUS gensec_spnego_update_in(struct gensec_security *gensec_security, return NT_STATUS_OK; } +static void gensec_spnego_update_pre(struct tevent_req *req) +{ + struct gensec_spnego_update_state *state = + tevent_req_data(req, + struct gensec_spnego_update_state); + struct gensec_security *gensec_security = state->gensec; + struct spnego_state *spnego_state = state->spnego; + struct tevent_context *ev = state->ev; + NTSTATUS status; + + if (spnego_state->state_position == SPNEGO_FALLBACK) { + status = gensec_update_ev(spnego_state->sub_sec_security, + state, ev, + state->full_in, + &spnego_state->out_frag); + /* + * We don't check status here. + */ + spnego_state->out_status = status; + return; + } + + switch (spnego_state->state_position) { + case SPNEGO_CLIENT_START: + if (state->spnego_in == NULL) { + /* client to produce negTokenInit */ + status = gensec_spnego_create_negTokenInit(gensec_security, + spnego_state, state, ev, + &spnego_state->out_frag); + if (GENSEC_UPDATE_IS_NTERROR(status)) { + tevent_req_nterror(req, status); + return; + } + break; + } + + status = gensec_spnego_client_negTokenInit(gensec_security, + spnego_state, ev, + state->spnego_in, state, + &spnego_state->out_frag); + break; + + case SPNEGO_CLIENT_TARG: + status = gensec_spnego_client_negTokenTarg(gensec_security, + spnego_state, ev, + state->spnego_in, state, + &spnego_state->out_frag); + if (GENSEC_UPDATE_IS_NTERROR(status)) { + tevent_req_nterror(req, status); + return; + } + break; + + case SPNEGO_SERVER_START: + if (state->spnego_in == NULL) { + /* server to produce negTokenInit */ + status = gensec_spnego_create_negTokenInit(gensec_security, + spnego_state, state, ev, + &spnego_state->out_frag); + if (GENSEC_UPDATE_IS_NTERROR(status)) { + tevent_req_nterror(req, status); + return; + } + break; + } + + status = gensec_spnego_server_negTokenInit(gensec_security, + spnego_state, ev, + state->spnego_in, state, + &spnego_state->out_frag); + if (GENSEC_UPDATE_IS_NTERROR(status)) { + tevent_req_nterror(req, status); + return; + } + break; + + case SPNEGO_SERVER_TARG: + status = gensec_spnego_server_negTokenTarg(gensec_security, + spnego_state, ev, + state->spnego_in, state, + &spnego_state->out_frag); + if (GENSEC_UPDATE_IS_NTERROR(status)) { + tevent_req_nterror(req, status); + return; + } + break; + + default: + smb_panic(__location__); + return; + } + + spnego_state->out_status = status; +} + +static void gensec_spnego_update_post(struct tevent_req *req) +{ + struct gensec_spnego_update_state *state = + tevent_req_data(req, + struct gensec_spnego_update_state); + struct spnego_state *spnego_state = state->spnego; + NTSTATUS status; + + if (spnego_state->state_position == SPNEGO_FALLBACK) { + status = spnego_state->out_status; + goto respond; + } + + /* + * For now just handle the sync processing done + * in gensec_spnego_update_pre() + */ + status = spnego_state->out_status; + + if (NT_STATUS_IS_OK(status)) { + bool reset_full = true; + + reset_full = !spnego_state->done_mic_check; + + status = gensec_may_reset_crypto(spnego_state->sub_sec_security, + reset_full); + if (tevent_req_nterror(req, status)) { + return; + } + } + +respond: + spnego_state->out_status = status; + + status = gensec_spnego_update_out(state->gensec, + state, &state->out); + if (GENSEC_UPDATE_IS_NTERROR(status)) { + tevent_req_nterror(req, status); + return; + } + + state->status = status; + tevent_req_done(req); + return; +} + static NTSTATUS gensec_spnego_update_out(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, DATA_BLOB *_out) -- cgit v1.2.1