NTSTATUS dcerpc_push_ncacn_packet(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,
- union dcerpc_payload u,
+ union dcerpc_payload *u,
DATA_BLOB *blob)
{
struct ncacn_packet r;
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;
- r.u = u;
+ r.u = *u;
ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
(ndr_push_flags_fn_t)ndr_push_ncacn_packet);
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_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;
+}
+
/*******************************************************************
*******************************************************************/
}
-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.
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;
};
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;
}
state->ev = ev;
state->cli = cli;
- state->prhdr = prhdr;
+ state->frag_len = RPC_HEADER_LEN;
state->pdu = pdu;
pdu_len = prs_data_size(pdu);
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;
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);
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;
}
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;
}
****************************************************************************/
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 = dcerpc_pull_ncacn_packet(cli, &blob, 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;
+ }
+
+ /* FIXME: until all functions are converted to take in
+ * a fully decoded packet
+ */
+ memcpy(&prhdr, pkt, sizeof(prhdr));
- 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));
+
+ 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;
}
*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:
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;
*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",
* 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;
}
}
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;
}
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;
****************************************************************************/
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. */
* 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;
}
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;
/* 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;
}
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);
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.
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)));
}
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;
}
}
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(
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;
}
const DATA_BLOB *auth_info)
{
uint16 auth_len = auth_info->length;
- uint16 frag_len = 0;
NTSTATUS status;
union dcerpc_payload u;
DATA_BLOB blob;
u.bind.ctx_list = ctx_list;
u.bind.auth_info = *auth_info;
- /* Start building the frag length. */
- frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&u.bind) + auth_len;
-
status = dcerpc_push_ncacn_packet(rpc_out->mem_ctx,
ptype,
DCERPC_PFC_FLAG_FIRST |
DCERPC_PFC_FLAG_LAST,
- frag_len,
auth_len ? auth_len - RPC_HDR_AUTH_LEN : 0,
rpc_call_id,
- u,
+ &u,
&blob);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
return NT_STATUS_INVALID_PARAMETER;
}
+ /* 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),
+ map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
+ cli->auth->auth_level,
+ ss_padding_len,
+ 1 /* context id. */,
+ &auth_blob,
+ &auth_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* append the header */
+ if (!prs_copy_data_in(rpc_out,
+ (char *)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;
+ }
+
switch (cli->auth->auth_level) {
case DCERPC_AUTH_LEVEL_PRIVACY:
/* Data portion is encrypted. */
return NT_STATUS_INVALID_PARAMETER;
}
- /* 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),
- cli->auth->auth_level,
- ss_padding_len,
- 1 /* context id. */,
- &auth_blob,
- &auth_info);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- if (!prs_copy_data_in(rpc_out, (const char *)auth_info.data, auth_info.length)) {
- DEBUG(0, ("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
- (unsigned int)auth_info.length));
+ /* Finally attach the blob. */
+ if (!prs_copy_data_in(rpc_out,
+ (char *)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;
}
status = dcerpc_push_ncacn_packet(prs_get_mem_context(&state->outgoing_frag),
DCERPC_PKT_REQUEST,
flags,
- frag_len,
auth_len,
state->call_id,
- u,
+ &u,
&blob);
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;
}
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);
DATA_BLOB *pauth_blob,
prs_struct *rpc_out)
{
- uint16_t auth_len = pauth_blob->length;
- uint16_t frag_len = 0;
NTSTATUS status;
union dcerpc_payload u;
DATA_BLOB blob;
return status;
}
- /* Start building the frag length. */
- frag_len = RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + auth_len;
-
status = dcerpc_push_ncacn_packet(prs_get_mem_context(rpc_out),
DCERPC_PKT_AUTH3,
DCERPC_PFC_FLAG_FIRST |
DCERPC_PFC_FLAG_LAST,
- frag_len,
- auth_len ? auth_len - RPC_HDR_AUTH_LEN : 0,
+ pauth_blob->length,
rpc_call_id,
- u,
+ &u,
&blob);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
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(), &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",
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.
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);
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);
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 "