diff options
Diffstat (limited to 'source4/librpc/rpc')
-rw-r--r-- | source4/librpc/rpc/binding.c | 3 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc.c | 56 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc.h | 3 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_auth.c | 6 |
4 files changed, 57 insertions, 11 deletions
diff --git a/source4/librpc/rpc/binding.c b/source4/librpc/rpc/binding.c index ae88dce1be..bfe62c4054 100644 --- a/source4/librpc/rpc/binding.c +++ b/source4/librpc/rpc/binding.c @@ -83,7 +83,8 @@ static const struct { {"print", DCERPC_DEBUG_PRINT_BOTH}, {"padcheck", DCERPC_DEBUG_PAD_CHECK}, {"bigendian", DCERPC_PUSH_BIGENDIAN}, - {"smb2", DCERPC_SMB2} + {"smb2", DCERPC_SMB2}, + {"hdrsign", DCERPC_HEADER_SIGNING} }; const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor) 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; diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index 487f9f2eda..1fd56cb052 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -163,6 +163,9 @@ struct dcerpc_pipe { /* this triggers the DCERPC_PFC_FLAG_CONC_MPX flag in the bind request */ #define DCERPC_CONCURRENT_MULTIPLEX (1<<19) +/* this triggers the DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN flag in the bind request */ +#define DCERPC_HEADER_SIGNING (1<<20) + /* this describes a binding to a particular transport/pipe */ struct dcerpc_binding { enum dcerpc_transport_t transport; diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c index f990029f1d..49fc3d9294 100644 --- a/source4/librpc/rpc/dcerpc_auth.c +++ b/source4/librpc/rpc/dcerpc_auth.c @@ -137,6 +137,10 @@ static void bind_auth_next_step(struct composite_context *c) if (!composite_is_ok(c)) return; + if (state->pipe->conn->flags & DCERPC_HEADER_SIGNING) { + gensec_want_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER); + } + if (state->credentials.length == 0) { composite_done(c); return; @@ -146,7 +150,7 @@ static void bind_auth_next_step(struct composite_context *c) if (!more_processing) { /* NO reply expected, so just send it */ - c->status = dcerpc_auth3(state->pipe->conn, state); + c->status = dcerpc_auth3(state->pipe, state); if (!composite_is_ok(c)) return; composite_done(c); |