s4:gensec: change gensec_update_send/recv to tevent_req
authorStefan Metzmacher <metze@samba.org>
Tue, 22 Dec 2009 15:24:44 +0000 (16:24 +0100)
committerStefan Metzmacher <metze@samba.org>
Thu, 24 Dec 2009 16:38:34 +0000 (17:38 +0100)
metze

source4/auth/gensec/config.mk
source4/auth/gensec/gensec.c
source4/auth/gensec/gensec.h
source4/smb_server/smb/sesssetup.c
source4/smb_server/smb2/sesssetup.c

index f7cbd5b197672169cddf50d7fe66be8518ab72c4..947a91e8529a0c49fdf912344d40df23f9846013 100644 (file)
@@ -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
 #################################
 
index ecd0778ee67dbdc175fda8ee84b4edac1691aaf4..3de0e1c9356d5fa6c631d7330ddd5f70174d6350 100644 (file)
@@ -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;
 }
 
index 2ea2402064eb3dacd7b2e26e881539aab85716fa..232f1a4500db72d1f55d44c20eca58fa96d55d0e 100644 (file)
@@ -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,
index 8cd2edcee3f4dbebce5c8784109871384d3702b8..e415a47699b0e03cec04c3a48121f768788a8e70 100644 (file)
@@ -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:
index 58090305a03b1f77332d1c9c4e8c2c62e582a4bc..9b601d17c00c9417eb0e5f2f4fe2fd0570200b8b 100644 (file)
@@ -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