diff options
author | Andrew Tridgell <tridge@samba.org> | 2003-11-23 06:28:12 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2003-11-23 06:28:12 +0000 |
commit | 800d3e0134b72135fa359fa5a239f1c68adf4ca1 (patch) | |
tree | 1f0e6cafab8f1d62dee9a3796443ab18b6394fe1 /source4/librpc/rpc | |
parent | 02dc7536dd625e0cdee23a96e66cb41b407cdba8 (diff) | |
download | samba-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')
-rw-r--r-- | source4/librpc/rpc/dcerpc.c | 561 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc.h | 87 |
2 files changed, 111 insertions, 537 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; diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index 65566878e3..ec6189302a 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -40,18 +40,6 @@ struct dcerpc_pipe { unsigned flags; }; -/* dcerpc packet types */ -#define DCERPC_PKT_REQUEST 0 -#define DCERPC_PKT_RESPONSE 2 -#define DCERPC_PKT_BIND 11 -#define DCERPC_PKT_BIND_ACK 12 -#define DCERPC_PKT_BIND_NAK 13 - -/* hdr.pfc_flags */ -#define DCERPC_PFC_FLAG_FIRST 0x01 -#define DCERPC_PFC_FLAG_LAST 0x02 -#define DCERPC_PFC_FLAG_NOCALL 0x20 - /* dcerpc pipe flags */ #define DCERPC_DEBUG_PRINT_IN 1 #define DCERPC_DEBUG_PRINT_OUT 2 @@ -60,78 +48,3 @@ struct dcerpc_pipe { #define DCERPC_DEBUG_VALIDATE_IN 4 #define DCERPC_DEBUG_VALIDATE_OUT 8 #define DCERPC_DEBUG_VALIDATE_BOTH (DCERPC_DEBUG_VALIDATE_IN | DCERPC_DEBUG_VALIDATE_OUT) - -/* - all dcerpc packets use this structure. -*/ -struct dcerpc_packet { - /* all requests and responses contain a dcerpc header */ - struct dcerpc_hdr { - uint8 rpc_vers; /* RPC version */ - uint8 rpc_vers_minor; /* Minor version */ - uint8 ptype; /* Packet type */ - uint8 pfc_flags; /* Fragmentation flags */ - uint8 drep[4]; /* NDR data representation */ - uint16 frag_length; /* Total length of fragment */ - uint16 auth_length; /* authenticator length */ - uint32 call_id; /* Call identifier */ - } hdr; - - union { - struct dcerpc_bind { - uint16 max_xmit_frag; - uint16 max_recv_frag; - uint32 assoc_group_id; - uint8 num_contexts; - struct { - uint16 context_id; - uint8 num_transfer_syntaxes; - struct dcerpc_syntax_id { - const char *uuid_str; - uint32 if_version; - } abstract_syntax; - const struct dcerpc_syntax_id *transfer_syntaxes; - } *ctx_list; - DATA_BLOB auth_verifier; - } bind; - - struct dcerpc_request { - uint32 alloc_hint; - uint16 context_id; - uint16 opnum; - DATA_BLOB stub_data; - DATA_BLOB auth_verifier; - } request; - } in; - - union { - struct dcerpc_bind_ack { - uint16 max_xmit_frag; - uint16 max_recv_frag; - uint32 assoc_group_id; - const char *secondary_address; - uint8 num_results; - struct { - uint16 result; - uint16 reason; - struct dcerpc_syntax_id syntax; - } *ctx_list; - DATA_BLOB auth_verifier; - } bind_ack; - - struct dcerpc_bind_nak { - uint16 reject_reason; - uint32 num_versions; - uint32 *versions; - } bind_nak; - - struct dcerpc_response { - uint32 alloc_hint; - uint16 context_id; - uint8 cancel_count; - DATA_BLOB stub_data; - DATA_BLOB auth_verifier; - } response; - } out; -}; - |