s4:librpc/rpc: convert dcerpc_bind_send/recv to tevent_req
authorStefan Metzmacher <metze@samba.org>
Tue, 13 Mar 2012 13:52:40 +0000 (14:52 +0100)
committerStefan Metzmacher <metze@samba.org>
Thu, 15 Mar 2012 06:35:28 +0000 (07:35 +0100)
Many thanks to Andrew Bartlett <abartlet@samba.org> for the
debugging, which lead to the following line:

       talloc_steal(state, raw_packet->data);

metze

source4/librpc/rpc/dcerpc.c
source4/librpc/rpc/dcerpc_auth.c

index 32436447218b519d643463fd461ba3516fe2af91..c1f27cc2637a2df0863c065b96efdc5174a2b2c1 100644 (file)
@@ -1071,65 +1071,6 @@ static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NT
        dcerpc_request_recv_data(conn, blob, &pkt);
 }
 
-/*
-  Receive a bind reply from the transport
-*/
-static void dcerpc_bind_recv_handler(struct rpc_request *req, 
-                                    DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
-{
-       struct composite_context *c;
-       struct dcecli_connection *conn;
-
-       c = talloc_get_type(req->async.private_data, struct composite_context);
-
-       if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
-               DEBUG(2,("dcerpc: bind_nak reason %d\n",
-                        pkt->u.bind_nak.reject_reason));
-               composite_error(c, dcerpc_map_reason(pkt->u.bind_nak.
-                                                    reject_reason));
-               return;
-       }
-
-       if ((pkt->ptype != DCERPC_PKT_BIND_ACK) ||
-           (pkt->u.bind_ack.num_results == 0) ||
-           (pkt->u.bind_ack.ctx_list[0].result != 0)) {
-               req->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
-               composite_error(c, NT_STATUS_NET_WRITE_FAULT);
-               return;
-       }
-
-       conn = req->p->conn;
-
-       conn->srv_max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
-       conn->srv_max_recv_frag = pkt->u.bind_ack.max_recv_frag;
-
-       if ((req->p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) &&
-           (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
-               conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
-       }
-
-       if ((req->p->binding->flags & DCERPC_HEADER_SIGNING) &&
-           (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
-               conn->flags |= DCERPC_HEADER_SIGNING;
-       }
-
-       /* the bind_ack might contain a reply set of credentials */
-       if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
-               NTSTATUS status;
-               uint32_t auth_length;
-               status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
-                                                 conn->security_state.auth_info, &auth_length, true);
-               if (!NT_STATUS_IS_OK(status)) {
-                       composite_error(c, status);
-                       return;
-               }
-       }
-
-       req->p->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
-
-       composite_done(c);
-}
-
 /*
   handle timeouts of individual dcerpc requests
 */
@@ -1151,23 +1092,35 @@ static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_time
        dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
 }
 
-/*
-  send a async dcerpc bind request
-*/
-struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
-                                          TALLOC_CTX *mem_ctx,
-                                          const struct ndr_syntax_id *syntax,
-                                          const struct ndr_syntax_id *transfer_syntax)
+struct dcerpc_bind_state {
+       struct dcerpc_pipe *p;
+};
+
+static void dcerpc_bind_fail_handler(struct rpc_request *subreq);
+static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
+                                    DATA_BLOB *raw_packet,
+                                    struct ncacn_packet *pkt);
+
+struct tevent_req *dcerpc_bind_send(TALLOC_CTX *mem_ctx,
+                                   struct tevent_context *ev,
+                                   struct dcerpc_pipe *p,
+                                   const struct ndr_syntax_id *syntax,
+                                   const struct ndr_syntax_id *transfer_syntax)
 {
-       struct composite_context *c;
+       struct tevent_req *req;
+       struct dcerpc_bind_state *state;
        struct ncacn_packet pkt;
        DATA_BLOB blob;
-       struct rpc_request *req;
+       NTSTATUS status;
+       struct rpc_request *subreq;
 
-       c = composite_create(mem_ctx,p->conn->event_ctx);
-       if (c == NULL) return NULL;
+       req = tevent_req_create(mem_ctx, &state,
+                               struct dcerpc_bind_state);
+       if (req == NULL) {
+               return NULL;
+       }
 
-       c->private_data = p;
+       state->p = p;
 
        p->syntax = *syntax;
        p->transfer_syntax = *transfer_syntax;
@@ -1192,7 +1145,9 @@ struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
        pkt.u.bind.assoc_group_id = p->binding->assoc_group_id;
        pkt.u.bind.num_contexts = 1;
        pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
-       if (composite_nomem(pkt.u.bind.ctx_list, c)) return c;
+       if (tevent_req_nomem(pkt.u.bind.ctx_list, req)) {
+               return tevent_req_post(req, ev);
+       }
        pkt.u.bind.ctx_list[0].context_id = p->context_id;
        pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
        pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
@@ -1200,9 +1155,11 @@ struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
        pkt.u.bind.auth_info = data_blob(NULL, 0);
 
        /* construct the NDR form of the packet */
-       c->status = ncacn_push_auth(&blob, c, &pkt,
-                                   p->conn->security_state.auth_info);
-       if (!composite_is_ok(c)) return c;
+       status = ncacn_push_auth(&blob, state, &pkt,
+                                p->conn->security_state.auth_info);
+       if (tevent_req_nterror(req, status)) {
+               return tevent_req_post(req, ev);
+       }
 
        p->conn->transport.recv_data = dcerpc_recv_data;
 
@@ -1210,37 +1167,114 @@ struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
         * we allocate a dcerpc_request so we can be in the same
         * request queue as normal requests
         */
-       req = talloc_zero(c, struct rpc_request);
-       if (composite_nomem(req, c)) return c;
+       subreq = talloc_zero(state, struct rpc_request);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
 
-       req->state = RPC_REQUEST_PENDING;
-       req->call_id = pkt.call_id;
-       req->async.private_data = c;
-       req->async.callback = dcerpc_composite_fail;
-       req->p = p;
-       req->recv_handler = dcerpc_bind_recv_handler;
-       DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);
-       talloc_set_destructor(req, dcerpc_req_dequeue);
+       subreq->state = RPC_REQUEST_PENDING;
+       subreq->call_id = pkt.call_id;
+       subreq->async.private_data = req;
+       subreq->async.callback = dcerpc_bind_fail_handler;
+       subreq->p = p;
+       subreq->recv_handler = dcerpc_bind_recv_handler;
+       DLIST_ADD_END(p->conn->pending, subreq, struct rpc_request *);
+       talloc_set_destructor(subreq, dcerpc_req_dequeue);
+
+       status = p->conn->transport.send_request(p->conn, &blob, true);
+       if (tevent_req_nterror(req, status)) {
+               return tevent_req_post(req, ev);
+       }
 
