diff options
-rw-r--r-- | source4/auth/gensec/config.mk | 2 | ||||
-rw-r--r-- | source4/auth/gensec/gensec.c | 117 | ||||
-rw-r--r-- | source4/auth/gensec/gensec.h | 22 | ||||
-rw-r--r-- | source4/smb_server/smb/sesssetup.c | 20 | ||||
-rw-r--r-- | source4/smb_server/smb2/sesssetup.c | 17 |
5 files changed, 110 insertions, 68 deletions
diff --git a/source4/auth/gensec/config.mk b/source4/auth/gensec/config.mk index f7cbd5b197..947a91e852 100644 --- a/source4/auth/gensec/config.mk +++ b/source4/auth/gensec/config.mk @@ -2,7 +2,7 @@ # Start SUBSYSTEM gensec [LIBRARY::gensec] PUBLIC_DEPENDENCIES = \ - CREDENTIALS LIBSAMBA-UTIL LIBCRYPTO ASN1_UTIL samba_socket LIBPACKET LIBTSOCKET + CREDENTIALS LIBSAMBA-UTIL LIBCRYPTO ASN1_UTIL samba_socket LIBPACKET LIBTSOCKET UTIL_TEVENT # End SUBSYSTEM gensec ################################# diff --git a/source4/auth/gensec/gensec.c b/source4/auth/gensec/gensec.c index ecd0778ee6..3de0e1c935 100644 --- a/source4/auth/gensec/gensec.c +++ b/source4/auth/gensec/gensec.c @@ -25,6 +25,7 @@ #include "lib/events/events.h" #include "lib/socket/socket.h" #include "lib/tsocket/tsocket.h" +#include "../lib/util/tevent_ntstatus.h" #include "librpc/rpc/dcerpc.h" #include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" @@ -982,71 +983,105 @@ _PUBLIC_ NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_ return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out); } -static void gensec_update_async_timed_handler(struct tevent_context *ev, struct tevent_timer *te, - struct timeval t, void *ptr) -{ - struct gensec_update_request *req = talloc_get_type(ptr, struct gensec_update_request); - req->status = req->gensec_security->ops->update(req->gensec_security, req, req->in, &req->out); - req->callback.fn(req, req->callback.private_data); -} +struct gensec_update_state { + struct tevent_immediate *im; + struct gensec_security *gensec_security; + DATA_BLOB in; + DATA_BLOB out; +}; +static void gensec_update_async_trigger(struct tevent_context *ctx, + struct tevent_immediate *im, + void *private_data); /** * Next state function for the GENSEC state machine async version - * + * + * @param mem_ctx The memory context for the request + * @param ev The event context for the request * @param gensec_security GENSEC State * @param in The request, as a DATA_BLOB - * @param callback The function that will be called when the operation is - * finished, it should return gensec_update_recv() to get output - * @param private_data A private pointer that will be passed to the callback function + * + * @return The request handle or NULL on no memory failure */ -_PUBLIC_ void gensec_update_send(struct gensec_security *gensec_security, const DATA_BLOB in, - void (*callback)(struct gensec_update_request *req, void *private_data), - void *private_data) +_PUBLIC_ struct tevent_req *gensec_update_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct gensec_security *gensec_security, + const DATA_BLOB in) +{ + struct tevent_req *req; + struct gensec_update_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, + struct gensec_update_state); + if (req == NULL) { + return NULL; + } + + state->gensec_security = gensec_security; + state->in = in; + state->out = data_blob(NULL, 0); + state->im = tevent_create_immediate(state); + if (tevent_req_nomem(state->im, req)) { + return tevent_req_post(req, ev); + } + + tevent_schedule_immediate(state->im, ev, + gensec_update_async_trigger, + req); + + return req; +} + +static void gensec_update_async_trigger(struct tevent_context *ctx, + struct tevent_immediate *im, + void *private_data) { - struct gensec_update_request *req = NULL; - struct tevent_timer *te = NULL; - - req = talloc(gensec_security, struct gensec_update_request); - if (!req) goto failed; - req->gensec_security = gensec_security; - req->in = in; - req->out = data_blob(NULL, 0); - req->callback.fn = callback; - req->callback.private_data = private_data; - - te = event_add_timed(gensec_security->event_ctx, req, - timeval_zero(), - gensec_update_async_timed_handler, req); - if (!te) goto failed; - - return; - -failed: - talloc_free(req); - callback(NULL, private_data); + struct tevent_req *req = + talloc_get_type_abort(private_data, struct tevent_req); + struct gensec_update_state *state = + tevent_req_data(req, struct gensec_update_state); + NTSTATUS status; + + status = gensec_update(state->gensec_security, state, + state->in, &state->out); + if (tevent_req_nterror(req, status)) { + return; + } + + tevent_req_done(req); } /** * Next state function for the GENSEC state machine * - * @param req GENSEC update request state + * @param req request state * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, * or NT_STATUS_OK if the user is authenticated. */ -_PUBLIC_ NTSTATUS gensec_update_recv(struct gensec_update_request *req, TALLOC_CTX *out_mem_ctx, DATA_BLOB *out) +_PUBLIC_ NTSTATUS gensec_update_recv(struct tevent_req *req, + TALLOC_CTX *out_mem_ctx, + DATA_BLOB *out) { + struct gensec_update_state *state = + tevent_req_data(req, struct gensec_update_state); NTSTATUS status; - NT_STATUS_HAVE_NO_MEMORY(req); + if (tevent_req_is_nterror(req, &status)) { + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + tevent_req_received(req); + return status; + } + } else { + status = NT_STATUS_OK; + } - *out = req->out; + *out = state->out; talloc_steal(out_mem_ctx, out->data); - status = req->status; - talloc_free(req); + tevent_req_received(req); return status; } diff --git a/source4/auth/gensec/gensec.h b/source4/auth/gensec/gensec.h index 2ea2402064..232f1a4500 100644 --- a/source4/auth/gensec/gensec.h +++ b/source4/auth/gensec/gensec.h @@ -69,18 +69,7 @@ struct auth_session_info; struct cli_credentials; struct gensec_settings; struct tevent_context; - -struct gensec_update_request { - struct gensec_security *gensec_security; - void *private_data; - DATA_BLOB in; - DATA_BLOB out; - NTSTATUS status; - struct { - void (*fn)(struct gensec_update_request *req, void *private_data); - void *private_data; - } callback; -}; +struct tevent_req; struct gensec_settings { struct loadparm_context *lp_ctx; @@ -231,10 +220,11 @@ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security, const char **sasl_names); NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, const DATA_BLOB in, DATA_BLOB *out); -void gensec_update_send(struct gensec_security *gensec_security, const DATA_BLOB in, - void (*callback)(struct gensec_update_request *req, void *private_data), - void *private_data); -NTSTATUS gensec_update_recv(struct gensec_update_request *req, TALLOC_CTX *out_mem_ctx, DATA_BLOB *out); +struct tevent_req *gensec_update_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct gensec_security *gensec_security, + const DATA_BLOB in); +NTSTATUS gensec_update_recv(struct tevent_req *req, TALLOC_CTX *out_mem_ctx, DATA_BLOB *out); void gensec_want_feature(struct gensec_security *gensec_security, uint32_t feature); bool gensec_have_feature(struct gensec_security *gensec_security, diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c index 8cd2edcee3..e415a47699 100644 --- a/source4/smb_server/smb/sesssetup.c +++ b/source4/smb_server/smb/sesssetup.c @@ -23,6 +23,7 @@ */ #include "includes.h" +#include <tevent.h> #include "version.h" #include "auth/gensec/gensec.h" #include "auth/auth.h" @@ -289,9 +290,9 @@ struct sesssetup_spnego_state { struct smbsrv_session *smb_sess; }; -static void sesssetup_spnego_send(struct gensec_update_request *greq, void *private_data) +static void sesssetup_spnego_send(struct tevent_req *subreq) { - struct sesssetup_spnego_state *s = talloc_get_type(private_data, + struct sesssetup_spnego_state *s = tevent_req_callback_data(subreq, struct sesssetup_spnego_state); struct smbsrv_request *req = s->req; union smb_sesssetup *sess = s->sess; @@ -301,7 +302,8 @@ static void sesssetup_spnego_send(struct gensec_update_request *greq, void *priv NTSTATUS skey_status; DATA_BLOB session_key; - status = gensec_update_recv(greq, req, &sess->spnego.out.secblob); + status = gensec_update_recv(subreq, req, &sess->spnego.out.secblob); + TALLOC_FREE(subreq); if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { goto done; } else if (!NT_STATUS_IS_OK(status)) { @@ -343,6 +345,7 @@ static void sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup *se struct smbsrv_session *smb_sess = NULL; struct sesssetup_spnego_state *s = NULL; uint16_t vuid; + struct tevent_req *subreq; sess->spnego.out.vuid = 0; sess->spnego.out.action = 0; @@ -410,8 +413,15 @@ static void sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup *se s->sess = sess; s->smb_sess = smb_sess; - gensec_update_send(smb_sess->gensec_ctx, sess->spnego.in.secblob, - sesssetup_spnego_send, s); + subreq = gensec_update_send(s, + req->smb_conn->connection->event.ctx, + smb_sess->gensec_ctx, + sess->spnego.in.secblob); + if (!subreq) { + goto nomem; + } + tevent_req_set_callback(subreq, sesssetup_spnego_send, s); + return; nomem: diff --git a/source4/smb_server/smb2/sesssetup.c b/source4/smb_server/smb2/sesssetup.c index 58090305a0..9b601d17c0 100644 --- a/source4/smb_server/smb2/sesssetup.c +++ b/source4/smb_server/smb2/sesssetup.c @@ -19,6 +19,7 @@ */ #include "includes.h" +#include <tevent.h> #include "auth/gensec/gensec.h" #include "auth/auth.h" #include "libcli/smb2/smb2.h" @@ -57,9 +58,9 @@ struct smb2srv_sesssetup_callback_ctx { struct smbsrv_session *smb_sess; }; -static void smb2srv_sesssetup_callback(struct gensec_update_request *greq, void *private_data) +static void smb2srv_sesssetup_callback(struct tevent_req *subreq) { - struct smb2srv_sesssetup_callback_ctx *ctx = talloc_get_type(private_data, + struct smb2srv_sesssetup_callback_ctx *ctx = tevent_req_callback_data(subreq, struct smb2srv_sesssetup_callback_ctx); struct smb2srv_request *req = ctx->req; union smb_sesssetup *io = ctx->io; @@ -67,7 +68,8 @@ static void smb2srv_sesssetup_callback(struct gensec_update_request *greq, void struct auth_session_info *session_info = NULL; NTSTATUS status; - status = gensec_update_recv(greq, req, &io->smb2.out.secblob); + status = gensec_update_recv(subreq, req, &io->smb2.out.secblob); + TALLOC_FREE(subreq); if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { goto done; } else if (!NT_STATUS_IS_OK(status)) { @@ -108,6 +110,7 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses struct smb2srv_sesssetup_callback_ctx *callback_ctx; struct smbsrv_session *smb_sess = NULL; uint64_t vuid; + struct tevent_req *subreq; io->smb2.out.session_flags = 0; io->smb2.out.uid = 0; @@ -174,8 +177,12 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses callback_ctx->io = io; callback_ctx->smb_sess = smb_sess; - gensec_update_send(smb_sess->gensec_ctx, io->smb2.in.secblob, - smb2srv_sesssetup_callback, callback_ctx); + subreq = gensec_update_send(callback_ctx, + req->smb_conn->connection->event.ctx, + smb_sess->gensec_ctx, + io->smb2.in.secblob); + if (!subreq) goto nomem; + tevent_req_set_callback(subreq, smb2srv_sesssetup_callback, callback_ctx); /* note that we ignore SMB2_NEGOTIATE_SIGNING_ENABLED from the client. This is deliberate as windows does not set it even when it does |