From d69c7020cf687e42249efebea10e35e2cf0306dc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 20 Sep 2013 14:38:13 +0200 Subject: [PATCH] source4/librpc/rpc/dcerpc.c sq bla --- source4/librpc/rpc/dcerpc.c | 119 ++++++++++++++++++++++++++++++------ 1 file changed, 101 insertions(+), 18 deletions(-) diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index 2e7f92a0ae28..a0bbf6b78c08 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -63,7 +63,7 @@ struct rpc_request { const struct GUID *object; uint16_t opnum; DATA_BLOB request_data; - bool request_data_allocated; + bool request_data_can_append; struct tevent_req *stub_subreq; bool ignore_timeout; bool wait_for_sync; @@ -379,7 +379,7 @@ static NTSTATUS dcerpc_bh_raw_call_recv(struct tevent_req *req, } struct dcerpc_bh_raw_call_in_state { - + uint8_t dummy; }; static struct tevent_req *dcerpc_bh_raw_call_in_send(TALLOC_CTX *mem_ctx, @@ -392,6 +392,9 @@ static struct tevent_req *dcerpc_bh_raw_call_in_send(TALLOC_CTX *mem_ctx, struct dcerpc_bh_raw_call_state *raw_call_state = NULL; struct tevent_req *req; struct dcerpc_bh_raw_call_in_state *state; + struct rpc_request *rpcreq = NULL; + DATA_BLOB *b = NULL; + bool ok; req = tevent_req_create(mem_ctx, &state, struct dcerpc_bh_raw_call_in_state); @@ -407,15 +410,71 @@ static struct tevent_req *dcerpc_bh_raw_call_in_send(TALLOC_CTX *mem_ctx, raw_call_state = tevent_req_data(raw_call_req, struct dcerpc_bh_raw_call_state); - - struct rpc_request *subreq; - - return req; + if (raw_call_state->subreq == NULL) { + tevent_req_nterror(req, NT_STATUS_RPC_CALL_FAILED); + return tevent_req_post(req, ev); + } + + rpcreq = raw_call_state->subreq; + + if (rpcreq->state != RPC_REQUEST_QUEUED) { + tevent_req_nterror(req, NT_STATUS_RPC_INVALID_PIPE_OPERATION); + return tevent_req_post(req, ev); + } + + if (!(in_flags & LIBNDR_FLAG_INCOMPLETE_BUFFER)) { + rpcreq->incomplete_request_data = false; + } + + b = &rpcreq->request_data; + + if (in_length == 0) { + if (in_flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) { + /* + * with LIBNDR_FLAG_INCOMPLETE_BUFFER + * we need to make sure we make any progress... + */ + tevent_req_nterror(req, NT_STATUS_RPC_INVALID_PIPE_OPERATION); + return tevent_req_post(req, ev); + } + + /* + * nothing to add + */ + } else if (rpcreq->request_data_can_append) { + ok = data_blob_append(rpcreq, b, in_data, in_length); + if (!ok) { + tevent_req_nomem(NULL, req); + return tevent_req_post(req, ev); + } + } else { + *b = data_blob_talloc(rpcreq, b->data, b->length); + if (tevent_req_nomem(b->data, req)) { + return tevent_req_post(req, ev); + } + rpcreq->request_data_can_append = true; + ok = data_blob_append(rpcreq, b, in_data, in_length); + if (!ok) { + tevent_req_nomem(NULL, req); + return tevent_req_post(req, ev); + } + } + + dcerpc_schedule_io_trigger(rpcreq->p->conn); + + if (b->length > (rpcreq->p->conn->srv_max_xmit_frag * 10)) { + rpcreq->stub_subreq = req; + //TODO + return req; + } + + tevent_req_done(req); + return tevent_req_post(req, ev); } -static NTSTATUS dcerpc_bh_raw_call_in__recv(struct tevent_req *req) +static NTSTATUS dcerpc_bh_raw_call_in_recv(struct tevent_req *req) { - + return tevent_req_simple_recv_ntstatus(req); } struct dcerpc_bh_disconnect_state { @@ -1479,7 +1538,7 @@ static void dcerpc_request_recv_data(struct dcecli_connection *c, goto req_done; } - if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) { + if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) { if (req->first_pdu_done) { req->status = NT_STATUS_RPC_PROTOCOL_ERROR; goto req_done; @@ -1602,8 +1661,13 @@ static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx, } req->opnum = opnum; - req->request_data.length = stub_data->length; - req->request_data.data = stub_data->data; + + if (stub_data->length > 0) { + req->request_data.length = stub_data->length; + req->request_data.data = stub_data->data; + } else { + req->request_data_can_append = true; + } status = dcerpc_request_prepare_vt(req); if (!NT_STATUS_IS_OK(status)) { @@ -1754,6 +1818,7 @@ static void dcerpc_ship_next_request(struct dcecli_connection *c) size_t sig_size = 0; bool need_async = false; bool can_async = true; + bool current_pdus_done = false; req = c->request_queue; if (req == NULL) { @@ -1767,6 +1832,15 @@ static void dcerpc_ship_next_request(struct dcecli_connection *c) need_async = true; } + remaining = stub_data->length; + + if ((remaining == 0) && req->incomplete_request_data) { + /* + * we're waiting for more data + */ + return; + } + if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_PACKET) { can_async = gensec_have_feature(c->security_state.generic_state, GENSEC_FEATURE_ASYNC_REPLIES); @@ -1779,8 +1853,6 @@ static void dcerpc_ship_next_request(struct dcecli_connection *c) init_ncacn_hdr(p->conn, &pkt); - remaining = stub_data->length; - /* we can write a full max_recv_frag size, minus the dcerpc request header size */ chunk_size = p->conn->srv_max_recv_frag; @@ -1814,7 +1886,7 @@ static void dcerpc_ship_next_request(struct dcecli_connection *c) } /* we send a series of pdus without waiting for a reply */ - while (remaining > 0 || !req->first_pdu_done) { + while (!current_pdus_done) { uint32_t chunk = MIN(chunk_size, remaining); bool last_frag = false; bool do_trans = false; @@ -1866,13 +1938,20 @@ static void dcerpc_ship_next_request(struct dcecli_connection *c) } remaining -= chunk; + if (remaining == 0) { + current_pdus_done = true; + } req->last_pdu_done = last_frag; } - if (req->request_data_allocated) { + if (req->request_data_can_append) { + /* + * request_data_can_append means the blob + * is a talloc child of req + */ data_blob_free(&req->request_data); } - req->request_data_allocated = false; + req->request_data_can_append = true; req->request_data = data_blob_null; if (req->last_pdu_done) { @@ -1886,11 +1965,15 @@ static void dcerpc_ship_next_request(struct dcecli_connection *c) req->last_pdu_done = false; } - if (req->stub_subreq == NULL) { + if (req->stub_subreq != NULL) { + struct tevent_req *stub_subreq = req->stub_subreq; + + req->stub_subreq = NULL; + + tevent_req_done(stub_subreq); return; } - tevent_req_done(req->stub_subreq); return; } -- 2.34.1