-       c->status = p->conn->transport.send_request(p->conn, &blob,
-                                                   true);
-       if (!composite_is_ok(c)) return c;
+       tevent_add_timer(ev, subreq,
+                        timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
+                        dcerpc_timeout_handler, subreq);
 
-       tevent_add_timer(c->event_ctx, req,
-                       timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
-                       dcerpc_timeout_handler, req);
+       return req;
+}
 
-       return c;
+static void dcerpc_bind_fail_handler(struct rpc_request *subreq)
+{
+       struct tevent_req *req =
+               talloc_get_type_abort(subreq->async.private_data,
+               struct tevent_req);
+       NTSTATUS status = subreq->status;
+
+       TALLOC_FREE(subreq);
+
+       tevent_req_nterror(req, status);
 }
 
-/*
-  recv side of async dcerpc bind request
-*/
-NTSTATUS dcerpc_bind_recv(struct composite_context *ctx)
+static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
+                                    DATA_BLOB *raw_packet,
+                                    struct ncacn_packet *pkt)
 {
-       NTSTATUS result = composite_wait(ctx);
-       talloc_free(ctx);
-       return result;
+       struct tevent_req *req =
+               talloc_get_type_abort(subreq->async.private_data,
+               struct tevent_req);
+       struct dcerpc_bind_state *state =
+               tevent_req_data(req,
+               struct dcerpc_bind_state);
+       struct dcecli_connection *conn = state->p->conn;
+       NTSTATUS status;
+
+       /*
+        * Note that pkt is allocated under raw_packet->data,
+        * while raw_packet->data is a child of subreq.
+        */
+       talloc_steal(state, raw_packet->data);
+       TALLOC_FREE(subreq);
+
+       if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
+               status = dcerpc_map_reason(pkt->u.bind_nak.reject_reason);
+
+               DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
+                        pkt->u.bind_nak.reject_reason, nt_errstr(status)));
+
+               tevent_req_nterror(req, status);
+               return;
+       }
+
+       if ((pkt->ptype != DCERPC_PKT_BIND_ACK) ||
+           (pkt->u.bind_ack.num_results == 0) ||
+           (pkt->u.bind_ack.ctx_list[0].result != 0)) {
+               state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
+               tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
+               return;
+       }
+
+       conn->srv_max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
+       conn->srv_max_recv_frag = pkt->u.bind_ack.max_recv_frag;
+
+       if ((state->p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) &&
+           (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
+               conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
+       }
+
+       if ((state->p->binding->flags & DCERPC_HEADER_SIGNING) &&
+           (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
+               conn->flags |= DCERPC_HEADER_SIGNING;
+       }
+
+       /* the bind_ack might contain a reply set of credentials */
+       if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
+               uint32_t auth_length;
+
+               status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
+                                                 conn->security_state.auth_info, &auth_length, true);
+               if (tevent_req_nterror(req, status)) {
+                       return;
+               }
+       }
+
+       state->p->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
+
+       tevent_req_done(req);
+}
+
+NTSTATUS dcerpc_bind_recv(struct tevent_req *req)
+{
+       return tevent_req_simple_recv_ntstatus(req);
 }
 
 /* 
index b3f4f2fdb05ade84add35f3e9eb1dccf671d6d1b..7af85aaab138b37e4e38904f3b88492bf72106bb 100644 (file)
@@ -22,6 +22,7 @@
 */
 
 #include "includes.h"
