diff options
Diffstat (limited to 'source3/rpc_client/cli_pipe.c')
-rw-r--r-- | source3/rpc_client/cli_pipe.c | 135 |
1 files changed, 77 insertions, 58 deletions
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 5d4d19bf6f..da1219ed61 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -567,22 +567,34 @@ static NTSTATUS rpc_write_recv(struct tevent_req *req) static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli, - struct rpc_hdr_info *prhdr, + 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. */ - if(!smb_io_rpc_hdr("rpc_hdr ", prhdr, pdu, 0)) { - DEBUG(0, ("get_current_pdu: Failed to unmarshall RPC_HDR.\n")); + 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 (prhdr->frag_len > cli->max_recv_frag) { + 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_len, + " we only allow %d\n", (int)prhdr->frag_length, (int)cli->max_recv_frag)); return NT_STATUS_BUFFER_TOO_SMALL; } @@ -598,7 +610,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 rpc_hdr_info *prhdr; + struct ncacn_packet_header *prhdr; prs_struct *pdu; }; @@ -608,7 +620,7 @@ 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 rpc_hdr_info *prhdr, + struct ncacn_packet_header *prhdr, prs_struct *pdu) { struct tevent_req *req, *subreq; @@ -654,15 +666,15 @@ static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx, /* * Ensure we have frag_len bytes of data. */ - if (pdu_len < prhdr->frag_len) { - if (!rpc_grow_buffer(pdu, prhdr->frag_len)) { + if (pdu_len < prhdr->frag_length) { + if (!rpc_grow_buffer(pdu, prhdr->frag_length)) { 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_len - pdu_len); + prhdr->frag_length - pdu_len); if (subreq == NULL) { status = NT_STATUS_NO_MEMORY; goto post_status; @@ -703,7 +715,7 @@ static void get_complete_frag_got_header(struct tevent_req *subreq) return; } - if (!rpc_grow_buffer(state->pdu, state->prhdr->frag_len)) { + if (!rpc_grow_buffer(state->pdu, state->prhdr->frag_length)) { tevent_req_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -716,7 +728,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_len - RPC_HEADER_LEN); + state->prhdr->frag_length - RPC_HEADER_LEN); if (tevent_req_nomem(subreq, req)) { return; } @@ -749,13 +761,14 @@ static NTSTATUS get_complete_frag_recv(struct tevent_req *req) In fact I should probably abstract these into identical pieces of code... JRA. ****************************************************************************/ -static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr, +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) { RPC_HDR_AUTH auth_info; uint32 save_offset = prs_offset(current_pdu); - uint32 auth_len = prhdr->auth_len; + 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; @@ -775,8 +788,9 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *pr /* Ensure there's enough data for an authenticated response. */ if (auth_len > RPC_MAX_PDU_FRAG_LEN || - prhdr->frag_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + - RPC_HDR_AUTH_LEN + auth_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 )); return NT_STATUS_BUFFER_TOO_SMALL; @@ -790,15 +804,15 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *pr */ data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN); - data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_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_len - auth_len; + 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_len - RPC_HDR_AUTH_LEN - auth_len)) { + 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; @@ -811,12 +825,12 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *pr /* Ensure auth_pad_len fits into the packet. */ if (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + auth_info.auth_pad_len + - RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len) { + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_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_len, (unsigned int)auth_len, - (unsigned int)prhdr->frag_len )); + (unsigned int)prhdr->frag_length)); return NT_STATUS_BUFFER_TOO_SMALL; } @@ -885,12 +899,13 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *pr schannel specific sign/seal. ****************************************************************************/ -static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr, +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) { RPC_HDR_AUTH auth_info; - uint32 auth_len = prhdr->auth_len; + 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; @@ -915,22 +930,22 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p /* 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_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 )); return NT_STATUS_INVALID_PARAMETER; } - data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len; + 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_len - RPC_HDR_AUTH_LEN - auth_len)) { + 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_len - + (unsigned int)(prhdr->frag_length - RPC_HDR_AUTH_LEN - auth_len) )); return NT_STATUS_BUFFER_TOO_SMALL; } @@ -942,12 +957,12 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p /* Ensure auth_pad_len fits into the packet. */ if (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + auth_info.auth_pad_len + - RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len) { + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_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_len, (unsigned int)auth_len, - (unsigned int)prhdr->frag_len )); + (unsigned int)prhdr->frag_length)); return NT_STATUS_BUFFER_TOO_SMALL; } @@ -1019,20 +1034,21 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *p Do the authentication checks on an incoming pdu. Check sign and unseal etc. ****************************************************************************/ -static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr, +static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, + struct ncacn_packet_header *prhdr, prs_struct *current_pdu, uint8 *p_ss_padding_len) { NTSTATUS ret = NT_STATUS_OK; /* Paranioa checks for auth_len. */ - if (prhdr->auth_len) { - if (prhdr->auth_len > prhdr->frag_len) { + if (prhdr->auth_length) { + if (prhdr->auth_length > prhdr->frag_length) { return NT_STATUS_INVALID_PARAMETER; } - if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len || - prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) { + 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) { /* Integer wrap attempt. */ return NT_STATUS_INVALID_PARAMETER; } @@ -1044,12 +1060,12 @@ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_ switch(cli->auth->auth_type) { case PIPE_AUTH_TYPE_NONE: - if (prhdr->auth_len) { + 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_len )); + (unsigned int)prhdr->auth_length)); return NT_STATUS_INVALID_PARAMETER; } break; @@ -1086,7 +1102,8 @@ static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_ Do basic authentication checks on an incoming pdu. ****************************************************************************/ -static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, +static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, + struct ncacn_packet_header *prhdr, prs_struct *current_pdu, uint8 expected_pkt_type, char **ppdata, @@ -1097,9 +1114,9 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_H NTSTATUS ret = NT_STATUS_OK; uint32 current_pdu_len = prs_data_size(current_pdu); - if (current_pdu_len != prhdr->frag_len) { + 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_len )); + (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_length)); return NT_STATUS_INVALID_PARAMETER; } @@ -1111,7 +1128,7 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_H *pdata_len = current_pdu_len; /* Ensure we have the correct type. */ - switch (prhdr->pkt_type) { + switch (prhdr->ptype) { case DCERPC_PKT_ALTER_RESP: case DCERPC_PKT_BIND_ACK: @@ -1146,13 +1163,13 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_H *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len; /* Remember to remove the auth footer. */ - if (prhdr->auth_len) { + if (prhdr->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_len) { + if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_length) { return NT_STATUS_BUFFER_TOO_SMALL; } - *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len); + *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_length); } DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n", @@ -1209,16 +1226,16 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_H default: DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received " "from %s!\n", - (unsigned int)prhdr->pkt_type, + (unsigned int)prhdr->ptype, rpccli_pipe_txt(talloc_tos(), cli))); return NT_STATUS_INVALID_INFO_CLASS; } - if (prhdr->pkt_type != expected_pkt_type) { + if (prhdr->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->pkt_type, + prhdr->ptype, expected_pkt_type)); return NT_STATUS_INVALID_INFO_CLASS; } @@ -1227,10 +1244,10 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_H data before now as we may have needed to do cryptographic actions on it before. */ - if ((prhdr->pkt_type == DCERPC_PKT_BIND_ACK) && !(prhdr->flags & DCERPC_PFC_FLAG_LAST)) { + if ((prhdr->ptype == DCERPC_PKT_BIND_ACK) && !(prhdr->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->flags |= DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST; + prhdr->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; } return NT_STATUS_OK; @@ -1243,16 +1260,18 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_H deal with that. ****************************************************************************/ -static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu) +static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, + struct ncacn_packet_header *prhdr, + prs_struct *current_pdu) { uint32 current_pdu_len = prs_data_size(current_pdu); - if (current_pdu_len < prhdr->frag_len) { + if (current_pdu_len < prhdr->frag_length) { return NT_STATUS_BUFFER_TOO_SMALL; } /* Common case. */ - if (current_pdu_len == (uint32)prhdr->frag_len) { + if (current_pdu_len == (uint32)prhdr->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. */ @@ -1265,14 +1284,14 @@ static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR * Cheat. Move the data down and shrink the buffer. */ - memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len, - current_pdu_len - prhdr->frag_len); + memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_length, + current_pdu_len - prhdr->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_len)) { + if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_length)) { return NT_STATUS_BUFFER_TOO_SMALL; } @@ -1470,7 +1489,7 @@ struct rpc_api_pipe_state { uint8_t expected_pkt_type; prs_struct incoming_frag; - struct rpc_hdr_info rhdr; + struct ncacn_packet_header rhdr; prs_struct incoming_pdu; /* Incoming reply */ uint32_t incoming_pdu_offset; @@ -1613,8 +1632,8 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) return; } - if ((state->rhdr.flags & DCERPC_PFC_FLAG_FIRST) - && (state->rhdr.pack_type[0] == 0)) { + if ((state->rhdr.pfc_flags & DCERPC_PFC_FLAG_FIRST) + && (state->rhdr.drep[0] == 0)) { /* * Set the data type correctly for big-endian data on the * first packet. @@ -1654,7 +1673,7 @@ static void rpc_api_pipe_got_pdu(struct tevent_req *subreq) return; } - if (state->rhdr.flags & DCERPC_PFC_FLAG_LAST) { + if (state->rhdr.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))); |