From 23ad6919a1e5f16d02e22adcf36ea7f039a9eeea Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Jul 2010 08:57:47 -0400 Subject: s3-dcerpc: Break memory hierarchy for shared structure Handles are shared among multiple pipes_struct. We cannot allocate them on any specific pipes_struct or it will vanish for all others as soon as that pipes_struct is freed, leaving back dangling pointers. Signed-off-by: Andreas Schneider --- source3/rpc_server/rpc_handles.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/rpc_server/rpc_handles.c b/source3/rpc_server/rpc_handles.c index bfdc7a8561..e073fe45a2 100644 --- a/source3/rpc_server/rpc_handles.c +++ b/source3/rpc_server/rpc_handles.c @@ -103,7 +103,7 @@ bool init_pipe_handles(pipes_struct *p, const struct ndr_syntax_id *syntax) /* * First open, we have to create the handle list */ - hl = talloc_zero(p, struct handle_list); + hl = talloc_zero(NULL, struct handle_list); if (hl == NULL) { return false; } -- cgit From ff93d58b60458678436f2f983803705020537991 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 15 Jul 2010 10:36:40 +0200 Subject: s3: Fix crashes in the printing code create_conn_struct did not create the conn->sconn!=NULL assumption we now depend on. Thanks to Andreas Schneider for testing! --- source3/smbd/msdfs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 433de8aea3..03de7e85de 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -255,6 +255,9 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, conn->params->service = snum; + conn->sconn = smbd_server_conn; + conn->sconn->smb1.tcons.num_open += 1; + if (server_info != NULL) { conn->server_info = copy_serverinfo(conn, server_info); if (conn->server_info == NULL) { -- cgit From 8ce15b3a71a29fe27b7146c1b802aa11e7c96433 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 15 Jul 2010 16:06:11 -0700 Subject: Fix bug - 7551 smbclient does not return proper exit code. Catch error in cli_push. Jeremy. --- source3/client/client.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3') diff --git a/source3/client/client.c b/source3/client/client.c index 416a4bb6cf..326c23e657 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -1717,6 +1717,7 @@ static int do_put(const char *rname, const char *lname, bool reput) &state); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, "cli_push returned %s\n", nt_errstr(status)); + rc = 1; } if (!NT_STATUS_IS_OK(cli_close(targetcli, fnum))) { -- cgit From 602e10f3fdb5f0f94e5f22b639121220d419d47f Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 12 Jul 2010 09:36:39 -0400 Subject: s3-dcerpc: Delay parsing rpc header in client code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_client/cli_pipe.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 91eb767667..a4b4e79916 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -671,7 +671,7 @@ static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli, struct get_complete_frag_state { struct event_context *ev; struct rpc_pipe_client *cli; - struct ncacn_packet_header *prhdr; + uint16_t frag_len; prs_struct *pdu; }; @@ -681,11 +681,11 @@ static void get_complete_frag_got_rest(struct tevent_req *subreq); static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct rpc_pipe_client *cli, - struct ncacn_packet_header *prhdr, prs_struct *pdu) { struct tevent_req *req, *subreq; struct get_complete_frag_state *state; + DATA_BLOB blob; uint32_t pdu_len; NTSTATUS status; @@ -696,7 +696,7 @@ static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx, } state->ev = ev; state->cli = cli; - state->prhdr = prhdr; + state->frag_len = RPC_HEADER_LEN; state->pdu = pdu; pdu_len = prs_data_size(pdu); @@ -719,23 +719,21 @@ static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx, return req; } - status = parse_rpc_header(cli, prhdr, pdu); - if (!NT_STATUS_IS_OK(status)) { - goto post_status; - } + blob = data_blob_const(prs_data_p(state->pdu), pdu_len); + state->frag_len = dcerpc_get_frag_length(&blob); /* * Ensure we have frag_len bytes of data. */ - if (pdu_len < prhdr->frag_length) { - if (!rpc_grow_buffer(pdu, prhdr->frag_length)) { + if (pdu_len < state->frag_len) { + if (!rpc_grow_buffer(pdu, state->frag_len)) { status = NT_STATUS_NO_MEMORY; goto post_status; } subreq = rpc_read_send(state, state->ev, state->cli->transport, (uint8_t *)(prs_data_p(pdu) + pdu_len), - prhdr->frag_length - pdu_len); + state->frag_len - pdu_len); if (subreq == NULL) { status = NT_STATUS_NO_MEMORY; goto post_status; @@ -762,6 +760,7 @@ static void get_complete_frag_got_header(struct tevent_req *subreq) struct get_complete_frag_state *state = tevent_req_data( req, struct get_complete_frag_state); NTSTATUS status; + DATA_BLOB pdu; status = rpc_read_recv(subreq); TALLOC_FREE(subreq); @@ -770,13 +769,11 @@ static void get_complete_frag_got_header(struct tevent_req *subreq) return; } - status = parse_rpc_header(state->cli, state->prhdr, state->pdu); - if (!NT_STATUS_IS_OK(status)) { - tevent_req_nterror(req, status); - return; - } + pdu = data_blob_const(prs_data_p(state->pdu), + prs_data_size(state->pdu)); + state->frag_len = dcerpc_get_frag_length(&pdu); - if (!rpc_grow_buffer(state->pdu, state->prhdr->frag_length)) { + if (!rpc_grow_buffer(state->pdu, state->frag_len)) { tevent_req_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -789,7 +786,7 @@ static void get_complete_frag_got_header(struct tevent_req *subreq) subreq = rpc_read_send( state, state->ev, state->cli->transport, (uint8_t *)(prs_data_p(state->pdu) + RPC_HEADER_LEN), - state->prhdr->frag_length - RPC_HEADER_LEN); + state->frag_len - RPC_HEADER_LEN); if (tevent_req_nomem(subreq, req)) { return; } @@ -1187,6 +1184,11 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, NTSTATUS ret = NT_STATUS_OK; uint32 current_pdu_len = prs_data_size(current_pdu); + ret = parse_rpc_header(cli, prhdr, current_pdu); + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } + if (current_pdu_len != prhdr->frag_length) { DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n", (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_length)); @@ -1672,7 +1674,7 @@ static void rpc_api_pipe_trans_done(struct tevent_req *subreq) /* Ensure we have enough data for a pdu. */ subreq = get_complete_frag_send(state, state->ev, state->cli, - &state->rhdr, &state->incoming_frag); + &state->incoming_frag); if (tevent_req_nomem(subreq, req)) { return; } @@ -1763,7 +1765,7 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) } subreq = get_complete_frag_send(state, state->ev, state->cli, - &state->rhdr, &state->incoming_frag); + &state->incoming_frag); if (tevent_req_nomem(subreq, req)) { return; } -- cgit From 459c8e32fd49766ba7382c4c3da1d0c61d9deadb Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Jul 2010 07:59:12 -0400 Subject: s3-dcerpc: Pull the whole packet at once instead of fetching just the header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_client/cli_pipe.c | 125 +++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 57 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index a4b4e79916..2eedc0bfeb 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1173,25 +1173,45 @@ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, ****************************************************************************/ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, - struct ncacn_packet_header *prhdr, + struct ncacn_packet *pkt, prs_struct *current_pdu, uint8 expected_pkt_type, char **ppdata, uint32 *pdata_len, prs_struct *return_data) { - + struct ncacn_packet_header prhdr; NTSTATUS ret = NT_STATUS_OK; uint32 current_pdu_len = prs_data_size(current_pdu); + DATA_BLOB blob = data_blob_const(prs_data_p(current_pdu), + prs_data_size(current_pdu)); - ret = parse_rpc_header(cli, prhdr, current_pdu); + ret = dcerpc_pull_ncacn_packet(cli, &blob, pkt); if (!NT_STATUS_IS_OK(ret)) { return ret; } - if (current_pdu_len != prhdr->frag_length) { - DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n", - (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_length)); + /* FIXME: although we already unmarshalled the whole packet, + * set the offset of the pdu to right after the header + * until the rest of the code downstream is changed + * to always use the already decoded packet and not try + * to unmarshall bits of the packet. + */ + if (!prs_set_offset(current_pdu, + prs_offset(current_pdu) + RPC_HEADER_LEN)) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + /* FIXME: until all functions are converted to take in + * a fully decoded packet + */ + memcpy(&prhdr, pkt, sizeof(prhdr)); + + + if (current_pdu_len != pkt->frag_length) { + DEBUG(5, ("Incorrect pdu length %u, expected %u\n", + (unsigned int)current_pdu_len, + (unsigned int)pkt->frag_length)); return NT_STATUS_INVALID_PARAMETER; } @@ -1203,7 +1223,7 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, *pdata_len = current_pdu_len; /* Ensure we have the correct type. */ - switch (prhdr->ptype) { + switch (pkt->ptype) { case DCERPC_PKT_ALTER_RESP: case DCERPC_PKT_BIND_ACK: @@ -1214,23 +1234,13 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, case DCERPC_PKT_RESPONSE: { uint8 ss_padding_len = 0; - DATA_BLOB blob; - struct ncacn_packet r; - - blob = data_blob_const(prs_data_p(current_pdu), - prs_data_size(current_pdu)); - - ret = dcerpc_pull_ncacn_packet(cli, &blob, &r); - if (!NT_STATUS_IS_OK(ret)) { - return ret; - } if (!prs_set_offset(current_pdu, prs_offset(current_pdu) + RPC_HDR_RESP_LEN)) { return NT_STATUS_BUFFER_TOO_SMALL; } /* Here's where we deal with incoming sign/seal. */ - ret = cli_pipe_validate_rpc_response(cli, prhdr, + ret = cli_pipe_validate_rpc_response(cli, &prhdr, current_pdu, &ss_padding_len); if (!NT_STATUS_IS_OK(ret)) { return ret; @@ -1246,13 +1256,13 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len; /* Remember to remove the auth footer. */ - if (prhdr->auth_length) { + if (pkt->auth_length) { /* We've already done integer wrap tests on auth_len in cli_pipe_validate_rpc_response(). */ - if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_length) { + if (*pdata_len < RPC_HDR_AUTH_LEN + pkt->auth_length) { return NT_STATUS_BUFFER_TOO_SMALL; } - *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_length); + *pdata_len -= (RPC_HDR_AUTH_LEN + pkt->auth_length); } DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n", @@ -1263,11 +1273,14 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, * set up the return_data parse_struct to the correct size. */ - if ((prs_data_size(return_data) == 0) && r.u.response.alloc_hint && (r.u.response.alloc_hint < 15*1024*1024)) { - if (!prs_set_buffer_size(return_data, r.u.response.alloc_hint)) { - DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u " - "too large to allocate\n", - (unsigned int)r.u.response.alloc_hint )); + if ((prs_data_size(return_data) == 0) && + pkt->u.response.alloc_hint && + (pkt->u.response.alloc_hint < 15*1024*1024)) { + if (!prs_set_buffer_size(return_data, + pkt->u.response.alloc_hint)) { + DEBUG(0, ("reply alloc hint %d too " + "large to allocate\n", + (int)pkt->u.response.alloc_hint)); return NT_STATUS_NO_MEMORY; } } @@ -1283,42 +1296,32 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, return NT_STATUS_NETWORK_ACCESS_DENIED; case DCERPC_PKT_FAULT: - { - DATA_BLOB blob; - struct ncacn_packet r; - blob = data_blob_const(prs_data_p(current_pdu), - prs_data_size(current_pdu)); - - ret = dcerpc_pull_ncacn_packet(cli, &blob, &r); - if (!NT_STATUS_IS_OK(ret)) { - return ret; - } DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault " "code %s received from %s!\n", - dcerpc_errstr(talloc_tos(), r.u.fault.status), + dcerpc_errstr(talloc_tos(), + pkt->u.fault.status), rpccli_pipe_txt(talloc_tos(), cli))); - if (NT_STATUS_IS_OK(NT_STATUS(r.u.fault.status))) { + if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) { return NT_STATUS_UNSUCCESSFUL; } else { - return NT_STATUS(r.u.fault.status); + return NT_STATUS(pkt->u.fault.status); } - } default: DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received " "from %s!\n", - (unsigned int)prhdr->ptype, + (unsigned int)pkt->ptype, rpccli_pipe_txt(talloc_tos(), cli))); return NT_STATUS_INVALID_INFO_CLASS; } - if (prhdr->ptype != expected_pkt_type) { + if (pkt->ptype != expected_pkt_type) { DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s " "got an unexpected RPC packet type - %u, not %u\n", rpccli_pipe_txt(talloc_tos(), cli), - prhdr->ptype, + pkt->ptype, expected_pkt_type)); return NT_STATUS_INVALID_INFO_CLASS; } @@ -1327,10 +1330,12 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, data before now as we may have needed to do cryptographic actions on it before. */ - if ((prhdr->ptype == DCERPC_PKT_BIND_ACK) && !(prhdr->pfc_flags & DCERPC_PFC_FLAG_LAST)) { + if ((pkt->ptype == DCERPC_PKT_BIND_ACK) && + !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) { DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), " "setting fragment first/last ON.\n")); - prhdr->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; + pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | + DCERPC_PFC_FLAG_LAST; } return NT_STATUS_OK; @@ -1344,17 +1349,17 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, ****************************************************************************/ static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, - struct ncacn_packet_header *prhdr, + struct ncacn_packet *pkt, prs_struct *current_pdu) { uint32 current_pdu_len = prs_data_size(current_pdu); - if (current_pdu_len < prhdr->frag_length) { + if (current_pdu_len < pkt->frag_length) { return NT_STATUS_BUFFER_TOO_SMALL; } /* Common case. */ - if (current_pdu_len == (uint32)prhdr->frag_length) { + if (current_pdu_len == (uint32)pkt->frag_length) { prs_mem_free(current_pdu); prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL); /* Make current_pdu dynamic with no memory. */ @@ -1367,14 +1372,14 @@ static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, * Cheat. Move the data down and shrink the buffer. */ - memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_length, - current_pdu_len - prhdr->frag_length); + memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + pkt->frag_length, + current_pdu_len - pkt->frag_length); /* Remember to set the read offset back to zero. */ prs_set_offset(current_pdu, 0); /* Shrink the buffer. */ - if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_length)) { + if (!prs_set_buffer_size(current_pdu, current_pdu_len - pkt->frag_length)) { return NT_STATUS_BUFFER_TOO_SMALL; } @@ -1572,7 +1577,7 @@ struct rpc_api_pipe_state { uint8_t expected_pkt_type; prs_struct incoming_frag; - struct ncacn_packet_header rhdr; + struct ncacn_packet *pkt; prs_struct incoming_pdu; /* Incoming reply */ uint32_t incoming_pdu_offset; @@ -1700,8 +1705,14 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) return; } + state->pkt = talloc(state, struct ncacn_packet); + if (!state->pkt) { + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + status = cli_pipe_validate_current_pdu( - state->cli, &state->rhdr, &state->incoming_frag, + state->cli, state->pkt, &state->incoming_frag, state->expected_pkt_type, &rdata, &rdata_len, &state->incoming_pdu); @@ -1715,8 +1726,8 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) return; } - if ((state->rhdr.pfc_flags & DCERPC_PFC_FLAG_FIRST) - && (state->rhdr.drep[0] == 0)) { + if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) + && (state->pkt->drep[0] == 0)) { /* * Set the data type correctly for big-endian data on the * first packet. @@ -1749,14 +1760,14 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) rdata, (size_t)rdata_len); state->incoming_pdu_offset += rdata_len; - status = cli_pipe_reset_current_pdu(state->cli, &state->rhdr, + status = cli_pipe_reset_current_pdu(state->cli, state->pkt, &state->incoming_frag); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return; } - if (state->rhdr.pfc_flags & DCERPC_PFC_FLAG_LAST) { + if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) { DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n", rpccli_pipe_txt(talloc_tos(), state->cli), (unsigned)prs_data_size(&state->incoming_pdu))); -- cgit From 137743fac2ef917e2e9ba7d85840aa392e3a6946 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Jul 2010 08:29:21 -0400 Subject: s3-dcerpc: Do not reparse the header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead pass back and use the packet we have already parsed. Signed-off-by: Günther Deschner --- source3/rpc_client/cli_pipe.c | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 2eedc0bfeb..ac43b18b46 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1784,6 +1784,7 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) } static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + struct ncacn_packet **pkt, prs_struct *reply_pdu) { struct rpc_api_pipe_state *state = tevent_req_data( @@ -1804,6 +1805,10 @@ static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, talloc_steal(mem_ctx, prs_data_p(reply_pdu)); prs_init_empty(&state->incoming_pdu, state, UNMARSHALL); + if (pkt) { + *pkt = talloc_steal(mem_ctx, state->pkt); + } + return NT_STATUS_OK; } @@ -2645,7 +2650,7 @@ static void rpc_api_pipe_req_done(struct tevent_req *subreq) req, struct rpc_api_pipe_req_state); NTSTATUS status; - status = rpc_api_pipe_recv(subreq, state, &state->reply_pdu); + status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); @@ -2945,7 +2950,7 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) struct ncacn_packet r; NTSTATUS status; - status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu); + status = rpc_api_pipe_recv(subreq, talloc_tos(), NULL, &reply_pdu); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n", @@ -3188,52 +3193,36 @@ static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq) subreq, struct tevent_req); struct rpc_pipe_bind_state *state = tevent_req_data( req, struct rpc_pipe_bind_state); - DATA_BLOB server_spnego_response = data_blob_null; DATA_BLOB tmp_blob = data_blob_null; + struct ncacn_packet *pkt; + struct dcerpc_auth auth; prs_struct reply_pdu; - struct ncacn_packet_header hdr; - struct rpc_hdr_auth_info hdr_auth; NTSTATUS status; - status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu); + status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return; } - status = parse_rpc_header(state->cli, &hdr, &reply_pdu); + status = dcerpc_pull_dcerpc_auth(pkt, + &pkt->u.alter_resp.auth_info, + &auth); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return; } - if (!prs_set_offset( - &reply_pdu, - hdr.frag_length - hdr.auth_length - RPC_HDR_AUTH_LEN)) { - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &reply_pdu, 0)) { - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - server_spnego_response = data_blob(NULL, hdr.auth_length); - prs_copy_data_out((char *)server_spnego_response.data, &reply_pdu, - hdr.auth_length); - /* Check we got a valid auth response. */ - if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, + if (!spnego_parse_auth_response(auth.credentials, + NT_STATUS_OK, OID_NTLMSSP, &tmp_blob)) { - data_blob_free(&server_spnego_response); data_blob_free(&tmp_blob); tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } - data_blob_free(&server_spnego_response); data_blob_free(&tmp_blob); DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to " -- cgit From 282db1f5d28fe923700faef4576aa78d312547c0 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Jul 2010 08:39:03 -0400 Subject: s3-dcerpc: Remove unused function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_client/cli_pipe.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index ac43b18b46..e7a119b630 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -627,42 +627,6 @@ static NTSTATUS rpc_write_recv(struct tevent_req *req) } -static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli, - struct ncacn_packet_header *prhdr, - prs_struct *pdu) -{ - NTSTATUS status; - DATA_BLOB blob = data_blob_const(prs_data_p(pdu), prs_data_size(pdu)); - - /* - * This next call sets the endian bit correctly in current_pdu. We - * will propagate this to rbuf later. - */ - - status = dcerpc_pull_ncacn_packet_header(cli, &blob, prhdr); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (!prs_set_offset(pdu, prs_offset(pdu) + RPC_HEADER_LEN)) { - return NT_STATUS_BUFFER_TOO_SMALL; - } - - if (UNMARSHALLING(pdu) && prhdr->drep[0] == 0) { - DEBUG(10,("parse_rpc_header: PDU data format is big-endian. Setting flag.\n")); - prs_set_endian_data(pdu, RPC_BIG_ENDIAN); - } - - if (prhdr->frag_length > cli->max_recv_frag) { - DEBUG(0, ("cli_pipe_get_current_pdu: Server sent fraglen %d," - " we only allow %d\n", (int)prhdr->frag_length, - (int)cli->max_recv_frag)); - return NT_STATUS_BUFFER_TOO_SMALL; - } - - return NT_STATUS_OK; -} - /**************************************************************************** Try and get a PDU's worth of data from current_pdu. If not, then read more from the wire. -- cgit From 7d9c62c646d3bc72d19c2d188305680ce0cd8ad0 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Jul 2010 08:49:35 -0400 Subject: s3-dcerpc: Do not parse the packet twice. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_client/cli_pipe.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index e7a119b630..391268ca34 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2910,11 +2910,10 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) struct rpc_pipe_bind_state *state = tevent_req_data( req, struct rpc_pipe_bind_state); prs_struct reply_pdu; - DATA_BLOB blob; - struct ncacn_packet r; + struct ncacn_packet *pkt; NTSTATUS status; - status = rpc_api_pipe_recv(subreq, talloc_tos(), NULL, &reply_pdu); + status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n", @@ -2924,23 +2923,14 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) return; } - blob = data_blob_const(prs_data_p(&reply_pdu), - prs_data_size(&reply_pdu)); - - status = dcerpc_pull_ncacn_packet(talloc_tos(), &blob, &r); - if (!NT_STATUS_IS_OK(status)) { - tevent_req_nterror(req, status); - return; - } - - if (!check_bind_response(&r.u.bind_ack, &state->cli->transfer_syntax)) { + if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) { DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n")); tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); return; } - state->cli->max_xmit_frag = r.u.bind_ack.max_xmit_frag; - state->cli->max_recv_frag = r.u.bind_ack.max_recv_frag; + state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag; + state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag; /* * For authenticated binds we may need to do 3 or 4 leg binds. @@ -2956,7 +2946,7 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) case PIPE_AUTH_TYPE_NTLMSSP: /* Need to send AUTH3 packet - no reply. */ - status = rpc_finish_auth3_bind_send(req, state, &r, + status = rpc_finish_auth3_bind_send(req, state, pkt, &reply_pdu); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); @@ -2965,7 +2955,7 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: /* Need to send alter context request and reply. */ - status = rpc_finish_spnego_ntlmssp_bind_send(req, state, &r, + status = rpc_finish_spnego_ntlmssp_bind_send(req, state, pkt, &reply_pdu); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); -- cgit From f0626d14f051c11cdb2356bd730342249feeb0a9 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Jul 2010 10:27:37 -0400 Subject: s3-dcerpc: Stop using hand marshalling in rpc_finish_auth3_bind_send() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_client/cli_pipe.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 391268ca34..f91e2e28b7 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2977,9 +2977,8 @@ static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req, struct ncacn_packet *r, prs_struct *reply_pdu) { - DATA_BLOB server_response = data_blob_null; DATA_BLOB client_reply = data_blob_null; - struct rpc_hdr_auth_info hdr_auth; + struct dcerpc_auth auth; struct tevent_req *subreq; NTSTATUS status; @@ -2988,24 +2987,19 @@ static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req, return NT_STATUS_INVALID_PARAMETER; } - if (!prs_set_offset( - reply_pdu, - r->frag_length - r->auth_length - RPC_HDR_AUTH_LEN)) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) { - return NT_STATUS_INVALID_PARAMETER; + status = dcerpc_pull_dcerpc_auth(talloc_tos(), + &r->u.bind_ack.auth_info, + &auth); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Failed to pull dcerpc auth: %s.\n", + nt_errstr(status))); + return status; } /* TODO - check auth_type/auth_level match. */ - server_response = data_blob_talloc(talloc_tos(), NULL, r->auth_length); - prs_copy_data_out((char *)server_response.data, reply_pdu, - r->auth_length); - status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state, - server_response, &client_reply); + auth.credentials, &client_reply); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server " -- cgit From 5918a6c751e9dc1a93c4e1851149a270c4216ee1 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Jul 2010 09:26:13 -0400 Subject: s3-dcerpc: Stop using hand marshalling in create_next_pdu_ntlmssp() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_server/srv_pipe.c | 76 +++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 38 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 85c212aa93..97dc3cbe3b 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -59,18 +59,17 @@ static DATA_BLOB generic_session_key(void) static bool create_next_pdu_ntlmssp(pipes_struct *p) { - DATA_BLOB hdr; + DATA_BLOB blob; uint8_t hdr_flags; - RPC_HDR_RESP hdr_resp; uint32 ss_padding_len = 0; uint32 data_space_available; uint32 data_len_left; uint32 data_len; NTSTATUS status; - DATA_BLOB auth_blob; - RPC_HDR_AUTH auth_info; + DATA_BLOB auth_blob = data_blob_null; uint8 auth_type, auth_level; struct auth_ntlmssp_state *a = p->auth.a_u.auth_ntlmssp_state; + union dcerpc_payload u; TALLOC_CTX *frame; /* @@ -83,7 +82,7 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) return True; } - memset((char *)&hdr_resp, '\0', sizeof(hdr_resp)); + ZERO_STRUCT(u.response); /* Set up rpc header flags. */ if (p->out_data.data_sent_length == 0) { @@ -136,7 +135,7 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) * send. */ - hdr_resp.alloc_hint = data_len_left; + u.response.alloc_hint = data_len_left; /* * Work out if this PDU will be the last. @@ -152,46 +151,39 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) */ prs_init_empty(&p->out_data.frag, p->mem_ctx, MARSHALL); - status = dcerpc_push_ncacn_packet_header( + /* Set the data into the PDU. */ + u.response.stub_and_verifier = + data_blob_const(prs_data_p(&p->out_data.rdata), data_len); + + status = dcerpc_push_ncacn_packet( prs_get_mem_context(&p->out_data.frag), DCERPC_PKT_RESPONSE, hdr_flags, - RPC_HEADER_LEN + RPC_HDR_RESP_LEN + - data_len + ss_padding_len + - RPC_HDR_AUTH_LEN + NTLMSSP_SIG_SIZE, NTLMSSP_SIG_SIZE, p->call_id, - &hdr); + &u, + &blob); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall RPC Header.\n")); prs_mem_free(&p->out_data.frag); return False; } - /* Store the header in the data stream. */ + /* Set the proper length on the pdu */ + dcerpc_set_frag_length(&blob, blob.length + + ss_padding_len + + RPC_HDR_AUTH_LEN + + NTLMSSP_SIG_SIZE); + + /* Store the packet in the data stream. */ if (!prs_copy_data_in(&p->out_data.frag, - (char *)hdr.data, hdr.length)) { + (char *)blob.data, blob.length)) { DEBUG(0, ("Out of memory.\n")); prs_mem_free(&p->out_data.frag); return False; } - if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &p->out_data.frag, 0)) { - DEBUG(0,("create_next_pdu_ntlmssp: failed to marshall RPC_HDR_RESP.\n")); - prs_mem_free(&p->out_data.frag); - return False; - } - - /* Copy the data into the PDU. */ - - if(!prs_append_some_prs_data(&p->out_data.frag, &p->out_data.rdata, - p->out_data.data_sent_length, data_len)) { - DEBUG(0,("create_next_pdu_ntlmssp: failed to copy %u bytes of data.\n", (unsigned int)data_len)); - prs_mem_free(&p->out_data.frag); - return False; - } - - /* Copy the sign/seal padding data. */ + /* Append the sign/seal padding data. */ if (ss_padding_len) { char pad[SERVER_NDR_PADDING_SIZE]; @@ -205,7 +197,6 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) } } - /* Now write out the auth header and null blob. */ if (p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP) { auth_type = DCERPC_AUTH_TYPE_NTLMSSP; @@ -218,11 +209,20 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; } - init_rpc_hdr_auth(&auth_info, auth_type, auth_level, ss_padding_len, 1 /* context id. */); - - if (!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, - &p->out_data.frag, 0)) { - DEBUG(0,("create_next_pdu_ntlmssp: failed to marshall RPC_HDR_AUTH.\n")); + /* auth_blob is intentionally null, it will be appended later */ + status = dcerpc_push_dcerpc_auth( + prs_get_mem_context(&p->out_data.frag), + auth_type, + auth_level, + ss_padding_len, + 1, /* context id. */ + &auth_blob, + &blob); + + /* Store auth header in the data stream. */ + if (!prs_copy_data_in(&p->out_data.frag, + (char *)blob.data, blob.length)) { + DEBUG(0, ("Out of memory.\n")); prs_mem_free(&p->out_data.frag); return False; } @@ -269,11 +269,11 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) return False; } - /* Append the auth blob. */ + /* Finally append the auth blob. */ if (!prs_copy_data_in(&p->out_data.frag, (char *)auth_blob.data, NTLMSSP_SIG_SIZE)) { - DEBUG(0,("create_next_pdu_ntlmssp: failed to add %u bytes auth blob.\n", - (unsigned int)NTLMSSP_SIG_SIZE)); + DEBUG(0, ("Failed to add %u bytes auth blob.\n", + (unsigned int)NTLMSSP_SIG_SIZE)); talloc_free(frame); prs_mem_free(&p->out_data.frag); return False; -- cgit From a678d4e3b4766ce9520152da3d8d3ba299a470f1 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Jul 2010 09:52:56 -0400 Subject: s3-dcerpc: Stop using hand marshalling in create_next_pdu_schannel() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_server/srv_pipe.c | 168 ++++++++++++++++++++---------------------- 1 file changed, 81 insertions(+), 87 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 97dc3cbe3b..40415cc465 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -297,15 +297,16 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) static bool create_next_pdu_schannel(pipes_struct *p) { - DATA_BLOB hdr; + DATA_BLOB blob; uint8_t hdr_flags; - RPC_HDR_RESP hdr_resp; uint32 ss_padding_len = 0; uint32 data_len; uint32 data_space_available; uint32 data_len_left; uint32 data_pos; NTSTATUS status; + union dcerpc_payload u; + DATA_BLOB auth_blob = data_blob_null; /* * If we're in the fault state, keep returning fault PDU's until @@ -317,7 +318,7 @@ static bool create_next_pdu_schannel(pipes_struct *p) return True; } - memset((char *)&hdr_resp, '\0', sizeof(hdr_resp)); + ZERO_STRUCT(u.response); /* Set up rpc header flags. */ if (p->out_data.data_sent_length == 0) { @@ -371,7 +372,7 @@ static bool create_next_pdu_schannel(pipes_struct *p) * send. */ - hdr_resp.alloc_hint = data_len_left; + u.response.alloc_hint = data_len_left; /* * Work out if this PDU will be the last. @@ -387,50 +388,43 @@ static bool create_next_pdu_schannel(pipes_struct *p) */ prs_init_empty(&p->out_data.frag, p->mem_ctx, MARSHALL); - status = dcerpc_push_ncacn_packet_header( + /* Set the data into the PDU. */ + u.response.stub_and_verifier = + data_blob_const(prs_data_p(&p->out_data.rdata) + + p->out_data.data_sent_length, data_len); + + status = dcerpc_push_ncacn_packet( prs_get_mem_context(&p->out_data.frag), DCERPC_PKT_RESPONSE, hdr_flags, - RPC_HEADER_LEN + RPC_HDR_RESP_LEN + - data_len + ss_padding_len + - RPC_HDR_AUTH_LEN + - RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, p->call_id, - &hdr); + &u, + &blob); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall RPC Header.\n")); prs_mem_free(&p->out_data.frag); return False; } - /* Store the header in the data stream. */ - if (!prs_copy_data_in(&p->out_data.frag, - (char *)hdr.data, hdr.length)) { - DEBUG(0, ("Out of memory.\n")); - prs_mem_free(&p->out_data.frag); - return False; - } + /* Store the data offset. */ + data_pos = blob.length - data_len; - if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &p->out_data.frag, 0)) { - DEBUG(0,("create_next_pdu_schannel: failed to marshall RPC_HDR_RESP.\n")); - prs_mem_free(&p->out_data.frag); - return False; - } - - /* Store the current offset. */ - data_pos = prs_offset(&p->out_data.frag); - - /* Copy the data into the PDU. */ + /* Set the proper length on the pdu */ + dcerpc_set_frag_length(&blob, blob.length + + ss_padding_len + + RPC_HDR_AUTH_LEN + + RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN); - if(!prs_append_some_prs_data(&p->out_data.frag, &p->out_data.rdata, - p->out_data.data_sent_length, data_len)) { - DEBUG(0,("create_next_pdu_schannel: failed to copy %u bytes of data.\n", (unsigned int)data_len)); + /* Store the packet in the data stream. */ + if (!prs_copy_data_in(&p->out_data.frag, + (char *)blob.data, blob.length)) { + DEBUG(0, ("Out of memory.\n")); prs_mem_free(&p->out_data.frag); return False; } - /* Copy the sign/seal padding data. */ + /* Append the sign/seal padding data. */ if (ss_padding_len) { char pad[SERVER_NDR_PADDING_SIZE]; memset(pad, '\0', SERVER_NDR_PADDING_SIZE); @@ -442,70 +436,70 @@ static bool create_next_pdu_schannel(pipes_struct *p) } } - { - /* - * Schannel processing. - */ - RPC_HDR_AUTH auth_info; - DATA_BLOB blob; - uint8_t *data; - - /* Check it's the type of reply we were expecting to decode */ - - init_rpc_hdr_auth(&auth_info, + /* auth_blob is intentionally null, it will be appended later */ + status = dcerpc_push_dcerpc_auth( + prs_get_mem_context(&p->out_data.frag), DCERPC_AUTH_TYPE_SCHANNEL, - p->auth.auth_level == DCERPC_AUTH_LEVEL_PRIVACY ? - DCERPC_AUTH_LEVEL_PRIVACY : DCERPC_AUTH_LEVEL_INTEGRITY, - ss_padding_len, 1); + p->auth.auth_level, + ss_padding_len, + 1, /* context id. */ + &auth_blob, + &blob); - if (!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, - &p->out_data.frag, 0)) { - DEBUG(0,("create_next_pdu_schannel: failed to marshall RPC_HDR_AUTH.\n")); - prs_mem_free(&p->out_data.frag); - return False; - } + /* Store auth header in the data stream. */ + if (!prs_copy_data_in(&p->out_data.frag, + (char *)blob.data, blob.length)) { + DEBUG(0, ("Out of memory.\n")); + prs_mem_free(&p->out_data.frag); + return False; + } - data = (uint8_t *)prs_data_p(&p->out_data.frag) + data_pos; + /* + * Schannel processing. + */ - switch (p->auth.auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - status = netsec_outgoing_packet(p->auth.a_u.schannel_auth, - talloc_tos(), - true, - data, - data_len + ss_padding_len, - &blob); - break; - case DCERPC_AUTH_LEVEL_INTEGRITY: - status = netsec_outgoing_packet(p->auth.a_u.schannel_auth, - talloc_tos(), - false, - data, - data_len + ss_padding_len, - &blob); - break; - default: - status = NT_STATUS_INTERNAL_ERROR; - break; - } + blob = data_blob_const(prs_data_p(&p->out_data.frag) + data_pos, + data_len + ss_padding_len); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("create_next_pdu_schannel: failed to process packet: %s\n", - nt_errstr(status))); - prs_mem_free(&p->out_data.frag); - return false; - } + switch (p->auth.auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = netsec_outgoing_packet(p->auth.a_u.schannel_auth, + talloc_tos(), + true, + blob.data, + blob.length, + &auth_blob); + break; + case DCERPC_AUTH_LEVEL_INTEGRITY: + status = netsec_outgoing_packet(p->auth.a_u.schannel_auth, + talloc_tos(), + false, + blob.data, + blob.length, + &auth_blob); + break; + default: + status = NT_STATUS_INTERNAL_ERROR; + break; + } - /* Finally marshall the blob. */ + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("create_next_pdu_schannel: failed to process packet: %s\n", + nt_errstr(status))); + prs_mem_free(&p->out_data.frag); + return false; + } - if (DEBUGLEVEL >= 10) { - dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob); - } + /* Finally marshall the blob. */ - if (!prs_copy_data_in(&p->out_data.frag, (const char *)blob.data, blob.length)) { - prs_mem_free(&p->out_data.frag); - return false; - } + if (DEBUGLEVEL >= 10) { + dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_blob); + } + + if (!prs_copy_data_in(&p->out_data.frag, + (char *)auth_blob.data, auth_blob.length)) { + prs_mem_free(&p->out_data.frag); + return false; } /* -- cgit From 8ffac961db75aa3e0727e0c8f3e15cb0916f64d7 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Jul 2010 11:53:41 -0400 Subject: s3-dcerpc: Stop using hand marshalling in create_next_pdu_noauth() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_server/srv_pipe.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 40415cc465..2fa598f428 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -519,13 +519,13 @@ static bool create_next_pdu_schannel(pipes_struct *p) static bool create_next_pdu_noauth(pipes_struct *p) { - DATA_BLOB hdr; + DATA_BLOB blob; uint8_t hdr_flags; NTSTATUS status; - RPC_HDR_RESP hdr_resp; uint32 data_len; uint32 data_space_available; uint32 data_len_left; + union dcerpc_payload u; /* * If we're in the fault state, keep returning fault PDU's until @@ -537,7 +537,7 @@ static bool create_next_pdu_noauth(pipes_struct *p) return True; } - memset((char *)&hdr_resp, '\0', sizeof(hdr_resp)); + ZERO_STRUCT(u.response); /* Set up rpc header flags. */ if (p->out_data.data_sent_length == 0) { @@ -576,7 +576,7 @@ static bool create_next_pdu_noauth(pipes_struct *p) * send. */ - hdr_resp.alloc_hint = data_len_left; + u.response.alloc_hint = data_len_left; /* * Work out if this PDU will be the last. @@ -591,43 +591,33 @@ static bool create_next_pdu_noauth(pipes_struct *p) */ prs_init_empty(&p->out_data.frag, p->mem_ctx, MARSHALL); - status = dcerpc_push_ncacn_packet_header( + /* Set the data into the PDU. */ + u.response.stub_and_verifier = + data_blob_const(prs_data_p(&p->out_data.rdata) + + p->out_data.data_sent_length, data_len); + + status = dcerpc_push_ncacn_packet( prs_get_mem_context(&p->out_data.frag), DCERPC_PKT_RESPONSE, hdr_flags, - RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len, 0, p->call_id, - &hdr); + &u, + &blob); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall RPC Header.\n")); prs_mem_free(&p->out_data.frag); return False; } - /* Store the header in the data stream. */ + /* Store the packet in the data stream. */ if (!prs_copy_data_in(&p->out_data.frag, - (char *)hdr.data, hdr.length)) { + (char *)blob.data, blob.length)) { DEBUG(0, ("Out of memory.\n")); prs_mem_free(&p->out_data.frag); return False; } - if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &p->out_data.frag, 0)) { - DEBUG(0,("create_next_pdu_noath: failed to marshall RPC_HDR_RESP.\n")); - prs_mem_free(&p->out_data.frag); - return False; - } - - /* Copy the data into the PDU. */ - - if(!prs_append_some_prs_data(&p->out_data.frag, &p->out_data.rdata, - p->out_data.data_sent_length, data_len)) { - DEBUG(0,("create_next_pdu_noauth: failed to copy %u bytes of data.\n", (unsigned int)data_len)); - prs_mem_free(&p->out_data.frag); - return False; - } - /* * Setup the counts for this PDU. */ -- cgit From 8246214e7ef5374acc0a1f97f4f1203374fba7f8 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Jul 2010 12:03:21 -0400 Subject: s3-dcerpc: Remove unused functions and headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit parse_rpc.c is dead, long live parse_rpc.c ! Signed-off-by: Günther Deschner --- source3/Makefile.in | 3 +- source3/include/proto.h | 24 ++------- source3/include/rpc_dce.h | 16 ------ source3/rpc_parse/parse_misc.c | 28 ----------- source3/rpc_parse/parse_rpc.c | 110 ----------------------------------------- 5 files changed, 6 insertions(+), 175 deletions(-) delete mode 100644 source3/rpc_parse/parse_rpc.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index b980b7f25c..a4b71f0765 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -356,8 +356,7 @@ LIBNDR_GEN_OBJ = librpc/gen_ndr/ndr_wkssvc.o \ # that requires knowledge of security contexts RPC_PARSE_OBJ1 = rpc_parse/parse_prs.o rpc_parse/parse_misc.o -RPC_PARSE_OBJ2 = rpc_parse/parse_rpc.o \ - rpc_client/init_netlogon.o \ +RPC_PARSE_OBJ2 = rpc_client/init_netlogon.o \ rpc_client/init_lsa.o LIBREPLACE_OBJ = @LIBREPLACE_OBJS@ diff --git a/source3/include/proto.h b/source3/include/proto.h index cfa68da723..4e36052b19 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4838,6 +4838,11 @@ void set_profile_level(int level, struct server_id src); bool profile_setup(struct messaging_context *msg_ctx, bool rdonly); /* The following definitions come from rpc_client/cli_pipe.c */ +bool smb_register_ndr_interface(const struct ndr_interface_table *interface); +const struct ndr_interface_table *get_iface_from_syntax( + const struct ndr_syntax_id *syntax); +const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx, + const struct ndr_syntax_id *syntax); struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, struct event_context *ev, @@ -5045,8 +5050,6 @@ NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, /* The following definitions come from rpc_parse/parse_misc.c */ bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth); -bool smb_io_uuid(const char *desc, struct GUID *uuid, - prs_struct *ps, int depth); /* The following definitions come from rpc_parse/parse_prs.c */ @@ -5096,23 +5099,6 @@ bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uin bool prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx); bool prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx); -/* The following definitions come from rpc_parse/parse_rpc.c */ - -bool smb_register_ndr_interface(const struct ndr_interface_table *interface); -const struct ndr_interface_table *get_iface_from_syntax( - const struct ndr_syntax_id *syntax); -const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx, - const struct ndr_syntax_id *syntax); -NTSTATUS dcerpc_pull_dcerpc_bind(TALLOC_CTX *mem_ctx, - const DATA_BLOB *blob, - struct dcerpc_bind *r); -bool smb_io_rpc_hdr_resp(const char *desc, RPC_HDR_RESP *rpc, prs_struct *ps, int depth); -void init_rpc_hdr_auth(RPC_HDR_AUTH *rai, - uint8 auth_type, uint8 auth_level, - uint8 auth_pad_len, - uint32 auth_context_id); -bool smb_io_rpc_hdr_auth(const char *desc, RPC_HDR_AUTH *rai, prs_struct *ps, int depth); - /* The following definitions come from rpc_server/srv_eventlog_nt.c */ /* The following definitions come from rpc_server/rpc_handles.c */ diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index 202382781e..e663a56ad6 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -37,24 +37,8 @@ #define RPC_HDR_REQ_LEN 8 -/* RPC_HDR_RESP - ms response rpc header */ -typedef struct rpc_hdr_resp_info { - uint32 alloc_hint; /* allocation hint - data size (bytes) minus header and tail. */ - uint16 context_id; /* 0 - presentation context identifier */ - uint8 cancel_count; /* 0 - cancel count */ - uint8 reserved; /* 0 - reserved. */ -} RPC_HDR_RESP; - #define RPC_HDR_RESP_LEN 8 -/* RPC_HDR_AUTH */ -typedef struct rpc_hdr_auth_info { - uint8 auth_type; /* See XXX_AUTH_TYPE above. */ - uint8 auth_level; /* See RPC_PIPE_AUTH_XXX_LEVEL above. */ - uint8 auth_pad_len; - uint8 auth_reserved; - uint32 auth_context_id; -} RPC_HDR_AUTH; #define RPC_HDR_AUTH_LEN 8 diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c index c000923b9e..21b4e56e54 100644 --- a/source3/rpc_parse/parse_misc.c +++ b/source3/rpc_parse/parse_misc.c @@ -57,31 +57,3 @@ bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth) return True; } - -/******************************************************************* - Reads or writes a struct GUID -********************************************************************/ - -bool smb_io_uuid(const char *desc, struct GUID *uuid, - prs_struct *ps, int depth) -{ - if (uuid == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_uuid"); - depth++; - - if(!prs_uint32 ("data ", ps, depth, &uuid->time_low)) - return False; - if(!prs_uint16 ("data ", ps, depth, &uuid->time_mid)) - return False; - if(!prs_uint16 ("data ", ps, depth, &uuid->time_hi_and_version)) - return False; - - if(!prs_uint8s (False, "data ", ps, depth, uuid->clock_seq, sizeof(uuid->clock_seq))) - return False; - if(!prs_uint8s (False, "data ", ps, depth, uuid->node, sizeof(uuid->node))) - return False; - - return True; -} diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c deleted file mode 100644 index 8ece183251..0000000000 --- a/source3/rpc_parse/parse_rpc.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1997, - * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, - * Copyright (C) Paul Ashton 1997. - * Copyright (C) Jeremy Allison 1999. - * Copyright (C) Simo Sorce 2010 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include "includes.h" -#include "librpc/gen_ndr/ndr_dcerpc.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_PARSE - -NTSTATUS dcerpc_pull_dcerpc_bind(TALLOC_CTX *mem_ctx, - const DATA_BLOB *blob, - struct dcerpc_bind *r) -{ - enum ndr_err_code ndr_err; - - ndr_err = ndr_pull_struct_blob(blob, mem_ctx, r, - (ndr_pull_flags_fn_t)ndr_pull_dcerpc_bind); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - return NT_STATUS_OK; -} - -/******************************************************************* - Reads or writes an RPC_HDR_RESP structure. -********************************************************************/ - -bool smb_io_rpc_hdr_resp(const char *desc, RPC_HDR_RESP *rpc, prs_struct *ps, int depth) -{ - if (rpc == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_rpc_hdr_resp"); - depth++; - - if(!prs_uint32("alloc_hint", ps, depth, &rpc->alloc_hint)) - return False; - if(!prs_uint16("context_id", ps, depth, &rpc->context_id)) - return False; - if(!prs_uint8 ("cancel_ct ", ps, depth, &rpc->cancel_count)) - return False; - if(!prs_uint8 ("reserved ", ps, depth, &rpc->reserved)) - return False; - return True; -} - -/******************************************************************* - Inits an RPC_HDR_AUTH structure. -********************************************************************/ - -void init_rpc_hdr_auth(RPC_HDR_AUTH *rai, - uint8 auth_type, uint8 auth_level, - uint8 auth_pad_len, - uint32 auth_context_id) -{ - rai->auth_type = auth_type; - rai->auth_level = auth_level; - rai->auth_pad_len = auth_pad_len; - rai->auth_reserved = 0; - rai->auth_context_id = auth_context_id; -} - -/******************************************************************* - Reads or writes an RPC_HDR_AUTH structure. - NB This writes UNALIGNED. Ensure you're correctly aligned before - calling. -********************************************************************/ - -bool smb_io_rpc_hdr_auth(const char *desc, RPC_HDR_AUTH *rai, prs_struct *ps, int depth) -{ - if (rai == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_rpc_hdr_auth"); - depth++; - - if(!prs_uint8 ("auth_type ", ps, depth, &rai->auth_type)) - return False; - if(!prs_uint8 ("auth_level ", ps, depth, &rai->auth_level)) - return False; - if(!prs_uint8 ("auth_pad_len ", ps, depth, &rai->auth_pad_len)) - return False; - if(!prs_uint8 ("auth_reserved", ps, depth, &rai->auth_reserved)) - return False; - if(!prs_uint32("auth_context_id", ps, depth, &rai->auth_context_id)) - return False; - - return True; -} -- cgit From 31b59bbf99835279a0a78858aca2f327150eb5e2 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Jul 2010 15:43:44 -0400 Subject: s3-dcerpc: Convert rdata from prs_struct to a simple DATA_BLOB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/include/ntdomain.h | 2 +- source3/include/proto.h | 2 +- source3/rpc_parse/parse_prs.c | 12 ++++++---- source3/rpc_server/rpc_ncacn_np_internal.c | 19 +++------------ source3/rpc_server/srv_pipe.c | 38 +++++++++++++++--------------- source3/rpc_server/srv_pipe_hnd.c | 22 +++++------------ source3/winbindd/winbindd_dual_ndr.c | 13 +++++----- 7 files changed, 45 insertions(+), 63 deletions(-) (limited to 'source3') diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index d0006923ff..84b0309195 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -67,7 +67,7 @@ typedef struct _output_data { /* * Raw RPC output data. This does not include RPC headers or footers. */ - prs_struct rdata; + DATA_BLOB rdata; /* The amount of data sent from the current rdata struct. */ uint32 data_sent_length; diff --git a/source3/include/proto.h b/source3/include/proto.h index 4e36052b19..fbd3d91063 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5055,7 +5055,7 @@ bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth); void prs_dump(const char *name, int v, prs_struct *ps); void prs_dump_before(const char *name, int v, prs_struct *ps); -void prs_dump_region(const char *name, int v, prs_struct *ps, +void prs_dump_region(const char *name, int v, uint8_t *data_p, int from_off, int to_off); void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name); bool prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, bool io); diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index ec5bc9cf6a..f8ae8d1d64 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -31,7 +31,9 @@ **/ void prs_dump(const char *name, int v, prs_struct *ps) { - prs_dump_region(name, v, ps, ps->data_offset, ps->buffer_size); + prs_dump_region(name, v, + (uint8_t *)ps->data_p, + ps->data_offset, ps->buffer_size); } /** @@ -39,13 +41,15 @@ void prs_dump(const char *name, int v, prs_struct *ps) **/ void prs_dump_before(const char *name, int v, prs_struct *ps) { - prs_dump_region(name, v, ps, 0, ps->data_offset); + prs_dump_region(name, v, + (uint8_t *)ps->data_p, + 0, ps->data_offset); } /** * Dump everything from the start of the prs up to the current location. **/ -void prs_dump_region(const char *name, int v, prs_struct *ps, +void prs_dump_region(const char *name, int v, uint8_t *data_p, int from_off, int to_off) { int fd, i; @@ -66,7 +70,7 @@ void prs_dump_region(const char *name, int v, prs_struct *ps, if (fd != -1 || errno != EEXIST) break; } if (fd != -1) { - sz = write(fd, ps->data_p + from_off, to_off - from_off); + sz = write(fd, data_p + from_off, to_off - from_off); i = close(fd); if ( (sz != to_off-from_off) || (i != 0) ) { DEBUG(0,("Error writing/closing %s: %ld!=%ld %d\n", fname, (unsigned long)sz, (unsigned long)to_off-from_off, i )); diff --git a/source3/rpc_server/rpc_ncacn_np_internal.c b/source3/rpc_server/rpc_ncacn_np_internal.c index 22e03525ff..ceda2c781c 100644 --- a/source3/rpc_server/rpc_ncacn_np_internal.c +++ b/source3/rpc_server/rpc_ncacn_np_internal.c @@ -172,11 +172,6 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, p->endian = RPC_LITTLE_ENDIAN; - /* - * Initialize the outgoing RPC data buffer with no memory. - */ - prs_init_empty(&p->out_data.rdata, p->mem_ctx, MARSHALL); - p->syntax = *syntax; DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n", @@ -247,8 +242,6 @@ static NTSTATUS internal_ndr_pull(TALLOC_CTX *mem_ctx, const struct ndr_interface_call *call; struct ndr_pull *pull; enum ndr_err_code ndr_err; - DATA_BLOB blob; - bool ret; if (!ndr_syntax_id_equal(&table->syntax_id, &cli->abstract_syntax) || (opnum >= table->num_calls)) { @@ -257,12 +250,8 @@ static NTSTATUS internal_ndr_pull(TALLOC_CTX *mem_ctx, call = &table->calls[opnum]; - ret = prs_data_blob(&cli->pipes_struct->out_data.rdata, &blob, mem_ctx); - if (!ret) { - return NT_STATUS_NO_MEMORY; - } - - pull = ndr_pull_init_blob(&blob, mem_ctx); + pull = ndr_pull_init_blob(&cli->pipes_struct->out_data.rdata, + mem_ctx); if (pull == NULL) { return NT_STATUS_NO_MEMORY; } @@ -314,8 +303,6 @@ static NTSTATUS rpc_pipe_internal_dispatch(struct rpc_pipe_client *cli, return NT_STATUS_INVALID_PARAMETER; } - prs_init_empty(&cli->pipes_struct->out_data.rdata, cli->pipes_struct->mem_ctx, MARSHALL); - status = internal_ndr_push(mem_ctx, cli, table, opnum, r); if (!NT_STATUS_IS_OK(status)) { return status; @@ -331,7 +318,7 @@ static NTSTATUS rpc_pipe_internal_dispatch(struct rpc_pipe_client *cli, } prs_mem_free(&cli->pipes_struct->in_data.data); - prs_mem_free(&cli->pipes_struct->out_data.rdata); + data_blob_free(&cli->pipes_struct->out_data.rdata); return NT_STATUS_OK; } diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 2fa598f428..b8807f17d2 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -95,7 +95,7 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) * Work out how much we can fit in a single PDU. */ - data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length; + data_len_left = p->out_data.rdata.length - p->out_data.data_sent_length; /* * Ensure there really is data left to send. @@ -141,7 +141,7 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) * Work out if this PDU will be the last. */ if (p->out_data.data_sent_length + data_len >= - prs_offset(&p->out_data.rdata)) { + p->out_data.rdata.length) { hdr_flags |= DCERPC_PFC_FLAG_LAST; } @@ -153,7 +153,7 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) /* Set the data into the PDU. */ u.response.stub_and_verifier = - data_blob_const(prs_data_p(&p->out_data.rdata), data_len); + data_blob_const(p->out_data.rdata.data, data_len); status = dcerpc_push_ncacn_packet( prs_get_mem_context(&p->out_data.frag), @@ -331,7 +331,7 @@ static bool create_next_pdu_schannel(pipes_struct *p) * Work out how much we can fit in a single PDU. */ - data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length; + data_len_left = p->out_data.rdata.length - p->out_data.data_sent_length; /* * Ensure there really is data left to send. @@ -378,7 +378,7 @@ static bool create_next_pdu_schannel(pipes_struct *p) * Work out if this PDU will be the last. */ if (p->out_data.data_sent_length + data_len >= - prs_offset(&p->out_data.rdata)) { + p->out_data.rdata.length) { hdr_flags |= DCERPC_PFC_FLAG_LAST; } @@ -390,7 +390,7 @@ static bool create_next_pdu_schannel(pipes_struct *p) /* Set the data into the PDU. */ u.response.stub_and_verifier = - data_blob_const(prs_data_p(&p->out_data.rdata) + + data_blob_const(p->out_data.rdata.data + p->out_data.data_sent_length, data_len); status = dcerpc_push_ncacn_packet( @@ -550,7 +550,7 @@ static bool create_next_pdu_noauth(pipes_struct *p) * Work out how much we can fit in a single PDU. */ - data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length; + data_len_left = p->out_data.rdata.length - p->out_data.data_sent_length; /* * Ensure there really is data left to send. @@ -581,7 +581,7 @@ static bool create_next_pdu_noauth(pipes_struct *p) /* * Work out if this PDU will be the last. */ - if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) { + if(p->out_data.data_sent_length + data_len >= p->out_data.rdata.length) { hdr_flags |= DCERPC_PFC_FLAG_LAST; } @@ -593,7 +593,7 @@ static bool create_next_pdu_noauth(pipes_struct *p) /* Set the data into the PDU. */ u.response.stub_and_verifier = - data_blob_const(prs_data_p(&p->out_data.rdata) + + data_blob_const(p->out_data.rdata.data + p->out_data.data_sent_length, data_len); status = dcerpc_push_ncacn_packet( @@ -831,7 +831,7 @@ static bool setup_bind_nak(pipes_struct *p, struct ncacn_packet *pkt) DATA_BLOB blob; /* Free any memory in the current return data buffer. */ - prs_mem_free(&p->out_data.rdata); + data_blob_free(&p->out_data.rdata); /* * Marshall directly into the outgoing PDU space. We @@ -892,7 +892,7 @@ bool setup_fault_pdu(pipes_struct *p, NTSTATUS fault_status) DATA_BLOB blob; /* Free any memory in the current return data buffer. */ - prs_mem_free(&p->out_data.rdata); + data_blob_free(&p->out_data.rdata); /* * Marshall directly into the outgoing PDU space. We @@ -1981,7 +1981,7 @@ bool api_pipe_request(pipes_struct *p, struct ncacn_packet *pkt) ((p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP) || (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) { if(!become_authenticated_pipe_user(p)) { - prs_mem_free(&p->out_data.rdata); + data_blob_free(&p->out_data.rdata); return False; } changed_user = True; @@ -2023,7 +2023,7 @@ static bool api_rpcTNP(pipes_struct *p, struct ncacn_packet *pkt, const struct api_struct *api_rpc_cmds, int n_cmds) { int fn_num; - uint32 offset1, offset2; + uint32_t offset1; /* interpret the command */ DEBUG(4,("api_rpcTNP: %s op 0x%x - ", @@ -2057,7 +2057,7 @@ static bool api_rpcTNP(pipes_struct *p, struct ncacn_packet *pkt, return True; } - offset1 = prs_offset(&p->out_data.rdata); + offset1 = p->out_data.rdata.length; DEBUG(6, ("api_rpc_cmds[%d].fn == %p\n", fn_num, api_rpc_cmds[fn_num].fn)); @@ -2066,7 +2066,7 @@ static bool api_rpcTNP(pipes_struct *p, struct ncacn_packet *pkt, DEBUG(0,("api_rpcTNP: %s: %s failed.\n", get_pipe_name_from_syntax(talloc_tos(), &p->syntax), api_rpc_cmds[fn_num].name)); - prs_mem_free(&p->out_data.rdata); + data_blob_free(&p->out_data.rdata); return False; } @@ -2084,15 +2084,15 @@ static bool api_rpcTNP(pipes_struct *p, struct ncacn_packet *pkt, return True; } - offset2 = prs_offset(&p->out_data.rdata); - prs_set_offset(&p->out_data.rdata, offset1); if (DEBUGLEVEL >= 50) { fstring name; slprintf(name, sizeof(name)-1, "out_%s", get_pipe_name_from_syntax(talloc_tos(), &p->syntax)); - prs_dump(name, pkt->u.request.opnum, &p->out_data.rdata); + prs_dump_region(name, pkt->u.request.opnum, + p->out_data.rdata.data, + offset1, + p->out_data.rdata.length); } - prs_set_offset(&p->out_data.rdata, offset2); DEBUG(5,("api_rpcTNP: called %s successfully\n", get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index b86a83bf07..3cd9028f44 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -45,16 +45,7 @@ static bool pipe_init_outgoing_data(pipes_struct *p) prs_mem_free(&o_data->frag); /* Free any memory in the current return data buffer. */ - prs_mem_free(&o_data->rdata); - - /* - * Initialize the outgoing RPC data buffer. - * we will use this as the raw data area for replying to rpc requests. - */ - if(!prs_init(&o_data->rdata, 128, p->mem_ctx, MARSHALL)) { - DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n")); - return False; - } + data_blob_free(&o_data->rdata); return True; } @@ -153,7 +144,7 @@ static bool get_pdu_size(pipes_struct *p) static void free_pipe_context(pipes_struct *p) { prs_mem_free(&p->out_data.frag); - prs_mem_free(&p->out_data.rdata); + data_blob_free(&p->out_data.rdata); prs_mem_free(&p->in_data.data); DEBUG(3, ("free_pipe_context: " @@ -840,13 +831,13 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, */ DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length " - "= %u, prs_offset(&p->out_data.rdata) = %u.\n", + "= %u, p->out_data.rdata.length = %u.\n", get_pipe_name_from_syntax(talloc_tos(), &p->syntax), (int)p->fault_state, (unsigned int)p->out_data.data_sent_length, - (unsigned int)prs_offset(&p->out_data.rdata) )); + (unsigned int)p->out_data.rdata.length)); - if(p->out_data.data_sent_length >= prs_offset(&p->out_data.rdata)) { + if (p->out_data.data_sent_length >= p->out_data.rdata.length) { /* * We have sent all possible data, return 0. */ @@ -882,8 +873,7 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, p->out_data.current_pdu_sent = 0; prs_mem_free(&p->out_data.frag); - if (p->out_data.data_sent_length - >= prs_offset(&p->out_data.rdata)) { + if (p->out_data.data_sent_length >= p->out_data.rdata.length) { /* * We're completely finished with both outgoing and * incoming data streams. It's safe to free all diff --git a/source3/winbindd/winbindd_dual_ndr.c b/source3/winbindd/winbindd_dual_ndr.c index aee5052687..08d92d45e6 100644 --- a/source3/winbindd/winbindd_dual_ndr.c +++ b/source3/winbindd/winbindd_dual_ndr.c @@ -266,19 +266,20 @@ enum winbindd_result winbindd_dual_ndrcmd(struct winbindd_domain *domain, p.mem_ctx = talloc_stackframe(); p.in_data.data.buffer_size = state->request->extra_len; p.in_data.data.data_p = state->request->extra_data.data; - prs_init(&p.out_data.rdata, 0, state->mem_ctx, MARSHALL); ret = fns[state->request->data.ndrcmd].fn(&p); - TALLOC_FREE(p.mem_ctx); if (!ret) { + TALLOC_FREE(p.mem_ctx); return WINBINDD_ERROR; } state->response->extra_data.data = - talloc_memdup(state->mem_ctx, p.out_data.rdata.data_p, - p.out_data.rdata.data_offset); - state->response->length += p.out_data.rdata.data_offset; - prs_mem_free(&p.out_data.rdata); + talloc_move(state->mem_ctx, &p.out_data.rdata.data); + state->response->length += p.out_data.rdata.length; + p.out_data.rdata.length = 0; + + TALLOC_FREE(p.mem_ctx); + if (state->response->extra_data.data == NULL) { return WINBINDD_ERROR; } -- cgit From 8cd3912afa51468e14d13b77394a308dd184b775 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Jul 2010 18:01:16 -0400 Subject: s3-dcerpc: Convert frag from prs_struct to a simple DATA_BLOB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/include/ntdomain.h | 2 +- source3/rpc_server/srv_pipe.c | 322 +++++++++++++++----------------------- source3/rpc_server/srv_pipe_hnd.c | 20 +-- 3 files changed, 134 insertions(+), 210 deletions(-) (limited to 'source3') diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index 84b0309195..f0a97ac24e 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -76,7 +76,7 @@ typedef struct _output_data { * The current fragment being returned. This inclues * headers, data and authentication footer. */ - prs_struct frag; + DATA_BLOB frag; /* The amount of data sent from the current PDU. */ uint32 current_pdu_sent; diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index b8807f17d2..62725f2e9c 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -145,54 +145,41 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) hdr_flags |= DCERPC_PFC_FLAG_LAST; } - /* - * Init the parse struct to point at the outgoing - * data. - */ - prs_init_empty(&p->out_data.frag, p->mem_ctx, MARSHALL); - /* Set the data into the PDU. */ u.response.stub_and_verifier = data_blob_const(p->out_data.rdata.data, data_len); - status = dcerpc_push_ncacn_packet( - prs_get_mem_context(&p->out_data.frag), - DCERPC_PKT_RESPONSE, - hdr_flags, - NTLMSSP_SIG_SIZE, - p->call_id, - &u, - &blob); + /* Store the packet in the data stream. */ + status = dcerpc_push_ncacn_packet(p->mem_ctx, + DCERPC_PKT_RESPONSE, + hdr_flags, + NTLMSSP_SIG_SIZE, + p->call_id, + &u, + &p->out_data.frag); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall RPC Header.\n")); - prs_mem_free(&p->out_data.frag); return False; } /* Set the proper length on the pdu */ - dcerpc_set_frag_length(&blob, blob.length + - ss_padding_len + - RPC_HDR_AUTH_LEN + - NTLMSSP_SIG_SIZE); - - /* Store the packet in the data stream. */ - if (!prs_copy_data_in(&p->out_data.frag, - (char *)blob.data, blob.length)) { - DEBUG(0, ("Out of memory.\n")); - prs_mem_free(&p->out_data.frag); - return False; - } + dcerpc_set_frag_length(&p->out_data.frag, + p->out_data.frag.length + + ss_padding_len + + RPC_HDR_AUTH_LEN + + NTLMSSP_SIG_SIZE); /* Append the sign/seal padding data. */ if (ss_padding_len) { char pad[SERVER_NDR_PADDING_SIZE]; memset(pad, '\0', SERVER_NDR_PADDING_SIZE); - if (!prs_copy_data_in(&p->out_data.frag, pad, + if (!data_blob_append(p->mem_ctx, + &p->out_data.frag, pad, ss_padding_len)) { DEBUG(0,("create_next_pdu_ntlmssp: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len)); - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); return False; } } @@ -209,9 +196,10 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; } + frame = talloc_stackframe(); + /* auth_blob is intentionally null, it will be appended later */ - status = dcerpc_push_dcerpc_auth( - prs_get_mem_context(&p->out_data.frag), + status = dcerpc_push_dcerpc_auth(frame, auth_type, auth_level, ss_padding_len, @@ -220,30 +208,30 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) &blob); /* Store auth header in the data stream. */ - if (!prs_copy_data_in(&p->out_data.frag, + if (!data_blob_append(p->mem_ctx, + &p->out_data.frag, (char *)blob.data, blob.length)) { DEBUG(0, ("Out of memory.\n")); - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); return False; } /* Generate the sign blob. */ - frame = talloc_stackframe(); switch (p->auth.auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: /* Data portion is encrypted. */ status = auth_ntlmssp_seal_packet( a, frame, - (uint8_t *)prs_data_p(&p->out_data.frag) + p->out_data.frag.data + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, data_len + ss_padding_len, - (unsigned char *)prs_data_p(&p->out_data.frag), - (size_t)prs_offset(&p->out_data.frag), + p->out_data.frag.data, + p->out_data.frag.length, &auth_blob); if (!NT_STATUS_IS_OK(status)) { talloc_free(frame); - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); return False; } break; @@ -251,31 +239,31 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p) /* Data is signed. */ status = auth_ntlmssp_sign_packet( a, frame, - (unsigned char *)prs_data_p(&p->out_data.frag) + p->out_data.frag.data + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, data_len + ss_padding_len, - (unsigned char *)prs_data_p(&p->out_data.frag), - (size_t)prs_offset(&p->out_data.frag), + p->out_data.frag.data, + p->out_data.frag.length, &auth_blob); if (!NT_STATUS_IS_OK(status)) { talloc_free(frame); - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); return False; } break; default: talloc_free(frame); - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); return False; } /* Finally append the auth blob. */ - if (!prs_copy_data_in(&p->out_data.frag, (char *)auth_blob.data, - NTLMSSP_SIG_SIZE)) { + if (!data_blob_append(p->mem_ctx, &p->out_data.frag, + auth_blob.data, NTLMSSP_SIG_SIZE)) { DEBUG(0, ("Failed to add %u bytes auth blob.\n", (unsigned int)NTLMSSP_SIG_SIZE)); talloc_free(frame); - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); return False; } talloc_free(frame); @@ -382,75 +370,61 @@ static bool create_next_pdu_schannel(pipes_struct *p) hdr_flags |= DCERPC_PFC_FLAG_LAST; } - /* - * Init the parse struct to point at the outgoing - * data. - */ - prs_init_empty(&p->out_data.frag, p->mem_ctx, MARSHALL); - /* Set the data into the PDU. */ u.response.stub_and_verifier = data_blob_const(p->out_data.rdata.data + p->out_data.data_sent_length, data_len); - status = dcerpc_push_ncacn_packet( - prs_get_mem_context(&p->out_data.frag), + /* Store the packet in the data stream. */ + status = dcerpc_push_ncacn_packet(p->mem_ctx, DCERPC_PKT_RESPONSE, hdr_flags, RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, p->call_id, &u, - &blob); + &p->out_data.frag); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall RPC Header.\n")); - prs_mem_free(&p->out_data.frag); return False; } /* Store the data offset. */ - data_pos = blob.length - data_len; + data_pos = p->out_data.frag.length - data_len; /* Set the proper length on the pdu */ - dcerpc_set_frag_length(&blob, blob.length + - ss_padding_len + - RPC_HDR_AUTH_LEN + - RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN); - - /* Store the packet in the data stream. */ - if (!prs_copy_data_in(&p->out_data.frag, - (char *)blob.data, blob.length)) { - DEBUG(0, ("Out of memory.\n")); - prs_mem_free(&p->out_data.frag); - return False; - } + dcerpc_set_frag_length(&p->out_data.frag, + p->out_data.frag.length + + ss_padding_len + + RPC_HDR_AUTH_LEN + + RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN); /* Append the sign/seal padding data. */ if (ss_padding_len) { char pad[SERVER_NDR_PADDING_SIZE]; memset(pad, '\0', SERVER_NDR_PADDING_SIZE); - if (!prs_copy_data_in(&p->out_data.frag, pad, + if (!data_blob_append(p->mem_ctx, + &p->out_data.frag, pad, ss_padding_len)) { DEBUG(0,("create_next_pdu_schannel: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len)); - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); return False; } } /* auth_blob is intentionally null, it will be appended later */ - status = dcerpc_push_dcerpc_auth( - prs_get_mem_context(&p->out_data.frag), - DCERPC_AUTH_TYPE_SCHANNEL, - p->auth.auth_level, - ss_padding_len, - 1, /* context id. */ - &auth_blob, - &blob); + status = dcerpc_push_dcerpc_auth(talloc_tos(), + DCERPC_AUTH_TYPE_SCHANNEL, + p->auth.auth_level, + ss_padding_len, + 1, /* context id. */ + &auth_blob, + &blob); /* Store auth header in the data stream. */ - if (!prs_copy_data_in(&p->out_data.frag, - (char *)blob.data, blob.length)) { + if (!data_blob_append(p->mem_ctx, &p->out_data.frag, + blob.data, blob.length)) { DEBUG(0, ("Out of memory.\n")); - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); return False; } @@ -458,7 +432,7 @@ static bool create_next_pdu_schannel(pipes_struct *p) * Schannel processing. */ - blob = data_blob_const(prs_data_p(&p->out_data.frag) + data_pos, + blob = data_blob_const(p->out_data.frag.data + data_pos, data_len + ss_padding_len); switch (p->auth.auth_level) { @@ -486,7 +460,7 @@ static bool create_next_pdu_schannel(pipes_struct *p) if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("create_next_pdu_schannel: failed to process packet: %s\n", nt_errstr(status))); - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); return false; } @@ -496,9 +470,9 @@ static bool create_next_pdu_schannel(pipes_struct *p) dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_blob); } - if (!prs_copy_data_in(&p->out_data.frag, - (char *)auth_blob.data, auth_blob.length)) { - prs_mem_free(&p->out_data.frag); + if (!data_blob_append(p->mem_ctx, &p->out_data.frag, + auth_blob.data, auth_blob.length)) { + data_blob_free(&p->out_data.frag); return false; } @@ -519,7 +493,6 @@ static bool create_next_pdu_schannel(pipes_struct *p) static bool create_next_pdu_noauth(pipes_struct *p) { - DATA_BLOB blob; uint8_t hdr_flags; NTSTATUS status; uint32 data_len; @@ -585,36 +558,21 @@ static bool create_next_pdu_noauth(pipes_struct *p) hdr_flags |= DCERPC_PFC_FLAG_LAST; } - /* - * Init the parse struct to point at the outgoing - * data. - */ - prs_init_empty(&p->out_data.frag, p->mem_ctx, MARSHALL); - /* Set the data into the PDU. */ u.response.stub_and_verifier = data_blob_const(p->out_data.rdata.data + p->out_data.data_sent_length, data_len); - status = dcerpc_push_ncacn_packet( - prs_get_mem_context(&p->out_data.frag), - DCERPC_PKT_RESPONSE, - hdr_flags, - 0, - p->call_id, - &u, - &blob); + /* Store the packet in the data stream. */ + status = dcerpc_push_ncacn_packet(p->mem_ctx, + DCERPC_PKT_RESPONSE, + hdr_flags, + 0, + p->call_id, + &u, + &p->out_data.frag); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall RPC Header.\n")); - prs_mem_free(&p->out_data.frag); - return False; - } - - /* Store the packet in the data stream. */ - if (!prs_copy_data_in(&p->out_data.frag, - (char *)blob.data, blob.length)) { - DEBUG(0, ("Out of memory.\n")); - prs_mem_free(&p->out_data.frag); return False; } @@ -828,19 +786,10 @@ static bool setup_bind_nak(pipes_struct *p, struct ncacn_packet *pkt) { NTSTATUS status; union dcerpc_payload u; - DATA_BLOB blob; /* Free any memory in the current return data buffer. */ data_blob_free(&p->out_data.rdata); - /* - * Marshall directly into the outgoing PDU space. We - * must do this as we need to set to the bind response - * header and are never sending more than one PDU here. - */ - - prs_init_empty(&p->out_data.frag, p->mem_ctx, MARSHALL); - /* * Initialize a bind_nak header. */ @@ -849,6 +798,12 @@ static bool setup_bind_nak(pipes_struct *p, struct ncacn_packet *pkt) u.bind_nak.reject_reason = 0; + /* + * Marshall directly into the outgoing PDU space. We + * must do this as we need to set to the bind response + * header and are never sending more than one PDU here. + */ + status = dcerpc_push_ncacn_packet(p->mem_ctx, DCERPC_PKT_BIND_NAK, DCERPC_PFC_FLAG_FIRST | @@ -856,15 +811,8 @@ static bool setup_bind_nak(pipes_struct *p, struct ncacn_packet *pkt) 0, pkt->call_id, &u, - &blob); + &p->out_data.frag); if (!NT_STATUS_IS_OK(status)) { - prs_mem_free(&p->out_data.frag); - return False; - } - - if (!prs_copy_data_in(&p->out_data.frag, - (char *)blob.data, blob.length)) { - prs_mem_free(&p->out_data.frag); return False; } @@ -889,19 +837,10 @@ bool setup_fault_pdu(pipes_struct *p, NTSTATUS fault_status) { NTSTATUS status; union dcerpc_payload u; - DATA_BLOB blob; /* Free any memory in the current return data buffer. */ data_blob_free(&p->out_data.rdata); - /* - * Marshall directly into the outgoing PDU space. We - * must do this as we need to set to the bind response - * header and are never sending more than one PDU here. - */ - - prs_init_empty(&p->out_data.frag, p->mem_ctx, MARSHALL); - /* * Initialize a fault header. */ @@ -911,6 +850,12 @@ bool setup_fault_pdu(pipes_struct *p, NTSTATUS fault_status) u.fault.status = NT_STATUS_V(fault_status); u.fault._pad = data_blob_talloc_zero(p->mem_ctx, 4); + /* + * Marshall directly into the outgoing PDU space. We + * must do this as we need to set to the bind response + * header and are never sending more than one PDU here. + */ + status = dcerpc_push_ncacn_packet(p->mem_ctx, DCERPC_PKT_FAULT, DCERPC_PFC_FLAG_FIRST | @@ -919,15 +864,8 @@ bool setup_fault_pdu(pipes_struct *p, NTSTATUS fault_status) 0, p->call_id, &u, - &blob); + &p->out_data.frag); if (!NT_STATUS_IS_OK(status)) { - prs_mem_free(&p->out_data.frag); - return False; - } - - if (!prs_copy_data_in(&p->out_data.frag, - (char *)blob.data, blob.length)) { - prs_mem_free(&p->out_data.frag); return False; } @@ -1425,7 +1363,6 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) struct dcerpc_ack_ctx bind_ack_ctx; DATA_BLOB auth_resp = data_blob_null; DATA_BLOB auth_blob = data_blob_null; - DATA_BLOB blob = data_blob_null; int pad_len = 0; /* No rebinds on a bound pipe - use alter context. */ @@ -1491,14 +1428,6 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) assoc_gid = 0x53f0; } - /* - * Marshall directly into the outgoing PDU space. We - * must do this as we need to set to the bind response - * header and are never sending more than one PDU here. - */ - - prs_init_empty(&p->out_data.frag, p->mem_ctx, MARSHALL); - /* * Create the bind response struct. */ @@ -1634,12 +1563,20 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) /* NOTE: We leave the auth_info empty so we can calculate the padding * later and then append the auth_info --simo */ - status = dcerpc_push_ncacn_packet(pkt, DCERPC_PKT_BIND_ACK, + /* + * Marshall directly into the outgoing PDU space. We + * must do this as we need to set to the bind response + * header and are never sending more than one PDU here. + */ + + status = dcerpc_push_ncacn_packet(p->mem_ctx, + DCERPC_PKT_BIND_ACK, DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST, auth_resp.length, pkt->call_id, - &u, &blob); + &u, + &p->out_data.frag); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n", nt_errstr(status))); @@ -1648,7 +1585,7 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) if (auth_resp.length) { /* Work out any padding needed before the auth footer. */ - pad_len = blob.length % SERVER_NDR_PADDING_SIZE; + pad_len = p->out_data.frag.length % SERVER_NDR_PADDING_SIZE; if (pad_len) { pad_len = SERVER_NDR_PADDING_SIZE - pad_len; DEBUG(10, ("auth pad_len = %u\n", @@ -1670,20 +1607,17 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) /* Now that we have the auth len store it into the right place in * the dcerpc header */ - dcerpc_set_frag_length(&blob, blob.length + pad_len + auth_blob.length); - - /* And finally copy all bits in the output pdu */ - if (!prs_copy_data_in(&p->out_data.frag, - (char *)blob.data, blob.length)) { - DEBUG(0, ("Failed to copy data to output buffer.\n")); - goto err_exit; - } + dcerpc_set_frag_length(&p->out_data.frag, + p->out_data.frag.length + + pad_len + + auth_blob.length); if (auth_blob.length) { if (pad_len) { char pad[SERVER_NDR_PADDING_SIZE]; memset(pad, '\0', SERVER_NDR_PADDING_SIZE); - if (!prs_copy_data_in(&p->out_data.frag, pad, pad_len)) { + if (!data_blob_append(p->mem_ctx, &p->out_data.frag, + pad, pad_len)) { DEBUG(0, ("api_pipe_bind_req: failed to add " "%u bytes of pad data.\n", (unsigned int)pad_len)); @@ -1691,9 +1625,8 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) } } - if (!prs_copy_data_in(&p->out_data.frag, - (char *)auth_blob.data, - auth_blob.length)) { + if (!data_blob_append(p->mem_ctx, &p->out_data.frag, + auth_blob.data, auth_blob.length)) { DEBUG(0, ("Append of auth info failed.\n")); goto err_exit; } @@ -1707,14 +1640,12 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) p->out_data.current_pdu_sent = 0; TALLOC_FREE(auth_blob.data); - TALLOC_FREE(blob.data); return True; err_exit: - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); TALLOC_FREE(auth_blob.data); - TALLOC_FREE(blob.data); return setup_bind_nak(p, pkt); } @@ -1732,7 +1663,6 @@ bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt) struct dcerpc_ack_ctx bind_ack_ctx; DATA_BLOB auth_resp = data_blob_null; DATA_BLOB auth_blob = data_blob_null; - DATA_BLOB blob = data_blob_null; int pad_len = 0; DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__)); @@ -1743,14 +1673,6 @@ bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt) assoc_gid = 0x53f0; } - /* - * Marshall directly into the outgoing PDU space. We - * must do this as we need to set to the bind response - * header and are never sending more than one PDU here. - */ - - prs_init_empty(&p->out_data.frag, p->mem_ctx, MARSHALL); - /* * Create the bind response struct. */ @@ -1840,12 +1762,20 @@ bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt) /* NOTE: We leave the auth_info empty so we can calculate the padding * later and then append the auth_info --simo */ - status = dcerpc_push_ncacn_packet(pkt, DCERPC_PKT_ALTER_RESP, + /* + * Marshall directly into the outgoing PDU space. We + * must do this as we need to set to the bind response + * header and are never sending more than one PDU here. + */ + + status = dcerpc_push_ncacn_packet(p->mem_ctx, + DCERPC_PKT_ALTER_RESP, DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST, auth_resp.length, pkt->call_id, - &u, &blob); + &u, + &p->out_data.frag); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n", nt_errstr(status))); @@ -1854,7 +1784,7 @@ bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt) if (auth_resp.length) { /* Work out any padding needed before the auth footer. */ - pad_len = blob.length % SERVER_NDR_PADDING_SIZE; + pad_len = p->out_data.frag.length % SERVER_NDR_PADDING_SIZE; if (pad_len) { pad_len = SERVER_NDR_PADDING_SIZE - pad_len; DEBUG(10, ("auth pad_len = %u\n", @@ -1876,20 +1806,17 @@ bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt) /* Now that we have the auth len store it into the right place in * the dcerpc header */ - dcerpc_set_frag_length(&blob, blob.length + pad_len + auth_blob.length); - - /* And finally copy all bits in the output pdu */ - if (!prs_copy_data_in(&p->out_data.frag, - (char *)blob.data, blob.length)) { - DEBUG(0, ("Failed to copy data to output buffer.\n")); - goto err_exit; - } + dcerpc_set_frag_length(&p->out_data.frag, + p->out_data.frag.length + + pad_len + auth_blob.length); if (auth_resp.length) { if (pad_len) { char pad[SERVER_NDR_PADDING_SIZE]; memset(pad, '\0', SERVER_NDR_PADDING_SIZE); - if (!prs_copy_data_in(&p->out_data.frag, pad, pad_len)) { + if (!data_blob_append(p->mem_ctx, + &p->out_data.frag, + pad, pad_len)) { DEBUG(0, ("api_pipe_bind_req: failed to add " "%u bytes of pad data.\n", (unsigned int)pad_len)); @@ -1897,9 +1824,8 @@ bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt) } } - if (!prs_copy_data_in(&p->out_data.frag, - (char *)auth_blob.data, - auth_blob.length)) { + if (!data_blob_append(p->mem_ctx, &p->out_data.frag, + auth_blob.data, auth_blob.length)) { DEBUG(0, ("Append of auth info failed.\n")); goto err_exit; } @@ -1913,14 +1839,12 @@ bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt) p->out_data.current_pdu_sent = 0; TALLOC_FREE(auth_blob.data); - TALLOC_FREE(blob.data); return True; err_exit: - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); TALLOC_FREE(auth_blob.data); - TALLOC_FREE(blob.data); return setup_bind_nak(p, pkt); } diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 3cd9028f44..f2fb76ea49 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -42,7 +42,7 @@ static bool pipe_init_outgoing_data(pipes_struct *p) o_data->data_sent_length = 0; o_data->current_pdu_sent = 0; - prs_mem_free(&o_data->frag); + data_blob_free(&o_data->frag); /* Free any memory in the current return data buffer. */ data_blob_free(&o_data->rdata); @@ -143,7 +143,7 @@ static bool get_pdu_size(pipes_struct *p) static void free_pipe_context(pipes_struct *p) { - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); data_blob_free(&p->out_data.rdata); prs_mem_free(&p->in_data.data); @@ -803,7 +803,7 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, * PDU. */ - pdu_remaining = prs_offset(&p->out_data.frag) + pdu_remaining = p->out_data.frag.length - p->out_data.current_pdu_sent; if (pdu_remaining > 0) { @@ -812,12 +812,12 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, " "current_pdu_sent = %u returning %d bytes.\n", get_pipe_name_from_syntax(talloc_tos(), &p->syntax), - (unsigned int)prs_offset(&p->out_data.frag), + (unsigned int)p->out_data.frag.length, (unsigned int)p->out_data.current_pdu_sent, (int)data_returned)); memcpy(data, - prs_data_p(&p->out_data.frag) + p->out_data.frag.data + p->out_data.current_pdu_sent, data_returned); @@ -858,20 +858,20 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, return -1; } - data_returned = MIN(n, prs_offset(&p->out_data.frag)); + data_returned = MIN(n, p->out_data.frag.length); - memcpy( data, prs_data_p(&p->out_data.frag), (size_t)data_returned); + memcpy(data, p->out_data.frag.data, (size_t)data_returned); p->out_data.current_pdu_sent += (uint32)data_returned; out: - (*is_data_outstanding) = prs_offset(&p->out_data.frag) > n; + (*is_data_outstanding) = p->out_data.frag.length > n; - if (p->out_data.current_pdu_sent == prs_offset(&p->out_data.frag)) { + if (p->out_data.current_pdu_sent == p->out_data.frag.length) { /* We've returned everything in the out_data.frag * so we're done with this pdu. Free it and reset * current_pdu_sent. */ p->out_data.current_pdu_sent = 0; - prs_mem_free(&p->out_data.frag); + data_blob_free(&p->out_data.frag); if (p->out_data.data_sent_length >= p->out_data.rdata.length) { /* -- cgit From 2452a7a4c1094047f4c67f0901b746e069639f8f Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 13 Jul 2010 23:56:01 -0400 Subject: s3-dcerpc: consolidate respones packet creation code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/include/proto.h | 1 + source3/include/rpc_dce.h | 2 +- source3/rpc_client/cli_pipe.c | 6 +- source3/rpc_server/srv_pipe.c | 679 ++++++++++++++---------------------------- 4 files changed, 236 insertions(+), 452 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index fbd3d91063..08c7020853 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4843,6 +4843,7 @@ const struct ndr_interface_table *get_iface_from_syntax( const struct ndr_syntax_id *syntax); const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax); +enum dcerpc_AuthType map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type); struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, struct event_context *ev, diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index e663a56ad6..32ab19c157 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -22,7 +22,7 @@ #ifndef _DCE_RPC_H /* _DCE_RPC_H */ #define _DCE_RPC_H -#define RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN 0x20 +#define SCHANNEL_SIG_SIZE 0x20 /* Maximum size of the signing data in a fragment. */ #define RPC_MAX_SIGN_SIZE 0x38 /* 56 */ diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index f91e2e28b7..bbcc832626 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -217,7 +217,7 @@ const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx, Map internal value to wire value. ********************************************************************/ -static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type) +enum dcerpc_AuthType map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type) { switch (auth_type) { @@ -945,7 +945,7 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, return NT_STATUS_OK; } - if (auth_len < RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) { + if (auth_len < SCHANNEL_SIG_SIZE) { DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len )); return NT_STATUS_INVALID_PARAMETER; } @@ -2348,7 +2348,7 @@ static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli, *p_auth_len = NTLMSSP_SIG_SIZE; break; case PIPE_AUTH_TYPE_SCHANNEL: - *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN; + *p_auth_len = SCHANNEL_SIG_SIZE; break; default: smb_panic("bad auth type"); diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 62725f2e9c..6b85141367 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -53,512 +53,218 @@ static DATA_BLOB generic_session_key(void) } /******************************************************************* - Generate the next PDU to be returned from the data in p->rdata. Handle NTLMSSP. ********************************************************************/ -static bool create_next_pdu_ntlmssp(pipes_struct *p) +static bool add_ntlmssp_auth(pipes_struct *p) { - DATA_BLOB blob; - uint8_t hdr_flags; - uint32 ss_padding_len = 0; - uint32 data_space_available; - uint32 data_len_left; - uint32 data_len; - NTSTATUS status; + enum dcerpc_AuthLevel auth_level = p->auth.auth_level; DATA_BLOB auth_blob = data_blob_null; - uint8 auth_type, auth_level; - struct auth_ntlmssp_state *a = p->auth.a_u.auth_ntlmssp_state; - union dcerpc_payload u; - TALLOC_CTX *frame; - - /* - * If we're in the fault state, keep returning fault PDU's until - * the pipe gets closed. JRA. - */ - - if(p->fault_state) { - setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); - return True; - } - - ZERO_STRUCT(u.response); - - /* Set up rpc header flags. */ - if (p->out_data.data_sent_length == 0) { - hdr_flags = DCERPC_PFC_FLAG_FIRST; - } else { - hdr_flags = 0; - } - - /* - * Work out how much we can fit in a single PDU. - */ - - data_len_left = p->out_data.rdata.length - p->out_data.data_sent_length; - - /* - * Ensure there really is data left to send. - */ - - if(!data_len_left) { - DEBUG(0,("create_next_pdu_ntlmssp: no data left to send !\n")); - return False; - } - - /* Space available - not including padding. */ - data_space_available = RPC_MAX_PDU_FRAG_LEN - RPC_HEADER_LEN - - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - NTLMSSP_SIG_SIZE; - - /* - * The amount we send is the minimum of the available - * space and the amount left to send. - */ - - data_len = MIN(data_len_left, data_space_available); - - /* Work out any padding alignment requirements. */ - if ((RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len) % SERVER_NDR_PADDING_SIZE) { - ss_padding_len = SERVER_NDR_PADDING_SIZE - - ((RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len) % SERVER_NDR_PADDING_SIZE); - DEBUG(10,("create_next_pdu_ntlmssp: adding sign/seal padding of %u\n", - ss_padding_len )); - /* If we're over filling the packet, we need to make space - * for the padding at the end of the data. */ - if (data_len + ss_padding_len > data_space_available) { - data_len -= SERVER_NDR_PADDING_SIZE; - } - } - - /* - * Set up the alloc hint. This should be the data left to - * send. - */ - - u.response.alloc_hint = data_len_left; + NTSTATUS status; - /* - * Work out if this PDU will be the last. + /* FIXME: Is this right ? + * Keeping only to avoid changing semantics during refactoring + * --simo */ - if (p->out_data.data_sent_length + data_len >= - p->out_data.rdata.length) { - hdr_flags |= DCERPC_PFC_FLAG_LAST; - } - - /* Set the data into the PDU. */ - u.response.stub_and_verifier = - data_blob_const(p->out_data.rdata.data, data_len); - - /* Store the packet in the data stream. */ - status = dcerpc_push_ncacn_packet(p->mem_ctx, - DCERPC_PKT_RESPONSE, - hdr_flags, - NTLMSSP_SIG_SIZE, - p->call_id, - &u, - &p->out_data.frag); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed to marshall RPC Header.\n")); - return False; - } - - /* Set the proper length on the pdu */ - dcerpc_set_frag_length(&p->out_data.frag, - p->out_data.frag.length + - ss_padding_len + - RPC_HDR_AUTH_LEN + - NTLMSSP_SIG_SIZE); - - /* Append the sign/seal padding data. */ - if (ss_padding_len) { - char pad[SERVER_NDR_PADDING_SIZE]; - - memset(pad, '\0', SERVER_NDR_PADDING_SIZE); - if (!data_blob_append(p->mem_ctx, - &p->out_data.frag, pad, - ss_padding_len)) { - DEBUG(0,("create_next_pdu_ntlmssp: failed to add %u bytes of pad data.\n", - (unsigned int)ss_padding_len)); - data_blob_free(&p->out_data.frag); - return False; - } - } - - /* Now write out the auth header and null blob. */ - if (p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP) { - auth_type = DCERPC_AUTH_TYPE_NTLMSSP; - } else { - auth_type = DCERPC_AUTH_TYPE_SPNEGO; - } - if (p->auth.auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { - auth_level = DCERPC_AUTH_LEVEL_PRIVACY; - } else { + if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) { auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; } - frame = talloc_stackframe(); - - /* auth_blob is intentionally null, it will be appended later */ - status = dcerpc_push_dcerpc_auth(frame, - auth_type, - auth_level, - ss_padding_len, - 1, /* context id. */ - &auth_blob, - &blob); - - /* Store auth header in the data stream. */ - if (!data_blob_append(p->mem_ctx, - &p->out_data.frag, - (char *)blob.data, blob.length)) { - DEBUG(0, ("Out of memory.\n")); - data_blob_free(&p->out_data.frag); - return False; - } - - /* Generate the sign blob. */ - - switch (p->auth.auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - /* Data portion is encrypted. */ - status = auth_ntlmssp_seal_packet( - a, frame, - p->out_data.frag.data - + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, - data_len + ss_padding_len, + /* Generate the auth blob. */ + switch (auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + /* Data portion is encrypted. */ + status = auth_ntlmssp_seal_packet( + p->auth.a_u.auth_ntlmssp_state, + (TALLOC_CTX *)p->out_data.frag.data, + &p->out_data.frag.data[DCERPC_RESPONSE_LENGTH], + p->out_data.frag.length + - DCERPC_RESPONSE_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH, p->out_data.frag.data, p->out_data.frag.length, &auth_blob); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(frame); - data_blob_free(&p->out_data.frag); - return False; - } - break; - case DCERPC_AUTH_LEVEL_INTEGRITY: - /* Data is signed. */ - status = auth_ntlmssp_sign_packet( - a, frame, - p->out_data.frag.data - + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, - data_len + ss_padding_len, + break; + + case DCERPC_AUTH_LEVEL_INTEGRITY: + /* Data is signed. */ + status = auth_ntlmssp_sign_packet( + p->auth.a_u.auth_ntlmssp_state, + (TALLOC_CTX *)p->out_data.frag.data, + &p->out_data.frag.data[DCERPC_RESPONSE_LENGTH], + p->out_data.frag.length + - DCERPC_RESPONSE_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH, p->out_data.frag.data, p->out_data.frag.length, &auth_blob); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(frame); - data_blob_free(&p->out_data.frag); - return False; - } - break; - default: - talloc_free(frame); - data_blob_free(&p->out_data.frag); - return False; + break; + + default: + status = NT_STATUS_INTERNAL_ERROR; + return false; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Failed to add NTLMSSP auth blob: %s\n", + nt_errstr(status))); + data_blob_free(&p->out_data.frag); + return false; } /* Finally append the auth blob. */ if (!data_blob_append(p->mem_ctx, &p->out_data.frag, - auth_blob.data, NTLMSSP_SIG_SIZE)) { + auth_blob.data, auth_blob.length)) { DEBUG(0, ("Failed to add %u bytes auth blob.\n", - (unsigned int)NTLMSSP_SIG_SIZE)); - talloc_free(frame); + (unsigned int)auth_blob.length)); data_blob_free(&p->out_data.frag); return False; } - talloc_free(frame); - - /* - * Setup the counts for this PDU. - */ - - p->out_data.data_sent_length += data_len; - p->out_data.current_pdu_sent = 0; + data_blob_free(&auth_blob); - return True; + return true; } /******************************************************************* - Generate the next PDU to be returned from the data in p->rdata. - Return an schannel authenticated fragment. + Append a schannel authenticated fragment. ********************************************************************/ -static bool create_next_pdu_schannel(pipes_struct *p) +static bool add_schannel_auth(pipes_struct *p) { - DATA_BLOB blob; - uint8_t hdr_flags; - uint32 ss_padding_len = 0; - uint32 data_len; - uint32 data_space_available; - uint32 data_len_left; - uint32 data_pos; - NTSTATUS status; - union dcerpc_payload u; DATA_BLOB auth_blob = data_blob_null; + NTSTATUS status; - /* - * If we're in the fault state, keep returning fault PDU's until - * the pipe gets closed. JRA. - */ - - if(p->fault_state) { - setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); - return True; - } - - ZERO_STRUCT(u.response); - - /* Set up rpc header flags. */ - if (p->out_data.data_sent_length == 0) { - hdr_flags = DCERPC_PFC_FLAG_FIRST; - } else { - hdr_flags = 0; - } - - /* - * Work out how much we can fit in a single PDU. - */ - - data_len_left = p->out_data.rdata.length - p->out_data.data_sent_length; - - /* - * Ensure there really is data left to send. - */ - - if(!data_len_left) { - DEBUG(0,("create_next_pdu_schannel: no data left to send !\n")); - return False; - } - - /* Space available - not including padding. */ - data_space_available = RPC_MAX_PDU_FRAG_LEN - RPC_HEADER_LEN - - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - - RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN; - - /* - * The amount we send is the minimum of the available - * space and the amount left to send. - */ - - data_len = MIN(data_len_left, data_space_available); - - /* Work out any padding alignment requirements. */ - if ((RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len) % SERVER_NDR_PADDING_SIZE) { - ss_padding_len = SERVER_NDR_PADDING_SIZE - - ((RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len) % SERVER_NDR_PADDING_SIZE); - DEBUG(10,("create_next_pdu_schannel: adding sign/seal padding of %u\n", - ss_padding_len )); - /* If we're over filling the packet, we need to make space - * for the padding at the end of the data. */ - if (data_len + ss_padding_len > data_space_available) { - data_len -= SERVER_NDR_PADDING_SIZE; - } - } - - /* - * Set up the alloc hint. This should be the data left to - * send. - */ - - u.response.alloc_hint = data_len_left; - - /* - * Work out if this PDU will be the last. - */ - if (p->out_data.data_sent_length + data_len >= - p->out_data.rdata.length) { - hdr_flags |= DCERPC_PFC_FLAG_LAST; - } - - /* Set the data into the PDU. */ - u.response.stub_and_verifier = - data_blob_const(p->out_data.rdata.data + - p->out_data.data_sent_length, data_len); - - /* Store the packet in the data stream. */ - status = dcerpc_push_ncacn_packet(p->mem_ctx, - DCERPC_PKT_RESPONSE, - hdr_flags, - RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, - p->call_id, - &u, - &p->out_data.frag); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed to marshall RPC Header.\n")); - return False; - } - - /* Store the data offset. */ - data_pos = p->out_data.frag.length - data_len; - - /* Set the proper length on the pdu */ - dcerpc_set_frag_length(&p->out_data.frag, - p->out_data.frag.length + - ss_padding_len + - RPC_HDR_AUTH_LEN + - RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN); - - /* Append the sign/seal padding data. */ - if (ss_padding_len) { - char pad[SERVER_NDR_PADDING_SIZE]; - memset(pad, '\0', SERVER_NDR_PADDING_SIZE); - if (!data_blob_append(p->mem_ctx, - &p->out_data.frag, pad, - ss_padding_len)) { - DEBUG(0,("create_next_pdu_schannel: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len)); - data_blob_free(&p->out_data.frag); - return False; - } - } - - /* auth_blob is intentionally null, it will be appended later */ - status = dcerpc_push_dcerpc_auth(talloc_tos(), - DCERPC_AUTH_TYPE_SCHANNEL, - p->auth.auth_level, - ss_padding_len, - 1, /* context id. */ - &auth_blob, - &blob); - - /* Store auth header in the data stream. */ - if (!data_blob_append(p->mem_ctx, &p->out_data.frag, - blob.data, blob.length)) { - DEBUG(0, ("Out of memory.\n")); - data_blob_free(&p->out_data.frag); - return False; - } - - /* - * Schannel processing. - */ - - blob = data_blob_const(p->out_data.frag.data + data_pos, - data_len + ss_padding_len); - + /* Schannel processing. */ switch (p->auth.auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: - status = netsec_outgoing_packet(p->auth.a_u.schannel_auth, - talloc_tos(), - true, - blob.data, - blob.length, - &auth_blob); + status = netsec_outgoing_packet( + p->auth.a_u.schannel_auth, + (TALLOC_CTX *)p->out_data.frag.data, + true, + &p->out_data.frag.data[DCERPC_RESPONSE_LENGTH], + p->out_data.frag.length + - DCERPC_RESPONSE_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH, + &auth_blob); break; + case DCERPC_AUTH_LEVEL_INTEGRITY: - status = netsec_outgoing_packet(p->auth.a_u.schannel_auth, - talloc_tos(), - false, - blob.data, - blob.length, - &auth_blob); + status = netsec_outgoing_packet( + p->auth.a_u.schannel_auth, + (TALLOC_CTX *)p->out_data.frag.data, + false, + &p->out_data.frag.data[DCERPC_RESPONSE_LENGTH], + p->out_data.frag.length + - DCERPC_RESPONSE_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH, + &auth_blob); break; + default: status = NT_STATUS_INTERNAL_ERROR; break; } if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("create_next_pdu_schannel: failed to process packet: %s\n", + DEBUG(0, ("Failed to add SCHANNEL auth blob: %s\n", nt_errstr(status))); data_blob_free(&p->out_data.frag); return false; } - /* Finally marshall the blob. */ - if (DEBUGLEVEL >= 10) { dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_blob); } if (!data_blob_append(p->mem_ctx, &p->out_data.frag, auth_blob.data, auth_blob.length)) { + DEBUG(0, ("Failed to add %u bytes auth blob.\n", + (unsigned int)auth_blob.length)); data_blob_free(&p->out_data.frag); return false; } + data_blob_free(&auth_blob); - /* - * Setup the counts for this PDU. - */ - - p->out_data.data_sent_length += data_len; - p->out_data.current_pdu_sent = 0; - - return True; + return true; } /******************************************************************* - Generate the next PDU to be returned from the data in p->rdata. - No authentication done. + Generate the next PDU to be returned from the data. ********************************************************************/ -static bool create_next_pdu_noauth(pipes_struct *p) +static bool create_next_packet(pipes_struct *p, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, + size_t auth_length) { - uint8_t hdr_flags; - NTSTATUS status; - uint32 data_len; - uint32 data_space_available; - uint32 data_len_left; union dcerpc_payload u; - - /* - * If we're in the fault state, keep returning fault PDU's until - * the pipe gets closed. JRA. - */ - - if(p->fault_state) { - setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); - return True; - } + uint8_t pfc_flags; + size_t data_len_left; + size_t data_len; + size_t max_len; + size_t pad_len = 0; + NTSTATUS status; ZERO_STRUCT(u.response); - /* Set up rpc header flags. */ + /* Set up rpc packet pfc flags. */ if (p->out_data.data_sent_length == 0) { - hdr_flags = DCERPC_PFC_FLAG_FIRST; + pfc_flags = DCERPC_PFC_FLAG_FIRST; } else { - hdr_flags = 0; + pfc_flags = 0; } - /* - * Work out how much we can fit in a single PDU. - */ - - data_len_left = p->out_data.rdata.length - p->out_data.data_sent_length; + /* Work out how much we can fit in a single PDU. */ + data_len_left = p->out_data.rdata.length - + p->out_data.data_sent_length; - /* - * Ensure there really is data left to send. - */ - - if(!data_len_left) { - DEBUG(0,("create_next_pdu_noath: no data left to send !\n")); - return False; + /* Ensure there really is data left to send. */ + if (!data_len_left) { + DEBUG(0, ("No data left to send !\n")); + return false; } - data_space_available = RPC_MAX_PDU_FRAG_LEN - RPC_HEADER_LEN - - RPC_HDR_RESP_LEN; + /* Max space available - not including padding. */ + if (auth_length) { + max_len = RPC_MAX_PDU_FRAG_LEN + - DCERPC_RESPONSE_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH + - auth_length; + } else { + max_len = RPC_MAX_PDU_FRAG_LEN - DCERPC_RESPONSE_LENGTH; + } /* - * The amount we send is the minimum of the available - * space and the amount left to send. + * The amount we send is the minimum of the max_len + * and the amount left to send. */ + data_len = MIN(data_len_left, max_len); - data_len = MIN(data_len_left, data_space_available); - - /* - * Set up the alloc hint. This should be the data left to - * send. - */ + if (auth_length) { + /* Work out any padding alignment requirements. */ + pad_len = (DCERPC_RESPONSE_LENGTH + data_len) % + SERVER_NDR_PADDING_SIZE; + if (pad_len) { + pad_len = SERVER_NDR_PADDING_SIZE - pad_len; + DEBUG(10, ("Padding size is: %d\n", (int)pad_len)); + /* If we're over filling the packet, we need to make + * space for the padding at the end of the data. */ + if (data_len + pad_len > max_len) { + data_len -= SERVER_NDR_PADDING_SIZE; + } + } + } + /* Set up the alloc hint. This should be the data left to send. */ u.response.alloc_hint = data_len_left; - /* - * Work out if this PDU will be the last. - */ - if(p->out_data.data_sent_length + data_len >= p->out_data.rdata.length) { - hdr_flags |= DCERPC_PFC_FLAG_LAST; + /* Work out if this PDU will be the last. */ + if (p->out_data.data_sent_length + + data_len >= p->out_data.rdata.length) { + pfc_flags |= DCERPC_PFC_FLAG_LAST; } - /* Set the data into the PDU. */ + /* Prepare data to be NDR encoded. */ u.response.stub_and_verifier = data_blob_const(p->out_data.rdata.data + p->out_data.data_sent_length, data_len); @@ -566,24 +272,69 @@ static bool create_next_pdu_noauth(pipes_struct *p) /* Store the packet in the data stream. */ status = dcerpc_push_ncacn_packet(p->mem_ctx, DCERPC_PKT_RESPONSE, - hdr_flags, - 0, + pfc_flags, + auth_length, p->call_id, &u, &p->out_data.frag); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed to marshall RPC Header.\n")); - return False; + DEBUG(0, ("Failed to marshall RPC Packet.\n")); + return false; } - /* - * Setup the counts for this PDU. - */ + if (auth_length) { + DATA_BLOB empty = data_blob_null; + DATA_BLOB auth_hdr; + /* Set the proper length on the pdu, including padding. + * Only needed if an auth trailer will be appended. */ + dcerpc_set_frag_length(&p->out_data.frag, + p->out_data.frag.length + + pad_len + + DCERPC_AUTH_TRAILER_LENGTH + + auth_length); + + if (pad_len) { + size_t offset = p->out_data.frag.length; + + if (!data_blob_realloc(p->mem_ctx, + &p->out_data.frag, + offset + pad_len)) { + DEBUG(0, ("Failed to add padding!\n")); + data_blob_free(&p->out_data.frag); + return false; + } + memset(&p->out_data.frag.data[offset], '\0', pad_len); + } + + /* auth blob is intentionally empty, + * it will be appended later */ + status = dcerpc_push_dcerpc_auth(p->out_data.frag.data, + auth_type, + auth_level, + pad_len, + 1, /* context id. */ + &empty, + &auth_hdr); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Failed to marshall RPC Auth.\n")); + return false; + } + + /* Store auth header in the data stream. */ + if (!data_blob_append(p->mem_ctx, &p->out_data.frag, + auth_hdr.data, auth_hdr.length)) { + DEBUG(0, ("Out of memory.\n")); + data_blob_free(&p->out_data.frag); + return false; + } + data_blob_free(&auth_hdr); + } + + /* Setup the counts for this PDU. */ p->out_data.data_sent_length += data_len; p->out_data.current_pdu_sent = 0; - - return True; + return true; } /******************************************************************* @@ -592,28 +343,60 @@ static bool create_next_pdu_noauth(pipes_struct *p) bool create_next_pdu(pipes_struct *p) { - switch(p->auth.auth_level) { - case DCERPC_AUTH_LEVEL_NONE: - case DCERPC_AUTH_LEVEL_CONNECT: - /* This is incorrect for auth level connect. Fixme. JRA */ - return create_next_pdu_noauth(p); + enum dcerpc_AuthType auth_type = + map_pipe_auth_type_to_rpc_auth_type(p->auth.auth_type); - default: - switch(p->auth.auth_type) { - case PIPE_AUTH_TYPE_NTLMSSP: - case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: - return create_next_pdu_ntlmssp(p); - case PIPE_AUTH_TYPE_SCHANNEL: - return create_next_pdu_schannel(p); - default: - break; + /* + * If we're in the fault state, keep returning fault PDU's until + * the pipe gets closed. JRA. + */ + if (p->fault_state) { + setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); + return true; + } + + switch (p->auth.auth_level) { + case DCERPC_AUTH_LEVEL_NONE: + case DCERPC_AUTH_LEVEL_CONNECT: + /* This is incorrect for auth level connect. Fixme. JRA */ + + /* No authentication done. */ + return create_next_packet(p, auth_type, + p->auth.auth_level, 0); + + case DCERPC_AUTH_LEVEL_CALL: + case DCERPC_AUTH_LEVEL_PACKET: + case DCERPC_AUTH_LEVEL_INTEGRITY: + case DCERPC_AUTH_LEVEL_PRIVACY: + + switch(p->auth.auth_type) { + case PIPE_AUTH_TYPE_NTLMSSP: + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + if (!create_next_packet(p, auth_type, + p->auth.auth_level, + NTLMSSP_SIG_SIZE)) { + return false; } + return add_ntlmssp_auth(p); + + case PIPE_AUTH_TYPE_SCHANNEL: + if (!create_next_packet(p, auth_type, + p->auth.auth_level, + SCHANNEL_SIG_SIZE)) { + return false; + } + return add_schannel_auth(p); + default: + break; + } + default: + break; } - DEBUG(0,("create_next_pdu: invalid internal auth level %u / type %u", - (unsigned int)p->auth.auth_level, - (unsigned int)p->auth.auth_type)); - return False; + DEBUG(0, ("Invalid internal auth level %u / type %u\n", + (unsigned int)p->auth.auth_level, + (unsigned int)p->auth.auth_type)); + return false; } /******************************************************************* -- cgit From f9a15d1d94b4ea97f560536c32780b1c7e43c451 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Jul 2010 01:59:10 -0400 Subject: s3-dcerpc: Refactor code and stop using ncacn_packet_header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_client/cli_pipe.c | 366 +++++++++++++++++++----------------------- 1 file changed, 164 insertions(+), 202 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index bbcc832626..364b1e8898 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -784,19 +784,12 @@ static NTSTATUS get_complete_frag_recv(struct tevent_req *req) ****************************************************************************/ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, - struct ncacn_packet_header *prhdr, - prs_struct *current_pdu, - uint8 *p_ss_padding_len) + struct ncacn_packet *pkt, + prs_struct *current_pdu, + uint8 *p_ss_padding_len) { + uint8_t *frag_data = (uint8_t *)prs_data_p(current_pdu); struct dcerpc_auth auth_info; - uint32 save_offset = prs_offset(current_pdu); - uint32_t auth_len = prhdr->auth_length; - struct ntlmssp_state *ntlmssp_state = cli->auth->a_u.ntlmssp_state; - unsigned char *data = NULL; - size_t data_len; - unsigned char *full_packet_data = NULL; - size_t full_packet_data_len; - DATA_BLOB auth_blob; DATA_BLOB blob; NTSTATUS status; @@ -805,44 +798,26 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, return NT_STATUS_OK; } - if (!ntlmssp_state) { + if (!cli->auth->a_u.ntlmssp_state) { return NT_STATUS_INVALID_PARAMETER; } /* Ensure there's enough data for an authenticated response. */ - if (auth_len > RPC_MAX_PDU_FRAG_LEN || - prhdr->frag_length < RPC_HEADER_LEN + - RPC_HDR_RESP_LEN + - RPC_HDR_AUTH_LEN + auth_len) { - DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n", - (unsigned int)auth_len )); + if ((pkt->auth_length > RPC_MAX_PDU_FRAG_LEN) || + (pkt->frag_length < DCERPC_RESPONSE_LENGTH + + DCERPC_AUTH_TRAILER_LENGTH + + pkt->auth_length)) { + DEBUG(0, ("auth_len %u is too long.\n", + (unsigned int)pkt->auth_length)); return NT_STATUS_BUFFER_TOO_SMALL; } - /* - * We need the full packet data + length (minus auth stuff) as well as the packet data + length - * after the RPC header. - * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal - * functions as NTLMv2 checks the rpc headers also. - */ - - data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN); - data_len = (size_t)(prhdr->frag_length - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len); - - full_packet_data = (unsigned char *)prs_data_p(current_pdu); - full_packet_data_len = prhdr->frag_length - auth_len; - - /* Pull the auth header and the following data into a blob. */ - /* NB. The offset of the auth_header is relative to the *end* - * of the packet, not the start. */ - if(!prs_set_offset(current_pdu, prhdr->frag_length - RPC_HDR_AUTH_LEN - auth_len)) { - DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n", - (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len )); - return NT_STATUS_BUFFER_TOO_SMALL; - } - - blob = data_blob_const(prs_data_p(current_pdu) + prs_offset(current_pdu), - prs_data_size(current_pdu) - prs_offset(current_pdu)); + /* get the auth blob at the end of the packet */ + blob = data_blob_const(frag_data + pkt->frag_length + - DCERPC_AUTH_TRAILER_LENGTH + - pkt->auth_length, + DCERPC_AUTH_TRAILER_LENGTH + + pkt->auth_length); status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info); if (!NT_STATUS_IS_OK(status)) { @@ -851,64 +826,72 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, } /* Ensure auth_pad_len fits into the packet. */ - if (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + auth_info.auth_pad_length + - RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_length) { + if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + + auth_info.auth_pad_length + + DCERPC_AUTH_TRAILER_LENGTH + + pkt->auth_length) { DEBUG(0,("cli_pipe_verify_ntlmssp: auth_info.auth_pad_len " "too large (%u), auth_len (%u), frag_len = (%u).\n", (unsigned int)auth_info.auth_pad_length, - (unsigned int)auth_len, - (unsigned int)prhdr->frag_length)); + (unsigned int)pkt->auth_length, + (unsigned int)pkt->frag_length)); return NT_STATUS_BUFFER_TOO_SMALL; } - - auth_blob = auth_info.credentials; + /* + * We need the full packet data + length (minus auth stuff) as well as the packet data + length + * after the RPC header. + * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal + * functions as NTLMv2 checks the rpc headers also. + */ switch (cli->auth->auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - /* Data is encrypted. */ - status = ntlmssp_unseal_packet(ntlmssp_state, - data, data_len, - full_packet_data, - full_packet_data_len, - &auth_blob); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal " - "packet from %s. Error was %s.\n", - rpccli_pipe_txt(talloc_tos(), cli), - nt_errstr(status) )); - return status; - } - break; - case DCERPC_AUTH_LEVEL_INTEGRITY: - /* Data is signed. */ - status = ntlmssp_check_packet(ntlmssp_state, - data, data_len, - full_packet_data, - full_packet_data_len, - &auth_blob); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on " - "packet from %s. Error was %s.\n", - rpccli_pipe_txt(talloc_tos(), cli), - nt_errstr(status) )); - return status; - } - break; - default: - DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal " - "auth level %d\n", cli->auth->auth_level)); - return NT_STATUS_INVALID_INFO_CLASS; - } + case DCERPC_AUTH_LEVEL_PRIVACY: + /* Data is encrypted. */ + status = ntlmssp_unseal_packet( + cli->auth->a_u.ntlmssp_state, + &frag_data[DCERPC_RESPONSE_LENGTH], + pkt->frag_length + - DCERPC_RESPONSE_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH + - pkt->auth_length, + frag_data, + pkt->frag_length - pkt->auth_length, + &auth_info.credentials); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("failed to unseal packet from %s." + " Error was %s.\n", + rpccli_pipe_txt(talloc_tos(), cli), + nt_errstr(status))); + return status; + } + break; - /* - * Return the current pointer to the data offset. - */ + case DCERPC_AUTH_LEVEL_INTEGRITY: + /* Data is signed. */ + status = ntlmssp_check_packet( + cli->auth->a_u.ntlmssp_state, + &frag_data[DCERPC_RESPONSE_LENGTH], + pkt->frag_length + - DCERPC_RESPONSE_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH + - pkt->auth_length, + frag_data, + pkt->frag_length - pkt->auth_length, + &auth_info.credentials); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("check signing failed on packet from %s." + " Error was %s.\n", + rpccli_pipe_txt(talloc_tos(), cli), + nt_errstr(status))); + return status; + } + break; - if(!prs_set_offset(current_pdu, save_offset)) { - DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n", - (unsigned int)save_offset )); - return NT_STATUS_BUFFER_TOO_SMALL; + default: + DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal " + "auth level %d\n", cli->auth->auth_level)); + return NT_STATUS_INVALID_INFO_CLASS; } /* @@ -926,17 +909,12 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, ****************************************************************************/ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, - struct ncacn_packet_header *prhdr, - prs_struct *current_pdu, - uint8 *p_ss_padding_len) + struct ncacn_packet *pkt, + prs_struct *current_pdu, + uint8 *p_ss_padding_len) { + uint8_t *frag_data = (uint8_t *)prs_data_p(current_pdu); struct dcerpc_auth auth_info; - uint32_t auth_len = prhdr->auth_length; - uint32 save_offset = prs_offset(current_pdu); - struct schannel_state *schannel_auth = - cli->auth->a_u.schannel_auth; - uint8_t *data; - uint32 data_len; DATA_BLOB blob; NTSTATUS status; @@ -945,41 +923,32 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, return NT_STATUS_OK; } - if (auth_len < SCHANNEL_SIG_SIZE) { - DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len )); + if (pkt->auth_length < SCHANNEL_SIG_SIZE) { + DEBUG(0, ("auth_len %u.\n", (unsigned int)pkt->auth_length)); return NT_STATUS_INVALID_PARAMETER; } - if (!schannel_auth) { + if (!cli->auth->a_u.schannel_auth) { return NT_STATUS_INVALID_PARAMETER; } /* Ensure there's enough data for an authenticated response. */ - if ((auth_len > RPC_MAX_PDU_FRAG_LEN) || - (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_length)) { - DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n", - (unsigned int)auth_len )); + if ((pkt->auth_length > RPC_MAX_PDU_FRAG_LEN) || + (pkt->frag_length < DCERPC_RESPONSE_LENGTH + + DCERPC_AUTH_TRAILER_LENGTH + + pkt->auth_length)) { + DEBUG(0, ("auth_len %u is too long.\n", + (unsigned int)pkt->auth_length)); return NT_STATUS_INVALID_PARAMETER; } - data_len = prhdr->frag_length - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len; - - /* Pull the auth header and the following data into a blob. */ - /* NB. The offset of the auth_header is relative to the *end* - * of the packet, not the start. */ - if(!prs_set_offset(current_pdu, - prhdr->frag_length - RPC_HDR_AUTH_LEN - auth_len)) { - DEBUG(0,("cli_pipe_verify_schannel: cannot move " - "offset to %u.\n", - (unsigned int)(prhdr->frag_length - - RPC_HDR_AUTH_LEN - auth_len) )); - return NT_STATUS_BUFFER_TOO_SMALL; - } + /* get the auth blob at the end of the packet */ + blob = data_blob_const(frag_data + pkt->frag_length + - DCERPC_AUTH_TRAILER_LENGTH + - pkt->auth_length, + DCERPC_AUTH_TRAILER_LENGTH + + pkt->auth_length); - blob = data_blob_const(prs_data_p(current_pdu) - + prs_offset(current_pdu), - prs_data_size(current_pdu) - - prs_offset(current_pdu)); status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info); if (!NT_STATUS_IS_OK(status)) { @@ -988,48 +957,52 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, } /* Ensure auth_pad_len fits into the packet. */ - if (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + auth_info.auth_pad_length + - RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_length) { + if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + + auth_info.auth_pad_length + + DCERPC_AUTH_TRAILER_LENGTH + + pkt->auth_length) { DEBUG(0,("cli_pipe_verify_schannel: auth_info.auth_pad_len " "too large (%u), auth_len (%u), frag_len = (%u).\n", (unsigned int)auth_info.auth_pad_length, - (unsigned int)auth_len, - (unsigned int)prhdr->frag_length)); + (unsigned int)pkt->auth_length, + (unsigned int)pkt->frag_length)); return NT_STATUS_BUFFER_TOO_SMALL; } if (auth_info.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { - DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n", - auth_info.auth_type)); + DEBUG(0, ("Invalid auth info %d on schannel\n", + auth_info.auth_type)); return NT_STATUS_BUFFER_TOO_SMALL; } - blob = data_blob_const(prs_data_p(current_pdu) + - prs_offset(current_pdu) + - RPC_HDR_AUTH_LEN, auth_len); - if (DEBUGLEVEL >= 10) { - dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob); + dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_info.credentials); } - data = (uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN; - switch (cli->auth->auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: - status = netsec_incoming_packet(schannel_auth, - talloc_tos(), - true, - data, - data_len, - &blob); + status = netsec_incoming_packet( + cli->auth->a_u.schannel_auth, + talloc_tos(), + true, + &frag_data[DCERPC_RESPONSE_LENGTH], + pkt->frag_length + - DCERPC_RESPONSE_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH + - pkt->auth_length, + &auth_info.credentials); break; case DCERPC_AUTH_LEVEL_INTEGRITY: - status = netsec_incoming_packet(schannel_auth, - talloc_tos(), - false, - data, - data_len, - &blob); + status = netsec_incoming_packet( + cli->auth->a_u.schannel_auth, + talloc_tos(), + false, + &frag_data[DCERPC_RESPONSE_LENGTH], + pkt->frag_length + - DCERPC_RESPONSE_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH + - pkt->auth_length, + &auth_info.credentials); break; default: status = NT_STATUS_INTERNAL_ERROR; @@ -1044,16 +1017,6 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, return NT_STATUS_INVALID_PARAMETER; } - /* - * Return the current pointer to the data offset. - */ - - if(!prs_set_offset(current_pdu, save_offset)) { - DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n", - (unsigned int)save_offset )); - return NT_STATUS_BUFFER_TOO_SMALL; - } - /* * Remember the padding length. We must remove it from the real data * stream once the sign/seal is done. @@ -1069,20 +1032,24 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, ****************************************************************************/ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, - struct ncacn_packet_header *prhdr, + struct ncacn_packet *pkt, prs_struct *current_pdu, uint8 *p_ss_padding_len) { NTSTATUS ret = NT_STATUS_OK; /* Paranioa checks for auth_len. */ - if (prhdr->auth_length) { - if (prhdr->auth_length > prhdr->frag_length) { + if (pkt->auth_length) { + if (pkt->auth_length > pkt->frag_length) { return NT_STATUS_INVALID_PARAMETER; } - if (prhdr->auth_length + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_length || - prhdr->auth_length + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) { + if ((pkt->auth_length + + (unsigned int)DCERPC_AUTH_TRAILER_LENGTH + < pkt->auth_length) || + (pkt->auth_length + + (unsigned int)DCERPC_AUTH_TRAILER_LENGTH + < (unsigned int)DCERPC_AUTH_TRAILER_LENGTH)) { /* Integer wrap attempt. */ return NT_STATUS_INVALID_PARAMETER; } @@ -1093,40 +1060,42 @@ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, */ switch(cli->auth->auth_type) { - case PIPE_AUTH_TYPE_NONE: - if (prhdr->auth_length) { - DEBUG(3, ("cli_pipe_validate_rpc_response: " - "Connection to %s - got non-zero " - "auth len %u.\n", - rpccli_pipe_txt(talloc_tos(), cli), - (unsigned int)prhdr->auth_length)); - return NT_STATUS_INVALID_PARAMETER; - } - break; + case PIPE_AUTH_TYPE_NONE: + if (pkt->auth_length) { + DEBUG(3, ("cli_pipe_validate_rpc_response: " + "Connection to %s - got non-zero " + "auth len %u.\n", + rpccli_pipe_txt(talloc_tos(), cli), + (unsigned int)pkt->auth_length)); + return NT_STATUS_INVALID_PARAMETER; + } + break; - case PIPE_AUTH_TYPE_NTLMSSP: - case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: - ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len); - if (!NT_STATUS_IS_OK(ret)) { - return ret; - } - break; + case PIPE_AUTH_TYPE_NTLMSSP: + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + ret = cli_pipe_verify_ntlmssp(cli, pkt, current_pdu, + p_ss_padding_len); + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } + break; - case PIPE_AUTH_TYPE_SCHANNEL: - ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len); - if (!NT_STATUS_IS_OK(ret)) { - return ret; - } - break; + case PIPE_AUTH_TYPE_SCHANNEL: + ret = cli_pipe_verify_schannel(cli, pkt, current_pdu, + p_ss_padding_len); + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } + break; - case PIPE_AUTH_TYPE_KRB5: - case PIPE_AUTH_TYPE_SPNEGO_KRB5: - default: - DEBUG(3, ("cli_pipe_validate_rpc_response: Connection " - "to %s - unknown internal auth type %u.\n", - rpccli_pipe_txt(talloc_tos(), cli), - cli->auth->auth_type )); - return NT_STATUS_INVALID_INFO_CLASS; + case PIPE_AUTH_TYPE_KRB5: + case PIPE_AUTH_TYPE_SPNEGO_KRB5: + default: + DEBUG(3, ("cli_pipe_validate_rpc_response: Connection " + "to %s - unknown internal auth type %u.\n", + rpccli_pipe_txt(talloc_tos(), cli), + cli->auth->auth_type )); + return NT_STATUS_INVALID_INFO_CLASS; } return NT_STATUS_OK; @@ -1144,7 +1113,6 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, uint32 *pdata_len, prs_struct *return_data) { - struct ncacn_packet_header prhdr; NTSTATUS ret = NT_STATUS_OK; uint32 current_pdu_len = prs_data_size(current_pdu); DATA_BLOB blob = data_blob_const(prs_data_p(current_pdu), @@ -1166,12 +1134,6 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, return NT_STATUS_BUFFER_TOO_SMALL; } - /* FIXME: until all functions are converted to take in - * a fully decoded packet - */ - memcpy(&prhdr, pkt, sizeof(prhdr)); - - if (current_pdu_len != pkt->frag_length) { DEBUG(5, ("Incorrect pdu length %u, expected %u\n", (unsigned int)current_pdu_len, @@ -1204,7 +1166,7 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, } /* Here's where we deal with incoming sign/seal. */ - ret = cli_pipe_validate_rpc_response(cli, &prhdr, + ret = cli_pipe_validate_rpc_response(cli, pkt, current_pdu, &ss_padding_len); if (!NT_STATUS_IS_OK(ret)) { return ret; -- cgit From cb3725a9310d88a8d5226025292e25d178d7a4db Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Jul 2010 02:04:04 -0400 Subject: dcerpc: remove ncacn_packet_header and related functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ncacn_packet_header was an artifact and it is not necessary anymore Signed-off-by: Günther Deschner --- source3/include/proto.h | 10 -------- source3/rpc_client/cli_pipe.c | 58 ------------------------------------------- 2 files changed, 68 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 08c7020853..04136a9a0d 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4859,19 +4859,9 @@ NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx, uint32_t call_id, union dcerpc_payload *u, DATA_BLOB *blob); -NTSTATUS dcerpc_push_ncacn_packet_header(TALLOC_CTX *mem_ctx, - enum dcerpc_pkt_type ptype, - uint8_t pfc_flags, - uint16_t frag_length, - uint16_t auth_length, - uint32_t call_id, - DATA_BLOB *blob); NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct ncacn_packet *r); -NTSTATUS dcerpc_pull_ncacn_packet_header(TALLOC_CTX *mem_ctx, - const DATA_BLOB *blob, - struct ncacn_packet_header *r); NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx, enum dcerpc_AuthType auth_type, enum dcerpc_AuthLevel auth_level, diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 364b1e8898..81bc0b308e 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -338,42 +338,6 @@ NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -NTSTATUS dcerpc_push_ncacn_packet_header(TALLOC_CTX *mem_ctx, - enum dcerpc_pkt_type ptype, - uint8_t pfc_flags, - uint16_t frag_length, - uint16_t auth_length, - uint32_t call_id, - DATA_BLOB *blob) -{ - struct ncacn_packet_header r; - enum ndr_err_code ndr_err; - - r.rpc_vers = 5; - r.rpc_vers_minor = 0; - r.ptype = ptype; - r.pfc_flags = pfc_flags; - r.drep[0] = DCERPC_DREP_LE; - r.drep[1] = 0; - r.drep[2] = 0; - r.drep[3] = 0; - r.frag_length = frag_length; - r.auth_length = auth_length; - r.call_id = call_id; - - ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r, - (ndr_push_flags_fn_t)ndr_push_ncacn_packet_header); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_DEBUG(ncacn_packet_header, &r); - } - - return NT_STATUS_OK; -} - /******************************************************************* *******************************************************************/ @@ -396,28 +360,6 @@ NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -/******************************************************************* -*******************************************************************/ - -NTSTATUS dcerpc_pull_ncacn_packet_header(TALLOC_CTX *mem_ctx, - const DATA_BLOB *blob, - struct ncacn_packet_header *r) -{ - enum ndr_err_code ndr_err; - - ndr_err = ndr_pull_struct_blob(blob, mem_ctx, r, - (ndr_pull_flags_fn_t)ndr_pull_ncacn_packet_header); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_DEBUG(ncacn_packet_header, r); - } - - return NT_STATUS_OK; -} - /******************************************************************* ********************************************************************/ -- cgit From ca3bdca52e93ec492f06f18d8428e80bbad375be Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Jul 2010 11:09:04 -0400 Subject: s3-dcerpc: Padding is never done on a DCERPC_PKT_BIND_ACK packet. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Empirically verified against Windows. It never pads the auth credentials on this packet type. Signed-off-by: Günther Deschner --- source3/rpc_server/srv_pipe.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 6b85141367..12ec27bd04 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -1146,7 +1146,6 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) struct dcerpc_ack_ctx bind_ack_ctx; DATA_BLOB auth_resp = data_blob_null; DATA_BLOB auth_blob = data_blob_null; - int pad_len = 0; /* No rebinds on a bound pipe - use alter context. */ if (p->pipe_bound) { @@ -1367,18 +1366,10 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) if (auth_resp.length) { - /* Work out any padding needed before the auth footer. */ - pad_len = p->out_data.frag.length % SERVER_NDR_PADDING_SIZE; - if (pad_len) { - pad_len = SERVER_NDR_PADDING_SIZE - pad_len; - DEBUG(10, ("auth pad_len = %u\n", - (unsigned int)pad_len)); - } - status = dcerpc_push_dcerpc_auth(pkt, auth_type, auth_info.auth_level, - pad_len, + 0, 1, /* auth_context_id */ &auth_resp, &auth_blob); @@ -1391,22 +1382,9 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) /* Now that we have the auth len store it into the right place in * the dcerpc header */ dcerpc_set_frag_length(&p->out_data.frag, - p->out_data.frag.length + - pad_len + - auth_blob.length); + p->out_data.frag.length + auth_blob.length); if (auth_blob.length) { - if (pad_len) { - char pad[SERVER_NDR_PADDING_SIZE]; - memset(pad, '\0', SERVER_NDR_PADDING_SIZE); - if (!data_blob_append(p->mem_ctx, &p->out_data.frag, - pad, pad_len)) { - DEBUG(0, ("api_pipe_bind_req: failed to add " - "%u bytes of pad data.\n", - (unsigned int)pad_len)); - goto err_exit; - } - } if (!data_blob_append(p->mem_ctx, &p->out_data.frag, auth_blob.data, auth_blob.length)) { -- cgit From bd19c964d54571b1cdb8e4f1ea47a24e790e6e3c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Jul 2010 12:18:49 -0400 Subject: s3-dcerpc: Move common helpers into a common file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/Makefile.in | 1 + source3/include/proto.h | 20 ---- source3/librpc/rpc/dcerpc.h | 27 +++++ source3/librpc/rpc/dcerpc_helpers.c | 212 ++++++++++++++++++++++++++++++++++++ source3/rpc_client/cli_pipe.c | 146 +------------------------ 5 files changed, 241 insertions(+), 165 deletions(-) create mode 100644 source3/librpc/rpc/dcerpc_helpers.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index a4b71f0765..99674268ed 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -564,6 +564,7 @@ LIBMSRPC_GEN_OBJ = librpc/gen_ndr/cli_lsa.o \ librpc/gen_ndr/cli_drsuapi.o \ librpc/gen_ndr/cli_spoolss.o \ ../librpc/rpc/dcerpc_util.o \ + librpc/rpc/dcerpc_helpers.o \ $(LIBNDR_GEN_OBJ) \ $(RPCCLIENT_NDR_OBJ) diff --git a/source3/include/proto.h b/source3/include/proto.h index 04136a9a0d..735f5e2bf8 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4852,26 +4852,6 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, prs_struct *req_data); NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, prs_struct *reply_pdu); -NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx, - enum dcerpc_pkt_type ptype, - uint8_t pfc_flags, - uint16_t auth_length, - uint32_t call_id, - union dcerpc_payload *u, - DATA_BLOB *blob); -NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx, - const DATA_BLOB *blob, - struct ncacn_packet *r); -NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx, - enum dcerpc_AuthType auth_type, - enum dcerpc_AuthLevel auth_level, - uint8_t auth_pad_length, - uint32_t auth_context_id, - const DATA_BLOB *credentials, - DATA_BLOB *blob); -NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx, - const DATA_BLOB *blob, - struct dcerpc_auth *r); struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct rpc_pipe_client *cli, diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h index 0c120dfef5..d18920ca0d 100644 --- a/source3/librpc/rpc/dcerpc.h +++ b/source3/librpc/rpc/dcerpc.h @@ -111,4 +111,31 @@ _PUBLIC_ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, const struct dcerpc_binding *binding, struct epm_tower *tower); +struct NL_AUTH_MESSAGE; + +/* The following definitions come from librpc/rpc/dcerpc_helpers.c */ +NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx, + enum dcerpc_pkt_type ptype, + uint8_t pfc_flags, + uint16_t auth_length, + uint32_t call_id, + union dcerpc_payload *u, + DATA_BLOB *blob); +NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx, + const DATA_BLOB *blob, + struct ncacn_packet *r); +NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx, + struct NL_AUTH_MESSAGE *r, + DATA_BLOB *blob); +NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, + uint8_t auth_pad_length, + uint32_t auth_context_id, + const DATA_BLOB *credentials, + DATA_BLOB *blob); +NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx, + const DATA_BLOB *blob, + struct dcerpc_auth *r); + #endif /* __DCERPC_H__ */ diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c new file mode 100644 index 0000000000..ce48a691ac --- /dev/null +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -0,0 +1,212 @@ +/* + * DCERPC Helper routines + * Günther Deschner 2010. + * Simo Sorce 2010. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + + +#include "includes.h" +#include "librpc/rpc/dcerpc.h" +#include "librpc/gen_ndr/ndr_dcerpc.h" +#include "librpc/gen_ndr/ndr_schannel.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_PARSE + +/** +* @brief NDR Encodes a ncacn_packet +* +* @param mem_ctx The memory context the blob will be allocated on +* @param ptype The DCERPC packet type +* @param pfc_flags The DCERPC PFC Falgs +* @param auth_length The length of the trailing auth blob +* @param call_id The call ID +* @param u The payload of the packet +* @param blob [out] The encoded blob if successful +* +* @return an NTSTATUS error code +*/ +NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx, + enum dcerpc_pkt_type ptype, + uint8_t pfc_flags, + uint16_t auth_length, + uint32_t call_id, + union dcerpc_payload *u, + DATA_BLOB *blob) +{ + struct ncacn_packet r; + enum ndr_err_code ndr_err; + + r.rpc_vers = 5; + r.rpc_vers_minor = 0; + r.ptype = ptype; + r.pfc_flags = pfc_flags; + r.drep[0] = DCERPC_DREP_LE; + r.drep[1] = 0; + r.drep[2] = 0; + r.drep[3] = 0; + r.auth_length = auth_length; + r.call_id = call_id; + r.u = *u; + + ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r, + (ndr_push_flags_fn_t)ndr_push_ncacn_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return ndr_map_error2ntstatus(ndr_err); + } + + dcerpc_set_frag_length(blob, blob->length); + + + if (DEBUGLEVEL >= 10) { + /* set frag len for print function */ + r.frag_length = blob->length; + NDR_PRINT_DEBUG(ncacn_packet, &r); + } + + return NT_STATUS_OK; +} + +/** +* @brief Decodes a ncacn_packet +* +* @param mem_ctx The memory context on which to allocate the packet +* elements +* @param blob The blob of data to decode +* @param r An empty ncacn_packet, must not be NULL +* +* @return a NTSTATUS error code +*/ +NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx, + const DATA_BLOB *blob, + struct ncacn_packet *r) +{ + enum ndr_err_code ndr_err; + + ndr_err = ndr_pull_struct_blob(blob, mem_ctx, r, + (ndr_pull_flags_fn_t)ndr_pull_ncacn_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return ndr_map_error2ntstatus(ndr_err); + } + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(ncacn_packet, r); + } + + return NT_STATUS_OK; +} + +/** +* @brief NDR Encodes a NL_AUTH_MESSAGE +* +* @param mem_ctx The memory context the blob will be allocated on +* @param r The NL_AUTH_MESSAGE to encode +* @param blob [out] The encoded blob if successful +* +* @return a NTSTATUS error code +*/ +NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx, + struct NL_AUTH_MESSAGE *r, + DATA_BLOB *blob) +{ + enum ndr_err_code ndr_err; + + ndr_err = ndr_push_struct_blob(blob, mem_ctx, r, + (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return ndr_map_error2ntstatus(ndr_err); + } + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, r); + } + + return NT_STATUS_OK; +} + +/** +* @brief NDR Encodes a dcerpc_auth structure +* +* @param mem_ctx The memory context the blob will be allocated on +* @param auth_type The DCERPC Authentication Type +* @param auth_level The DCERPC Authentication Level +* @param auth_pad_length The padding added to the packet this blob will be +* appended to. +* @param auth_context_id The context id +* @param credentials The authentication credentials blob (signature) +* @param blob [out] The encoded blob if successful +* +* @return a NTSTATUS error code +*/ +NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, + uint8_t auth_pad_length, + uint32_t auth_context_id, + const DATA_BLOB *credentials, + DATA_BLOB *blob) +{ + struct dcerpc_auth r; + enum ndr_err_code ndr_err; + + r.auth_type = auth_type; + r.auth_level = auth_level; + r.auth_pad_length = auth_pad_length; + r.auth_reserved = 0; + r.auth_context_id = auth_context_id; + r.credentials = *credentials; + + ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r, + (ndr_push_flags_fn_t)ndr_push_dcerpc_auth); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return ndr_map_error2ntstatus(ndr_err); + } + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(dcerpc_auth, &r); + } + + return NT_STATUS_OK; +} + +/** +* @brief Decodes a dcerpc_auth blob +* +* @param mem_ctx The memory context on which to allocate the packet +* elements +* @param blob The blob of data to decode +* @param r An empty dcerpc_auth structure, must not be NULL +* +* @return a NTSTATUS error code +*/ +NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx, + const DATA_BLOB *blob, + struct dcerpc_auth *r) +{ + enum ndr_err_code ndr_err; + + ndr_err = ndr_pull_struct_blob(blob, mem_ctx, r, + (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return ndr_map_error2ntstatus(ndr_err); + } + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(dcerpc_auth, r); + } + + return NT_STATUS_OK; +} diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 81bc0b308e..0f1d4a85db 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -42,6 +42,7 @@ #include "../libcli/auth/ntlmssp.h" #include "rpc_client/cli_netlogon.h" #include "librpc/gen_ndr/ndr_dcerpc.h" +#include "librpc/rpc/dcerpc.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_CLI @@ -294,116 +295,6 @@ static bool rpc_grow_buffer(prs_struct *pdu, size_t size) return true; } -/******************************************************************* -*******************************************************************/ - -NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx, - enum dcerpc_pkt_type ptype, - uint8_t pfc_flags, - uint16_t auth_length, - uint32_t call_id, - union dcerpc_payload *u, - DATA_BLOB *blob) -{ - struct ncacn_packet r; - enum ndr_err_code ndr_err; - - r.rpc_vers = 5; - r.rpc_vers_minor = 0; - r.ptype = ptype; - r.pfc_flags = pfc_flags; - r.drep[0] = DCERPC_DREP_LE; - r.drep[1] = 0; - r.drep[2] = 0; - r.drep[3] = 0; - r.auth_length = auth_length; - r.call_id = call_id; - r.u = *u; - - ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r, - (ndr_push_flags_fn_t)ndr_push_ncacn_packet); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - dcerpc_set_frag_length(blob, blob->length); - - - if (DEBUGLEVEL >= 10) { - /* set frag len for print function */ - r.frag_length = blob->length; - NDR_PRINT_DEBUG(ncacn_packet, &r); - } - - return NT_STATUS_OK; -} - -/******************************************************************* -*******************************************************************/ - -NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx, - const DATA_BLOB *blob, - struct ncacn_packet *r) -{ - enum ndr_err_code ndr_err; - - ndr_err = ndr_pull_struct_blob(blob, mem_ctx, r, - (ndr_pull_flags_fn_t)ndr_pull_ncacn_packet); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_DEBUG(ncacn_packet, r); - } - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx, - struct NL_AUTH_MESSAGE *r, - DATA_BLOB *blob) -{ - enum ndr_err_code ndr_err; - - ndr_err = ndr_push_struct_blob(blob, mem_ctx, r, - (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, r); - } - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx, - const DATA_BLOB *blob, - struct dcerpc_auth *r) -{ - enum ndr_err_code ndr_err; - - ndr_err = ndr_pull_struct_blob(blob, mem_ctx, r, - (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_DEBUG(dcerpc_auth, r); - } - - return NT_STATUS_OK; -} - /******************************************************************* Use SMBreadX to get rest of one fragment's worth of rpc data. Reads the whole size or give an error message @@ -1680,41 +1571,6 @@ static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -/******************************************************************* - Creates an auth_data blob. - ********************************************************************/ - -NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx, - enum dcerpc_AuthType auth_type, - enum dcerpc_AuthLevel auth_level, - uint8_t auth_pad_length, - uint32_t auth_context_id, - const DATA_BLOB *credentials, - DATA_BLOB *blob) -{ - struct dcerpc_auth r; - enum ndr_err_code ndr_err; - - r.auth_type = auth_type; - r.auth_level = auth_level; - r.auth_pad_length = auth_pad_length; - r.auth_reserved = 0; - r.auth_context_id = auth_context_id; - r.credentials = *credentials; - - ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r, - (ndr_push_flags_fn_t)ndr_push_dcerpc_auth); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_DEBUG(dcerpc_auth, &r); - } - - return NT_STATUS_OK; -} - /******************************************************************* Creates krb5 auth bind. ********************************************************************/ -- cgit From 84c50a248e3a7c02d6cbcbb5ce49a6580700d39a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Jul 2010 14:01:44 -0400 Subject: Reformat and cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_client/cli_pipe.c | 150 +++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 75 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 0f1d4a85db..5093a54729 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -950,6 +950,7 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, uint32 current_pdu_len = prs_data_size(current_pdu); DATA_BLOB blob = data_blob_const(prs_data_p(current_pdu), prs_data_size(current_pdu)); + uint8 ss_padding_len = 0; ret = dcerpc_pull_ncacn_packet(cli, &blob, pkt); if (!NT_STATUS_IS_OK(ret)) { @@ -983,97 +984,96 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, /* Ensure we have the correct type. */ switch (pkt->ptype) { - case DCERPC_PKT_ALTER_RESP: - case DCERPC_PKT_BIND_ACK: + case DCERPC_PKT_ALTER_RESP: + case DCERPC_PKT_BIND_ACK: - /* Alter context and bind ack share the same packet definitions. */ - break; + /* Alter context and bind ack share the same packet definitions. */ + break; - case DCERPC_PKT_RESPONSE: - { - uint8 ss_padding_len = 0; + case DCERPC_PKT_RESPONSE: - if (!prs_set_offset(current_pdu, prs_offset(current_pdu) + RPC_HDR_RESP_LEN)) { - return NT_STATUS_BUFFER_TOO_SMALL; - } + if (!prs_set_offset(current_pdu, + prs_offset(current_pdu) + RPC_HDR_RESP_LEN)) { + return NT_STATUS_BUFFER_TOO_SMALL; + } - /* Here's where we deal with incoming sign/seal. */ - ret = cli_pipe_validate_rpc_response(cli, pkt, - current_pdu, &ss_padding_len); - if (!NT_STATUS_IS_OK(ret)) { - return ret; - } + /* Here's where we deal with incoming sign/seal. */ + ret = cli_pipe_validate_rpc_response(cli, pkt, + current_pdu, &ss_padding_len); + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } - /* Point the return values at the NDR data. Remember to remove any ss padding. */ - *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN; + /* Point the return values at the NDR data. + * Remember to remove any ss padding. */ + *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN; - if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) { + if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len; + + /* Remember to remove the auth footer. */ + if (pkt->auth_length) { + /* We've already done integer wrap tests on auth_len in + cli_pipe_validate_rpc_response(). */ + if (*pdata_len < RPC_HDR_AUTH_LEN + pkt->auth_length) { return NT_STATUS_BUFFER_TOO_SMALL; } + *pdata_len -= (RPC_HDR_AUTH_LEN + pkt->auth_length); + } - *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len; + DEBUG(10, ("Got pdu len %u, data_len %u, ss_len %u\n", + current_pdu_len, *pdata_len, ss_padding_len)); - /* Remember to remove the auth footer. */ - if (pkt->auth_length) { - /* We've already done integer wrap tests on auth_len in - cli_pipe_validate_rpc_response(). */ - if (*pdata_len < RPC_HDR_AUTH_LEN + pkt->auth_length) { - return NT_STATUS_BUFFER_TOO_SMALL; - } - *pdata_len -= (RPC_HDR_AUTH_LEN + pkt->auth_length); - } + /* + * If this is the first reply, and the allocation hint is + * reasonable, try and set up the return_data parse_struct to + * the correct size. + */ - DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n", - current_pdu_len, *pdata_len, ss_padding_len )); - - /* - * If this is the first reply, and the allocation hint is reasonably, try and - * set up the return_data parse_struct to the correct size. - */ - - if ((prs_data_size(return_data) == 0) && - pkt->u.response.alloc_hint && - (pkt->u.response.alloc_hint < 15*1024*1024)) { - if (!prs_set_buffer_size(return_data, - pkt->u.response.alloc_hint)) { - DEBUG(0, ("reply alloc hint %d too " - "large to allocate\n", - (int)pkt->u.response.alloc_hint)); - return NT_STATUS_NO_MEMORY; - } + if ((prs_data_size(return_data) == 0) && + pkt->u.response.alloc_hint && + (pkt->u.response.alloc_hint < 15*1024*1024)) { + if (!prs_set_buffer_size(return_data, + pkt->u.response.alloc_hint)) { + DEBUG(0, ("reply alloc hint %d too " + "large to allocate\n", + (int)pkt->u.response.alloc_hint)); + return NT_STATUS_NO_MEMORY; } - - break; } - case DCERPC_PKT_BIND_NAK: - DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK " - "received from %s!\n", - rpccli_pipe_txt(talloc_tos(), cli))); - /* Use this for now... */ - return NT_STATUS_NETWORK_ACCESS_DENIED; - - case DCERPC_PKT_FAULT: - - DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault " - "code %s received from %s!\n", - dcerpc_errstr(talloc_tos(), - pkt->u.fault.status), - rpccli_pipe_txt(talloc_tos(), cli))); - - if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) { - return NT_STATUS_UNSUCCESSFUL; - } else { - return NT_STATUS(pkt->u.fault.status); - } + break; - default: - DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received " - "from %s!\n", - (unsigned int)pkt->ptype, - rpccli_pipe_txt(talloc_tos(), cli))); - return NT_STATUS_INVALID_INFO_CLASS; + case DCERPC_PKT_BIND_NAK: + DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK " + "received from %s!\n", + rpccli_pipe_txt(talloc_tos(), cli))); + /* Use this for now... */ + return NT_STATUS_NETWORK_ACCESS_DENIED; + + case DCERPC_PKT_FAULT: + + DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault " + "code %s received from %s!\n", + dcerpc_errstr(talloc_tos(), + pkt->u.fault.status), + rpccli_pipe_txt(talloc_tos(), cli))); + + if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) { + return NT_STATUS_UNSUCCESSFUL; + } else { + return NT_STATUS(pkt->u.fault.status); + } + + default: + DEBUG(0, ("Unknown packet type %u received from %s!\n", + (unsigned int)pkt->ptype, + rpccli_pipe_txt(talloc_tos(), cli))); + return NT_STATUS_INVALID_INFO_CLASS; } if (pkt->ptype != expected_pkt_type) { -- cgit From 79c207ed62ef661add5d48ea898b7a415a9c17d9 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Jul 2010 13:56:13 -0400 Subject: s3-dceprc: Use IDL defined constants for length calculations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/include/rpc_dce.h | 9 ------ source3/rpc_client/cli_pipe.c | 71 +++++++++++++++++++++++-------------------- source3/rpc_server/srv_pipe.c | 18 +++++------ 3 files changed, 47 insertions(+), 51 deletions(-) (limited to 'source3') diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index 32ab19c157..4a4068be6f 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -31,15 +31,6 @@ /* #define MAX_PDU_FRAG_LEN 0x1630 this is what wnt sets */ #define RPC_MAX_PDU_FRAG_LEN 0x10b8 /* this is what w2k sets */ -#define RPC_IFACE_LEN (UUID_SIZE + 4) - #define RPC_HEADER_LEN 16 -#define RPC_HDR_REQ_LEN 8 - -#define RPC_HDR_RESP_LEN 8 - - -#define RPC_HDR_AUTH_LEN 8 - #endif /* _DCE_RPC_H */ diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 5093a54729..60dd22d3a0 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -993,11 +993,6 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, case DCERPC_PKT_RESPONSE: - if (!prs_set_offset(current_pdu, - prs_offset(current_pdu) + RPC_HDR_RESP_LEN)) { - return NT_STATUS_BUFFER_TOO_SMALL; - } - /* Here's where we deal with incoming sign/seal. */ ret = cli_pipe_validate_rpc_response(cli, pkt, current_pdu, &ss_padding_len); @@ -1007,22 +1002,24 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, /* Point the return values at the NDR data. * Remember to remove any ss padding. */ - *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN; + *ppdata = prs_data_p(current_pdu) + DCERPC_RESPONSE_LENGTH; - if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) { + if (current_pdu_len < DCERPC_RESPONSE_LENGTH + ss_padding_len) { return NT_STATUS_BUFFER_TOO_SMALL; } - *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len; + *pdata_len = current_pdu_len - DCERPC_RESPONSE_LENGTH - ss_padding_len; /* Remember to remove the auth footer. */ if (pkt->auth_length) { /* We've already done integer wrap tests on auth_len in cli_pipe_validate_rpc_response(). */ - if (*pdata_len < RPC_HDR_AUTH_LEN + pkt->auth_length) { + if (*pdata_len < DCERPC_AUTH_TRAILER_LENGTH + + pkt->auth_length) { return NT_STATUS_BUFFER_TOO_SMALL; } - *pdata_len -= (RPC_HDR_AUTH_LEN + pkt->auth_length); + *pdata_len -= (DCERPC_AUTH_TRAILER_LENGTH + + pkt->auth_length); } DEBUG(10, ("Got pdu len %u, data_len %u, ss_len %u\n", @@ -1816,6 +1813,10 @@ static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type ptype, return status; } + if (auth_len) { + auth_len -= DCERPC_AUTH_TRAILER_LENGTH; + } + u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN; u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN; u.bind.assoc_group_id = 0x0; @@ -1827,7 +1828,7 @@ static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type ptype, ptype, DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST, - auth_len ? auth_len - RPC_HDR_AUTH_LEN : 0, + auth_len, rpc_call_id, &u, &blob); @@ -1915,8 +1916,8 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli, DATA_BLOB auth_info; NTSTATUS status; DATA_BLOB auth_blob = data_blob_null; - uint16_t data_and_pad_len = - prs_offset(rpc_out) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; + uint16_t data_and_pad_len = prs_offset(rpc_out) + - DCERPC_RESPONSE_LENGTH; if (!cli->auth->a_u.ntlmssp_state) { return NT_STATUS_INVALID_PARAMETER; @@ -1951,8 +1952,7 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli, status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state, prs_get_mem_context(rpc_out), (unsigned char *)prs_data_p(rpc_out) - + RPC_HEADER_LEN - + RPC_HDR_RESP_LEN, + + DCERPC_RESPONSE_LENGTH, data_and_pad_len, (unsigned char *)prs_data_p(rpc_out), (size_t)prs_offset(rpc_out), @@ -1967,8 +1967,7 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli, status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state, prs_get_mem_context(rpc_out), (unsigned char *)prs_data_p(rpc_out) - + RPC_HEADER_LEN - + RPC_HDR_RESP_LEN, + + DCERPC_RESPONSE_LENGTH, data_and_pad_len, (unsigned char *)prs_data_p(rpc_out), (size_t)prs_offset(rpc_out), @@ -2007,8 +2006,9 @@ static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli, { DATA_BLOB auth_info; struct schannel_state *sas = cli->auth->a_u.schannel_auth; - char *data_p = prs_data_p(rpc_out) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN; - size_t data_and_pad_len = prs_offset(rpc_out) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; + char *data_p = prs_data_p(rpc_out) + DCERPC_RESPONSE_LENGTH; + size_t data_and_pad_len = prs_offset(rpc_out) + - DCERPC_RESPONSE_LENGTH; DATA_BLOB blob; NTSTATUS status; @@ -2092,11 +2092,11 @@ static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli, switch (cli->auth->auth_level) { case DCERPC_AUTH_LEVEL_NONE: case DCERPC_AUTH_LEVEL_CONNECT: - data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN; + data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH; data_len = MIN(data_space, data_left); *p_ss_padding = 0; *p_auth_len = 0; - *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len; + *p_frag_len = DCERPC_REQUEST_LENGTH + data_len; return data_len; case DCERPC_AUTH_LEVEL_INTEGRITY: @@ -2115,17 +2115,20 @@ static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli, break; } - data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - - RPC_HDR_AUTH_LEN - *p_auth_len; + data_space = cli->max_xmit_frag + - DCERPC_REQUEST_LENGTH + - DCERPC_AUTH_TRAILER_LENGTH + - *p_auth_len; data_len = MIN(data_space, data_left); *p_ss_padding = 0; if (data_len % CLIENT_NDR_PADDING_SIZE) { *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE); } - *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */ - data_len + *p_ss_padding + /* data plus padding. */ - RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */ + *p_frag_len = DCERPC_REQUEST_LENGTH + + data_len + *p_ss_padding + + DCERPC_AUTH_TRAILER_LENGTH + + *p_auth_len; return data_len; default: @@ -2181,8 +2184,8 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, state->req_data_sent = 0; state->call_id = get_rpc_call_id(); - if (cli->max_xmit_frag - < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) { + if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH + + RPC_MAX_SIGN_SIZE) { /* Server is screwed up ! */ status = NT_STATUS_INVALID_PARAMETER; goto post_status; @@ -2743,7 +2746,8 @@ static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req, NTSTATUS status; if ((r->auth_length == 0) - || (r->frag_length < r->auth_length + RPC_HDR_AUTH_LEN)) { + || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH + + r->auth_length)) { return NT_STATUS_INVALID_PARAMETER; } @@ -2818,14 +2822,15 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req, NTSTATUS status; if ((r->auth_length == 0) - || (r->frag_length < r->auth_length + RPC_HDR_AUTH_LEN)) { + || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH + + r->auth_length)) { return NT_STATUS_INVALID_PARAMETER; } /* Process the returned NTLMSSP blob first. */ - if (!prs_set_offset( - rpc_in, - r->frag_length - r->auth_length - RPC_HDR_AUTH_LEN)) { + if (!prs_set_offset(rpc_in, r->frag_length + - DCERPC_AUTH_TRAILER_LENGTH + - r->auth_length)) { return NT_STATUS_INVALID_PARAMETER; } diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 12ec27bd04..29b6d8e261 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -498,22 +498,22 @@ static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) bool api_pipe_bind_auth3(pipes_struct *p, struct ncacn_packet *pkt) { struct dcerpc_auth auth_info; - uint32_t auth_len = pkt->auth_length; NTSTATUS status; - DEBUG(5,("api_pipe_bind_auth3: decode request. %d\n", __LINE__)); + DEBUG(5, ("api_pipe_bind_auth3: decode request. %d\n", __LINE__)); - if (auth_len == 0) { - DEBUG(0,("api_pipe_bind_auth3: No auth field sent !\n")); + if (pkt->auth_length == 0) { + DEBUG(0, ("No auth field sent for bind request!\n")); goto err; } /* Ensure there's enough data for an authenticated request. */ - if (RPC_HEADER_LEN + RPC_HDR_AUTH_LEN + auth_len > - pkt->frag_length) { + if (pkt->frag_length < RPC_HEADER_LEN + + DCERPC_AUTH_TRAILER_LENGTH + + pkt->auth_length) { DEBUG(0,("api_pipe_ntlmssp_auth_process: auth_len " "%u is too large.\n", - (unsigned int)auth_len )); + (unsigned int)pkt->auth_length)); goto err; } @@ -1244,7 +1244,7 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt) * prevents overrun. */ if (pkt->frag_length < RPC_HEADER_LEN + - RPC_HDR_AUTH_LEN + + DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length) { DEBUG(0,("api_pipe_bind_req: auth_len (%u) " "too long for fragment %u.\n", @@ -1468,7 +1468,7 @@ bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt) * prevents overrun. */ if (pkt->frag_length < RPC_HEADER_LEN + - RPC_HDR_AUTH_LEN + + DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length) { DEBUG(0,("api_pipe_alter_context: auth_len (%u) " "too long for fragment %u.\n", -- cgit From cc15396c8a70270d4c85055111e58d71f5c96dd6 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Jul 2010 16:15:13 -0400 Subject: s3-dcerpc: Read a pdu in 2 steps, header first the payload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can't really cope with receiving more data than expected anyway as there is code that checks if the size of the buffer is consistent with pkt->frag_length and throws an error if not. Signed-off-by: Günther Deschner --- source3/rpc_client/cli_pipe.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 60dd22d3a0..005f19307e 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1125,21 +1125,13 @@ static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, /* * Oh no ! More data in buffer than we processed in current pdu. - * Cheat. Move the data down and shrink the buffer. + * This shouldn't happen, we only read exactly pkt->frag_length. + * Something is wrong here, throw an error. */ - memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + pkt->frag_length, - current_pdu_len - pkt->frag_length); - - /* Remember to set the read offset back to zero. */ - prs_set_offset(current_pdu, 0); - - /* Shrink the buffer. */ - if (!prs_set_buffer_size(current_pdu, current_pdu_len - pkt->frag_length)) { - return NT_STATUS_BUFFER_TOO_SMALL; - } - - return NT_STATUS_OK; + DEBUG(0, ("Data buffer size (%u) and pkt->frag_length (%u) differ\n!", + (unsigned)current_pdu_len, (unsigned)pkt->frag_length)); + return NT_STATUS_INVALID_BUFFER_SIZE; } /**************************************************************************** @@ -1378,11 +1370,9 @@ static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx, DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli))); - max_recv_frag = cli->max_recv_frag; - -#if 0 - max_recv_frag = RPC_HEADER_LEN + 10 + (sys_random() % 32); -#endif + /* get the header first, then fetch the rest once we have + * the frag_length available */ + max_recv_frag = RPC_HEADER_LEN; subreq = cli_api_pipe_send(state, ev, cli->transport, (uint8_t *)prs_data_p(data), -- cgit From b44a91b2206b514ff47b8841d607ffd2cc297c8b Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Jul 2010 18:29:32 -0400 Subject: s3-dcerpc: Use DATA_BLOB instead of prs_struct for incoming fragments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_client/cli_pipe.c | 253 ++++++++++++++---------------------------- 1 file changed, 84 insertions(+), 169 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 005f19307e..ce38f965c5 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -270,31 +270,6 @@ static uint32 get_rpc_call_id(void) return ++call_id; } -/* - * Realloc pdu to have a least "size" bytes - */ - -static bool rpc_grow_buffer(prs_struct *pdu, size_t size) -{ - size_t extra_size; - - if (prs_data_size(pdu) >= size) { - return true; - } - - extra_size = size - prs_data_size(pdu); - - if (!prs_force_grow(pdu, extra_size)) { - DEBUG(0, ("rpc_grow_buffer: Failed to grow parse struct by " - "%d bytes.\n", (int)extra_size)); - return false; - } - - DEBUG(5, ("rpc_grow_buffer: grew buffer by %d bytes to %u\n", - (int)extra_size, prs_data_size(pdu))); - return true; -} - /******************************************************************* Use SMBreadX to get rest of one fragment's worth of rpc data. Reads the whole size or give an error message @@ -469,7 +444,7 @@ struct get_complete_frag_state { struct event_context *ev; struct rpc_pipe_client *cli; uint16_t frag_len; - prs_struct *pdu; + DATA_BLOB *pdu; }; static void get_complete_frag_got_header(struct tevent_req *subreq); @@ -478,12 +453,11 @@ static void get_complete_frag_got_rest(struct tevent_req *subreq); static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct rpc_pipe_client *cli, - prs_struct *pdu) + DATA_BLOB *pdu) { struct tevent_req *req, *subreq; struct get_complete_frag_state *state; - DATA_BLOB blob; - uint32_t pdu_len; + size_t received; NTSTATUS status; req = tevent_req_create(mem_ctx, &state, @@ -496,17 +470,16 @@ static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx, state->frag_len = RPC_HEADER_LEN; state->pdu = pdu; - pdu_len = prs_data_size(pdu); - if (pdu_len < RPC_HEADER_LEN) { - if (!rpc_grow_buffer(pdu, RPC_HEADER_LEN)) { + received = pdu->length; + if (received < RPC_HEADER_LEN) { + if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) { status = NT_STATUS_NO_MEMORY; goto post_status; } - subreq = rpc_read_send( - state, state->ev, - state->cli->transport, - (uint8_t *)(prs_data_p(state->pdu) + pdu_len), - RPC_HEADER_LEN - pdu_len); + subreq = rpc_read_send(state, state->ev, + state->cli->transport, + pdu->data + received, + RPC_HEADER_LEN - received); if (subreq == NULL) { status = NT_STATUS_NO_MEMORY; goto post_status; @@ -516,21 +489,20 @@ static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx, return req; } - blob = data_blob_const(prs_data_p(state->pdu), pdu_len); - state->frag_len = dcerpc_get_frag_length(&blob); + state->frag_len = dcerpc_get_frag_length(pdu); /* * Ensure we have frag_len bytes of data. */ - if (pdu_len < state->frag_len) { - if (!rpc_grow_buffer(pdu, state->frag_len)) { + if (received < state->frag_len) { + if (!data_blob_realloc(NULL, pdu, state->frag_len)) { status = NT_STATUS_NO_MEMORY; goto post_status; } subreq = rpc_read_send(state, state->ev, - state->cli->transport, - (uint8_t *)(prs_data_p(pdu) + pdu_len), - state->frag_len - pdu_len); + state->cli->transport, + pdu->data + received, + state->frag_len - received); if (subreq == NULL) { status = NT_STATUS_NO_MEMORY; goto post_status; @@ -557,7 +529,6 @@ static void get_complete_frag_got_header(struct tevent_req *subreq) struct get_complete_frag_state *state = tevent_req_data( req, struct get_complete_frag_state); NTSTATUS status; - DATA_BLOB pdu; status = rpc_read_recv(subreq); TALLOC_FREE(subreq); @@ -566,11 +537,9 @@ static void get_complete_frag_got_header(struct tevent_req *subreq) return; } - pdu = data_blob_const(prs_data_p(state->pdu), - prs_data_size(state->pdu)); - state->frag_len = dcerpc_get_frag_length(&pdu); + state->frag_len = dcerpc_get_frag_length(state->pdu); - if (!rpc_grow_buffer(state->pdu, state->frag_len)) { + if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) { tevent_req_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -580,10 +549,9 @@ static void get_complete_frag_got_header(struct tevent_req *subreq) * RPC_HEADER_LEN bytes into state->pdu. */ - subreq = rpc_read_send( - state, state->ev, state->cli->transport, - (uint8_t *)(prs_data_p(state->pdu) + RPC_HEADER_LEN), - state->frag_len - RPC_HEADER_LEN); + subreq = rpc_read_send(state, state->ev, state->cli->transport, + state->pdu->data + RPC_HEADER_LEN, + state->frag_len - RPC_HEADER_LEN); if (tevent_req_nomem(subreq, req)) { return; } @@ -618,10 +586,9 @@ static NTSTATUS get_complete_frag_recv(struct tevent_req *req) static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, struct ncacn_packet *pkt, - prs_struct *current_pdu, + DATA_BLOB *pdu, uint8 *p_ss_padding_len) { - uint8_t *frag_data = (uint8_t *)prs_data_p(current_pdu); struct dcerpc_auth auth_info; DATA_BLOB blob; NTSTATUS status; @@ -646,7 +613,7 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, } /* get the auth blob at the end of the packet */ - blob = data_blob_const(frag_data + pkt->frag_length + blob = data_blob_const(pdu->data + pkt->frag_length - DCERPC_AUTH_TRAILER_LENGTH - pkt->auth_length, DCERPC_AUTH_TRAILER_LENGTH @@ -683,12 +650,12 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, /* Data is encrypted. */ status = ntlmssp_unseal_packet( cli->auth->a_u.ntlmssp_state, - &frag_data[DCERPC_RESPONSE_LENGTH], + pdu->data + DCERPC_RESPONSE_LENGTH, pkt->frag_length - DCERPC_RESPONSE_LENGTH - DCERPC_AUTH_TRAILER_LENGTH - pkt->auth_length, - frag_data, + pdu->data, pkt->frag_length - pkt->auth_length, &auth_info.credentials); if (!NT_STATUS_IS_OK(status)) { @@ -704,12 +671,12 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, /* Data is signed. */ status = ntlmssp_check_packet( cli->auth->a_u.ntlmssp_state, - &frag_data[DCERPC_RESPONSE_LENGTH], + pdu->data + DCERPC_RESPONSE_LENGTH, pkt->frag_length - DCERPC_RESPONSE_LENGTH - DCERPC_AUTH_TRAILER_LENGTH - pkt->auth_length, - frag_data, + pdu->data, pkt->frag_length - pkt->auth_length, &auth_info.credentials); if (!NT_STATUS_IS_OK(status)) { @@ -743,10 +710,9 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, struct ncacn_packet *pkt, - prs_struct *current_pdu, + DATA_BLOB *pdu, uint8 *p_ss_padding_len) { - uint8_t *frag_data = (uint8_t *)prs_data_p(current_pdu); struct dcerpc_auth auth_info; DATA_BLOB blob; NTSTATUS status; @@ -776,7 +742,7 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, } /* get the auth blob at the end of the packet */ - blob = data_blob_const(frag_data + pkt->frag_length + blob = data_blob_const(pdu->data + pkt->frag_length - DCERPC_AUTH_TRAILER_LENGTH - pkt->auth_length, DCERPC_AUTH_TRAILER_LENGTH @@ -818,7 +784,7 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, cli->auth->a_u.schannel_auth, talloc_tos(), true, - &frag_data[DCERPC_RESPONSE_LENGTH], + pdu->data + DCERPC_RESPONSE_LENGTH, pkt->frag_length - DCERPC_RESPONSE_LENGTH - DCERPC_AUTH_TRAILER_LENGTH @@ -830,7 +796,7 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, cli->auth->a_u.schannel_auth, talloc_tos(), false, - &frag_data[DCERPC_RESPONSE_LENGTH], + pdu->data + DCERPC_RESPONSE_LENGTH, pkt->frag_length - DCERPC_RESPONSE_LENGTH - DCERPC_AUTH_TRAILER_LENGTH @@ -865,9 +831,9 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, ****************************************************************************/ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, - struct ncacn_packet *pkt, - prs_struct *current_pdu, - uint8 *p_ss_padding_len) + struct ncacn_packet *pkt, + DATA_BLOB *pdu, + uint8 *p_ss_padding_len) { NTSTATUS ret = NT_STATUS_OK; @@ -906,16 +872,16 @@ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, case PIPE_AUTH_TYPE_NTLMSSP: case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: - ret = cli_pipe_verify_ntlmssp(cli, pkt, current_pdu, - p_ss_padding_len); + ret = cli_pipe_verify_ntlmssp(cli, pkt, pdu, + p_ss_padding_len); if (!NT_STATUS_IS_OK(ret)) { return ret; } break; case PIPE_AUTH_TYPE_SCHANNEL: - ret = cli_pipe_verify_schannel(cli, pkt, current_pdu, - p_ss_padding_len); + ret = cli_pipe_verify_schannel(cli, pkt, pdu, + p_ss_padding_len); if (!NT_STATUS_IS_OK(ret)) { return ret; } @@ -940,37 +906,22 @@ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, struct ncacn_packet *pkt, - prs_struct *current_pdu, + DATA_BLOB *pdu, uint8 expected_pkt_type, - char **ppdata, - uint32 *pdata_len, + DATA_BLOB *rdata, prs_struct *return_data) { NTSTATUS ret = NT_STATUS_OK; - uint32 current_pdu_len = prs_data_size(current_pdu); - DATA_BLOB blob = data_blob_const(prs_data_p(current_pdu), - prs_data_size(current_pdu)); uint8 ss_padding_len = 0; - ret = dcerpc_pull_ncacn_packet(cli, &blob, pkt); + ret = dcerpc_pull_ncacn_packet(cli, pdu, pkt); if (!NT_STATUS_IS_OK(ret)) { return ret; } - /* FIXME: although we already unmarshalled the whole packet, - * set the offset of the pdu to right after the header - * until the rest of the code downstream is changed - * to always use the already decoded packet and not try - * to unmarshall bits of the packet. - */ - if (!prs_set_offset(current_pdu, - prs_offset(current_pdu) + RPC_HEADER_LEN)) { - return NT_STATUS_BUFFER_TOO_SMALL; - } - - if (current_pdu_len != pkt->frag_length) { + if (pdu->length != pkt->frag_length) { DEBUG(5, ("Incorrect pdu length %u, expected %u\n", - (unsigned int)current_pdu_len, + (unsigned int)pdu->length, (unsigned int)pkt->frag_length)); return NT_STATUS_INVALID_PARAMETER; } @@ -979,8 +930,7 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, * Point the return values at the real data including the RPC * header. Just in case the caller wants it. */ - *ppdata = prs_data_p(current_pdu); - *pdata_len = current_pdu_len; + *rdata = *pdu; /* Ensure we have the correct type. */ switch (pkt->ptype) { @@ -994,36 +944,38 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, case DCERPC_PKT_RESPONSE: /* Here's where we deal with incoming sign/seal. */ - ret = cli_pipe_validate_rpc_response(cli, pkt, - current_pdu, &ss_padding_len); + ret = cli_pipe_validate_rpc_response(cli, pkt, pdu, + &ss_padding_len); if (!NT_STATUS_IS_OK(ret)) { return ret; } /* Point the return values at the NDR data. * Remember to remove any ss padding. */ - *ppdata = prs_data_p(current_pdu) + DCERPC_RESPONSE_LENGTH; + rdata->data = pdu->data + DCERPC_RESPONSE_LENGTH; - if (current_pdu_len < DCERPC_RESPONSE_LENGTH + ss_padding_len) { + if (pdu->length < DCERPC_RESPONSE_LENGTH + ss_padding_len) { return NT_STATUS_BUFFER_TOO_SMALL; } - *pdata_len = current_pdu_len - DCERPC_RESPONSE_LENGTH - ss_padding_len; + rdata->length = pdu->length + - DCERPC_RESPONSE_LENGTH + - ss_padding_len; /* Remember to remove the auth footer. */ if (pkt->auth_length) { /* We've already done integer wrap tests on auth_len in cli_pipe_validate_rpc_response(). */ - if (*pdata_len < DCERPC_AUTH_TRAILER_LENGTH - + pkt->auth_length) { + if (rdata->length < DCERPC_AUTH_TRAILER_LENGTH + + pkt->auth_length) { return NT_STATUS_BUFFER_TOO_SMALL; } - *pdata_len -= (DCERPC_AUTH_TRAILER_LENGTH - + pkt->auth_length); + rdata->length -= (DCERPC_AUTH_TRAILER_LENGTH + + pkt->auth_length); } - DEBUG(10, ("Got pdu len %u, data_len %u, ss_len %u\n", - current_pdu_len, *pdata_len, ss_padding_len)); + DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n", + pdu->length, rdata->length, ss_padding_len)); /* * If this is the first reply, and the allocation hint is @@ -1097,43 +1049,6 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, return NT_STATUS_OK; } -/**************************************************************************** - Ensure we eat the just processed pdu from the current_pdu prs_struct. - Normally the frag_len and buffer size will match, but on the first trans - reply there is a theoretical chance that buffer size > frag_len, so we must - deal with that. - ****************************************************************************/ - -static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, - struct ncacn_packet *pkt, - prs_struct *current_pdu) -{ - uint32 current_pdu_len = prs_data_size(current_pdu); - - if (current_pdu_len < pkt->frag_length) { - return NT_STATUS_BUFFER_TOO_SMALL; - } - - /* Common case. */ - if (current_pdu_len == (uint32)pkt->frag_length) { - prs_mem_free(current_pdu); - prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL); - /* Make current_pdu dynamic with no memory. */ - prs_give_memory(current_pdu, 0, 0, True); - return NT_STATUS_OK; - } - - /* - * Oh no ! More data in buffer than we processed in current pdu. - * This shouldn't happen, we only read exactly pkt->frag_length. - * Something is wrong here, throw an error. - */ - - DEBUG(0, ("Data buffer size (%u) and pkt->frag_length (%u) differ\n!", - (unsigned)current_pdu_len, (unsigned)pkt->frag_length)); - return NT_STATUS_INVALID_BUFFER_SIZE; -} - /**************************************************************************** Call a remote api on an arbitrary pipe. takes param, data and setup buffers. ****************************************************************************/ @@ -1324,7 +1239,7 @@ struct rpc_api_pipe_state { struct rpc_pipe_client *cli; uint8_t expected_pkt_type; - prs_struct incoming_frag; + DATA_BLOB incoming_frag; struct ncacn_packet *pkt; prs_struct incoming_pdu; /* Incoming reply */ @@ -1353,8 +1268,7 @@ static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx, state->cli = cli; state->expected_pkt_type = expected_pkt_type; state->incoming_pdu_offset = 0; - - prs_init_empty(&state->incoming_frag, state, UNMARSHALL); + state->incoming_frag = data_blob_null; prs_init_empty(&state->incoming_pdu, state, UNMARSHALL); /* Make incoming_pdu dynamic with no memory. */ @@ -1417,11 +1331,14 @@ static void rpc_api_pipe_trans_done(struct tevent_req *subreq) } /* - * This is equivalent to a talloc_steal - gives rdata to - * the prs_struct state->incoming_frag. + * Move data on state->incoming_frag. */ - prs_give_memory(&state->incoming_frag, (char *)rdata, rdata_len, true); - rdata = NULL; + state->incoming_frag.data = talloc_move(state, &rdata); + state->incoming_frag.length = rdata_len; + if (!state->incoming_frag.data) { + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return; + } /* Ensure we have enough data for a pdu. */ subreq = get_complete_frag_send(state, state->ev, state->cli, @@ -1439,8 +1356,7 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) struct rpc_api_pipe_state *state = tevent_req_data( req, struct rpc_api_pipe_state); NTSTATUS status; - char *rdata = NULL; - uint32_t rdata_len = 0; + DATA_BLOB rdata = data_blob_null; status = get_complete_frag_recv(subreq); TALLOC_FREE(subreq); @@ -1457,13 +1373,14 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) return; } - status = cli_pipe_validate_current_pdu( - state->cli, state->pkt, &state->incoming_frag, - state->expected_pkt_type, &rdata, &rdata_len, - &state->incoming_pdu); + status = cli_pipe_validate_current_pdu(state->cli, state->pkt, + &state->incoming_frag, + state->expected_pkt_type, + &rdata, + &state->incoming_pdu); DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n", - (unsigned)prs_data_size(&state->incoming_frag), + (unsigned)state->incoming_frag.length, (unsigned)state->incoming_pdu_offset, nt_errstr(status))); @@ -1473,7 +1390,7 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) } if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) - && (state->pkt->drep[0] == 0)) { + && (state->pkt->drep[0] != DCERPC_DREP_LE)) { /* * Set the data type correctly for big-endian data on the * first packet. @@ -1486,32 +1403,30 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) /* * Check endianness on subsequent packets. */ - if (state->incoming_frag.bigendian_data - != state->incoming_pdu.bigendian_data) { + if (state->incoming_pdu.bigendian_data && + (state->pkt->drep[0] == DCERPC_DREP_LE)) { DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to " "%s\n", state->incoming_pdu.bigendian_data?"big":"little", - state->incoming_frag.bigendian_data?"big":"little")); + (state->pkt->drep[0] != DCERPC_DREP_LE)?"big":"little")); tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } /* Now copy the data portion out of the pdu into rbuf. */ - if (!prs_force_grow(&state->incoming_pdu, rdata_len)) { + if (!prs_force_grow(&state->incoming_pdu, rdata.length)) { tevent_req_nterror(req, NT_STATUS_NO_MEMORY); return; } memcpy(prs_data_p(&state->incoming_pdu) + state->incoming_pdu_offset, - rdata, (size_t)rdata_len); - state->incoming_pdu_offset += rdata_len; + rdata.data, rdata.length); + state->incoming_pdu_offset += rdata.length; - status = cli_pipe_reset_current_pdu(state->cli, state->pkt, - &state->incoming_frag); - if (!NT_STATUS_IS_OK(status)) { - tevent_req_nterror(req, status); - return; - } + /* reset state->incoming_frag, there is no need to free it, + * it will be reallocated to the right size the next time + * it is used */ + state->incoming_frag.length = 0; if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) { DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n", -- cgit From ff121c89d365db657128bb53bd63d18c8bfa7155 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Jul 2010 19:39:54 -0400 Subject: s3-dcerpc: Use DATA_BLOB instead of prs_struct for reply_pdu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/include/proto.h | 2 +- source3/rpc_client/cli_pipe.c | 145 ++++++++++++++++++++---------------------- source3/rpc_client/ndr.c | 14 ++-- 3 files changed, 75 insertions(+), 86 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index 735f5e2bf8..a7d8782497 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4851,7 +4851,7 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, uint8_t op_num, prs_struct *req_data); NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - prs_struct *reply_pdu); + DATA_BLOB *reply_pdu); struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct rpc_pipe_client *cli, diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index ce38f965c5..d6b4e6cd67 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -904,12 +904,13 @@ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, Do basic authentication checks on an incoming pdu. ****************************************************************************/ -static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, - struct ncacn_packet *pkt, - DATA_BLOB *pdu, - uint8 expected_pkt_type, - DATA_BLOB *rdata, - prs_struct *return_data) +static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx, + struct rpc_pipe_client *cli, + struct ncacn_packet *pkt, + DATA_BLOB *pdu, + uint8_t expected_pkt_type, + DATA_BLOB *rdata, + DATA_BLOB *reply_pdu) { NTSTATUS ret = NT_STATUS_OK; uint8 ss_padding_len = 0; @@ -979,15 +980,15 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, /* * If this is the first reply, and the allocation hint is - * reasonable, try and set up the return_data parse_struct to - * the correct size. + * reasonable, try and set up the reply_pdu DATA_BLOB to the + * correct size. */ - if ((prs_data_size(return_data) == 0) && + if ((reply_pdu->length == 0) && pkt->u.response.alloc_hint && (pkt->u.response.alloc_hint < 15*1024*1024)) { - if (!prs_set_buffer_size(return_data, - pkt->u.response.alloc_hint)) { + if (!data_blob_realloc(mem_ctx, reply_pdu, + pkt->u.response.alloc_hint)) { DEBUG(0, ("reply alloc hint %d too " "large to allocate\n", (int)pkt->u.response.alloc_hint)); @@ -1242,8 +1243,10 @@ struct rpc_api_pipe_state { DATA_BLOB incoming_frag; struct ncacn_packet *pkt; - prs_struct incoming_pdu; /* Incoming reply */ - uint32_t incoming_pdu_offset; + /* Incoming reply */ + DATA_BLOB reply_pdu; + size_t reply_pdu_offset; + uint8_t endianess; }; static void rpc_api_pipe_trans_done(struct tevent_req *subreq); @@ -1267,12 +1270,10 @@ 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->incoming_pdu_offset = 0; state->incoming_frag = data_blob_null; - - prs_init_empty(&state->incoming_pdu, state, UNMARSHALL); - /* Make incoming_pdu dynamic with no memory. */ - prs_give_memory(&state->incoming_pdu, NULL, 0, true); + state->reply_pdu = data_blob_null; + state->reply_pdu_offset = 0; + state->endianess = DCERPC_DREP_LE; /* * Ensure we're not sending too much. @@ -1373,15 +1374,16 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) return; } - status = cli_pipe_validate_current_pdu(state->cli, state->pkt, + status = cli_pipe_validate_current_pdu(state, + state->cli, state->pkt, &state->incoming_frag, state->expected_pkt_type, &rdata, - &state->incoming_pdu); + &state->reply_pdu); DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n", (unsigned)state->incoming_frag.length, - (unsigned)state->incoming_pdu_offset, + (unsigned)state->reply_pdu_offset, nt_errstr(status))); if (!NT_STATUS_IS_OK(status)) { @@ -1398,30 +1400,32 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) DEBUG(10,("rpc_api_pipe: On %s PDU data format is " "big-endian.\n", rpccli_pipe_txt(talloc_tos(), state->cli))); - prs_set_endian_data(&state->incoming_pdu, RPC_BIG_ENDIAN); + state->endianess = 0x00; /* BIG ENDIAN */ } /* * Check endianness on subsequent packets. */ - if (state->incoming_pdu.bigendian_data && - (state->pkt->drep[0] == DCERPC_DREP_LE)) { + if (state->endianess != state->pkt->drep[0]) { DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to " "%s\n", - state->incoming_pdu.bigendian_data?"big":"little", - (state->pkt->drep[0] != DCERPC_DREP_LE)?"big":"little")); + state->endianess?"little":"big", + state->pkt->drep[0]?"little":"big")); tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } /* Now copy the data portion out of the pdu into rbuf. */ - if (!prs_force_grow(&state->incoming_pdu, rdata.length)) { - tevent_req_nterror(req, NT_STATUS_NO_MEMORY); - return; + if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) { + if (!data_blob_realloc(NULL, &state->reply_pdu, + state->reply_pdu_offset + rdata.length)) { + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return; + } } - memcpy(prs_data_p(&state->incoming_pdu) + state->incoming_pdu_offset, - rdata.data, rdata.length); - state->incoming_pdu_offset += rdata.length; + memcpy(state->reply_pdu.data + state->reply_pdu_offset, + rdata.data, rdata.length); + state->reply_pdu_offset += rdata.length; /* reset state->incoming_frag, there is no need to free it, * it will be reallocated to the right size the next time @@ -1429,9 +1433,13 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) state->incoming_frag.length = 0; if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) { + /* make sure the pdu length is right now that we + * have all the data available (alloc hint may + * have allocated more than was actually used) */ + state->reply_pdu.length = state->reply_pdu_offset; DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n", rpccli_pipe_txt(talloc_tos(), state->cli), - (unsigned)prs_data_size(&state->incoming_pdu))); + (unsigned)state->reply_pdu.length)); tevent_req_done(req); return; } @@ -1446,7 +1454,7 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct ncacn_packet **pkt, - prs_struct *reply_pdu) + DATA_BLOB *reply_pdu) { struct rpc_api_pipe_state *state = tevent_req_data( req, struct rpc_api_pipe_state); @@ -1456,15 +1464,14 @@ static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, return status; } - *reply_pdu = state->incoming_pdu; - reply_pdu->mem_ctx = mem_ctx; - - /* - * Prevent state->incoming_pdu from being freed - * when state is freed. - */ - talloc_steal(mem_ctx, prs_data_p(reply_pdu)); - prs_init_empty(&state->incoming_pdu, state, UNMARSHALL); + /* return data to caller and assign it ownership of memory */ + if (reply_pdu) { + reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data); + reply_pdu->length = state->reply_pdu.length; + state->reply_pdu.length = 0; + } else { + data_blob_free(&state->reply_pdu); + } if (pkt) { *pkt = talloc_steal(mem_ctx, state->pkt); @@ -2058,7 +2065,7 @@ struct rpc_api_pipe_req_state { prs_struct *req_data; uint32_t req_data_sent; prs_struct outgoing_frag; - prs_struct reply_pdu; + DATA_BLOB reply_pdu; }; static void rpc_api_pipe_req_write_done(struct tevent_req *subreq); @@ -2088,6 +2095,7 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, state->req_data = req_data; state->req_data_sent = 0; state->call_id = get_rpc_call_id(); + state->reply_pdu = data_blob_null; if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH + RPC_MAX_SIGN_SIZE) { @@ -2096,8 +2104,6 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, goto post_status; } - prs_init_empty(&state->reply_pdu, state, UNMARSHALL); - if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag, state, MARSHALL)) { goto fail; @@ -2292,7 +2298,7 @@ static void rpc_api_pipe_req_done(struct tevent_req *subreq) } NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - prs_struct *reply_pdu) + DATA_BLOB *reply_pdu) { struct rpc_api_pipe_req_state *state = tevent_req_data( req, struct rpc_api_pipe_req_state); @@ -2303,19 +2309,14 @@ NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, * We always have to initialize to reply pdu, even if there is * none. The rpccli_* caller routines expect this. */ - prs_init_empty(reply_pdu, mem_ctx, UNMARSHALL); + *reply_pdu = data_blob_null; return status; } - *reply_pdu = state->reply_pdu; - reply_pdu->mem_ctx = mem_ctx; - - /* - * Prevent state->req_pdu from being freed - * when state is freed. - */ - talloc_steal(mem_ctx, prs_data_p(reply_pdu)); - prs_init_empty(&state->reply_pdu, state, UNMARSHALL); + /* return data to caller and assign it ownership of memory */ + reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data); + reply_pdu->length = state->reply_pdu.length; + state->reply_pdu.length = 0; return NT_STATUS_OK; } @@ -2507,13 +2508,12 @@ struct rpc_pipe_bind_state { static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq); static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req, struct rpc_pipe_bind_state *state, - struct ncacn_packet *r, - prs_struct *reply_pdu); + struct ncacn_packet *r); static void rpc_bind_auth3_write_done(struct tevent_req *subreq); static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req, struct rpc_pipe_bind_state *state, struct ncacn_packet *r, - prs_struct *reply_pdu); + DATA_BLOB *reply_pdu); static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq); struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, @@ -2577,7 +2577,7 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) subreq, struct tevent_req); struct rpc_pipe_bind_state *state = tevent_req_data( req, struct rpc_pipe_bind_state); - prs_struct reply_pdu; + DATA_BLOB reply_pdu; struct ncacn_packet *pkt; NTSTATUS status; @@ -2614,8 +2614,7 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) case PIPE_AUTH_TYPE_NTLMSSP: /* Need to send AUTH3 packet - no reply. */ - status = rpc_finish_auth3_bind_send(req, state, pkt, - &reply_pdu); + status = rpc_finish_auth3_bind_send(req, state, pkt); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); } @@ -2642,8 +2641,7 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req, struct rpc_pipe_bind_state *state, - struct ncacn_packet *r, - prs_struct *reply_pdu) + struct ncacn_packet *r) { DATA_BLOB client_reply = data_blob_null; struct dcerpc_auth auth; @@ -2716,7 +2714,7 @@ static void rpc_bind_auth3_write_done(struct tevent_req *subreq) static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req, struct rpc_pipe_bind_state *state, struct ncacn_packet *r, - prs_struct *rpc_in) + DATA_BLOB *reply_pdu) { DATA_BLOB server_ntlm_response = data_blob_null; DATA_BLOB client_reply = data_blob_null; @@ -2733,14 +2731,12 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req, } /* Process the returned NTLMSSP blob first. */ - if (!prs_set_offset(rpc_in, r->frag_length + auth_blob = data_blob_const(reply_pdu->data + + r->frag_length - DCERPC_AUTH_TRAILER_LENGTH - - r->auth_length)) { - return NT_STATUS_INVALID_PARAMETER; - } - - auth_blob = data_blob_const(prs_data_p(rpc_in) + prs_offset(rpc_in), - prs_data_size(rpc_in) - prs_offset(rpc_in)); + - r->auth_length, + DCERPC_AUTH_TRAILER_LENGTH + + r->auth_length); status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info); if (!NT_STATUS_IS_OK(status)) { @@ -2814,10 +2810,9 @@ static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq) DATA_BLOB tmp_blob = data_blob_null; struct ncacn_packet *pkt; struct dcerpc_auth auth; - prs_struct reply_pdu; NTSTATUS status; - status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu); + status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); diff --git a/source3/rpc_client/ndr.c b/source3/rpc_client/ndr.c index 8e03f2e015..2fb9655207 100644 --- a/source3/rpc_client/ndr.c +++ b/source3/rpc_client/ndr.c @@ -24,7 +24,8 @@ struct cli_do_rpc_ndr_state { const struct ndr_interface_call *call; - prs_struct q_ps, r_ps; + prs_struct q_ps; + DATA_BLOB r_pdu; void *r; }; @@ -101,7 +102,7 @@ static void cli_do_rpc_ndr_done(struct tevent_req *subreq) req, struct cli_do_rpc_ndr_state); NTSTATUS status; - status = rpc_api_pipe_req_recv(subreq, state, &state->r_ps); + status = rpc_api_pipe_req_recv(subreq, state, &state->r_pdu); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); @@ -117,19 +118,12 @@ NTSTATUS cli_do_rpc_ndr_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx) struct ndr_pull *pull; enum ndr_err_code ndr_err; NTSTATUS status; - DATA_BLOB blob; - bool ret; if (tevent_req_is_nterror(req, &status)) { return status; } - ret = prs_data_blob(&state->r_ps, &blob, talloc_tos()); - if (!ret) { - return NT_STATUS_NO_MEMORY; - } - - pull = ndr_pull_init_blob(&blob, mem_ctx); + pull = ndr_pull_init_blob(&state->r_pdu, mem_ctx); if (pull == NULL) { return NT_STATUS_NO_MEMORY; } -- cgit From 3b83211cd8859429541b383bafb657d58f16fe30 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Jul 2010 19:57:01 -0400 Subject: s3-dcerpc: Avoid unnecessary memory allocation for dcerpc_ctx_list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_client/cli_pipe.c | 42 +++++++----------------------------------- 1 file changed, 7 insertions(+), 35 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index d6b4e6cd67..4cff6ac0ae 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1675,33 +1675,6 @@ static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli, return NT_STATUS_OK; } -/******************************************************************* - ********************************************************************/ - -static NTSTATUS init_dcerpc_ctx_list(TALLOC_CTX *mem_ctx, - const struct ndr_syntax_id *abstract_syntax, - const struct ndr_syntax_id *transfer_syntax, - struct dcerpc_ctx_list **ctx_list_p) -{ - struct dcerpc_ctx_list *ctx_list; - - ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1); - NT_STATUS_HAVE_NO_MEMORY(ctx_list); - - ctx_list[0].context_id = 0; - ctx_list[0].num_transfer_syntaxes = 1; - ctx_list[0].abstract_syntax = *abstract_syntax; - ctx_list[0].transfer_syntaxes = talloc_array(ctx_list, - struct ndr_syntax_id, - ctx_list[0].num_transfer_syntaxes); - NT_STATUS_HAVE_NO_MEMORY(ctx_list[0].transfer_syntaxes); - ctx_list[0].transfer_syntaxes[0] = *transfer_syntax; - - *ctx_list_p = ctx_list; - - return NT_STATUS_OK; -} - /******************************************************************* Creates the internals of a DCE/RPC bind request or alter context PDU. ********************************************************************/ @@ -1717,23 +1690,22 @@ static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type ptype, NTSTATUS status; union dcerpc_payload u; DATA_BLOB blob; - struct dcerpc_ctx_list *ctx_list; - - status = init_dcerpc_ctx_list(rpc_out->mem_ctx, abstract, transfer, - &ctx_list); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + struct dcerpc_ctx_list ctx_list; if (auth_len) { auth_len -= DCERPC_AUTH_TRAILER_LENGTH; } + ctx_list.context_id = 0; + ctx_list.num_transfer_syntaxes = 1; + ctx_list.abstract_syntax = *abstract; + ctx_list.transfer_syntaxes = discard_const(transfer); + u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN; u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN; u.bind.assoc_group_id = 0x0; u.bind.num_contexts = 1; - u.bind.ctx_list = ctx_list; + u.bind.ctx_list = &ctx_list; u.bind.auth_info = *auth_info; status = dcerpc_push_ncacn_packet(rpc_out->mem_ctx, -- cgit From 8e9cd4144e0997991c1b54acf4e62213bce9019e Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 14 Jul 2010 23:31:38 -0400 Subject: s3-dcerpc: Use DATA_BLOB instead of prs_struct for rpc_out MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_client/cli_pipe.c | 230 ++++++++++++++++++++---------------------- 1 file changed, 108 insertions(+), 122 deletions(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 4cff6ac0ae..73aa3dc7a3 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1210,7 +1210,7 @@ static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, } /**************************************************************************** - Send data on an rpc pipe via trans. The prs_struct data must be the last + Send data on an rpc pipe via trans. The data must be the last pdu fragment of an NDR data stream. Receive response data from an rpc pipe, which may be large... @@ -1255,7 +1255,7 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq); static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct rpc_pipe_client *cli, - prs_struct *data, /* Outgoing PDU */ + DATA_BLOB *data, /* Outgoing PDU */ uint8_t expected_pkt_type) { struct tevent_req *req, *subreq; @@ -1278,7 +1278,7 @@ static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx, /* * Ensure we're not sending too much. */ - if (prs_offset(data) > cli->max_xmit_frag) { + if (data->length > cli->max_xmit_frag) { status = NT_STATUS_INVALID_PARAMETER; goto post_status; } @@ -1290,8 +1290,7 @@ static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx, max_recv_frag = RPC_HEADER_LEN; subreq = cli_api_pipe_send(state, ev, cli->transport, - (uint8_t *)prs_data_p(data), - prs_offset(data), max_recv_frag); + data->data, data->length, max_recv_frag); if (subreq == NULL) { goto fail; } @@ -1679,17 +1678,17 @@ static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli, Creates the internals of a DCE/RPC bind request or alter context PDU. ********************************************************************/ -static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type ptype, - prs_struct *rpc_out, +static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx, + enum dcerpc_pkt_type ptype, uint32 rpc_call_id, const struct ndr_syntax_id *abstract, const struct ndr_syntax_id *transfer, - const DATA_BLOB *auth_info) + const DATA_BLOB *auth_info, + DATA_BLOB *blob) { uint16 auth_len = auth_info->length; NTSTATUS status; union dcerpc_payload u; - DATA_BLOB blob; struct dcerpc_ctx_list ctx_list; if (auth_len) { @@ -1708,23 +1707,19 @@ static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type ptype, u.bind.ctx_list = &ctx_list; u.bind.auth_info = *auth_info; - status = dcerpc_push_ncacn_packet(rpc_out->mem_ctx, + status = dcerpc_push_ncacn_packet(mem_ctx, ptype, DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST, auth_len, rpc_call_id, &u, - &blob); + blob); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n")); + DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n")); return status; } - if (!prs_copy_data_in(rpc_out, (char *)blob.data, blob.length)) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; } @@ -1732,13 +1727,14 @@ static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type ptype, Creates a DCE/RPC bind request. ********************************************************************/ -static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli, - prs_struct *rpc_out, +static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, + struct rpc_pipe_client *cli, uint32 rpc_call_id, const struct ndr_syntax_id *abstract, const struct ndr_syntax_id *transfer, enum pipe_auth_type auth_type, - enum dcerpc_AuthLevel auth_level) + enum dcerpc_AuthLevel auth_level, + DATA_BLOB *rpc_out) { DATA_BLOB auth_info = data_blob_null; NTSTATUS ret = NT_STATUS_OK; @@ -1780,12 +1776,13 @@ static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli, return NT_STATUS_INVALID_INFO_CLASS; } - ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_BIND, - rpc_out, + ret = create_bind_or_alt_ctx_internal(mem_ctx, + DCERPC_PKT_BIND, rpc_call_id, abstract, transfer, - &auth_info); + &auth_info, + rpc_out); return ret; } @@ -1795,13 +1792,12 @@ static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli, static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli, uint32 ss_padding_len, - prs_struct *rpc_out) + DATA_BLOB *rpc_out) { DATA_BLOB auth_info; NTSTATUS status; DATA_BLOB auth_blob = data_blob_null; - uint16_t data_and_pad_len = prs_offset(rpc_out) - - DCERPC_RESPONSE_LENGTH; + uint16_t data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH; if (!cli->auth->a_u.ntlmssp_state) { return NT_STATUS_INVALID_PARAMETER; @@ -1810,7 +1806,7 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli, /* marshall the dcerpc_auth with an actually empty auth_blob. * this is needed because the ntmlssp signature includes the * auth header */ - status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out), + status = dcerpc_push_dcerpc_auth(rpc_out->data, map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type), cli->auth->auth_level, ss_padding_len, @@ -1822,25 +1818,25 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli, } /* append the header */ - if (!prs_copy_data_in(rpc_out, - (char *)auth_info.data, - auth_info.length)) { + if (!data_blob_append(NULL, rpc_out, + auth_info.data, auth_info.length)) { DEBUG(0, ("Failed to add %u bytes auth blob.\n", (unsigned int)auth_info.length)); return NT_STATUS_NO_MEMORY; } + data_blob_free(&auth_info); switch (cli->auth->auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: /* Data portion is encrypted. */ status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state, - prs_get_mem_context(rpc_out), - (unsigned char *)prs_data_p(rpc_out) + rpc_out->data, + rpc_out->data + DCERPC_RESPONSE_LENGTH, - data_and_pad_len, - (unsigned char *)prs_data_p(rpc_out), - (size_t)prs_offset(rpc_out), - &auth_blob); + data_and_pad_len, + rpc_out->data, + rpc_out->length, + &auth_blob); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -1849,13 +1845,13 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli, case DCERPC_AUTH_LEVEL_INTEGRITY: /* Data is signed. */ status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state, - prs_get_mem_context(rpc_out), - (unsigned char *)prs_data_p(rpc_out) + rpc_out->data, + rpc_out->data + DCERPC_RESPONSE_LENGTH, - data_and_pad_len, - (unsigned char *)prs_data_p(rpc_out), - (size_t)prs_offset(rpc_out), - &auth_blob); + data_and_pad_len, + rpc_out->data, + rpc_out->length, + &auth_blob); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -1869,13 +1865,13 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli, } /* Finally attach the blob. */ - if (!prs_copy_data_in(rpc_out, - (char *)auth_blob.data, - auth_blob.length)) { + if (!data_blob_append(NULL, rpc_out, + auth_blob.data, auth_blob.length)) { DEBUG(0, ("Failed to add %u bytes auth blob.\n", (unsigned int)auth_info.length)); return NT_STATUS_NO_MEMORY; } + data_blob_free(&auth_blob); return NT_STATUS_OK; } @@ -1886,12 +1882,12 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli, static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli, uint32 ss_padding_len, - prs_struct *rpc_out) + DATA_BLOB *rpc_out) { DATA_BLOB auth_info; struct schannel_state *sas = cli->auth->a_u.schannel_auth; - char *data_p = prs_data_p(rpc_out) + DCERPC_RESPONSE_LENGTH; - size_t data_and_pad_len = prs_offset(rpc_out) + uint8_t *data_p = rpc_out->data + DCERPC_RESPONSE_LENGTH; + size_t data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH; DATA_BLOB blob; NTSTATUS status; @@ -1906,17 +1902,17 @@ static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli, switch (cli->auth->auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: status = netsec_outgoing_packet(sas, - talloc_tos(), + rpc_out->data, true, - (uint8_t *)data_p, + data_p, data_and_pad_len, &blob); break; case DCERPC_AUTH_LEVEL_INTEGRITY: status = netsec_outgoing_packet(sas, - talloc_tos(), + rpc_out->data, false, - (uint8_t *)data_p, + data_p, data_and_pad_len, &blob); break; @@ -1936,8 +1932,8 @@ static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli, } /* Finally marshall the blob. */ - status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out), - map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type), + status = dcerpc_push_dcerpc_auth(rpc_out->data, + map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type), cli->auth->auth_level, ss_padding_len, 1 /* context id. */, @@ -1946,10 +1942,13 @@ static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli, if (!NT_STATUS_IS_OK(status)) { return status; } + data_blob_free(&blob); - if (!prs_copy_data_in(rpc_out, (const char *)auth_info.data, auth_info.length)) { + if (!data_blob_append(NULL, rpc_out, + auth_info.data, auth_info.length)) { return NT_STATUS_NO_MEMORY; } + data_blob_free(&auth_info); return NT_STATUS_OK; } @@ -2036,7 +2035,7 @@ struct rpc_api_pipe_req_state { uint32_t call_id; prs_struct *req_data; uint32_t req_data_sent; - prs_struct outgoing_frag; + DATA_BLOB rpc_out; DATA_BLOB reply_pdu; }; @@ -2068,6 +2067,7 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, state->req_data_sent = 0; state->call_id = get_rpc_call_id(); state->reply_pdu = data_blob_null; + state->rpc_out = data_blob_null; if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH + RPC_MAX_SIGN_SIZE) { @@ -2076,11 +2076,6 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, goto post_status; } - if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag, - state, MARSHALL)) { - goto fail; - } - status = prepare_next_frag(state, &is_last_frag); if (!NT_STATUS_IS_OK(status)) { goto post_status; @@ -2088,17 +2083,16 @@ 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->outgoing_frag, + &state->rpc_out, DCERPC_PKT_RESPONSE); if (subreq == NULL) { goto fail; } tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req); } else { - subreq = rpc_write_send( - state, ev, cli->transport, - (uint8_t *)prs_data_p(&state->outgoing_frag), - prs_offset(&state->outgoing_frag)); + subreq = rpc_write_send(state, ev, cli->transport, + state->rpc_out.data, + state->rpc_out.length); if (subreq == NULL) { goto fail; } @@ -2127,7 +2121,6 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, char pad[8] = { 0, }; NTSTATUS status; union dcerpc_payload u; - DATA_BLOB blob; data_left = prs_offset(state->req_data) - state->req_data_sent; @@ -2142,9 +2135,7 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, flags |= DCERPC_PFC_FLAG_LAST; } - if (!prs_set_offset(&state->outgoing_frag, 0)) { - return NT_STATUS_NO_MEMORY; - } + data_blob_free(&state->rpc_out); ZERO_STRUCT(u.request); @@ -2152,35 +2143,35 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, u.request.context_id = 0; u.request.opnum = state->op_num; - status = dcerpc_push_ncacn_packet(prs_get_mem_context(&state->outgoing_frag), + status = dcerpc_push_ncacn_packet(state, DCERPC_PKT_REQUEST, flags, auth_len, state->call_id, &u, - &blob); + &state->rpc_out); if (!NT_STATUS_IS_OK(status)) { return status; } /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't * compute it right for requests */ - dcerpc_set_frag_length(&blob, frag_len); - - if (!prs_copy_data_in(&state->outgoing_frag, (const char *)blob.data, blob.length)) { - return NT_STATUS_NO_MEMORY; - } + dcerpc_set_frag_length(&state->rpc_out, frag_len); /* Copy in the data, plus any ss padding. */ - if (!prs_append_some_prs_data(&state->outgoing_frag, - state->req_data, state->req_data_sent, - data_sent_thistime)) { + if (!data_blob_append(NULL, &state->rpc_out, + prs_data_p(state->req_data) + + state->req_data_sent, + data_sent_thistime)) { return NT_STATUS_NO_MEMORY; } - /* Copy the sign/seal padding data. */ - if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) { - return NT_STATUS_NO_MEMORY; + if (ss_padding) { + /* Copy the sign/seal padding data. */ + if (!data_blob_append(NULL, &state->rpc_out, + pad, ss_padding)) { + return NT_STATUS_NO_MEMORY; + } } /* Generate any auth sign/seal and add the auth footer. */ @@ -2191,11 +2182,11 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, case PIPE_AUTH_TYPE_NTLMSSP: case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: status = add_ntlmssp_auth_footer(state->cli, ss_padding, - &state->outgoing_frag); + &state->rpc_out); break; case PIPE_AUTH_TYPE_SCHANNEL: status = add_schannel_auth_footer(state->cli, ss_padding, - &state->outgoing_frag); + &state->rpc_out); break; default: status = NT_STATUS_INVALID_PARAMETER; @@ -2232,18 +2223,17 @@ 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->outgoing_frag, + &state->rpc_out, DCERPC_PKT_RESPONSE); if (tevent_req_nomem(subreq, req)) { return; } tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req); } else { - subreq = rpc_write_send( - state, state->ev, - state->cli->transport, - (uint8_t *)prs_data_p(&state->outgoing_frag), - prs_offset(&state->outgoing_frag)); + subreq = rpc_write_send(state, state->ev, + state->cli->transport, + state->rpc_out.data, + state->rpc_out.length); if (tevent_req_nomem(subreq, req)) { return; } @@ -2382,20 +2372,20 @@ static bool check_bind_response(const struct dcerpc_bind_ack *r, the authentication handshake. ********************************************************************/ -static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli, +static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx, + struct rpc_pipe_client *cli, uint32 rpc_call_id, enum pipe_auth_type auth_type, enum dcerpc_AuthLevel auth_level, DATA_BLOB *pauth_blob, - prs_struct *rpc_out) + DATA_BLOB *rpc_out) { NTSTATUS status; union dcerpc_payload u; - DATA_BLOB blob; u.auth3._pad = 0; - status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out), + status = dcerpc_push_dcerpc_auth(mem_ctx, map_pipe_auth_type_to_rpc_auth_type(auth_type), auth_level, 0, /* auth_pad_length */ @@ -2406,23 +2396,20 @@ static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli, return status; } - status = dcerpc_push_ncacn_packet(prs_get_mem_context(rpc_out), + status = dcerpc_push_ncacn_packet(mem_ctx, DCERPC_PKT_AUTH3, DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST, pauth_blob->length, rpc_call_id, &u, - &blob); + rpc_out); + data_blob_free(&u.auth3.auth_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n")); return status; } - if (!prs_copy_data_in(rpc_out, (char *)blob.data, blob.length)) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; } @@ -2431,17 +2418,18 @@ static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli, may contain a spnego auth blobl ********************************************************************/ -static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id, +static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx, + uint32 rpc_call_id, const struct ndr_syntax_id *abstract, const struct ndr_syntax_id *transfer, enum dcerpc_AuthLevel auth_level, const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */ - prs_struct *rpc_out) + DATA_BLOB *rpc_out) { DATA_BLOB auth_info; NTSTATUS status; - status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out), + status = dcerpc_push_dcerpc_auth(mem_ctx, DCERPC_AUTH_TYPE_SPNEGO, auth_level, 0, /* auth_pad_length */ @@ -2452,17 +2440,14 @@ static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id, return status; } - - status = create_bind_or_alt_ctx_internal(DCERPC_PKT_ALTER, - rpc_out, + status = create_bind_or_alt_ctx_internal(mem_ctx, + DCERPC_PKT_ALTER, rpc_call_id, abstract, transfer, - &auth_info); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - + &auth_info, + rpc_out); + data_blob_free(&auth_info); return status; } @@ -2473,7 +2458,7 @@ static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id, struct rpc_pipe_bind_state { struct event_context *ev; struct rpc_pipe_client *cli; - prs_struct rpc_out; + DATA_BLOB rpc_out; uint32_t rpc_call_id; }; @@ -2510,18 +2495,18 @@ struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->cli = cli; state->rpc_call_id = get_rpc_call_id(); - - prs_init_empty(&state->rpc_out, state, MARSHALL); + state->rpc_out = data_blob_null; cli->auth = talloc_move(cli, &auth); /* Marshall the outgoing data. */ - status = create_rpc_bind_req(cli, &state->rpc_out, + status = create_rpc_bind_req(state, cli, state->rpc_call_id, &cli->abstract_syntax, &cli->transfer_syntax, cli->auth->auth_type, - cli->auth->auth_level); + cli->auth->auth_level, + &state->rpc_out); if (!NT_STATUS_IS_OK(status)) { goto post_status; @@ -2646,9 +2631,10 @@ static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req, return status; } - prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL); + data_blob_free(&state->rpc_out); - status = create_rpc_bind_auth3(state->cli, state->rpc_call_id, + status = create_rpc_bind_auth3(state, + state->cli, state->rpc_call_id, state->cli->auth->auth_type, state->cli->auth->auth_level, &client_reply, &state->rpc_out); @@ -2659,8 +2645,7 @@ static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req, } subreq = rpc_write_send(state, state->ev, state->cli->transport, - (uint8_t *)prs_data_p(&state->rpc_out), - prs_offset(&state->rpc_out)); + state->rpc_out.data, state->rpc_out.length); if (subreq == NULL) { return NT_STATUS_NO_MEMORY; } @@ -2750,9 +2735,10 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req, tmp_blob = data_blob_null; /* Now prepare the alter context pdu. */ - prs_init_empty(&state->rpc_out, state, MARSHALL); + data_blob_free(&state->rpc_out); - status = create_rpc_alter_context(state->rpc_call_id, + status = create_rpc_alter_context(state, + state->rpc_call_id, &state->cli->abstract_syntax, &state->cli->transfer_syntax, state->cli->auth->auth_level, -- cgit From 8f2bfa88b5846528aa78840979a8ce8babef2cc0 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 15 Jul 2010 08:48:51 -0400 Subject: s3-dcerpc: Use DATA_BLOB instead of prs_struct for req_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/include/proto.h | 2 +- source3/rpc_client/cli_pipe.c | 11 +++++------ source3/rpc_client/ndr.c | 17 +++++------------ 3 files changed, 11 insertions(+), 19 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index a7d8782497..cb01c38a30 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4849,7 +4849,7 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct rpc_pipe_client *cli, uint8_t op_num, - prs_struct *req_data); + DATA_BLOB *req_data); NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, DATA_BLOB *reply_pdu); struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 73aa3dc7a3..bda152c505 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2033,7 +2033,7 @@ struct rpc_api_pipe_req_state { struct rpc_pipe_client *cli; uint8_t op_num; uint32_t call_id; - prs_struct *req_data; + DATA_BLOB *req_data; uint32_t req_data_sent; DATA_BLOB rpc_out; DATA_BLOB reply_pdu; @@ -2048,7 +2048,7 @@ struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct rpc_pipe_client *cli, uint8_t op_num, - prs_struct *req_data) + DATA_BLOB *req_data) { struct tevent_req *req, *subreq; struct rpc_api_pipe_req_state *state; @@ -2122,7 +2122,7 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, NTSTATUS status; union dcerpc_payload u; - data_left = prs_offset(state->req_data) - state->req_data_sent; + data_left = state->req_data->length - state->req_data_sent; data_sent_thistime = calculate_data_len_tosend( state->cli, data_left, &frag_len, &auth_len, &ss_padding); @@ -2139,7 +2139,7 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, ZERO_STRUCT(u.request); - u.request.alloc_hint = prs_offset(state->req_data); + u.request.alloc_hint = state->req_data->length; u.request.context_id = 0; u.request.opnum = state->op_num; @@ -2160,8 +2160,7 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, /* Copy in the data, plus any ss padding. */ if (!data_blob_append(NULL, &state->rpc_out, - prs_data_p(state->req_data) - + state->req_data_sent, + state->req_data->data + state->req_data_sent, data_sent_thistime)) { return NT_STATUS_NO_MEMORY; } diff --git a/source3/rpc_client/ndr.c b/source3/rpc_client/ndr.c index 2fb9655207..a1642c03ff 100644 --- a/source3/rpc_client/ndr.c +++ b/source3/rpc_client/ndr.c @@ -24,7 +24,7 @@ struct cli_do_rpc_ndr_state { const struct ndr_interface_call *call; - prs_struct q_ps; + DATA_BLOB q_pdu; DATA_BLOB r_pdu; void *r; }; @@ -41,9 +41,7 @@ struct tevent_req *cli_do_rpc_ndr_send(TALLOC_CTX *mem_ctx, struct tevent_req *req, *subreq; struct cli_do_rpc_ndr_state *state; struct ndr_push *push; - DATA_BLOB blob; enum ndr_err_code ndr_err; - bool ret; req = tevent_req_create(mem_ctx, &state, struct cli_do_rpc_ndr_state); @@ -65,7 +63,7 @@ struct tevent_req *cli_do_rpc_ndr_send(TALLOC_CTX *mem_ctx, state->call->name, NDR_IN, r); } - push = ndr_push_init_ctx(talloc_tos()); + push = ndr_push_init_ctx(state); if (tevent_req_nomem(push, req)) { return tevent_req_post(req, ev); } @@ -77,16 +75,11 @@ struct tevent_req *cli_do_rpc_ndr_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - blob = ndr_push_blob(push); - ret = prs_init_data_blob(&state->q_ps, &blob, state); + state->q_pdu = ndr_push_blob(push); + talloc_steal(mem_ctx, state->q_pdu.data); TALLOC_FREE(push); - if (!ret) { - tevent_req_nterror(req, NT_STATUS_NO_MEMORY); - return tevent_req_post(req, ev); - } - - subreq = rpc_api_pipe_req_send(state, ev, cli, opnum, &state->q_ps); + subreq = rpc_api_pipe_req_send(state, ev, cli, opnum, &state->q_pdu); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } -- cgit From 100d37fc4624690423f6a932709b3f9046d05c64 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 15 Jul 2010 10:28:59 -0400 Subject: s3-dcerpc: Use DATA_BLOB for pipes_struct input data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/include/ntdomain.h | 3 +- source3/librpc/gen_ndr/README | 1 - source3/rpc_server/rpc_ncacn_np_internal.c | 26 ++----------- source3/rpc_server/srv_pipe.c | 19 ++++----- source3/rpc_server/srv_pipe_hnd.c | 62 +++++++----------------------- source3/winbindd/winbindd_dual_ndr.c | 4 +- 6 files changed, 29 insertions(+), 86 deletions(-) delete mode 100644 source3/librpc/gen_ndr/README (limited to 'source3') diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index f0a97ac24e..524c9ecc9b 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -105,7 +105,8 @@ typedef struct _input_data { * the rpc headers and auth footers removed. * The maximum length of this (1Mb) is strictly enforced. */ - prs_struct data; + DATA_BLOB data; + } input_data; struct handle_list; diff --git a/source3/librpc/gen_ndr/README b/source3/librpc/gen_ndr/README deleted file mode 100644 index 0c1fd160a5..0000000000 --- a/source3/librpc/gen_ndr/README +++ /dev/null @@ -1 +0,0 @@ -This contains the generated files from PIDL for the IDL files in ../idl/*.idl diff --git a/source3/rpc_server/rpc_ncacn_np_internal.c b/source3/rpc_server/rpc_ncacn_np_internal.c index ceda2c781c..b79b479a08 100644 --- a/source3/rpc_server/rpc_ncacn_np_internal.c +++ b/source3/rpc_server/rpc_ncacn_np_internal.c @@ -144,20 +144,6 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, return NULL; } - /* - * Initialize the incoming RPC data buffer with one PDU worth of memory. - * We cheat here and say we're marshalling, as we intend to add incoming - * data directly into the prs_struct and we want it to auto grow. We will - * change the type to UNMARSALLING before processing the stream. - */ - - if(!prs_init(&p->in_data.data, 128, p->mem_ctx, MARSHALL)) { - DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n")); - close_policy_by_pipe(p); - TALLOC_FREE(p); - return NULL; - } - p->server_info = copy_serverinfo(p, server_info); if (p->server_info == NULL) { DEBUG(0, ("open_rpc_pipe_p: copy_serverinfo failed\n")); @@ -194,8 +180,6 @@ static NTSTATUS internal_ndr_push(TALLOC_CTX *mem_ctx, const struct ndr_interface_call *call; struct ndr_push *push; enum ndr_err_code ndr_err; - DATA_BLOB blob; - bool ret; if (!ndr_syntax_id_equal(&table->syntax_id, &cli->abstract_syntax) || (opnum >= table->num_calls)) { @@ -220,12 +204,10 @@ static NTSTATUS internal_ndr_push(TALLOC_CTX *mem_ctx, return ndr_map_error2ntstatus(ndr_err); } - blob = ndr_push_blob(push); - ret = prs_init_data_blob(&cli->pipes_struct->in_data.data, &blob, mem_ctx); + cli->pipes_struct->in_data.data = ndr_push_blob(push); + talloc_steal(cli->pipes_struct->mem_ctx, + cli->pipes_struct->in_data.data.data); TALLOC_FREE(push); - if (!ret) { - return NT_STATUS_NO_MEMORY; - } return NT_STATUS_OK; } @@ -317,7 +299,7 @@ static NTSTATUS rpc_pipe_internal_dispatch(struct rpc_pipe_client *cli, return status; } - prs_mem_free(&cli->pipes_struct->in_data.data); + data_blob_free(&cli->pipes_struct->in_data.data); data_blob_free(&cli->pipes_struct->out_data.rdata); return NT_STATUS_OK; diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 29b6d8e261..eae8a7dbf2 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -1719,7 +1719,9 @@ static bool api_rpcTNP(pipes_struct *p, struct ncacn_packet *pkt, fstring name; slprintf(name, sizeof(name)-1, "in_%s", get_pipe_name_from_syntax(talloc_tos(), &p->syntax)); - prs_dump(name, pkt->u.request.opnum, &p->in_data.data); + prs_dump_region(name, pkt->u.request.opnum, + p->in_data.data.data, 0, + p->in_data.data.length); } for (fn_num = 0; fn_num < n_cmds; fn_num++) { @@ -1783,18 +1785,11 @@ static bool api_rpcTNP(pipes_struct *p, struct ncacn_packet *pkt, get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); /* Check for buffer underflow in rpc parsing */ - - if ((DEBUGLEVEL >= 10) && - (prs_offset(&p->in_data.data) != prs_data_size(&p->in_data.data))) { - size_t data_len = prs_data_size(&p->in_data.data) - prs_offset(&p->in_data.data); - char *data = (char *)SMB_MALLOC(data_len); - + if ((DEBUGLEVEL >= 10) && + (pkt->frag_length < p->in_data.data.length)) { DEBUG(10, ("api_rpcTNP: rpc input buffer underflow (parse error?)\n")); - if (data) { - prs_uint8s(False, "", &p->in_data.data, 0, (unsigned char *)data, (uint32)data_len); - SAFE_FREE(data); - } - + dump_data(10, p->in_data.data.data + pkt->frag_length, + p->in_data.data.length - pkt->frag_length); } return True; diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index f2fb76ea49..3055e1a29c 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -56,7 +56,7 @@ static bool pipe_init_outgoing_data(pipes_struct *p) static void set_incoming_fault(pipes_struct *p) { - prs_mem_free(&p->in_data.data); + data_blob_free(&p->in_data.data); p->in_data.pdu_needed_len = 0; p->in_data.pdu.length = 0; p->fault_state = True; @@ -145,21 +145,12 @@ static void free_pipe_context(pipes_struct *p) { data_blob_free(&p->out_data.frag); data_blob_free(&p->out_data.rdata); - prs_mem_free(&p->in_data.data); + data_blob_free(&p->in_data.data); DEBUG(3, ("free_pipe_context: " "destroying talloc pool of size %lu\n", (unsigned long)talloc_total_size(p->mem_ctx))); talloc_free_children(p->mem_ctx); - /* - * Re-initialize to set back to marshalling and set the - * offset back to the start of the buffer. - */ - if(!prs_init(&p->in_data.data, 128, p->mem_ctx, MARSHALL)) { - DEBUG(0, ("free_pipe_context: " - "rps_init failed!\n")); - p->fault_state = True; - } } /**************************************************************************** @@ -348,10 +339,10 @@ static bool process_request_pdu(pipes_struct *p, struct ncacn_packet *pkt) * will not fit in the initial buffer of size 0x1068 --jerry 22/01/2002 */ - if (prs_offset(&p->in_data.data) + data.length > MAX_RPC_DATA_SIZE) { + if (p->in_data.data.length + data.length > MAX_RPC_DATA_SIZE) { DEBUG(0, ("process_request_pdu: " "rpc data buffer too large (%u) + (%u)\n", - (unsigned int)prs_data_size(&p->in_data.data), + (unsigned int)p->in_data.data.length, (unsigned int)data.length)); set_incoming_fault(p); return False; @@ -361,14 +352,16 @@ static bool process_request_pdu(pipes_struct *p, struct ncacn_packet *pkt) * Append the data portion into the buffer and return. */ - if (!prs_copy_data_in(&p->in_data.data, - (char *)data.data, data.length)) { - DEBUG(0, ("process_request_pdu: Unable to append data size %u " - "to parse buffer of size %u.\n", - (unsigned int)data.length, - (unsigned int)prs_data_size(&p->in_data.data))); - set_incoming_fault(p); - return False; + if (data.length) { + if (!data_blob_append(p->mem_ctx, &p->in_data.data, + data.data, data.length)) { + DEBUG(0, ("Unable to append data size %u " + "to parse buffer of size %u.\n", + (unsigned int)data.length, + (unsigned int)p->in_data.data.length)); + set_incoming_fault(p); + return False; + } } if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) { @@ -378,31 +371,9 @@ static bool process_request_pdu(pipes_struct *p, struct ncacn_packet *pkt) * Call the rpc command to process it. */ - /* - * Ensure the internal prs buffer size is *exactly* the same - * size as the current offset. - */ - - if (!prs_set_buffer_size(&p->in_data.data, - prs_offset(&p->in_data.data))) { - DEBUG(0, ("process_request_pdu: " - "Call to prs_set_buffer_size failed!\n")); - set_incoming_fault(p); - return False; - } - - /* - * Set the parse offset to the start of the data and set the - * prs_struct to UNMARSHALL. - */ - - prs_set_offset(&p->in_data.data, 0); - prs_switch_type(&p->in_data.data, UNMARSHALL); - /* * Process the complete data stream here. */ - if (pipe_init_outgoing_data(p)) { ret = api_pipe_request(p, pkt); } @@ -454,7 +425,6 @@ static void process_complete_pdu(pipes_struct *p) } else { p->endian = RPC_BIG_ENDIAN; } - prs_set_endian_data(&p->in_data.data, p->endian); DEBUG(10, ("Processing packet type %d\n", (int)pkt->ptype)); @@ -591,10 +561,6 @@ static void process_complete_pdu(pipes_struct *p) } done: - /* Reset to little endian. - * Probably don't need this but it won't hurt. */ - prs_set_endian_data(&p->in_data.data, RPC_LITTLE_ENDIAN); - if (!reply) { DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on " "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(), diff --git a/source3/winbindd/winbindd_dual_ndr.c b/source3/winbindd/winbindd_dual_ndr.c index 08d92d45e6..f67a48dfeb 100644 --- a/source3/winbindd/winbindd_dual_ndr.c +++ b/source3/winbindd/winbindd_dual_ndr.c @@ -264,8 +264,8 @@ enum winbindd_result winbindd_dual_ndrcmd(struct winbindd_domain *domain, ZERO_STRUCT(p); p.mem_ctx = talloc_stackframe(); - p.in_data.data.buffer_size = state->request->extra_len; - p.in_data.data.data_p = state->request->extra_data.data; + p.in_data.data = data_blob_const(state->request->extra_data.data, + state->request->extra_len); ret = fns[state->request->data.ndrcmd].fn(&p); if (!ret) { -- cgit From 67b6fe3dc39aaf88787471b1ce10f47db74c5b1e Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 15 Jul 2010 16:19:04 -0400 Subject: s3-misc: Move smb_io_time() to regfio.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the last file using this function and we do not want anyone else to keep using hand marshalled stuff anyway. So make it also private to that file. Signed-off-by: Günther Deschner --- source3/Makefile.in | 2 +- source3/include/proto.h | 4 --- source3/registry/regfio.c | 32 +++++++++++++++++++++++ source3/rpc_parse/parse_misc.c | 59 ------------------------------------------ 4 files changed, 33 insertions(+), 64 deletions(-) delete mode 100644 source3/rpc_parse/parse_misc.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 99674268ed..08d629a754 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -354,7 +354,7 @@ LIBNDR_GEN_OBJ = librpc/gen_ndr/ndr_wkssvc.o \ # this includes only the low level parse code, not stuff # that requires knowledge of security contexts -RPC_PARSE_OBJ1 = rpc_parse/parse_prs.o rpc_parse/parse_misc.o +RPC_PARSE_OBJ1 = rpc_parse/parse_prs.o RPC_PARSE_OBJ2 = rpc_client/init_netlogon.o \ rpc_client/init_lsa.o diff --git a/source3/include/proto.h b/source3/include/proto.h index cb01c38a30..a9ae3d6973 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5018,10 +5018,6 @@ NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, const struct ndr_interface_table *table, uint32 opnum, void *r); -/* The following definitions come from rpc_parse/parse_misc.c */ - -bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth); - /* The following definitions come from rpc_parse/parse_prs.c */ void prs_dump(const char *name, int v, prs_struct *ps); diff --git a/source3/registry/regfio.c b/source3/registry/regfio.c index d64eab84f9..5ba936273d 100644 --- a/source3/registry/regfio.c +++ b/source3/registry/regfio.c @@ -31,6 +31,38 @@ * ******************************************************************/ +/******************************************************************* + Reads or writes an NTTIME structure. +********************************************************************/ + +static bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth) +{ + uint32 low, high; + if (nttime == NULL) + return False; + + prs_debug(ps, depth, desc, "smb_io_time"); + depth++; + + if(!prs_align(ps)) + return False; + + if (MARSHALLING(ps)) { + low = *nttime & 0xFFFFFFFF; + high = *nttime >> 32; + } + + if(!prs_uint32("low ", ps, depth, &low)) /* low part */ + return False; + if(!prs_uint32("high", ps, depth, &high)) /* high part */ + return False; + + if (UNMARSHALLING(ps)) { + *nttime = (((uint64_t)high << 32) + low); + } + + return True; +} /******************************************************************* *******************************************************************/ diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c deleted file mode 100644 index 21b4e56e54..0000000000 --- a/source3/rpc_parse/parse_misc.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1997, - * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, - * Copyright (C) Paul Ashton 1997. - * Copyright (C) Gerald (Jerry) Carter 2005 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include "includes.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_PARSE - -/******************************************************************* - Reads or writes an NTTIME structure. -********************************************************************/ - -bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth) -{ - uint32 low, high; - if (nttime == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_time"); - depth++; - - if(!prs_align(ps)) - return False; - - if (MARSHALLING(ps)) { - low = *nttime & 0xFFFFFFFF; - high = *nttime >> 32; - } - - if(!prs_uint32("low ", ps, depth, &low)) /* low part */ - return False; - if(!prs_uint32("high", ps, depth, &high)) /* high part */ - return False; - - if (UNMARSHALLING(ps)) { - *nttime = (((uint64_t)high << 32) + low); - } - - return True; -} -- cgit From 53945a2e990df92cdee8b54b3d1c3ade0305e99c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 15 Jul 2010 16:54:14 -0400 Subject: s3-dcerpc: Use a local function to dump pdu regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/rpc_parse/parse_prs.c | 1 - source3/rpc_server/srv_pipe.c | 54 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 6 deletions(-) (limited to 'source3') diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index f8ae8d1d64..ebe1f4ec55 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -21,7 +21,6 @@ */ #include "includes.h" -#include "../librpc/gen_ndr/ndr_schannel.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_PARSE diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index eae8a7dbf2..6d37ec2bc2 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -37,6 +37,51 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV +/** + * Dump everything from the start of the end up of the provided data + * into a file, but only at debug level >= 50 + **/ +static void dump_pdu_region(const char *name, int v, + DATA_BLOB *data, size_t start, size_t end) +{ + int fd, i; + char *fname = NULL; + ssize_t sz; + + if (DEBUGLEVEL < 50) return; + + if (start > data->length || end > data->length || start > end) return; + + for (i = 1; i < 100; i++) { + if (v != -1) { + fname = talloc_asprintf(talloc_tos(), + "/tmp/%s_%d.%d.prs", + name, v, i); + } else { + fname = talloc_asprintf(talloc_tos(), + "/tmp/%s_%d.prs", + name, i); + } + if (!fname) { + return; + } + fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644); + if (fd != -1 || errno != EEXIST) break; + } + if (fd != -1) { + sz = write(fd, data->data + start, end - start); + i = close(fd); + if ((sz != end - start) || (i != 0) ) { + DEBUG(0, ("Error writing/closing %s: %ld!=%ld %d\n", + fname, (unsigned long)sz, + (unsigned long)end - start, i)); + } else { + DEBUG(0,("created %s\n", fname)); + } + } + TALLOC_FREE(fname); +} + static void free_pipe_ntlmssp_auth_data(struct pipe_auth_data *auth) { struct auth_ntlmssp_state *a = auth->a_u.auth_ntlmssp_state; @@ -1719,8 +1764,8 @@ static bool api_rpcTNP(pipes_struct *p, struct ncacn_packet *pkt, fstring name; slprintf(name, sizeof(name)-1, "in_%s", get_pipe_name_from_syntax(talloc_tos(), &p->syntax)); - prs_dump_region(name, pkt->u.request.opnum, - p->in_data.data.data, 0, + dump_pdu_region(name, pkt->u.request.opnum, + &p->in_data.data, 0, p->in_data.data.length); } @@ -1775,9 +1820,8 @@ static bool api_rpcTNP(pipes_struct *p, struct ncacn_packet *pkt, fstring name; slprintf(name, sizeof(name)-1, "out_%s", get_pipe_name_from_syntax(talloc_tos(), &p->syntax)); - prs_dump_region(name, pkt->u.request.opnum, - p->out_data.rdata.data, - offset1, + dump_pdu_region(name, pkt->u.request.opnum, + &p->out_data.rdata, offset1, p->out_data.rdata.length); } -- cgit From 7520d8e9263f43e756d73dfd036cab215fe0d5fb Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 15 Jul 2010 17:27:11 -0400 Subject: s3-parse_prs: Remove unuesd functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- source3/include/proto.h | 4 ---- source3/rpc_parse/parse_prs.c | 55 ------------------------------------------- 2 files changed, 59 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index a9ae3d6973..abb498ce4d 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5020,10 +5020,6 @@ NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, /* The following definitions come from rpc_parse/parse_prs.c */ -void prs_dump(const char *name, int v, prs_struct *ps); -void prs_dump_before(const char *name, int v, prs_struct *ps); -void prs_dump_region(const char *name, int v, uint8_t *data_p, - int from_off, int to_off); void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name); bool prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, bool io); void prs_mem_free(prs_struct *ps); diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index ebe1f4ec55..0eecc4c698 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -25,61 +25,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_PARSE -/** - * Dump a prs to a file: from the current location through to the end. - **/ -void prs_dump(const char *name, int v, prs_struct *ps) -{ - prs_dump_region(name, v, - (uint8_t *)ps->data_p, - ps->data_offset, ps->buffer_size); -} - -/** - * Dump from the start of the prs to the current location. - **/ -void prs_dump_before(const char *name, int v, prs_struct *ps) -{ - prs_dump_region(name, v, - (uint8_t *)ps->data_p, - 0, ps->data_offset); -} - -/** - * Dump everything from the start of the prs up to the current location. - **/ -void prs_dump_region(const char *name, int v, uint8_t *data_p, - int from_off, int to_off) -{ - int fd, i; - char *fname = NULL; - ssize_t sz; - if (DEBUGLEVEL < 50) return; - for (i=1;i<100;i++) { - if (v != -1) { - if (asprintf(&fname,"/tmp/%s_%d.%d.prs", name, v, i) < 0) { - return; - } - } else { - if (asprintf(&fname,"/tmp/%s.%d.prs", name, i) < 0) { - return; - } - } - fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644); - if (fd != -1 || errno != EEXIST) break; - } - if (fd != -1) { - sz = write(fd, data_p + from_off, to_off - from_off); - i = close(fd); - if ( (sz != to_off-from_off) || (i != 0) ) { - DEBUG(0,("Error writing/closing %s: %ld!=%ld %d\n", fname, (unsigned long)sz, (unsigned long)to_off-from_off, i )); - } else { - DEBUG(0,("created %s\n", fname)); - } - } - SAFE_FREE(fname); -} - /******************************************************************* Debug output for parsing info -- cgit From f4c6c7e7b8714e8ab6b1245ab95e19133956d83e Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 15 Jul 2010 17:45:29 -0400 Subject: Move the remnants of rpc_parse code under registry/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The registry code is the only last user of this code. Move everything under registry/ and hope someone will get rid od it completely from there in the future. Signed-off-by: Günther Deschner --- source3/Makefile.in | 4 +- source3/include/ntdomain.h | 35 -- source3/include/proto.h | 44 -- source3/include/regfio.h | 1 + source3/include/rpc_dce.h | 3 + source3/registry/reg_parse_prs.c | 867 +++++++++++++++++++++++++++++++++++++ source3/registry/reg_parse_prs.h | 101 +++++ source3/registry/reg_perfcount.h | 2 + source3/registry/regfio.c | 1 + source3/rpc_parse/parse_prs.c | 866 ------------------------------------ source3/rpc_server/srv_winreg_nt.c | 1 + 11 files changed, 978 insertions(+), 947 deletions(-) create mode 100644 source3/registry/reg_parse_prs.c create mode 100644 source3/registry/reg_parse_prs.h delete mode 100644 source3/rpc_parse/parse_prs.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 08d629a754..9676b37927 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -354,7 +354,7 @@ LIBNDR_GEN_OBJ = librpc/gen_ndr/ndr_wkssvc.o \ # this includes only the low level parse code, not stuff # that requires knowledge of security contexts -RPC_PARSE_OBJ1 = rpc_parse/parse_prs.o +REG_PARSE_PRS_OBJ = registry/reg_parse_prs.o RPC_PARSE_OBJ2 = rpc_client/init_netlogon.o \ rpc_client/init_lsa.o @@ -487,7 +487,7 @@ LIBSMB_ERR_OBJ0 = $(NTERR_OBJ) $(DOSERR_OBJ) $(ERRORMAP_OBJ) $(DCE_RPC_ERR_OBJ) LIBSMB_ERR_OBJ1 = ../libcli/auth/smbdes.o ../libcli/auth/smbencrypt.o ../libcli/auth/msrpc_parse.o ../libcli/auth/session.o LIBSMB_ERR_OBJ = $(LIBSMB_ERR_OBJ0) $(LIBSMB_ERR_OBJ1) \ - $(RPC_PARSE_OBJ1) \ + $(REG_PARSE_PRS_OBJ) \ $(SECRETS_OBJ) LIBSMB_OBJ0 = \ diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index 524c9ecc9b..629e51cea3 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -28,41 +28,6 @@ * in the NTDOM branch - it didn't belong there. */ -#define prs_init_empty( _ps_, _ctx_, _io_ ) (void) prs_init((_ps_), 0, (_ctx_), (_io_)) - -typedef struct _prs_struct { - bool io; /* parsing in or out of data stream */ - /* - * If the (incoming) data is big-endian. On output we are - * always little-endian. - */ - bool bigendian_data; - uint8 align; /* data alignment */ - bool is_dynamic; /* Do we own this memory or not ? */ - uint32 data_offset; /* Current working offset into data. */ - uint32 buffer_size; /* Current allocated size of the buffer. */ - uint32 grow_size; /* size requested via prs_grow() calls */ - /* The buffer itself. If "is_dynamic" is true this - * MUST BE TALLOC'ed off mem_ctx. */ - char *data_p; - TALLOC_CTX *mem_ctx; /* When unmarshalling, use this.... */ -} prs_struct; - -/* - * Defines for io member of prs_struct. - */ - -#define MARSHALL 0 -#define UNMARSHALL 1 - -#define MARSHALLING(ps) (!(ps)->io) -#define UNMARSHALLING(ps) ((ps)->io) - -#define RPC_BIG_ENDIAN 1 -#define RPC_LITTLE_ENDIAN 0 - -#define RPC_PARSE_ALIGN 4 - typedef struct _output_data { /* * Raw RPC output data. This does not include RPC headers or footers. diff --git a/source3/include/proto.h b/source3/include/proto.h index abb498ce4d..ad16e7e52f 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5018,50 +5018,6 @@ NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, const struct ndr_interface_table *table, uint32 opnum, void *r); -/* The following definitions come from rpc_parse/parse_prs.c */ - -void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name); -bool prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, bool io); -void prs_mem_free(prs_struct *ps); -void prs_mem_clear(prs_struct *ps); -char *prs_alloc_mem_(prs_struct *ps, size_t size, unsigned int count); -char *prs_alloc_mem(prs_struct *ps, size_t size, unsigned int count); -TALLOC_CTX *prs_get_mem_context(prs_struct *ps); -void prs_give_memory(prs_struct *ps, char *buf, uint32 size, bool is_dynamic); -bool prs_set_buffer_size(prs_struct *ps, uint32 newsize); -bool prs_grow(prs_struct *ps, uint32 extra_space); -bool prs_force_grow(prs_struct *ps, uint32 extra_space); -char *prs_data_p(prs_struct *ps); -uint32 prs_data_size(prs_struct *ps); -uint32 prs_offset(prs_struct *ps); -bool prs_set_offset(prs_struct *ps, uint32 offset); -bool prs_append_prs_data(prs_struct *dst, prs_struct *src); -bool prs_append_some_data(prs_struct *dst, void *src_base, uint32_t start, - uint32_t len); -bool prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, uint32 len); -bool prs_copy_data_in(prs_struct *dst, const char *src, uint32 len); -bool prs_copy_data_out(char *dst, prs_struct *src, uint32 len); -bool prs_copy_all_data_out(char *dst, prs_struct *src); -void prs_set_endian_data(prs_struct *ps, bool endian); -bool prs_align(prs_struct *ps); -bool prs_align_uint16(prs_struct *ps); -bool prs_align_uint64(prs_struct *ps); -bool prs_align_custom(prs_struct *ps, uint8 boundary); -bool prs_align_needed(prs_struct *ps, uint32 needed); -char *prs_mem_get(prs_struct *ps, uint32 extra_size); -void prs_switch_type(prs_struct *ps, bool io); -bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8); -bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16); -bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32); -bool prs_int32(const char *name, prs_struct *ps, int depth, int32 *data32); -bool prs_uint64(const char *name, prs_struct *ps, int depth, uint64 *data64); -bool prs_dcerpc_status(const char *name, prs_struct *ps, int depth, NTSTATUS *status); -bool prs_uint8s(bool charmode, const char *name, prs_struct *ps, int depth, uint8 *data8s, int len); -bool prs_uint16s(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len); -bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uint32 *data32s, int len); -bool prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx); -bool prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx); - /* The following definitions come from rpc_server/srv_eventlog_nt.c */ /* The following definitions come from rpc_server/rpc_handles.c */ diff --git a/source3/include/regfio.h b/source3/include/regfio.h index 840fbcd89a..f2d952b169 100644 --- a/source3/include/regfio.h +++ b/source3/include/regfio.h @@ -23,6 +23,7 @@ * Thanks Nigel! ***********************************************************/ +#include "registry/reg_parse_prs.h" #ifndef _REGFIO_H #define _REGFIO_H diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index 4a4068be6f..7be8a8a6f7 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -33,4 +33,7 @@ #define RPC_HEADER_LEN 16 +#define RPC_BIG_ENDIAN 1 +#define RPC_LITTLE_ENDIAN 0 + #endif /* _DCE_RPC_H */ diff --git a/source3/registry/reg_parse_prs.c b/source3/registry/reg_parse_prs.c new file mode 100644 index 0000000000..c1b941bbae --- /dev/null +++ b/source3/registry/reg_parse_prs.c @@ -0,0 +1,867 @@ +/* + Unix SMB/CIFS implementation. + Samba memory buffer functions + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Jeremy Allison 1999 + Copyright (C) Andrew Bartlett 2003. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "reg_parse_prs.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_PARSE + +/******************************************************************* + Debug output for parsing info + + XXXX side-effect of this function is to increase the debug depth XXXX. + +********************************************************************/ + +void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name) +{ + DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(5+depth,depth), ps->data_offset, fn_name, desc)); +} + +/** + * Initialise an expandable parse structure. + * + * @param size Initial buffer size. If >0, a new buffer will be + * created with talloc(). + * + * @return False if allocation fails, otherwise True. + **/ + +bool prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, bool io) +{ + ZERO_STRUCTP(ps); + ps->io = io; + ps->bigendian_data = RPC_LITTLE_ENDIAN; + ps->align = RPC_PARSE_ALIGN; + ps->is_dynamic = False; + ps->data_offset = 0; + ps->buffer_size = 0; + ps->data_p = NULL; + ps->mem_ctx = ctx; + + if (size != 0) { + ps->buffer_size = size; + ps->data_p = (char *)talloc_zero_size(ps->mem_ctx, size); + if(ps->data_p == NULL) { + DEBUG(0,("prs_init: talloc fail for %u bytes.\n", (unsigned int)size)); + return False; + } + ps->is_dynamic = True; /* We own this memory. */ + } else if (MARSHALLING(ps)) { + /* If size is zero and we're marshalling we should allocate memory on demand. */ + ps->is_dynamic = True; + } + + return True; +} + +/******************************************************************* + Delete the memory in a parse structure - if we own it. + + NOTE: Contrary to the somewhat confusing naming, this function is not + intended for freeing memory allocated by prs_alloc_mem(). + That memory is also attached to the talloc context given by + ps->mem_ctx, but is only freed when that talloc context is + freed. prs_mem_free() is used to delete "dynamic" memory + allocated in marshalling/unmarshalling. + ********************************************************************/ + +void prs_mem_free(prs_struct *ps) +{ + if(ps->is_dynamic) { + TALLOC_FREE(ps->data_p); + } + ps->is_dynamic = False; + ps->buffer_size = 0; + ps->data_offset = 0; +} + +/******************************************************************* + Clear the memory in a parse structure. + ********************************************************************/ + +void prs_mem_clear(prs_struct *ps) +{ + if (ps->buffer_size) + memset(ps->data_p, '\0', (size_t)ps->buffer_size); +} + +/******************************************************************* + Allocate memory when unmarshalling... Always zero clears. + ********************************************************************/ + +#if defined(PARANOID_MALLOC_CHECKER) +char *prs_alloc_mem_(prs_struct *ps, size_t size, unsigned int count) +#else +char *prs_alloc_mem(prs_struct *ps, size_t size, unsigned int count) +#endif +{ + char *ret = NULL; + + if (size && count) { + /* We can't call the type-safe version here. */ + ret = (char *)_talloc_zero_array(ps->mem_ctx, size, count, + "parse_prs"); + } + return ret; +} + +/******************************************************************* + Return the current talloc context we're using. + ********************************************************************/ + +TALLOC_CTX *prs_get_mem_context(prs_struct *ps) +{ + return ps->mem_ctx; +} + +/******************************************************************* + Hand some already allocated memory to a prs_struct. + If "is_dynamic" is true, this is a talloc_steal. + If "is_dynamic" is false, just make ps->data_p a pointer to + the unwritable memory. + ********************************************************************/ + +void prs_give_memory(prs_struct *ps, char *buf, uint32 size, bool is_dynamic) +{ + ps->is_dynamic = is_dynamic; + if (ps->is_dynamic && buf) { + talloc_steal(ps->mem_ctx, buf); + } + ps->data_p = buf; + ps->buffer_size = size; +} + +/******************************************************************* + Set a prs_struct to exactly a given size. Will grow or tuncate if neccessary. + ********************************************************************/ + +bool prs_set_buffer_size(prs_struct *ps, uint32 newsize) +{ + if (newsize > ps->buffer_size) + return prs_force_grow(ps, newsize - ps->buffer_size); + + if (newsize < ps->buffer_size) { + ps->buffer_size = newsize; + + /* newsize == 0 acts as a free and set pointer to NULL */ + if (newsize == 0) { + TALLOC_FREE(ps->data_p); + } else { + ps->data_p = talloc_realloc(ps->mem_ctx, + ps->data_p, + char, + newsize); + + if (ps->data_p == NULL) { + DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n", + (unsigned int)newsize)); + return False; + } + } + } + + return True; +} + +/******************************************************************* + Attempt, if needed, to grow a data buffer. + Also depends on the data stream mode (io). + ********************************************************************/ + +bool prs_grow(prs_struct *ps, uint32 extra_space) +{ + uint32 new_size; + + ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space); + + if(ps->data_offset + extra_space <= ps->buffer_size) + return True; + + /* + * We cannot grow the buffer if we're not reading + * into the prs_struct, or if we don't own the memory. + */ + + if(UNMARSHALLING(ps) || !ps->is_dynamic) { + DEBUG(0,("prs_grow: Buffer overflow - unable to expand buffer by %u bytes.\n", + (unsigned int)extra_space)); + return False; + } + + /* + * Decide how much extra space we really need. + */ + + extra_space -= (ps->buffer_size - ps->data_offset); + if(ps->buffer_size == 0) { + + /* + * Start with 128 bytes (arbitrary value), enough for small rpc + * requests + */ + new_size = MAX(128, extra_space); + + ps->data_p = (char *)talloc_zero_size(ps->mem_ctx, new_size); + if(ps->data_p == NULL) { + DEBUG(0,("prs_grow: talloc failure for size %u.\n", (unsigned int)new_size)); + return False; + } + } else { + /* + * If the current buffer size is bigger than the space needed, + * just double it, else add extra_space. Always keep 64 bytes + * more, so that after we added a large blob we don't have to + * realloc immediately again. + */ + new_size = MAX(ps->buffer_size*2, + ps->buffer_size + extra_space + 64); + + ps->data_p = talloc_realloc(ps->mem_ctx, + ps->data_p, + char, + new_size); + if (ps->data_p == NULL) { + DEBUG(0,("prs_grow: Realloc failure for size %u.\n", + (unsigned int)new_size)); + return False; + } + + memset(&ps->data_p[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size)); + } + ps->buffer_size = new_size; + + return True; +} + +/******************************************************************* + Attempt to force a data buffer to grow by len bytes. + This is only used when appending more data onto a prs_struct + when reading an rpc reply, before unmarshalling it. + ********************************************************************/ + +bool prs_force_grow(prs_struct *ps, uint32 extra_space) +{ + uint32 new_size = ps->buffer_size + extra_space; + + if(!UNMARSHALLING(ps) || !ps->is_dynamic) { + DEBUG(0,("prs_force_grow: Buffer overflow - unable to expand buffer by %u bytes.\n", + (unsigned int)extra_space)); + return False; + } + + ps->data_p = (char *)talloc_realloc(ps->mem_ctx, + ps->data_p, + char, + new_size); + if(ps->data_p == NULL) { + DEBUG(0,("prs_force_grow: Realloc failure for size %u.\n", + (unsigned int)new_size)); + return False; + } + + memset(&ps->data_p[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size)); + + ps->buffer_size = new_size; + + return True; +} + +/******************************************************************* + Get the data pointer (external interface). +********************************************************************/ + +char *prs_data_p(prs_struct *ps) +{ + return ps->data_p; +} + +/******************************************************************* + Get the current data size (external interface). + ********************************************************************/ + +uint32 prs_data_size(prs_struct *ps) +{ + return ps->buffer_size; +} + +/******************************************************************* + Fetch the current offset (external interface). + ********************************************************************/ + +uint32 prs_offset(prs_struct *ps) +{ + return ps->data_offset; +} + +/******************************************************************* + Set the current offset (external interface). + ********************************************************************/ + +bool prs_set_offset(prs_struct *ps, uint32 offset) +{ + if ((offset > ps->data_offset) + && !prs_grow(ps, offset - ps->data_offset)) { + return False; + } + + ps->data_offset = offset; + return True; +} + +/******************************************************************* + Append the data from one parse_struct into another. + ********************************************************************/ + +bool prs_append_prs_data(prs_struct *dst, prs_struct *src) +{ + if (prs_offset(src) == 0) + return True; + + if(!prs_grow(dst, prs_offset(src))) + return False; + + memcpy(&dst->data_p[dst->data_offset], src->data_p, (size_t)prs_offset(src)); + dst->data_offset += prs_offset(src); + + return True; +} + +/******************************************************************* + Append some data from one parse_struct into another. + ********************************************************************/ + +bool prs_append_some_data(prs_struct *dst, void *src_base, uint32_t start, + uint32_t len) +{ + if (len == 0) { + return true; + } + + if(!prs_grow(dst, len)) { + return false; + } + + memcpy(&dst->data_p[dst->data_offset], ((char *)src_base) + start, (size_t)len); + dst->data_offset += len; + return true; +} + +bool prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, + uint32 len) +{ + return prs_append_some_data(dst, src->data_p, start, len); +} + +/******************************************************************* + Append the data from a buffer into a parse_struct. + ********************************************************************/ + +bool prs_copy_data_in(prs_struct *dst, const char *src, uint32 len) +{ + if (len == 0) + return True; + + if(!prs_grow(dst, len)) + return False; + + memcpy(&dst->data_p[dst->data_offset], src, (size_t)len); + dst->data_offset += len; + + return True; +} + +/******************************************************************* + Copy some data from a parse_struct into a buffer. + ********************************************************************/ + +bool prs_copy_data_out(char *dst, prs_struct *src, uint32 len) +{ + if (len == 0) + return True; + + if(!prs_mem_get(src, len)) + return False; + + memcpy(dst, &src->data_p[src->data_offset], (size_t)len); + src->data_offset += len; + + return True; +} + +/******************************************************************* + Copy all the data from a parse_struct into a buffer. + ********************************************************************/ + +bool prs_copy_all_data_out(char *dst, prs_struct *src) +{ + uint32 len = prs_offset(src); + + if (!len) + return True; + + prs_set_offset(src, 0); + return prs_copy_data_out(dst, src, len); +} + +/******************************************************************* + Set the data as X-endian (external interface). + ********************************************************************/ + +void prs_set_endian_data(prs_struct *ps, bool endian) +{ + ps->bigendian_data = endian; +} + +/******************************************************************* + Align a the data_len to a multiple of align bytes - filling with + zeros. + ********************************************************************/ + +bool prs_align(prs_struct *ps) +{ + uint32 mod = ps->data_offset & (ps->align-1); + + if (ps->align != 0 && mod != 0) { + uint32 extra_space = (ps->align - mod); + if(!prs_grow(ps, extra_space)) + return False; + memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space); + ps->data_offset += extra_space; + } + + return True; +} + +/****************************************************************** + Align on a 2 byte boundary + *****************************************************************/ + +bool prs_align_uint16(prs_struct *ps) +{ + bool ret; + uint8 old_align = ps->align; + + ps->align = 2; + ret = prs_align(ps); + ps->align = old_align; + + return ret; +} + +/****************************************************************** + Align on a 8 byte boundary + *****************************************************************/ + +bool prs_align_uint64(prs_struct *ps) +{ + bool ret; + uint8 old_align = ps->align; + + ps->align = 8; + ret = prs_align(ps); + ps->align = old_align; + + return ret; +} + +/****************************************************************** + Align on a specific byte boundary + *****************************************************************/ + +bool prs_align_custom(prs_struct *ps, uint8 boundary) +{ + bool ret; + uint8 old_align = ps->align; + + ps->align = boundary; + ret = prs_align(ps); + ps->align = old_align; + + return ret; +} + + + +/******************************************************************* + Align only if required (for the unistr2 string mainly) + ********************************************************************/ + +bool prs_align_needed(prs_struct *ps, uint32 needed) +{ + if (needed==0) + return True; + else + return prs_align(ps); +} + +/******************************************************************* + Ensure we can read/write to a given offset. + ********************************************************************/ + +char *prs_mem_get(prs_struct *ps, uint32 extra_size) +{ + if(UNMARSHALLING(ps)) { + /* + * If reading, ensure that we can read the requested size item. + */ + if (ps->data_offset + extra_size > ps->buffer_size) { + DEBUG(0,("prs_mem_get: reading data of size %u would overrun " + "buffer by %u bytes.\n", + (unsigned int)extra_size, + (unsigned int)(ps->data_offset + extra_size - ps->buffer_size) )); + return NULL; + } + } else { + /* + * Writing - grow the buffer if needed. + */ + if(!prs_grow(ps, extra_size)) + return NULL; + } + return &ps->data_p[ps->data_offset]; +} + +/******************************************************************* + Change the struct type. + ********************************************************************/ + +void prs_switch_type(prs_struct *ps, bool io) +{ + if ((ps->io ^ io) == True) + ps->io=io; +} + +/******************************************************************* + Stream a uint8. + ********************************************************************/ + +bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8) +{ + char *q = prs_mem_get(ps, 1); + if (q == NULL) + return False; + + if (UNMARSHALLING(ps)) + *data8 = CVAL(q,0); + else + SCVAL(q,0,*data8); + + DEBUGADD(5,("%s%04x %s: %02x\n", tab_depth(5,depth), ps->data_offset, name, *data8)); + + ps->data_offset += 1; + + return True; +} + +/******************************************************************* + Stream a uint16. + ********************************************************************/ + +bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16) +{ + char *q = prs_mem_get(ps, sizeof(uint16)); + if (q == NULL) + return False; + + if (UNMARSHALLING(ps)) { + if (ps->bigendian_data) + *data16 = RSVAL(q,0); + else + *data16 = SVAL(q,0); + } else { + if (ps->bigendian_data) + RSSVAL(q,0,*data16); + else + SSVAL(q,0,*data16); + } + + DEBUGADD(5,("%s%04x %s: %04x\n", tab_depth(5,depth), ps->data_offset, name, *data16)); + + ps->data_offset += sizeof(uint16); + + return True; +} + +/******************************************************************* + Stream a uint32. + ********************************************************************/ + +bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32) +{ + char *q = prs_mem_get(ps, sizeof(uint32)); + if (q == NULL) + return False; + + if (UNMARSHALLING(ps)) { + if (ps->bigendian_data) + *data32 = RIVAL(q,0); + else + *data32 = IVAL(q,0); + } else { + if (ps->bigendian_data) + RSIVAL(q,0,*data32); + else + SIVAL(q,0,*data32); + } + + DEBUGADD(5,("%s%04x %s: %08x\n", tab_depth(5,depth), ps->data_offset, name, *data32)); + + ps->data_offset += sizeof(uint32); + + return True; +} + +/******************************************************************* + Stream an int32. + ********************************************************************/ + +bool prs_int32(const char *name, prs_struct *ps, int depth, int32 *data32) +{ + char *q = prs_mem_get(ps, sizeof(int32)); + if (q == NULL) + return False; + + if (UNMARSHALLING(ps)) { + if (ps->bigendian_data) + *data32 = RIVALS(q,0); + else + *data32 = IVALS(q,0); + } else { + if (ps->bigendian_data) + RSIVALS(q,0,*data32); + else + SIVALS(q,0,*data32); + } + + DEBUGADD(5,("%s%04x %s: %08x\n", tab_depth(5,depth), ps->data_offset, name, *data32)); + + ps->data_offset += sizeof(int32); + + return True; +} + +/******************************************************************* + Stream a uint64_struct + ********************************************************************/ +bool prs_uint64(const char *name, prs_struct *ps, int depth, uint64 *data64) +{ + if (UNMARSHALLING(ps)) { + uint32 high, low; + + if (!prs_uint32(name, ps, depth+1, &low)) + return False; + + if (!prs_uint32(name, ps, depth+1, &high)) + return False; + + *data64 = ((uint64_t)high << 32) + low; + + return True; + } else { + uint32 high = (*data64) >> 32, low = (*data64) & 0xFFFFFFFF; + return prs_uint32(name, ps, depth+1, &low) && + prs_uint32(name, ps, depth+1, &high); + } +} + +/******************************************************************* + Stream a DCE error code + ********************************************************************/ + +bool prs_dcerpc_status(const char *name, prs_struct *ps, int depth, NTSTATUS *status) +{ + char *q = prs_mem_get(ps, sizeof(uint32)); + if (q == NULL) + return False; + + if (UNMARSHALLING(ps)) { + if (ps->bigendian_data) + *status = NT_STATUS(RIVAL(q,0)); + else + *status = NT_STATUS(IVAL(q,0)); + } else { + if (ps->bigendian_data) + RSIVAL(q,0,NT_STATUS_V(*status)); + else + SIVAL(q,0,NT_STATUS_V(*status)); + } + + DEBUGADD(5,("%s%04x %s: %s\n", tab_depth(5,depth), ps->data_offset, name, + dcerpc_errstr(talloc_tos(), NT_STATUS_V(*status)))); + + ps->data_offset += sizeof(uint32); + + return True; +} + +/****************************************************************** + Stream an array of uint8s. Length is number of uint8s. + ********************************************************************/ + +bool prs_uint8s(bool charmode, const char *name, prs_struct *ps, int depth, uint8 *data8s, int len) +{ + int i; + char *q = prs_mem_get(ps, len); + if (q == NULL) + return False; + + if (UNMARSHALLING(ps)) { + for (i = 0; i < len; i++) + data8s[i] = CVAL(q,i); + } else { + for (i = 0; i < len; i++) + SCVAL(q, i, data8s[i]); + } + + DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset ,name)); + if (charmode) + print_asc(5, (unsigned char*)data8s, len); + else { + for (i = 0; i < len; i++) + DEBUGADD(5,("%02x ", data8s[i])); + } + DEBUGADD(5,("\n")); + + ps->data_offset += len; + + return True; +} + +/****************************************************************** + Stream an array of uint16s. Length is number of uint16s. + ********************************************************************/ + +bool prs_uint16s(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len) +{ + int i; + char *q = prs_mem_get(ps, len * sizeof(uint16)); + if (q == NULL) + return False; + + if (UNMARSHALLING(ps)) { + if (ps->bigendian_data) { + for (i = 0; i < len; i++) + data16s[i] = RSVAL(q, 2*i); + } else { + for (i = 0; i < len; i++) + data16s[i] = SVAL(q, 2*i); + } + } else { + if (ps->bigendian_data) { + for (i = 0; i < len; i++) + RSSVAL(q, 2*i, data16s[i]); + } else { + for (i = 0; i < len; i++) + SSVAL(q, 2*i, data16s[i]); + } + } + + DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); + if (charmode) + print_asc(5, (unsigned char*)data16s, 2*len); + else { + for (i = 0; i < len; i++) + DEBUGADD(5,("%04x ", data16s[i])); + } + DEBUGADD(5,("\n")); + + ps->data_offset += (len * sizeof(uint16)); + + return True; +} + +/****************************************************************** + Stream an array of uint32s. Length is number of uint32s. + ********************************************************************/ + +bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uint32 *data32s, int len) +{ + int i; + char *q = prs_mem_get(ps, len * sizeof(uint32)); + if (q == NULL) + return False; + + if (UNMARSHALLING(ps)) { + if (ps->bigendian_data) { + for (i = 0; i < len; i++) + data32s[i] = RIVAL(q, 4*i); + } else { + for (i = 0; i < len; i++) + data32s[i] = IVAL(q, 4*i); + } + } else { + if (ps->bigendian_data) { + for (i = 0; i < len; i++) + RSIVAL(q, 4*i, data32s[i]); + } else { + for (i = 0; i < len; i++) + SIVAL(q, 4*i, data32s[i]); + } + } + + DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); + if (charmode) + print_asc(5, (unsigned char*)data32s, 4*len); + else { + for (i = 0; i < len; i++) + DEBUGADD(5,("%08x ", data32s[i])); + } + DEBUGADD(5,("\n")); + + ps->data_offset += (len * sizeof(uint32)); + + return True; +} + +/******************************************************************* +creates a new prs_struct containing a DATA_BLOB +********************************************************************/ +bool prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx) +{ + if (!prs_init( prs, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL )) + return False; + + + if (!prs_copy_data_in(prs, (char *)blob->data, blob->length)) + return False; + + return True; +} + +/******************************************************************* +return the contents of a prs_struct in a DATA_BLOB +********************************************************************/ +bool prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx) +{ + blob->length = prs_data_size(prs); + blob->data = (uint8 *)TALLOC_ZERO_SIZE(mem_ctx, blob->length); + + /* set the pointer at the end of the buffer */ + prs_set_offset( prs, prs_data_size(prs) ); + + if (!prs_copy_all_data_out((char *)blob->data, prs)) + return False; + + return True; +} diff --git a/source3/registry/reg_parse_prs.h b/source3/registry/reg_parse_prs.h new file mode 100644 index 0000000000..0dd475a026 --- /dev/null +++ b/source3/registry/reg_parse_prs.h @@ -0,0 +1,101 @@ +/* + Unix SMB/CIFS implementation. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 + Copyright (C) Jeremy Allison 2000-2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _REG_PARSE_PRS_H_ +#define _REG_PARSE_PRS_H_ + + +#define prs_init_empty( _ps_, _ctx_, _io_ ) (void) prs_init((_ps_), 0, (_ctx_), (_io_)) + +typedef struct _prs_struct { + bool io; /* parsing in or out of data stream */ + /* + * If the (incoming) data is big-endian. On output we are + * always little-endian. + */ + bool bigendian_data; + uint8 align; /* data alignment */ + bool is_dynamic; /* Do we own this memory or not ? */ + uint32 data_offset; /* Current working offset into data. */ + uint32 buffer_size; /* Current allocated size of the buffer. */ + uint32 grow_size; /* size requested via prs_grow() calls */ + /* The buffer itself. If "is_dynamic" is true this + * MUST BE TALLOC'ed off mem_ctx. */ + char *data_p; + TALLOC_CTX *mem_ctx; /* When unmarshalling, use this.... */ +} prs_struct; + +/* + * Defines for io member of prs_struct. + */ + +#define MARSHALL 0 +#define UNMARSHALL 1 + +#define MARSHALLING(ps) (!(ps)->io) +#define UNMARSHALLING(ps) ((ps)->io) + +#define RPC_PARSE_ALIGN 4 + +void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name); +bool prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, bool io); +void prs_mem_free(prs_struct *ps); +void prs_mem_clear(prs_struct *ps); +char *prs_alloc_mem_(prs_struct *ps, size_t size, unsigned int count); +char *prs_alloc_mem(prs_struct *ps, size_t size, unsigned int count); +TALLOC_CTX *prs_get_mem_context(prs_struct *ps); +void prs_give_memory(prs_struct *ps, char *buf, uint32 size, bool is_dynamic); +bool prs_set_buffer_size(prs_struct *ps, uint32 newsize); +bool prs_grow(prs_struct *ps, uint32 extra_space); +bool prs_force_grow(prs_struct *ps, uint32 extra_space); +char *prs_data_p(prs_struct *ps); +uint32 prs_data_size(prs_struct *ps); +uint32 prs_offset(prs_struct *ps); +bool prs_set_offset(prs_struct *ps, uint32 offset); +bool prs_append_prs_data(prs_struct *dst, prs_struct *src); +bool prs_append_some_data(prs_struct *dst, void *src_base, uint32_t start, + uint32_t len); +bool prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, uint32 len); +bool prs_copy_data_in(prs_struct *dst, const char *src, uint32 len); +bool prs_copy_data_out(char *dst, prs_struct *src, uint32 len); +bool prs_copy_all_data_out(char *dst, prs_struct *src); +void prs_set_endian_data(prs_struct *ps, bool endian); +bool prs_align(prs_struct *ps); +bool prs_align_uint16(prs_struct *ps); +bool prs_align_uint64(prs_struct *ps); +bool prs_align_custom(prs_struct *ps, uint8 boundary); +bool prs_align_needed(prs_struct *ps, uint32 needed); +char *prs_mem_get(prs_struct *ps, uint32 extra_size); +void prs_switch_type(prs_struct *ps, bool io); +bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8); +bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16); +bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32); +bool prs_int32(const char *name, prs_struct *ps, int depth, int32 *data32); +bool prs_uint64(const char *name, prs_struct *ps, int depth, uint64 *data64); +bool prs_dcerpc_status(const char *name, prs_struct *ps, int depth, NTSTATUS *status); +bool prs_uint8s(bool charmode, const char *name, prs_struct *ps, int depth, uint8 *data8s, int len); +bool prs_uint16s(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len); +bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uint32 *data32s, int len); +bool prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx); +bool prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx); + +#endif diff --git a/source3/registry/reg_perfcount.h b/source3/registry/reg_perfcount.h index c6b76a5360..671153f21c 100644 --- a/source3/registry/reg_perfcount.h +++ b/source3/registry/reg_perfcount.h @@ -22,6 +22,8 @@ #ifndef _REG_PERFCOUNT_H #define _REG_PERFCOUNT_H +#include "reg_parse_prs.h" + void perfcount_init_keys( void ); uint32 reg_perfcount_get_base_index(void); uint32 reg_perfcount_get_last_counter(uint32 base_index); diff --git a/source3/registry/regfio.c b/source3/registry/regfio.c index 5ba936273d..7a362d205e 100644 --- a/source3/registry/regfio.c +++ b/source3/registry/regfio.c @@ -18,6 +18,7 @@ */ #include "includes.h" +#include "reg_parse_prs.h" #include "regfio.h" #include "reg_objects.h" #include "../librpc/gen_ndr/ndr_security.h" diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c deleted file mode 100644 index 0eecc4c698..0000000000 --- a/source3/rpc_parse/parse_prs.c +++ /dev/null @@ -1,866 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba memory buffer functions - Copyright (C) Andrew Tridgell 1992-1997 - Copyright (C) Luke Kenneth Casson Leighton 1996-1997 - Copyright (C) Jeremy Allison 1999 - Copyright (C) Andrew Bartlett 2003. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_PARSE - -/******************************************************************* - Debug output for parsing info - - XXXX side-effect of this function is to increase the debug depth XXXX. - -********************************************************************/ - -void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name) -{ - DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(5+depth,depth), ps->data_offset, fn_name, desc)); -} - -/** - * Initialise an expandable parse structure. - * - * @param size Initial buffer size. If >0, a new buffer will be - * created with talloc(). - * - * @return False if allocation fails, otherwise True. - **/ - -bool prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, bool io) -{ - ZERO_STRUCTP(ps); - ps->io = io; - ps->bigendian_data = RPC_LITTLE_ENDIAN; - ps->align = RPC_PARSE_ALIGN; - ps->is_dynamic = False; - ps->data_offset = 0; - ps->buffer_size = 0; - ps->data_p = NULL; - ps->mem_ctx = ctx; - - if (size != 0) { - ps->buffer_size = size; - ps->data_p = (char *)talloc_zero_size(ps->mem_ctx, size); - if(ps->data_p == NULL) { - DEBUG(0,("prs_init: talloc fail for %u bytes.\n", (unsigned int)size)); - return False; - } - ps->is_dynamic = True; /* We own this memory. */ - } else if (MARSHALLING(ps)) { - /* If size is zero and we're marshalling we should allocate memory on demand. */ - ps->is_dynamic = True; - } - - return True; -} - -/******************************************************************* - Delete the memory in a parse structure - if we own it. - - NOTE: Contrary to the somewhat confusing naming, this function is not - intended for freeing memory allocated by prs_alloc_mem(). - That memory is also attached to the talloc context given by - ps->mem_ctx, but is only freed when that talloc context is - freed. prs_mem_free() is used to delete "dynamic" memory - allocated in marshalling/unmarshalling. - ********************************************************************/ - -void prs_mem_free(prs_struct *ps) -{ - if(ps->is_dynamic) { - TALLOC_FREE(ps->data_p); - } - ps->is_dynamic = False; - ps->buffer_size = 0; - ps->data_offset = 0; -} - -/******************************************************************* - Clear the memory in a parse structure. - ********************************************************************/ - -void prs_mem_clear(prs_struct *ps) -{ - if (ps->buffer_size) - memset(ps->data_p, '\0', (size_t)ps->buffer_size); -} - -/******************************************************************* - Allocate memory when unmarshalling... Always zero clears. - ********************************************************************/ - -#if defined(PARANOID_MALLOC_CHECKER) -char *prs_alloc_mem_(prs_struct *ps, size_t size, unsigned int count) -#else -char *prs_alloc_mem(prs_struct *ps, size_t size, unsigned int count) -#endif -{ - char *ret = NULL; - - if (size && count) { - /* We can't call the type-safe version here. */ - ret = (char *)_talloc_zero_array(ps->mem_ctx, size, count, - "parse_prs"); - } - return ret; -} - -/******************************************************************* - Return the current talloc context we're using. - ********************************************************************/ - -TALLOC_CTX *prs_get_mem_context(prs_struct *ps) -{ - return ps->mem_ctx; -} - -/******************************************************************* - Hand some already allocated memory to a prs_struct. - If "is_dynamic" is true, this is a talloc_steal. - If "is_dynamic" is false, just make ps->data_p a pointer to - the unwritable memory. - ********************************************************************/ - -void prs_give_memory(prs_struct *ps, char *buf, uint32 size, bool is_dynamic) -{ - ps->is_dynamic = is_dynamic; - if (ps->is_dynamic && buf) { - talloc_steal(ps->mem_ctx, buf); - } - ps->data_p = buf; - ps->buffer_size = size; -} - -/******************************************************************* - Set a prs_struct to exactly a given size. Will grow or tuncate if neccessary. - ********************************************************************/ - -bool prs_set_buffer_size(prs_struct *ps, uint32 newsize) -{ - if (newsize > ps->buffer_size) - return prs_force_grow(ps, newsize - ps->buffer_size); - - if (newsize < ps->buffer_size) { - ps->buffer_size = newsize; - - /* newsize == 0 acts as a free and set pointer to NULL */ - if (newsize == 0) { - TALLOC_FREE(ps->data_p); - } else { - ps->data_p = talloc_realloc(ps->mem_ctx, - ps->data_p, - char, - newsize); - - if (ps->data_p == NULL) { - DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n", - (unsigned int)newsize)); - return False; - } - } - } - - return True; -} - -/******************************************************************* - Attempt, if needed, to grow a data buffer. - Also depends on the data stream mode (io). - ********************************************************************/ - -bool prs_grow(prs_struct *ps, uint32 extra_space) -{ - uint32 new_size; - - ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space); - - if(ps->data_offset + extra_space <= ps->buffer_size) - return True; - - /* - * We cannot grow the buffer if we're not reading - * into the prs_struct, or if we don't own the memory. - */ - - if(UNMARSHALLING(ps) || !ps->is_dynamic) { - DEBUG(0,("prs_grow: Buffer overflow - unable to expand buffer by %u bytes.\n", - (unsigned int)extra_space)); - return False; - } - - /* - * Decide how much extra space we really need. - */ - - extra_space -= (ps->buffer_size - ps->data_offset); - if(ps->buffer_size == 0) { - - /* - * Start with 128 bytes (arbitrary value), enough for small rpc - * requests - */ - new_size = MAX(128, extra_space); - - ps->data_p = (char *)talloc_zero_size(ps->mem_ctx, new_size); - if(ps->data_p == NULL) { - DEBUG(0,("prs_grow: talloc failure for size %u.\n", (unsigned int)new_size)); - return False; - } - } else { - /* - * If the current buffer size is bigger than the space needed, - * just double it, else add extra_space. Always keep 64 bytes - * more, so that after we added a large blob we don't have to - * realloc immediately again. - */ - new_size = MAX(ps->buffer_size*2, - ps->buffer_size + extra_space + 64); - - ps->data_p = talloc_realloc(ps->mem_ctx, - ps->data_p, - char, - new_size); - if (ps->data_p == NULL) { - DEBUG(0,("prs_grow: Realloc failure for size %u.\n", - (unsigned int)new_size)); - return False; - } - - memset(&ps->data_p[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size)); - } - ps->buffer_size = new_size; - - return True; -} - -/******************************************************************* - Attempt to force a data buffer to grow by len bytes. - This is only used when appending more data onto a prs_struct - when reading an rpc reply, before unmarshalling it. - ********************************************************************/ - -bool prs_force_grow(prs_struct *ps, uint32 extra_space) -{ - uint32 new_size = ps->buffer_size + extra_space; - - if(!UNMARSHALLING(ps) || !ps->is_dynamic) { - DEBUG(0,("prs_force_grow: Buffer overflow - unable to expand buffer by %u bytes.\n", - (unsigned int)extra_space)); - return False; - } - - ps->data_p = (char *)talloc_realloc(ps->mem_ctx, - ps->data_p, - char, - new_size); - if(ps->data_p == NULL) { - DEBUG(0,("prs_force_grow: Realloc failure for size %u.\n", - (unsigned int)new_size)); - return False; - } - - memset(&ps->data_p[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size)); - - ps->buffer_size = new_size; - - return True; -} - -/******************************************************************* - Get the data pointer (external interface). -********************************************************************/ - -char *prs_data_p(prs_struct *ps) -{ - return ps->data_p; -} - -/******************************************************************* - Get the current data size (external interface). - ********************************************************************/ - -uint32 prs_data_size(prs_struct *ps) -{ - return ps->buffer_size; -} - -/******************************************************************* - Fetch the current offset (external interface). - ********************************************************************/ - -uint32 prs_offset(prs_struct *ps) -{ - return ps->data_offset; -} - -/******************************************************************* - Set the current offset (external interface). - ********************************************************************/ - -bool prs_set_offset(prs_struct *ps, uint32 offset) -{ - if ((offset > ps->data_offset) - && !prs_grow(ps, offset - ps->data_offset)) { - return False; - } - - ps->data_offset = offset; - return True; -} - -/******************************************************************* - Append the data from one parse_struct into another. - ********************************************************************/ - -bool prs_append_prs_data(prs_struct *dst, prs_struct *src) -{ - if (prs_offset(src) == 0) - return True; - - if(!prs_grow(dst, prs_offset(src))) - return False; - - memcpy(&dst->data_p[dst->data_offset], src->data_p, (size_t)prs_offset(src)); - dst->data_offset += prs_offset(src); - - return True; -} - -/******************************************************************* - Append some data from one parse_struct into another. - ********************************************************************/ - -bool prs_append_some_data(prs_struct *dst, void *src_base, uint32_t start, - uint32_t len) -{ - if (len == 0) { - return true; - } - - if(!prs_grow(dst, len)) { - return false; - } - - memcpy(&dst->data_p[dst->data_offset], ((char *)src_base) + start, (size_t)len); - dst->data_offset += len; - return true; -} - -bool prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, - uint32 len) -{ - return prs_append_some_data(dst, src->data_p, start, len); -} - -/******************************************************************* - Append the data from a buffer into a parse_struct. - ********************************************************************/ - -bool prs_copy_data_in(prs_struct *dst, const char *src, uint32 len) -{ - if (len == 0) - return True; - - if(!prs_grow(dst, len)) - return False; - - memcpy(&dst->data_p[dst->data_offset], src, (size_t)len); - dst->data_offset += len; - - return True; -} - -/******************************************************************* - Copy some data from a parse_struct into a buffer. - ********************************************************************/ - -bool prs_copy_data_out(char *dst, prs_struct *src, uint32 len) -{ - if (len == 0) - return True; - - if(!prs_mem_get(src, len)) - return False; - - memcpy(dst, &src->data_p[src->data_offset], (size_t)len); - src->data_offset += len; - - return True; -} - -/******************************************************************* - Copy all the data from a parse_struct into a buffer. - ********************************************************************/ - -bool prs_copy_all_data_out(char *dst, prs_struct *src) -{ - uint32 len = prs_offset(src); - - if (!len) - return True; - - prs_set_offset(src, 0); - return prs_copy_data_out(dst, src, len); -} - -/******************************************************************* - Set the data as X-endian (external interface). - ********************************************************************/ - -void prs_set_endian_data(prs_struct *ps, bool endian) -{ - ps->bigendian_data = endian; -} - -/******************************************************************* - Align a the data_len to a multiple of align bytes - filling with - zeros. - ********************************************************************/ - -bool prs_align(prs_struct *ps) -{ - uint32 mod = ps->data_offset & (ps->align-1); - - if (ps->align != 0 && mod != 0) { - uint32 extra_space = (ps->align - mod); - if(!prs_grow(ps, extra_space)) - return False; - memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space); - ps->data_offset += extra_space; - } - - return True; -} - -/****************************************************************** - Align on a 2 byte boundary - *****************************************************************/ - -bool prs_align_uint16(prs_struct *ps) -{ - bool ret; - uint8 old_align = ps->align; - - ps->align = 2; - ret = prs_align(ps); - ps->align = old_align; - - return ret; -} - -/****************************************************************** - Align on a 8 byte boundary - *****************************************************************/ - -bool prs_align_uint64(prs_struct *ps) -{ - bool ret; - uint8 old_align = ps->align; - - ps->align = 8; - ret = prs_align(ps); - ps->align = old_align; - - return ret; -} - -/****************************************************************** - Align on a specific byte boundary - *****************************************************************/ - -bool prs_align_custom(prs_struct *ps, uint8 boundary) -{ - bool ret; - uint8 old_align = ps->align; - - ps->align = boundary; - ret = prs_align(ps); - ps->align = old_align; - - return ret; -} - - - -/******************************************************************* - Align only if required (for the unistr2 string mainly) - ********************************************************************/ - -bool prs_align_needed(prs_struct *ps, uint32 needed) -{ - if (needed==0) - return True; - else - return prs_align(ps); -} - -/******************************************************************* - Ensure we can read/write to a given offset. - ********************************************************************/ - -char *prs_mem_get(prs_struct *ps, uint32 extra_size) -{ - if(UNMARSHALLING(ps)) { - /* - * If reading, ensure that we can read the requested size item. - */ - if (ps->data_offset + extra_size > ps->buffer_size) { - DEBUG(0,("prs_mem_get: reading data of size %u would overrun " - "buffer by %u bytes.\n", - (unsigned int)extra_size, - (unsigned int)(ps->data_offset + extra_size - ps->buffer_size) )); - return NULL; - } - } else { - /* - * Writing - grow the buffer if needed. - */ - if(!prs_grow(ps, extra_size)) - return NULL; - } - return &ps->data_p[ps->data_offset]; -} - -/******************************************************************* - Change the struct type. - ********************************************************************/ - -void prs_switch_type(prs_struct *ps, bool io) -{ - if ((ps->io ^ io) == True) - ps->io=io; -} - -/******************************************************************* - Stream a uint8. - ********************************************************************/ - -bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8) -{ - char *q = prs_mem_get(ps, 1); - if (q == NULL) - return False; - - if (UNMARSHALLING(ps)) - *data8 = CVAL(q,0); - else - SCVAL(q,0,*data8); - - DEBUGADD(5,("%s%04x %s: %02x\n", tab_depth(5,depth), ps->data_offset, name, *data8)); - - ps->data_offset += 1; - - return True; -} - -/******************************************************************* - Stream a uint16. - ********************************************************************/ - -bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16) -{ - char *q = prs_mem_get(ps, sizeof(uint16)); - if (q == NULL) - return False; - - if (UNMARSHALLING(ps)) { - if (ps->bigendian_data) - *data16 = RSVAL(q,0); - else - *data16 = SVAL(q,0); - } else { - if (ps->bigendian_data) - RSSVAL(q,0,*data16); - else - SSVAL(q,0,*data16); - } - - DEBUGADD(5,("%s%04x %s: %04x\n", tab_depth(5,depth), ps->data_offset, name, *data16)); - - ps->data_offset += sizeof(uint16); - - return True; -} - -/******************************************************************* - Stream a uint32. - ********************************************************************/ - -bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32) -{ - char *q = prs_mem_get(ps, sizeof(uint32)); - if (q == NULL) - return False; - - if (UNMARSHALLING(ps)) { - if (ps->bigendian_data) - *data32 = RIVAL(q,0); - else - *data32 = IVAL(q,0); - } else { - if (ps->bigendian_data) - RSIVAL(q,0,*data32); - else - SIVAL(q,0,*data32); - } - - DEBUGADD(5,("%s%04x %s: %08x\n", tab_depth(5,depth), ps->data_offset, name, *data32)); - - ps->data_offset += sizeof(uint32); - - return True; -} - -/******************************************************************* - Stream an int32. - ********************************************************************/ - -bool prs_int32(const char *name, prs_struct *ps, int depth, int32 *data32) -{ - char *q = prs_mem_get(ps, sizeof(int32)); - if (q == NULL) - return False; - - if (UNMARSHALLING(ps)) { - if (ps->bigendian_data) - *data32 = RIVALS(q,0); - else - *data32 = IVALS(q,0); - } else { - if (ps->bigendian_data) - RSIVALS(q,0,*data32); - else - SIVALS(q,0,*data32); - } - - DEBUGADD(5,("%s%04x %s: %08x\n", tab_depth(5,depth), ps->data_offset, name, *data32)); - - ps->data_offset += sizeof(int32); - - return True; -} - -/******************************************************************* - Stream a uint64_struct - ********************************************************************/ -bool prs_uint64(const char *name, prs_struct *ps, int depth, uint64 *data64) -{ - if (UNMARSHALLING(ps)) { - uint32 high, low; - - if (!prs_uint32(name, ps, depth+1, &low)) - return False; - - if (!prs_uint32(name, ps, depth+1, &high)) - return False; - - *data64 = ((uint64_t)high << 32) + low; - - return True; - } else { - uint32 high = (*data64) >> 32, low = (*data64) & 0xFFFFFFFF; - return prs_uint32(name, ps, depth+1, &low) && - prs_uint32(name, ps, depth+1, &high); - } -} - -/******************************************************************* - Stream a DCE error code - ********************************************************************/ - -bool prs_dcerpc_status(const char *name, prs_struct *ps, int depth, NTSTATUS *status) -{ - char *q = prs_mem_get(ps, sizeof(uint32)); - if (q == NULL) - return False; - - if (UNMARSHALLING(ps)) { - if (ps->bigendian_data) - *status = NT_STATUS(RIVAL(q,0)); - else - *status = NT_STATUS(IVAL(q,0)); - } else { - if (ps->bigendian_data) - RSIVAL(q,0,NT_STATUS_V(*status)); - else - SIVAL(q,0,NT_STATUS_V(*status)); - } - - DEBUGADD(5,("%s%04x %s: %s\n", tab_depth(5,depth), ps->data_offset, name, - dcerpc_errstr(talloc_tos(), NT_STATUS_V(*status)))); - - ps->data_offset += sizeof(uint32); - - return True; -} - -/****************************************************************** - Stream an array of uint8s. Length is number of uint8s. - ********************************************************************/ - -bool prs_uint8s(bool charmode, const char *name, prs_struct *ps, int depth, uint8 *data8s, int len) -{ - int i; - char *q = prs_mem_get(ps, len); - if (q == NULL) - return False; - - if (UNMARSHALLING(ps)) { - for (i = 0; i < len; i++) - data8s[i] = CVAL(q,i); - } else { - for (i = 0; i < len; i++) - SCVAL(q, i, data8s[i]); - } - - DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset ,name)); - if (charmode) - print_asc(5, (unsigned char*)data8s, len); - else { - for (i = 0; i < len; i++) - DEBUGADD(5,("%02x ", data8s[i])); - } - DEBUGADD(5,("\n")); - - ps->data_offset += len; - - return True; -} - -/****************************************************************** - Stream an array of uint16s. Length is number of uint16s. - ********************************************************************/ - -bool prs_uint16s(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len) -{ - int i; - char *q = prs_mem_get(ps, len * sizeof(uint16)); - if (q == NULL) - return False; - - if (UNMARSHALLING(ps)) { - if (ps->bigendian_data) { - for (i = 0; i < len; i++) - data16s[i] = RSVAL(q, 2*i); - } else { - for (i = 0; i < len; i++) - data16s[i] = SVAL(q, 2*i); - } - } else { - if (ps->bigendian_data) { - for (i = 0; i < len; i++) - RSSVAL(q, 2*i, data16s[i]); - } else { - for (i = 0; i < len; i++) - SSVAL(q, 2*i, data16s[i]); - } - } - - DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); - if (charmode) - print_asc(5, (unsigned char*)data16s, 2*len); - else { - for (i = 0; i < len; i++) - DEBUGADD(5,("%04x ", data16s[i])); - } - DEBUGADD(5,("\n")); - - ps->data_offset += (len * sizeof(uint16)); - - return True; -} - -/****************************************************************** - Stream an array of uint32s. Length is number of uint32s. - ********************************************************************/ - -bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uint32 *data32s, int len) -{ - int i; - char *q = prs_mem_get(ps, len * sizeof(uint32)); - if (q == NULL) - return False; - - if (UNMARSHALLING(ps)) { - if (ps->bigendian_data) { - for (i = 0; i < len; i++) - data32s[i] = RIVAL(q, 4*i); - } else { - for (i = 0; i < len; i++) - data32s[i] = IVAL(q, 4*i); - } - } else { - if (ps->bigendian_data) { - for (i = 0; i < len; i++) - RSIVAL(q, 4*i, data32s[i]); - } else { - for (i = 0; i < len; i++) - SIVAL(q, 4*i, data32s[i]); - } - } - - DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); - if (charmode) - print_asc(5, (unsigned char*)data32s, 4*len); - else { - for (i = 0; i < len; i++) - DEBUGADD(5,("%08x ", data32s[i])); - } - DEBUGADD(5,("\n")); - - ps->data_offset += (len * sizeof(uint32)); - - return True; -} - -/******************************************************************* -creates a new prs_struct containing a DATA_BLOB -********************************************************************/ -bool prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx) -{ - if (!prs_init( prs, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL )) - return False; - - - if (!prs_copy_data_in(prs, (char *)blob->data, blob->length)) - return False; - - return True; -} - -/******************************************************************* -return the contents of a prs_struct in a DATA_BLOB -********************************************************************/ -bool prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx) -{ - blob->length = prs_data_size(prs); - blob->data = (uint8 *)TALLOC_ZERO_SIZE(mem_ctx, blob->length); - - /* set the pointer at the end of the buffer */ - prs_set_offset( prs, prs_data_size(prs) ); - - if (!prs_copy_all_data_out((char *)blob->data, prs)) - return False; - - return True; -} diff --git a/source3/rpc_server/srv_winreg_nt.c b/source3/rpc_server/srv_winreg_nt.c index 209deadd70..73d2775b16 100644 --- a/source3/rpc_server/srv_winreg_nt.c +++ b/source3/rpc_server/srv_winreg_nt.c @@ -22,6 +22,7 @@ #include "includes.h" #include "../librpc/gen_ndr/srv_winreg.h" +#include "registry/reg_parse_prs.h" #include "registry.h" #include "registry/reg_perfcount.h" -- cgit From 7cf4797dd3c13555dee59fdf0c959ac66b7633b1 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 16 Jul 2010 01:11:39 +0200 Subject: s3-dcerpc: fix c++ warning. Guenther --- source3/rpc_client/cli_pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index bda152c505..c90e06095c 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1698,7 +1698,7 @@ static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx, ctx_list.context_id = 0; ctx_list.num_transfer_syntaxes = 1; ctx_list.abstract_syntax = *abstract; - ctx_list.transfer_syntaxes = discard_const(transfer); + ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer); u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN; u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN; -- cgit From 196b4e83424c65f8d56ef17e5fca1dfb11c9cf2b Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 16 Jul 2010 02:07:51 +0200 Subject: s3-waf: fix the build. Guenther --- source3/wscript_build | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/wscript_build b/source3/wscript_build index 8f18c3e47b..38d680518f 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -88,10 +88,9 @@ LIBNDR_GEN_SRC = '''../librpc/gen_ndr/ndr_wkssvc.c # this includes only the low level parse code, not stuff # that requires knowledge of security contexts -RPC_PARSE_SRC1 = '''rpc_parse/parse_prs.c rpc_parse/parse_misc.c''' +REG_PARSE_PRS_SRC = '''registry/reg_parse_prs.c''' -RPC_PARSE_SRC2 = '''rpc_parse/parse_rpc.c - rpc_client/init_netlogon.c +RPC_PARSE_SRC2 = '''rpc_client/init_netlogon.c rpc_client/init_lsa.c''' LIBREPLACE_SRC = '''${LIBREPLACE_SRCS}''' @@ -233,7 +232,7 @@ LIBSMB_ERR_SRC0 = '''${NTERR_SRC} ${DOSERR_SRC} ${ERRORMAP_SRC} ${DCE_RPC_ERR_SR LIBSMB_ERR_SRC1 = '''../libcli/auth/smbdes.c ../libcli/auth/smbencrypt.c ../libcli/auth/msrpc_parse.c ../libcli/auth/session.c''' -LIBSMB_ERR_SRC = '${LIBSMB_ERR_SRC0} ${LIBSMB_ERR_SRC1} ${RPC_PARSE_SRC1}' +LIBSMB_ERR_SRC = '${LIBSMB_ERR_SRC0} ${LIBSMB_ERR_SRC1} ${REG_PARSE_PRS_SRC}' LIBSMB_SRC0 = ''' ../libcli/auth/ntlm_check.c @@ -302,6 +301,7 @@ LIBMSRPC_GEN_SRC = '''../librpc/gen_ndr/cli_lsa.c ../librpc/gen_ndr/cli_drsuapi.c ../librpc/gen_ndr/cli_spoolss.c ../librpc/rpc/dcerpc_util.c + librpc/rpc/dcerpc_helpers.c ${LIBNDR_GEN_SRC} ${RPCCLIENT_NDR_SRC}''' -- cgit From 914fd13eddef5cd917a10da1816565acfaa5fd57 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 16 Jul 2010 02:20:34 +0200 Subject: s3-registry: use some prs macros to the only place where they are used. Guenther --- source3/include/smb_macros.h | 4 ---- source3/registry/regfio.c | 6 ++++++ 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h index e5af20bac3..757c8a2c1e 100644 --- a/source3/include/smb_macros.h +++ b/source3/include/smb_macros.h @@ -273,8 +273,6 @@ NULL returns on zero request. JRA. #if defined(PARANOID_MALLOC_CHECKER) -#define PRS_ALLOC_MEM(ps, type, count) (type *)prs_alloc_mem_((ps),sizeof(type),(count)) - /* Get medieval on our ass about malloc.... */ /* Restrictions on malloc/realloc/calloc. */ @@ -311,8 +309,6 @@ NULL returns on zero request. JRA. #else -#define PRS_ALLOC_MEM(ps, type, count) (type *)prs_alloc_mem((ps),sizeof(type),(count)) - /* Regular malloc code. */ #define SMB_MALLOC(s) malloc(s) diff --git a/source3/registry/regfio.c b/source3/registry/regfio.c index 7a362d205e..7ab262d822 100644 --- a/source3/registry/regfio.c +++ b/source3/registry/regfio.c @@ -32,6 +32,12 @@ * ******************************************************************/ +#if defined(PARANOID_MALLOC_CHECKER) +#define PRS_ALLOC_MEM(ps, type, count) (type *)prs_alloc_mem_((ps),sizeof(type),(count)) +#else +#define PRS_ALLOC_MEM(ps, type, count) (type *)prs_alloc_mem((ps),sizeof(type),(count)) +#endif + /******************************************************************* Reads or writes an NTTIME structure. ********************************************************************/ -- cgit