+#include <tevent.h>
 #include "libcli/composite/composite.h"
 #include "auth/gensec/gensec.h"
 #include "librpc/rpc/dcerpc.h"
@@ -52,6 +53,8 @@ static NTSTATUS dcerpc_init_syntaxes(const struct ndr_interface_table *table,
 /*
   Send request to do a non-authenticated dcerpc bind
 */
+static void dcerpc_bind_auth_none_done(struct tevent_req *subreq);
+
 struct composite_context *dcerpc_bind_auth_none_send(TALLOC_CTX *mem_ctx,
                                                     struct dcerpc_pipe *p,
                                                     const struct ndr_interface_table *table)
@@ -60,6 +63,7 @@ struct composite_context *dcerpc_bind_auth_none_send(TALLOC_CTX *mem_ctx,
        struct ndr_syntax_id transfer_syntax;
 
        struct composite_context *c;
+       struct tevent_req *subreq;
 
        c = composite_create(mem_ctx, p->conn->event_ctx);
        if (c == NULL) return NULL;
@@ -73,19 +77,35 @@ struct composite_context *dcerpc_bind_auth_none_send(TALLOC_CTX *mem_ctx,
                return c;
        }
 
-       /* c was only allocated as a container for a possible error */
-       talloc_free(c);
+       subreq = dcerpc_bind_send(mem_ctx, p->conn->event_ctx, p,
+                                 &syntax, &transfer_syntax);
+       if (composite_nomem(subreq, c)) return c;
+       tevent_req_set_callback(subreq, dcerpc_bind_auth_none_done, c);
 
-       return dcerpc_bind_send(p, mem_ctx, &syntax, &transfer_syntax);
+       return c;
 }
 
+static void dcerpc_bind_auth_none_done(struct tevent_req *subreq)
+{
+       struct composite_context *ctx =
+               tevent_req_callback_data(subreq,
+               struct composite_context);
+
+       ctx->status = dcerpc_bind_recv(subreq);
+       TALLOC_FREE(subreq);
+       if (!composite_is_ok(ctx)) return;
+
+       composite_done(ctx);
+}
 
 /*
   Receive result of a non-authenticated dcerpc bind
 */
 NTSTATUS dcerpc_bind_auth_none_recv(struct composite_context *ctx)
 {
-       return dcerpc_bind_recv(ctx);
+       NTSTATUS result = composite_wait(ctx);
+       TALLOC_FREE(ctx);
+       return result;
 }
 
 
@@ -191,14 +211,16 @@ static void bind_auth_recv_alter(struct composite_context *creq)
 }
 
 
-static void bind_auth_recv_bindreply(struct composite_context *creq)
+static void bind_auth_recv_bindreply(struct tevent_req *subreq)
 {
-       struct composite_context *c = talloc_get_type(creq->async.private_data,
-                                                     struct composite_context);
+       struct composite_context *c =
+               tevent_req_callback_data(subreq,
+               struct composite_context);
        struct bind_auth_state *state = talloc_get_type(c->private_data,
                                                        struct bind_auth_state);
 
-       c->status = dcerpc_bind_recv(creq);
+       c->status = dcerpc_bind_recv(subreq);
+       TALLOC_FREE(subreq);
        if (!composite_is_ok(c)) return;
 
        if (!state->more_processing) {
@@ -232,9 +254,10 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
                                                uint8_t auth_type, uint8_t auth_level,
                                                const char *service)
 {
-       struct composite_context *c, *creq;
+       struct composite_context *c;
        struct bind_auth_state *state;
        struct dcecli_security *sec;
+       struct tevent_req *subreq;
 
        struct ndr_syntax_id syntax, transfer_syntax;
 
@@ -355,12 +378,13 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
 
        /* The first request always is a dcerpc_bind. The subsequent ones
         * depend on gensec results */
-       creq = dcerpc_bind_send(p, state, &syntax, &transfer_syntax);
+       subreq = dcerpc_bind_send(state, p->conn->event_ctx, p,
+                                 &syntax, &transfer_syntax);
        data_blob_free(&state->credentials);
        sec->auth_info->credentials = data_blob(NULL, 0);
-       if (composite_nomem(creq, c)) return c;
+       if (composite_nomem(subreq, c)) return c;
+       tevent_req_set_callback(subreq, bind_auth_recv_bindreply, c);
 
-       composite_continue(c, creq, bind_auth_recv_bindreply, c);
        return c;
 }