diff options
Diffstat (limited to 'source4/librpc/rpc/dcerpc.c')
-rw-r--r-- | source4/librpc/rpc/dcerpc.c | 56 |
1 files changed, 47 insertions, 9 deletions
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index 4758189d3b..28b5cd65a9 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -334,6 +334,7 @@ static NTSTATUS ncacn_pull_request_auth(struct dcerpc_connection *c, TALLOC_CTX */ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx, + size_t sig_size, struct ncacn_packet *pkt) { NTSTATUS status; @@ -384,8 +385,7 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c, * GENSEC mech does AEAD signing of the packet * headers */ c->security_state.auth_info->credentials - = data_blob_talloc(mem_ctx, NULL, gensec_sig_size(c->security_state.generic_state, - payload_length)); + = data_blob_talloc(mem_ctx, NULL, sig_size); data_blob_clear(&c->security_state.auth_info->credentials); break; @@ -658,6 +658,16 @@ static void dcerpc_bind_recv_handler(struct rpc_request *req, 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) { @@ -731,6 +741,10 @@ struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p, pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; } + if (p->binding->flags & DCERPC_HEADER_SIGNING) { + pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; + } + pkt.u.bind.max_xmit_frag = 5840; pkt.u.bind.max_recv_frag = 5840; pkt.u.bind.assoc_group_id = p->binding->assoc_group_id; @@ -790,30 +804,41 @@ NTSTATUS dcerpc_bind_recv(struct composite_context *ctx) /* perform a continued bind (and auth3) */ -NTSTATUS dcerpc_auth3(struct dcerpc_connection *c, +NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) { struct ncacn_packet pkt; NTSTATUS status; DATA_BLOB blob; - init_ncacn_hdr(c, &pkt); + init_ncacn_hdr(p->conn, &pkt); pkt.ptype = DCERPC_PKT_AUTH3; pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; - pkt.call_id = next_call_id(c); + pkt.call_id = next_call_id(p->conn); pkt.auth_length = 0; pkt.u.auth3._pad = 0; pkt.u.auth3.auth_info = data_blob(NULL, 0); + if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) { + pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; + } + + if (p->binding->flags & DCERPC_HEADER_SIGNING) { + pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; + } + /* construct the NDR form of the packet */ - status = ncacn_push_auth(&blob, mem_ctx, c->iconv_convenience, &pkt, c->security_state.auth_info); + status = ncacn_push_auth(&blob, mem_ctx, + p->conn->iconv_convenience, + &pkt, + p->conn->security_state.auth_info); if (!NT_STATUS_IS_OK(status)) { return status; } /* send it on its way */ - status = c->transport.send_request(c, &blob, false); + status = p->conn->transport.send_request(p->conn, &blob, false); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -1017,6 +1042,7 @@ static void dcerpc_ship_next_request(struct dcerpc_connection *c) DATA_BLOB blob; uint32_t remaining, chunk_size; bool first_packet = true; + size_t sig_size = 0; req = c->request_queue; if (req == NULL) { @@ -1040,7 +1066,15 @@ static void dcerpc_ship_next_request(struct dcerpc_connection *c) /* we can write a full max_recv_frag size, minus the dcerpc request header size */ - chunk_size = p->conn->srv_max_recv_frag - (DCERPC_MAX_SIGN_SIZE+DCERPC_REQUEST_LENGTH); + chunk_size = p->conn->srv_max_recv_frag; + chunk_size -= DCERPC_REQUEST_LENGTH; + if (c->security_state.generic_state) { + chunk_size -= DCERPC_AUTH_TRAILER_LENGTH; + sig_size = gensec_sig_size(c->security_state.generic_state, + p->conn->srv_max_recv_frag); + chunk_size -= sig_size; + chunk_size -= (chunk_size % 16); + } pkt.ptype = DCERPC_PKT_REQUEST; pkt.call_id = req->call_id; @@ -1076,7 +1110,7 @@ static void dcerpc_ship_next_request(struct dcerpc_connection *c) (stub_data->length - remaining); pkt.u.request.stub_and_verifier.length = chunk; - req->status = ncacn_push_request_sign(p->conn, &blob, req, &pkt); + req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt); if (!NT_STATUS_IS_OK(req->status)) { req->state = RPC_REQUEST_DONE; DLIST_REMOVE(p->conn->pending, req); @@ -1627,6 +1661,10 @@ struct composite_context *dcerpc_alter_context_send(struct dcerpc_pipe *p, pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; } + if (p->binding->flags & DCERPC_HEADER_SIGNING) { + pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; + } + pkt.u.alter.max_xmit_frag = 5840; pkt.u.alter.max_recv_frag = 5840; pkt.u.alter.assoc_group_id = p->binding->assoc_group_id; |