summaryrefslogtreecommitdiff
path: root/source4/librpc/rpc/dcerpc.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2003-11-23 06:28:12 +0000
committerAndrew Tridgell <tridge@samba.org>2003-11-23 06:28:12 +0000
commit800d3e0134b72135fa359fa5a239f1c68adf4ca1 (patch)
tree1f0e6cafab8f1d62dee9a3796443ab18b6394fe1 /source4/librpc/rpc/dcerpc.c
parent02dc7536dd625e0cdee23a96e66cb41b407cdba8 (diff)
downloadsamba-800d3e0134b72135fa359fa5a239f1c68adf4ca1.tar.gz
samba-800d3e0134b72135fa359fa5a239f1c68adf4ca1.tar.bz2
samba-800d3e0134b72135fa359fa5a239f1c68adf4ca1.zip
ooh, this is fun!
I have recoded the core dcerpc packet structures (all the PDUs etc) in terms of IDL, which means we now use pidl to generate all the code for handling the most basic dcerpc packets. This is not normally possible as it isn't completely valid NDR, but pidl has a number of extensions that make it quite easy. This also means we get the server side dcerpc marshalling/unmarshalling code for free. (This used to be commit 92bcad02587c3c1b31b523ee9fa46658a6cef9ff)
Diffstat (limited to 'source4/librpc/rpc/dcerpc.c')
-rw-r--r--source4/librpc/rpc/dcerpc.c561
1 files changed, 111 insertions, 450 deletions
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index 2cb52ece0b..6a8b867136 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -59,446 +59,94 @@ void dcerpc_pipe_close(struct dcerpc_pipe *p)
}
}
-#define BLOB_CHECK_BOUNDS(blob, offset, len) do { \
- if ((offset) > blob->length || (blob->length - (offset) < (len))) { \
- return NT_STATUS_INVALID_PARAMETER; \
- } \
-} while (0)
-
-#define DCERPC_ALIGN(offset, n) do { \
- (offset) = ((offset) + ((n)-1)) & ~((n)-1); \
-} while (0)
-
-/*
- pull a wire format uuid into a string. This will consume 16 bytes
-*/
-static char *dcerpc_pull_uuid(char *data, TALLOC_CTX *mem_ctx)
-{
- uint32 time_low;
- uint16 time_mid, time_hi_and_version;
- uint8 clock_seq_hi_and_reserved;
- uint8 clock_seq_low;
- uint8 node[6];
- int i;
-
- time_low = IVAL(data, 0);
- time_mid = SVAL(data, 4);
- time_hi_and_version = SVAL(data, 6);
- clock_seq_hi_and_reserved = CVAL(data, 8);
- clock_seq_low = CVAL(data, 9);
- for (i=0;i<6;i++) {
- node[i] = CVAL(data, 10 + i);
- }
-
- return talloc_asprintf(mem_ctx,
- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- time_low, time_mid, time_hi_and_version,
- clock_seq_hi_and_reserved, clock_seq_low,
- node[0], node[1], node[2], node[3], node[4], node[5]);
-}
-
-/*
- push a uuid_str into wire format. It will consume 16 bytes
-*/
-static NTSTATUS push_uuid_str(char *data, const char *uuid_str)
-{
- uint32 time_low;
- uint32 time_mid, time_hi_and_version;
- uint32 clock_seq_hi_and_reserved;
- uint32 clock_seq_low;
- uint32 node[6];
- int i;
-
- if (11 != sscanf(uuid_str, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- &time_low, &time_mid, &time_hi_and_version,
- &clock_seq_hi_and_reserved, &clock_seq_low,
- &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- SIVAL(data, 0, time_low);
- SSVAL(data, 4, time_mid);
- SSVAL(data, 6, time_hi_and_version);
- SCVAL(data, 8, clock_seq_hi_and_reserved);
- SCVAL(data, 9, clock_seq_low);
- for (i=0;i<6;i++) {
- SCVAL(data, 10 + i, node[i]);
- }
-
- return NT_STATUS_OK;
-}
-
-/*
- pull a dcerpc syntax id from a blob
-*/
-static NTSTATUS dcerpc_pull_syntax_id(DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
- uint32 *offset,
- struct dcerpc_syntax_id *syntax)
-{
- syntax->uuid_str = dcerpc_pull_uuid(blob->data + (*offset), mem_ctx);
- if (!syntax->uuid_str) {
- return NT_STATUS_NO_MEMORY;
- }
- (*offset) += 16;
- syntax->if_version = IVAL(blob->data, *offset);
- (*offset) += 4;
- return NT_STATUS_OK;
-}
/*
- push a syntax id onto the wire. It will consume 20 bytes
+ build a GUID from a string
*/
-static NTSTATUS push_syntax_id(char *data, const struct dcerpc_syntax_id *syntax)
+static NTSTATUS guid_from_string(const char *s, struct GUID *guid)
{
- NTSTATUS status;
-
- status = push_uuid_str(data, syntax->uuid_str);
- SIVAL(data, 16, syntax->if_version);
-
- return status;
-}
-
-/*
- pull an auth verifier from a packet
-*/
-static NTSTATUS dcerpc_pull_auth_verifier(DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
- uint32 *offset,
- struct dcerpc_hdr *hdr,
- DATA_BLOB *auth)
-{
- if (hdr->auth_length == 0) {
- return NT_STATUS_OK;
- }
-
- BLOB_CHECK_BOUNDS(blob, *offset, hdr->auth_length);
- *auth = data_blob_talloc(mem_ctx, blob->data + (*offset), hdr->auth_length);
- if (!auth->data) {
- return NT_STATUS_NO_MEMORY;
- }
- (*offset) += hdr->auth_length;
- return NT_STATUS_OK;
-}
-
-/*
- parse a struct dcerpc_response
-*/
-static NTSTATUS dcerpc_pull_response(DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
- uint32 *offset,
- struct dcerpc_hdr *hdr,
- struct dcerpc_response *pkt)
-{
- uint32 stub_len;
-
- BLOB_CHECK_BOUNDS(blob, *offset, 8);
-
- pkt->alloc_hint = IVAL(blob->data, (*offset) + 0);
- pkt->context_id = SVAL(blob->data, (*offset) + 4);
- pkt->cancel_count = CVAL(blob->data, (*offset) + 6);
-
- (*offset) += 8;
-
- stub_len = blob->length - ((*offset) + hdr->auth_length);
- BLOB_CHECK_BOUNDS(blob, *offset, stub_len);
- pkt->stub_data = data_blob_talloc(mem_ctx, blob->data + (*offset), stub_len);
- if (stub_len != 0 && !pkt->stub_data.data) {
- return NT_STATUS_NO_MEMORY;
- }
- (*offset) += stub_len;
-
- return dcerpc_pull_auth_verifier(blob, mem_ctx, offset, hdr, &pkt->auth_verifier);
-}
-
-
-/*
- parse a struct bind_ack
-*/
-static NTSTATUS dcerpc_pull_bind_ack(DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
- uint32 *offset,
- struct dcerpc_hdr *hdr,
- struct dcerpc_bind_ack *pkt)
-{
- uint16 len;
- int i;
-
- BLOB_CHECK_BOUNDS(blob, *offset, 10);
- pkt->max_xmit_frag = SVAL(blob->data, (*offset) + 0);
- pkt->max_recv_frag = SVAL(blob->data, (*offset) + 2);
- pkt->assoc_group_id = IVAL(blob->data, (*offset) + 4);
- len = SVAL(blob->data, (*offset) + 8);
- (*offset) += 10;
-
- if (len) {
- BLOB_CHECK_BOUNDS(blob, *offset, len);
- pkt->secondary_address = talloc_strndup(mem_ctx, blob->data + (*offset), len);
- if (!pkt->secondary_address) {
- return NT_STATUS_NO_MEMORY;
- }
- (*offset) += len;
- }
-
- DCERPC_ALIGN(*offset, 4);
- BLOB_CHECK_BOUNDS(blob, *offset, 4);
- pkt->num_results = CVAL(blob->data, *offset);
- (*offset) += 4;
-
- if (pkt->num_results > 0) {
- pkt->ctx_list = talloc(mem_ctx, sizeof(pkt->ctx_list[0]) * pkt->num_results);
- if (!pkt->ctx_list) {
- return NT_STATUS_NO_MEMORY;
- }
- }
-
- for (i=0;i<pkt->num_results;i++) {
- NTSTATUS status;
-
- BLOB_CHECK_BOUNDS(blob, *offset, 24);
- pkt->ctx_list[i].result = SVAL(blob->data, *offset);
- pkt->ctx_list[i].reason = SVAL(blob->data, 2 + *offset);
- (*offset) += 4;
- status = dcerpc_pull_syntax_id(blob, mem_ctx, offset, &pkt->ctx_list[i].syntax);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- }
-
- return dcerpc_pull_auth_verifier(blob, mem_ctx, offset, hdr, &pkt->auth_verifier);
-}
-
-
-/*
- parse a dcerpc header
-*/
-static NTSTATUS dcerpc_pull_hdr(DATA_BLOB *blob, uint32 *offset, struct dcerpc_hdr *hdr)
-{
- BLOB_CHECK_BOUNDS(blob, *offset, 16);
-
- hdr->rpc_vers = CVAL(blob->data, (*offset) + 0);
- hdr->rpc_vers_minor = CVAL(blob->data, (*offset) + 1);
- hdr->ptype = CVAL(blob->data, (*offset) + 2);
- hdr->pfc_flags = CVAL(blob->data, (*offset) + 3);
- memcpy(hdr->drep, blob->data + (*offset) + 4, 4);
- hdr->frag_length = SVAL(blob->data, (*offset) + 8);
- hdr->auth_length = SVAL(blob->data, (*offset) + 10);
- hdr->call_id = IVAL(blob->data, (*offset) + 12);
-
- (*offset) += 16;
-
- return NT_STATUS_OK;
+ uint32 time_low;
+ uint32 time_mid, time_hi_and_version;
+ uint32 clock_seq_hi_and_reserved;
+ uint32 clock_seq_low;
+ uint32 node[6];
+ int i;
+
+ if (11 != sscanf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ &time_low, &time_mid, &time_hi_and_version,
+ &clock_seq_hi_and_reserved, &clock_seq_low,
+ &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ SIVAL(guid->info, 0, time_low);
+ SSVAL(guid->info, 4, time_mid);
+ SSVAL(guid->info, 6, time_hi_and_version);
+ SCVAL(guid->info, 8, clock_seq_hi_and_reserved);
+ SCVAL(guid->info, 9, clock_seq_low);
+ for (i=0;i<6;i++) {
+ SCVAL(guid->info, 10 + i, node[i]);
+ }
+
+ return NT_STATUS_OK;
}
/*
- parse a dcerpc header. It consumes 16 bytes
-*/
-static void dcerpc_push_hdr(char *data, struct dcerpc_hdr *hdr)
-{
- SCVAL(data, 0, hdr->rpc_vers);
- SCVAL(data, 1, hdr->rpc_vers_minor);
- SCVAL(data, 2, hdr->ptype);
- SCVAL(data, 3, hdr->pfc_flags);
- memcpy(data + 4, hdr->drep, 4);
- SSVAL(data, 8, hdr->frag_length);
- SSVAL(data, 12, hdr->call_id);
-}
-
-
-
-/*
parse a data blob into a dcerpc_packet structure. This handles both
input and output packets
*/
NTSTATUS dcerpc_pull(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct dcerpc_packet *pkt)
{
- NTSTATUS status;
- uint32 offset = 0;
+ struct ndr_pull *ndr;
- status = dcerpc_pull_hdr(blob, &offset, &pkt->hdr);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- switch (pkt->hdr.ptype) {
- case DCERPC_PKT_BIND_ACK:
- status = dcerpc_pull_bind_ack(blob, mem_ctx, &offset, &pkt->hdr, &pkt->out.bind_ack);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- break;
-
- case DCERPC_PKT_RESPONSE:
- status = dcerpc_pull_response(blob, mem_ctx, &offset, &pkt->hdr, &pkt->out.response);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- break;
-
- default:
- return NT_STATUS_NET_WRITE_FAULT;
- }
-
- return status;
-}
-
-
-/*
- push a dcerpc_bind into a blob
-*/
-static NTSTATUS dcerpc_push_bind(DATA_BLOB *blob, uint32 *offset,
- struct dcerpc_hdr *hdr,
- struct dcerpc_bind *pkt)
-{
- int i, j;
-
- SSVAL(blob->data, (*offset) + 0, pkt->max_xmit_frag);
- SSVAL(blob->data, (*offset) + 2, pkt->max_recv_frag);
- SIVAL(blob->data, (*offset) + 4, pkt->assoc_group_id);
- SCVAL(blob->data, (*offset) + 8, pkt->num_contexts);
- (*offset) += 12;
-
- for (i=0;i<pkt->num_contexts;i++) {
- NTSTATUS status;
-
- SSVAL(blob->data, (*offset) + 0, pkt->ctx_list[i].context_id);
- SCVAL(blob->data, (*offset) + 2, pkt->ctx_list[i].num_transfer_syntaxes);
- status = push_syntax_id(blob->data + (*offset) + 4, &pkt->ctx_list[i].abstract_syntax);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- (*offset) += 24;
- for (j=0;j<pkt->ctx_list[i].num_transfer_syntaxes;j++) {
- status = push_syntax_id(blob->data + (*offset),
- &pkt->ctx_list[i].transfer_syntaxes[j]);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- (*offset) += 20;
- }
+ ndr = ndr_pull_init_blob(blob, mem_ctx);
+ if (!ndr) {
+ return NT_STATUS_NO_MEMORY;
}
- return NT_STATUS_OK;
-}
-
-/*
- push a dcerpc_request into a blob
-*/
-static NTSTATUS dcerpc_push_request(DATA_BLOB *blob, uint32 *offset,
- struct dcerpc_hdr *hdr,
- struct dcerpc_request *pkt)
-{
- SIVAL(blob->data, (*offset) + 0, pkt->alloc_hint);
- SSVAL(blob->data, (*offset) + 4, pkt->context_id);
- SSVAL(blob->data, (*offset) + 6, pkt->opnum);
-
- (*offset) += 8;
-
- memcpy(blob->data + (*offset), pkt->stub_data.data, pkt->stub_data.length);
- (*offset) += pkt->stub_data.length;
-
- memcpy(blob->data + (*offset), pkt->auth_verifier.data, pkt->auth_verifier.length);
- (*offset) += pkt->auth_verifier.length;
-
- return NT_STATUS_OK;
+ return ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
}
-/*
- work out the wire size of a dcerpc packet
-*/
-static uint32 dcerpc_wire_size(struct dcerpc_packet *pkt)
-{
- int i;
- uint32 size = 0;
-
- size += 16; /* header */
-
- switch (pkt->hdr.ptype) {
- case DCERPC_PKT_REQUEST:
- size += 8;
- size += pkt->in.request.stub_data.length;
- size += pkt->in.request.auth_verifier.length;
- break;
-
- case DCERPC_PKT_RESPONSE:
- size += 8;
- size += pkt->out.response.stub_data.length;
- size += pkt->hdr.auth_length;
- break;
-
- case DCERPC_PKT_BIND:
- size += 12;
- for (i=0;i<pkt->in.bind.num_contexts;i++) {
- size += 24;
- size += pkt->in.bind.ctx_list[i].num_transfer_syntaxes * 20;
- }
- size += pkt->hdr.auth_length;
- break;
-
- case DCERPC_PKT_BIND_ACK:
- size += 10;
- if (pkt->out.bind_ack.secondary_address) {
- size += strlen(pkt->out.bind_ack.secondary_address) + 1;
- }
- size += 4;
- size += pkt->out.bind_ack.num_results * 24;
- size += pkt->hdr.auth_length;
- break;
- }
-
- return size;
-}
-
/*
push a dcerpc_packet into a blob. This handles both input and
output packets
*/
NTSTATUS dcerpc_push(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct dcerpc_packet *pkt)
{
- uint32 offset = 0;
- uint32 wire_size;
+ struct ndr_push *ndr;
NTSTATUS status;
- /* work out how big the packet will be on the wire */
- wire_size = dcerpc_wire_size(pkt);
-
- (*blob) = data_blob_talloc(mem_ctx, NULL, wire_size);
- if (!blob->data) {
+ ndr = ndr_push_init_ctx(mem_ctx);
+ if (!ndr) {
return NT_STATUS_NO_MEMORY;
}
- pkt->hdr.frag_length = wire_size;
-
- dcerpc_push_hdr(blob->data + offset, &pkt->hdr);
- offset += 16;
+ status = ndr_push_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- switch (pkt->hdr.ptype) {
- case DCERPC_PKT_BIND:
- status = dcerpc_push_bind(blob, &offset, &pkt->hdr, &pkt->in.bind);
- break;
+ *blob = ndr_push_blob(ndr);
- case DCERPC_PKT_REQUEST:
- status = dcerpc_push_request(blob, &offset, &pkt->hdr, &pkt->in.request);
- break;
-
- default:
- status = NT_STATUS_NET_WRITE_FAULT;
- }
+ /* fill in the frag length */
+ SSVAL(blob->data, 8, blob->length);
return status;
}
-
-
/*
fill in the fixed values in a dcerpc header
*/
-static void init_dcerpc_hdr(struct dcerpc_hdr *hdr)
+static void init_dcerpc_hdr(struct dcerpc_packet *pkt)
{
- hdr->rpc_vers = 5;
- hdr->rpc_vers_minor = 0;
- hdr->drep[0] = 0x10; /* Little endian */
- hdr->drep[1] = 0;
- hdr->drep[2] = 0;
- hdr->drep[3] = 0;
+ pkt->rpc_vers = 5;
+ pkt->rpc_vers_minor = 0;
+ pkt->drep[0] = 0x10; /* Little endian */
+ pkt->drep[1] = 0;
+ pkt->drep[2] = 0;
+ pkt->drep[3] = 0;
}
@@ -510,38 +158,39 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p,
const struct dcerpc_syntax_id *transfer_syntax)
{
TALLOC_CTX *mem_ctx;
- struct dcerpc_packet pkt;
+ struct dcerpc_packet pkt;
NTSTATUS status;
DATA_BLOB blob;
DATA_BLOB blob_out;
+ struct dcerpc_syntax_id tsyntax;
mem_ctx = talloc_init("dcerpc_bind");
if (!mem_ctx) {
return NT_STATUS_NO_MEMORY;
}
- init_dcerpc_hdr(&pkt.hdr);
+ init_dcerpc_hdr(&pkt);
- pkt.hdr.ptype = DCERPC_PKT_BIND;
- pkt.hdr.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
- pkt.hdr.call_id = p->call_id++;
- pkt.hdr.auth_length = 0;
+ pkt.ptype = DCERPC_PKT_BIND;
+ pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
+ pkt.call_id = p->call_id++;
+ pkt.auth_length = 0;
- pkt.in.bind.max_xmit_frag = 0x2000;
- pkt.in.bind.max_recv_frag = 0x2000;
- pkt.in.bind.assoc_group_id = 0;
- pkt.in.bind.num_contexts = 1;
- pkt.in.bind.ctx_list = talloc(mem_ctx, sizeof(pkt.in.bind.ctx_list[0]));
- if (!pkt.in.bind.ctx_list) {
+ pkt.u.bind.max_xmit_frag = 0x2000;
+ pkt.u.bind.max_recv_frag = 0x2000;
+ pkt.u.bind.assoc_group_id = 0;
+ pkt.u.bind.num_contexts = 1;
+ pkt.u.bind.ctx_list = talloc(mem_ctx, sizeof(pkt.u.bind.ctx_list[0]));
+ if (!pkt.u.bind.ctx_list) {
talloc_destroy(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
- pkt.in.bind.ctx_list[0].context_id = 0;
- pkt.in.bind.ctx_list[0].num_transfer_syntaxes = 1;
- pkt.in.bind.ctx_list[0].abstract_syntax = *syntax;
- pkt.in.bind.ctx_list[0].transfer_syntaxes = transfer_syntax;
-
- pkt.in.bind.auth_verifier = data_blob(NULL, 0);
+ pkt.u.bind.ctx_list[0].context_id = 0;
+ pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
+ pkt.u.bind.ctx_list[0].abstract_syntax = *syntax;
+ tsyntax = *transfer_syntax;
+ pkt.u.bind.ctx_list[0].transfer_syntaxes = &tsyntax;
+ pkt.u.bind.auth_verifier = data_blob(NULL, 0);
status = dcerpc_push(&blob, mem_ctx, &pkt);
if (!NT_STATUS_IS_OK(status)) {
@@ -561,14 +210,14 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p,
return status;
}
- if (pkt.hdr.ptype != DCERPC_PKT_BIND_ACK ||
- pkt.out.bind_ack.num_results == 0 ||
- pkt.out.bind_ack.ctx_list[0].result != 0) {
+ if (pkt.ptype != DCERPC_PKT_BIND_ACK ||
+ pkt.u.bind_ack.num_results == 0 ||
+ pkt.u.bind_ack.ctx_list[0].result != 0) {
status = NT_STATUS_UNSUCCESSFUL;
}
- p->srv_max_xmit_frag = pkt.out.bind_ack.max_xmit_frag;
- p->srv_max_recv_frag = pkt.out.bind_ack.max_recv_frag;
+ p->srv_max_xmit_frag = pkt.u.bind_ack.max_xmit_frag;
+ p->srv_max_recv_frag = pkt.u.bind_ack.max_recv_frag;
talloc_destroy(mem_ctx);
@@ -581,11 +230,20 @@ NTSTATUS dcerpc_bind_byuuid(struct dcerpc_pipe *p,
{
struct dcerpc_syntax_id syntax;
struct dcerpc_syntax_id transfer_syntax;
+ NTSTATUS status;
- syntax.uuid_str = uuid;
+ status = guid_from_string(uuid, &syntax.uuid);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(2,("Invalid uuid string in dcerpc_bind_byuuid\n"));
+ return status;
+ }
syntax.if_version = version;
- transfer_syntax.uuid_str = "8a885d04-1ceb-11c9-9fe8-08002b104860";
+ status = guid_from_string("8a885d04-1ceb-11c9-9fe8-08002b104860",
+ &transfer_syntax.uuid);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
transfer_syntax.if_version = 2;
return dcerpc_bind(p, &syntax, &transfer_syntax);
@@ -606,7 +264,7 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
DATA_BLOB blob_in, blob_out, payload;
uint32 remaining, chunk_size;
- init_dcerpc_hdr(&pkt.hdr);
+ init_dcerpc_hdr(&pkt);
remaining = stub_data_in->length;
@@ -614,26 +272,25 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
request header size */
chunk_size = p->srv_max_recv_frag - 24;
- pkt.hdr.ptype = DCERPC_PKT_REQUEST;
- pkt.hdr.call_id = p->call_id++;
- pkt.hdr.auth_length = 0;
- pkt.in.request.alloc_hint = remaining;
- pkt.in.request.context_id = 0;
- pkt.in.request.opnum = opnum;
- pkt.in.request.auth_verifier = data_blob(NULL, 0);
+ pkt.ptype = DCERPC_PKT_REQUEST;
+ pkt.call_id = p->call_id++;
+ pkt.auth_length = 0;
+ pkt.u.request.alloc_hint = remaining;
+ pkt.u.request.context_id = 0;
+ pkt.u.request.opnum = opnum;
/* we send a series of pdus without waiting for a reply until
the last pdu */
while (remaining > chunk_size) {
if (remaining == stub_data_in->length) {
- pkt.hdr.pfc_flags = DCERPC_PFC_FLAG_FIRST;
+ pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST;
} else {
- pkt.hdr.pfc_flags = 0;
+ pkt.pfc_flags = 0;
}
- pkt.in.request.stub_data.data = stub_data_in->data +
+ pkt.u.request.stub_and_verifier.data = stub_data_in->data +
(stub_data_in->length - remaining);
- pkt.in.request.stub_data.length = chunk_size;
+ pkt.u.request.stub_and_verifier.length = chunk_size;
status = dcerpc_push(&blob_in, mem_ctx, &pkt);
if (!NT_STATUS_IS_OK(status)) {
@@ -651,14 +308,14 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
/* now we send a pdu with LAST_FRAG sent and get the first
part of the reply */
if (remaining == stub_data_in->length) {
- pkt.hdr.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
+ pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
} else {
- pkt.hdr.pfc_flags = DCERPC_PFC_FLAG_LAST;
+ pkt.pfc_flags = DCERPC_PFC_FLAG_LAST;
}
- pkt.in.request.stub_data.data = stub_data_in->data +
+ pkt.u.request.stub_and_verifier.data = stub_data_in->data +
(stub_data_in->length - remaining);
- pkt.in.request.stub_data.length = remaining;
-
+ pkt.u.request.stub_and_verifier.length = remaining;
+
status = dcerpc_push(&blob_in, mem_ctx, &pkt);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -672,19 +329,23 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
return status;
}
- if (pkt.hdr.ptype != DCERPC_PKT_RESPONSE) {
+ if (pkt.ptype == DCERPC_PKT_FAULT) {
+ return NT_STATUS_NET_WRITE_FAULT;
+ }
+
+ if (pkt.ptype != DCERPC_PKT_RESPONSE) {
return NT_STATUS_UNSUCCESSFUL;
}
- if (!(pkt.hdr.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
+ if (!(pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
/* something is badly wrong! */
return NT_STATUS_UNSUCCESSFUL;
}
- payload = pkt.out.response.stub_data;
+ payload = pkt.u.response.stub_and_verifier;
/* continue receiving fragments */
- while (!(pkt.hdr.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
+ while (!(pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
uint32 length;
status = dcerpc_raw_packet_secondary(p, mem_ctx, &blob_out);
@@ -697,16 +358,16 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
return status;
}
- if (pkt.hdr.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
+ if (pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
/* start of another packet!? */
return NT_STATUS_UNSUCCESSFUL;
}
- if (pkt.hdr.ptype != DCERPC_PKT_RESPONSE) {
+ if (pkt.ptype != DCERPC_PKT_RESPONSE) {
return NT_STATUS_UNSUCCESSFUL;
}
- length = pkt.out.response.stub_data.length;
+ length = pkt.u.response.stub_and_verifier.length;
payload.data = talloc_realloc(mem_ctx,
payload.data,
@@ -716,7 +377,7 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
}
memcpy(payload.data + payload.length,
- pkt.out.response.stub_data.data,
+ pkt.u.response.stub_and_verifier.data,
length);
payload.length += length;