diff options
author | Andrew Tridgell <tridge@samba.org> | 2003-11-03 06:22:45 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2003-11-03 06:22:45 +0000 |
commit | c5cf47443985c34ad32c44c322901e0fc3a065d7 (patch) | |
tree | f7d6abd03304c4f2359a4753aae23e41982c0e17 /source4/libcli/rpc | |
parent | 7fd381376f88ae99a4bf022d89f21ae497b48c1a (diff) | |
download | samba-c5cf47443985c34ad32c44c322901e0fc3a065d7.tar.gz samba-c5cf47443985c34ad32c44c322901e0fc3a065d7.tar.bz2 samba-c5cf47443985c34ad32c44c322901e0fc3a065d7.zip |
a major revamp of the low level dcerpc code in samba4, We can now do a
successful LSA OpenPolicy using smbtorture
(This used to be commit e925c315f55905060fcca1b188ae1f7e40baf514)
Diffstat (limited to 'source4/libcli/rpc')
-rw-r--r-- | source4/libcli/rpc/dcerpc.c | 644 | ||||
-rw-r--r-- | source4/libcli/rpc/dcerpc.h | 124 | ||||
-rw-r--r-- | source4/libcli/rpc/librpc.h | 71 | ||||
-rw-r--r-- | source4/libcli/rpc/rpc_basic.c | 97 | ||||
-rw-r--r-- | source4/libcli/rpc/rpc_sec.c | 179 | ||||
-rw-r--r-- | source4/libcli/rpc/rpc_sec.h | 81 | ||||
-rw-r--r-- | source4/libcli/rpc/rpcparse.c | 105 |
7 files changed, 768 insertions, 533 deletions
diff --git a/source4/libcli/rpc/dcerpc.c b/source4/libcli/rpc/dcerpc.c new file mode 100644 index 0000000000..56c6d95482 --- /dev/null +++ b/source4/libcli/rpc/dcerpc.c @@ -0,0 +1,644 @@ +/* + Unix SMB/CIFS implementation. + raw dcerpc operations + + Copyright (C) Tim Potter 2003 + Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* initialise a dcerpc pipe. This currently assumes a SMB named pipe + transport */ +struct dcerpc_pipe *dcerpc_pipe_init(struct cli_tree *tree) +{ + struct dcerpc_pipe *p; + + TALLOC_CTX *mem_ctx = talloc_init("cli_dcerpc_tree"); + if (mem_ctx == NULL) + return NULL; + + p = talloc(mem_ctx, sizeof(*p)); + if (!p) { + talloc_destroy(mem_ctx); + return NULL; + } + + p->mem_ctx = mem_ctx; + p->tree = tree; + p->tree->reference_count++; + p->call_id = 1; + p->fnum = 0; + + return p; +} + +/* close down a dcerpc over SMB pipe */ +void dcerpc_pipe_close(struct dcerpc_pipe *p) +{ + if (!p) return; + p->reference_count--; + if (p->reference_count <= 0) { + cli_tree_close(p->tree); + talloc_destroy(p->mem_ctx); + } +} + +#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 +*/ +static NTSTATUS push_syntax_id(char *data, const struct dcerpc_syntax_id *syntax) +{ + 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 alloc_hint, stub_len; + + BLOB_CHECK_BOUNDS(blob, *offset, 8); + + 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 (!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 = IVAL(blob->data, *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; +} + +/* + 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; + + 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_INVALID_LEVEL; + } + + 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; + } + } + + 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) +{ + uint32 alloc_hint = 8 + pkt->stub_data.length + pkt->auth_verifier.length; + + SIVAL(blob->data, (*offset) + 0, 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; +} + + +/* + 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; + 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) { + return NT_STATUS_NO_MEMORY; + } + + pkt->hdr.frag_length = wire_size; + + dcerpc_push_hdr(blob->data + offset, &pkt->hdr); + offset += 16; + + switch (pkt->hdr.ptype) { + case DCERPC_PKT_BIND: + status = dcerpc_push_bind(blob, &offset, &pkt->hdr, &pkt->in.bind); + break; + + case DCERPC_PKT_REQUEST: + status = dcerpc_push_request(blob, &offset, &pkt->hdr, &pkt->in.request); + break; + + default: + status = NT_STATUS_INVALID_LEVEL; + } + + return status; +} + + + + +/* + fill in the fixed values in a dcerpc header +*/ +static void init_dcerpc_hdr(struct dcerpc_hdr *hdr) +{ + 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; +} + + +/* + perform a bind using the given syntax +*/ +NTSTATUS dcerpc_bind(struct dcerpc_pipe *p, + const struct dcerpc_syntax_id *syntax, + const struct dcerpc_syntax_id *transfer_syntax) +{ + TALLOC_CTX *mem_ctx; + struct dcerpc_packet pkt; + NTSTATUS status; + DATA_BLOB blob; + DATA_BLOB blob_out; + + mem_ctx = talloc_init("cli_dcerpc_bind"); + if (!mem_ctx) { + return NT_STATUS_NO_MEMORY; + } + + init_dcerpc_hdr(&pkt.hdr); + + 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.in.bind.max_xmit_frag = 5680; + pkt.in.bind.max_recv_frag = 5680; + 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) { + 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); + + status = dcerpc_push(&blob, mem_ctx, &pkt); + if (!NT_STATUS_IS_OK(status)) { + talloc_destroy(mem_ctx); + return status; + } + + status = dcerpc_raw_packet(p, mem_ctx, &blob, &blob_out); + if (!NT_STATUS_IS_OK(status)) { + talloc_destroy(mem_ctx); + return status; + } + + status = dcerpc_pull(&blob_out, mem_ctx, &pkt); + if (!NT_STATUS_IS_OK(status)) { + talloc_destroy(mem_ctx); + return status; + } + + if (pkt.hdr.ptype != DCERPC_PKT_BIND_ACK) { + 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; + + talloc_destroy(mem_ctx); + + return status; +} + +#define TRANSFER_SYNTAX_V2 {"8a885d04-1ceb-11c9-9fe8-08002b104860", 2} + +static const struct { + const char *name; + struct dcerpc_syntax_id syntax; + struct dcerpc_syntax_id transfer_syntax; +} known_pipes[] = { + { "lsarpc" , { "12345778-1234-abcd-ef00-0123456789ab", 0 }, TRANSFER_SYNTAX_V2 }, + { "samr" , { "12345778-1234-abcd-ef00-0123456789ac", 1 }, TRANSFER_SYNTAX_V2 }, + { "netlogon", { "12345778-1234-abcd-ef00-01234567cffb", 1 }, TRANSFER_SYNTAX_V2 }, + { "srvsvc" , { "4b324fc8-1670-01d3-1278-5a47bf6ee188", 3 }, TRANSFER_SYNTAX_V2 }, + { "wkssvc" , { "6bffd098-a112-3610-9833-46c3f87e345a", 1 }, TRANSFER_SYNTAX_V2 }, + { "winreg" , { "338cd001-2244-31f1-aaaa-900038001003", 1 }, TRANSFER_SYNTAX_V2 }, + { "spoolss" , { "12345678-1234-abcd-ef00-0123456789ab", 1 }, TRANSFER_SYNTAX_V2 }, + { "netdfs" , { "4fc742e0-4a10-11cf-8273-00aa004ae673", 3 }, TRANSFER_SYNTAX_V2 }, + { NULL , } +}; + + +/* Perform a bind using the given well-known pipe name */ +NTSTATUS cli_dcerpc_bind_byname(struct dcerpc_pipe *p, const char *pipe_name) +{ + int i; + + for (i=0; known_pipes[i].name; i++) { + if (strcasecmp(known_pipes[i].name, pipe_name) == 0) + break; + } + + if (known_pipes[i].name == NULL) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + return dcerpc_bind(p, &known_pipes[i].syntax, &known_pipes[i].transfer_syntax); +} + +NTSTATUS cli_dcerpc_request(struct dcerpc_pipe *p, + uint16 opnum, + TALLOC_CTX *mem_ctx, + DATA_BLOB *stub_data_in, + DATA_BLOB *stub_data_out) +{ + + struct dcerpc_packet pkt; + NTSTATUS status; + DATA_BLOB blob; + + init_dcerpc_hdr(&pkt.hdr); + + pkt.hdr.ptype = DCERPC_PKT_REQUEST; + 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.in.request.context_id = 0; + pkt.in.request.opnum = opnum; + pkt.in.request.stub_data = *stub_data_in; + pkt.in.request.auth_verifier = data_blob(NULL, 0); + + status = dcerpc_push(&blob, mem_ctx, &pkt); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = dcerpc_raw_packet(p, mem_ctx, &blob, stub_data_out); + + return status; +} diff --git a/source4/libcli/rpc/dcerpc.h b/source4/libcli/rpc/dcerpc.h new file mode 100644 index 0000000000..cd1bc728e2 --- /dev/null +++ b/source4/libcli/rpc/dcerpc.h @@ -0,0 +1,124 @@ +/* + Unix SMB/CIFS implementation. + DCERPC interface structures + + Copyright (C) Tim Potter 2003 + Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + see http://www.opengroup.org/onlinepubs/9629399/chap12.htm for details + of these structures + + note that the structure definitions here don't include some of the + fields that are wire-artifacts. Those are put on the wire by the + marshalling/unmarshalling routines in decrpc.c +*/ + +struct dcerpc_pipe { + TALLOC_CTX *mem_ctx; + uint16 fnum; + int reference_count; + uint32 call_id; + uint32 srv_max_xmit_frag; + uint32 srv_max_recv_frag; + struct cli_tree *tree; +}; + +/* 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 + +/* + 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 { + 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 { + uint32 result; + 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 { + uint16 context_id; + uint8 cancel_count; + DATA_BLOB stub_data; + DATA_BLOB auth_verifier; + } response; + } out; +}; + diff --git a/source4/libcli/rpc/librpc.h b/source4/libcli/rpc/librpc.h deleted file mode 100644 index f4f7101c90..0000000000 --- a/source4/libcli/rpc/librpc.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - Unix SMB/CIFS implementation. - rpc interface definitions - Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - this provides definitions for the libcli/rpc/ MSRPC library -*/ - - -/* this is the base structure passed to routines that - parse MSRPC formatted data - - note that in Samba4 we use separate routines and structures for - MSRPC marshalling and unmarshalling. Also note that these routines - are being kept deliberately very simple, and are not tied to a - particular transport -*/ -struct ndr_parse { - uint32 flags; /* LIBNDR_FLAG_* */ - char *data; - uint32 data_size; - uint32 offset; - TALLOC_CTX *mem_ctx; -}; - -struct ndr_parse_save { - uint32 data_size; - uint32 offset; -}; - -#define LIBNDR_FLAG_BIGENDIAN 1 - - -/* these are used to make the error checking on each element in libndr - less tedious, hopefully making the code more readable */ -#define NDR_CHECK(call) do { NTSTATUS _status; \ - _status = call; \ - if (!NT_STATUS_IS_OK(_status)) \ - return _status; \ - } while (0) - - -#define NDR_ALLOC(ndr, s) do { \ - (s) = talloc(ndr->mem_ctx, sizeof(*(s))); \ - if (!(s)) return NT_STATUS_NO_MEMORY; \ - } while (0) - -#define NDR_ALLOC_N(ndr, s, n) do { \ - if ((n) == 0) { \ - (s) = NULL; \ - } else { \ - (s) = talloc(ndr->mem_ctx, (n) * sizeof(*(s))); \ - if (!(s)) return NT_STATUS_NO_MEMORY; \ - } \ - } while (0) diff --git a/source4/libcli/rpc/rpc_basic.c b/source4/libcli/rpc/rpc_basic.c deleted file mode 100644 index 5ff17f9d99..0000000000 --- a/source4/libcli/rpc/rpc_basic.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - routines for marshalling/unmarshalling basic types - - Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -#define NDR_NEED_BYTES(ndr, n) do { \ - if ((n) > ndr->data_size || ndr->offset + (n) > ndr->data_size) { \ - return NT_STATUS_BUFFER_TOO_SMALL; \ - } \ -} while(0) - -#define NDR_ALIGN(ndr, n) do { \ - ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \ - if (ndr->offset >= ndr->data_size) { \ - return NT_STATUS_BUFFER_TOO_SMALL; \ - } \ -} while(0) - -/* - parse a GUID -*/ -NTSTATUS ndr_parse_guid(struct ndr_parse *ndr, GUID *guid) -{ - int i; - NDR_NEED_BYTES(ndr, GUID_SIZE); - for (i=0;i<GUID_SIZE;i++) { - guid->info[i] = CVAL(ndr->data, ndr->offset + i); - } - ndr->offset += i; - return NT_STATUS_OK; -} - - -/* - parse a u8 -*/ -NTSTATUS ndr_parse_u8(struct ndr_parse *ndr, uint8 *v) -{ - NDR_NEED_BYTES(ndr, 1); - *v = CVAL(ndr->data, ndr->offset); - ndr->offset += 1; - return NT_STATUS_OK; -} - - -/* - parse a u16 -*/ -NTSTATUS ndr_parse_u16(struct ndr_parse *ndr, uint16 *v) -{ - NDR_ALIGN(ndr, 2); - NDR_NEED_BYTES(ndr, 2); - if (ndr->flags & LIBNDR_FLAG_BIGENDIAN) { - *v = RSVAL(ndr->data, ndr->offset); - } else { - *v = SVAL(ndr->data, ndr->offset); - } - ndr->offset += 2; - return NT_STATUS_OK; -} - - -/* - parse a u32 -*/ -NTSTATUS ndr_parse_u32(struct ndr_parse *ndr, uint32 *v) -{ - NDR_ALIGN(ndr, 4); - NDR_NEED_BYTES(ndr, 4); - if (ndr->flags & LIBNDR_FLAG_BIGENDIAN) { - *v = RIVAL(ndr->data, ndr->offset); - } else { - *v = IVAL(ndr->data, ndr->offset); - } - ndr->offset += 2; - return NT_STATUS_OK; -} - diff --git a/source4/libcli/rpc/rpc_sec.c b/source4/libcli/rpc/rpc_sec.c deleted file mode 100644 index 49b50c758c..0000000000 --- a/source4/libcli/rpc/rpc_sec.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - routines for marshalling/unmarshalling security descriptors - and related structures - - Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - - -#include "includes.h" - -/* - parse a security_ace -*/ -NTSTATUS ndr_parse_security_ace(struct ndr_parse *ndr, struct security_ace *ace) -{ - uint16 size; - struct ndr_parse_save save; - - ndr_parse_save(ndr, &save); - - NDR_CHECK(ndr_parse_u8(ndr, &ace->type)); - NDR_CHECK(ndr_parse_u8(ndr, &ace->flags)); - NDR_CHECK(ndr_parse_u16(ndr, &size)); - NDR_CHECK(ndr_parse_limit_size(ndr, size, 4)); - - NDR_CHECK(ndr_parse_u32(ndr, &ace->access_mask)); - - if (sec_ace_object(ace->type)) { - NDR_ALLOC(ndr, ace->obj); - NDR_CHECK(ndr_parse_u32(ndr, &ace->obj->flags)); - if (ace->obj->flags & SEC_ACE_OBJECT_PRESENT) { - NDR_CHECK(ndr_parse_guid(ndr, &ace->obj->object_guid)); - } - if (ace->obj->flags & SEC_ACE_OBJECT_INHERITED_PRESENT) { - NDR_CHECK(ndr_parse_guid(ndr, &ace->obj->inherit_guid)); - } - } - - - NDR_CHECK(ndr_parse_dom_sid(ndr, &ace->trustee)); - - ndr_parse_restore(ndr, &save); - NDR_CHECK(ndr_parse_advance(ndr, size)); - - return NT_STATUS_OK; -} - -/* - parse a security_acl -*/ -NTSTATUS ndr_parse_security_acl(struct ndr_parse *ndr, struct security_acl *acl) -{ - int i; - uint16 size; - struct ndr_parse_save save; - - ndr_parse_save(ndr, &save); - - NDR_CHECK(ndr_parse_u16(ndr, &acl->revision)); - NDR_CHECK(ndr_parse_u16(ndr, &size)); - NDR_CHECK(ndr_parse_limit_size(ndr, size, 4)); - NDR_CHECK(ndr_parse_u32(ndr, &acl->num_aces)); - - NDR_ALLOC_N(ndr, acl->aces, acl->num_aces); - - for (i=0;i<acl->num_aces;i++) { - NDR_CHECK(ndr_parse_security_ace(ndr, &acl->aces[i])); - } - - ndr_parse_restore(ndr, &save); - NDR_CHECK(ndr_parse_advance(ndr, size)); - - return NT_STATUS_OK; -} - -/* - parse a security_acl offset and structure -*/ -NTSTATUS ndr_parse_security_acl_ofs(struct ndr_parse *ndr, struct security_acl **acl) -{ - uint32 ofs; - struct ndr_parse_save save; - - NDR_CHECK(ndr_parse_u32(ndr, &ofs)); - if (ofs == 0) { - /* it is valid for an acl ptr to be NULL */ - *acl = NULL; - return NT_STATUS_OK; - } - - ndr_parse_save(ndr, &save); - NDR_CHECK(ndr_parse_set_offset(ndr, ofs)); - NDR_ALLOC(ndr, *acl); - NDR_CHECK(ndr_parse_security_acl(ndr, *acl)); - ndr_parse_restore(ndr, &save); - - return NT_STATUS_OK; -} - - -/* - parse a dom_sid -*/ -NTSTATUS ndr_parse_dom_sid(struct ndr_parse *ndr, struct dom_sid *sid) -{ - int i; - - NDR_CHECK(ndr_parse_u8(ndr, &sid->sid_rev_num)); - NDR_CHECK(ndr_parse_u8(ndr, &sid->num_auths)); - for (i=0;i<6;i++) { - NDR_CHECK(ndr_parse_u8(ndr, &sid->id_auth[i])); - } - - NDR_ALLOC_N(ndr, sid->sub_auths, sid->num_auths); - - for (i=0;i<sid->num_auths;i++) { - NDR_CHECK(ndr_parse_u32(ndr, &sid->sub_auths[i])); - } - - return NT_STATUS_OK; -} - -/* - parse a dom_sid offset and structure -*/ -NTSTATUS ndr_parse_dom_sid_ofs(struct ndr_parse *ndr, struct dom_sid **sid) -{ - uint32 ofs; - struct ndr_parse_save save; - - NDR_CHECK(ndr_parse_u32(ndr, &ofs)); - if (ofs == 0) { - /* it is valid for a dom_sid ptr to be NULL */ - *sid = NULL; - return NT_STATUS_OK; - } - - ndr_parse_save(ndr, &save); - NDR_CHECK(ndr_parse_set_offset(ndr, ofs)); - NDR_ALLOC(ndr, *sid); - NDR_CHECK(ndr_parse_dom_sid(ndr, *sid)); - ndr_parse_restore(ndr, &save); - - return NT_STATUS_OK; -} - -/* - parse a security descriptor -*/ -NTSTATUS ndr_parse_security_descriptor(struct ndr_parse *ndr, - struct security_descriptor **sd) -{ - NDR_ALLOC(ndr, *sd); - - NDR_CHECK(ndr_parse_u8(ndr, &(*sd)->revision)); - NDR_CHECK(ndr_parse_u16(ndr, &(*sd)->type)); - NDR_CHECK(ndr_parse_dom_sid_ofs(ndr, &(*sd)->owner_sid)); - NDR_CHECK(ndr_parse_dom_sid_ofs(ndr, &(*sd)->group_sid)); - NDR_CHECK(ndr_parse_security_acl_ofs(ndr, &(*sd)->sacl)); - NDR_CHECK(ndr_parse_security_acl_ofs(ndr, &(*sd)->dacl)); - - return NT_STATUS_OK; -} diff --git a/source4/libcli/rpc/rpc_sec.h b/source4/libcli/rpc/rpc_sec.h deleted file mode 100644 index 3cda400eb2..0000000000 --- a/source4/libcli/rpc/rpc_sec.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - definitions for marshalling/unmarshalling security descriptors - and related structures - - Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - - -/* a domain SID. Note that unlike Samba3 this contains a pointer, - so you can't copy them using assignment */ -struct dom_sid { - uint8 sid_rev_num; /**< SID revision number */ - uint8 num_auths; /**< Number of sub-authorities */ - uint8 id_auth[6]; /**< Identifier Authority */ - uint32 *sub_auths; -}; - -/* an access control element */ -struct security_ace { - uint8 type; /* xxxx_xxxx_ACE_TYPE - e.g allowed / denied etc */ - uint8 flags; /* xxxx_INHERIT_xxxx - e.g OBJECT_INHERIT_ACE */ - - uint32 access_mask; - - /* the 'obj' part is present when type is XXXX_TYPE_XXXX_OBJECT */ - struct { - uint32 flags; - GUID object_guid; - GUID inherit_guid; - } *obj; - - struct dom_sid trustee; -}; - - -/* a security ACL */ -struct security_acl { - uint16 revision; - uint32 num_aces; - - struct security_ace *aces; -}; - - -/* a security descriptor */ -struct security_descriptor { - uint8 revision; - uint16 type; /* SEC_DESC_xxxx flags */ - - struct dom_sid *owner_sid; - struct dom_sid *group_sid; - struct security_acl *sacl; /* system ACL */ - struct security_acl *dacl; /* user (discretionary) ACL */ -}; - -/* query security descriptor */ -struct smb_query_secdesc { - struct { - uint16 fnum; - uint32 secinfo_flags; - } in; - struct { - struct security_descriptor *sd; - } out; -}; diff --git a/source4/libcli/rpc/rpcparse.c b/source4/libcli/rpc/rpcparse.c deleted file mode 100644 index 41e6919b72..0000000000 --- a/source4/libcli/rpc/rpcparse.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - Unix SMB/CIFS implementation. - libndr interface - Copyright (C) Andrew Tridgell 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - this provides the core routines for MSNDR parsing functions -*/ - -#include "includes.h" - -/* - initialise a ndr parse structure from a data blob -*/ -struct ndr_parse *ndr_parse_init_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx) -{ - struct ndr_parse *ndr; - - ndr = talloc(mem_ctx, sizeof(*ndr)); - if (!ndr) return NULL; - - ndr->data = blob->data; - ndr->data_size = blob->length; - ndr->offset = 0; - ndr->mem_ctx = mem_ctx; - - return ndr; -} - - -/* limit the remaining size of the current ndr parse structure to the - given size, starting at the given offset - - this is used when a ndr packet has an explicit size on the wire, and we - need to make sure that we don't use more data than is indicated - - the 'ofs' parameter indicates how many bytes back from the current - offset in the buffer the 'size' number of bytes starts -*/ -NTSTATUS ndr_parse_limit_size(struct ndr_parse *ndr, uint32 size, uint32 ofs) -{ - uint32 new_size; - new_size = ndr->offset + size - ofs; - - if (new_size > ndr->data_size) { - return NT_STATUS_BUFFER_TOO_SMALL; - } - ndr->data_size = new_size; - - return NT_STATUS_OK; -} - - -/* - advance by 'size' bytes -*/ -NTSTATUS ndr_parse_advance(struct ndr_parse *ndr, uint32 size) -{ - ndr->offset += size; - if (ndr->offset > ndr->data_size) { - return NT_STATUS_BUFFER_TOO_SMALL; - } - return NT_STATUS_OK; -} - -/* - set the parse offset to 'ofs' -*/ -NTSTATUS ndr_parse_set_offset(struct ndr_parse *ndr, uint32 ofs) -{ - ndr->offset = ofs; - if (ndr->offset > ndr->data_size) { - return NT_STATUS_BUFFER_TOO_SMALL; - } - return NT_STATUS_OK; -} - -/* save the offset/size of the current ndr state */ -void ndr_parse_save(struct ndr_parse *ndr, struct ndr_parse_save *save) -{ - save->offset = ndr->offset; - save->data_size = ndr->data_size; -} - -/* restore the size/offset of a ndr structure */ -void ndr_parse_restore(struct ndr_parse *ndr, struct ndr_parse_save *save) -{ - ndr->offset = save->offset; - ndr->data_size = save->data_size; -} |