summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2017-06-13 23:43:01 +0200
committerAndreas Schneider <asn@cryptomilk.org>2017-07-25 13:51:10 +0200
commit81df16a54ab28b0e4925623aaec93ac6238eb4be (patch)
tree7af5d329e8f47a1faf7840a7a289a75dbc2cf6e0
parent9502f535338f06f334e294827ea339001d8625b8 (diff)
downloadsamba-81df16a54ab28b0e4925623aaec93ac6238eb4be.tar.gz
auth/spnego: make the SPNEGO_FALLBACK continuation completely async
Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
-rw-r--r--auth/gensec/spnego.c74
1 files changed, 62 insertions, 12 deletions
diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c
index f16b39a2c70..0e37c3faf21 100644
--- a/auth/gensec/spnego.c
+++ b/auth/gensec/spnego.c
@@ -1168,9 +1168,18 @@ struct gensec_spnego_update_state {
struct tevent_context *ev;
struct gensec_security *gensec;
struct spnego_state *spnego;
+
DATA_BLOB full_in;
struct spnego_data _spnego_in;
struct spnego_data *spnego_in;
+
+ struct {
+ bool needed;
+ DATA_BLOB in;
+ NTSTATUS status;
+ DATA_BLOB out;
+ } sub;
+
NTSTATUS status;
DATA_BLOB out;
};
@@ -1200,6 +1209,7 @@ 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_done(struct tevent_req *subreq);
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,
@@ -1334,9 +1344,24 @@ static struct tevent_req *gensec_spnego_update_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
- /*
- * TODO: prepare async processing here in future.
- */
+ if (state->sub.needed) {
+ struct tevent_req *subreq = NULL;
+
+ /*
+ * We may need one more roundtrip...
+ */
+ subreq = gensec_update_send(state, state->ev,
+ spnego_state->sub_sec_security,
+ state->sub.in);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq,
+ gensec_spnego_update_done,
+ req);
+ state->sub.needed = false;
+ return req;
+ }
gensec_spnego_update_post(req);
if (!tevent_req_is_in_progress(req)) {
@@ -1464,15 +1489,15 @@ static void gensec_spnego_update_pre(struct tevent_req *req)
struct tevent_context *ev = state->ev;
NTSTATUS status;
+ state->sub.needed = false;
+ state->sub.in = data_blob_null;
+ state->sub.status = NT_STATUS_INTERNAL_ERROR;
+ state->sub.out = data_blob_null;
+
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;
+ state->sub.in = state->full_in;
+ state->full_in = data_blob_null;
+ state->sub.needed = true;
return;
}
@@ -1549,6 +1574,25 @@ static void gensec_spnego_update_pre(struct tevent_req *req)
spnego_state->out_status = status;
}
+static void gensec_spnego_update_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct gensec_spnego_update_state *state =
+ tevent_req_data(req,
+ struct gensec_spnego_update_state);
+ struct spnego_state *spnego_state = state->spnego;
+
+ state->sub.status = gensec_update_recv(subreq, state, &state->sub.out);
+ TALLOC_FREE(subreq);
+ if (NT_STATUS_IS_OK(state->sub.status)) {
+ spnego_state->sub_sec_ready = true;
+ }
+
+ gensec_spnego_update_post(req);
+}
+
static void gensec_spnego_update_post(struct tevent_req *req)
{
struct gensec_spnego_update_state *state =
@@ -1557,8 +1601,14 @@ static void gensec_spnego_update_post(struct tevent_req *req)
struct spnego_state *spnego_state = state->spnego;
NTSTATUS status;
+ state->sub.in = data_blob_null;
+ state->sub.needed = false;
+
if (spnego_state->state_position == SPNEGO_FALLBACK) {
- status = spnego_state->out_status;
+ status = state->sub.status;
+ spnego_state->out_frag = state->sub.out;
+ talloc_steal(spnego_state, spnego_state->out_frag.data);
+ state->sub.out = data_blob_null;
goto respond;
}