diff options
author | Jeremy Allison <jra@samba.org> | 2013-10-17 14:44:35 -0700 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2013-12-09 07:05:46 +0100 |
commit | a516ae6868386aa23f2beb52a576b0cf68042b1d (patch) | |
tree | 19cffcf413ec06354e6e30c91ccb49e93d7c5306 | |
parent | 068dafc4d8f0c82a16ca5c092eb5f5144dd5f199 (diff) | |
download | samba-a516ae6868386aa23f2beb52a576b0cf68042b1d.tar.gz |
CVE-2013-4408:s3:Ensure we always check call_id when validating an RPC reply.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=10185
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r-- | source3/rpc_client/cli_pipe.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 0769d6dbe6b..87c3e8ff0b2 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -386,6 +386,7 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx, struct ncacn_packet *pkt, DATA_BLOB *pdu, uint8_t expected_pkt_type, + uint32_t call_id, DATA_BLOB *rdata, DATA_BLOB *reply_pdu) { @@ -484,7 +485,7 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx, "from %s!\n", (unsigned int)pkt->ptype, rpccli_pipe_txt(talloc_tos(), cli))); - return NT_STATUS_INVALID_INFO_CLASS; + return NT_STATUS_RPC_PROTOCOL_ERROR; } if (pkt->ptype != expected_pkt_type) { @@ -492,7 +493,15 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx, "RPC packet type - %u, not %u\n", rpccli_pipe_txt(talloc_tos(), cli), pkt->ptype, expected_pkt_type)); - return NT_STATUS_INVALID_INFO_CLASS; + return NT_STATUS_RPC_PROTOCOL_ERROR; + } + + if (pkt->call_id != call_id) { + DEBUG(3, (__location__ ": Connection to %s got an unexpected " + "RPC call_id - %u, not %u\n", + rpccli_pipe_txt(talloc_tos(), cli), + pkt->call_id, call_id)); + return NT_STATUS_RPC_PROTOCOL_ERROR; } /* Do this just before return - we don't want to modify any rpc header @@ -698,6 +707,7 @@ struct rpc_api_pipe_state { struct tevent_context *ev; struct rpc_pipe_client *cli; uint8_t expected_pkt_type; + uint32_t call_id; DATA_BLOB incoming_frag; struct ncacn_packet *pkt; @@ -716,7 +726,8 @@ static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct rpc_pipe_client *cli, DATA_BLOB *data, /* Outgoing PDU */ - uint8_t expected_pkt_type) + uint8_t expected_pkt_type, + uint32_t call_id) { struct tevent_req *req, *subreq; struct rpc_api_pipe_state *state; @@ -730,6 +741,7 @@ static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->cli = cli; state->expected_pkt_type = expected_pkt_type; + state->call_id = call_id; state->endianess = DCERPC_DREP_LE; /* @@ -878,6 +890,7 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) state->cli, state->pkt, &state->incoming_frag, state->expected_pkt_type, + state->call_id, &rdata, &state->reply_pdu); @@ -1177,7 +1190,8 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, if (is_last_frag) { subreq = rpc_api_pipe_send(state, ev, state->cli, &state->rpc_out, - DCERPC_PKT_RESPONSE); + DCERPC_PKT_RESPONSE, + state->call_id); if (subreq == NULL) { goto fail; } @@ -1313,7 +1327,8 @@ static void rpc_api_pipe_req_write_done(struct tevent_req *subreq) if (is_last_frag) { subreq = rpc_api_pipe_send(state, state->ev, state->cli, &state->rpc_out, - DCERPC_PKT_RESPONSE); + DCERPC_PKT_RESPONSE, + state->call_id); if (tevent_req_nomem(subreq, req)) { return; } @@ -1553,7 +1568,7 @@ struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, } subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out, - DCERPC_PKT_BIND_ACK); + DCERPC_PKT_BIND_ACK, state->rpc_call_id); if (subreq == NULL) { goto fail; } @@ -1714,7 +1729,8 @@ static NTSTATUS rpc_bind_next_send(struct tevent_req *req, } subreq = rpc_api_pipe_send(state, state->ev, state->cli, - &state->rpc_out, DCERPC_PKT_ALTER_RESP); + &state->rpc_out, DCERPC_PKT_ALTER_RESP, + state->rpc_call_id); if (subreq == NULL) { return NT_STATUS_NO_MEMORY; } @@ -1746,7 +1762,8 @@ static NTSTATUS rpc_bind_finish_send(struct tevent_req *req, } subreq = rpc_api_pipe_send(state, state->ev, state->cli, - &state->rpc_out, DCERPC_PKT_AUTH3); + &state->rpc_out, DCERPC_PKT_AUTH3, + state->rpc_call_id); if (subreq == NULL) { return NT_STATUS_NO_MEMORY; } |