summaryrefslogtreecommitdiff
path: root/source4/librpc/rpc/dcerpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/librpc/rpc/dcerpc.c')
-rw-r--r--source4/librpc/rpc/dcerpc.c232
1 files changed, 133 insertions, 99 deletions
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index 3243644721..c1f27cc263 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -1072,65 +1072,6 @@ static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NT
}
/*
- 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
*/
static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
@@ -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);
}
/*