1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

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 <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
Stefan Metzmacher 2017-06-13 23:43:01 +02:00 committed by Andreas Schneider
parent cb8f370abd
commit 3bf4946450

View File

@ -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;
/*
* TODO: prepare async processing here in future.
*/
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;
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)