From c5cf47443985c34ad32c44c322901e0fc3a065d7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 3 Nov 2003 06:22:45 +0000 Subject: 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) --- source4/libcli/clidcerpc.c | 254 ---------------- source4/libcli/ndr/libndr.h | 85 ++++++ source4/libcli/ndr/ndr.c | 184 ++++++++++++ source4/libcli/ndr/ndr_basic.c | 140 +++++++++ source4/libcli/ndr/ndr_sec.c | 201 +++++++++++++ source4/libcli/ndr/ndr_sec.h | 90 ++++++ source4/libcli/raw/clisession.c | 4 +- source4/libcli/raw/rawacl.c | 52 +++- source4/libcli/raw/rawdcerpc.c | 215 +++----------- source4/libcli/raw/rawsearch.c | 8 +- source4/libcli/rpc/dcerpc.c | 644 ++++++++++++++++++++++++++++++++++++++++ source4/libcli/rpc/dcerpc.h | 124 ++++++++ source4/libcli/rpc/librpc.h | 71 ----- source4/libcli/rpc/rpc_basic.c | 97 ------ source4/libcli/rpc/rpc_sec.c | 179 ----------- source4/libcli/rpc/rpc_sec.h | 81 ----- source4/libcli/rpc/rpcparse.c | 105 ------- 17 files changed, 1560 insertions(+), 974 deletions(-) delete mode 100644 source4/libcli/clidcerpc.c create mode 100644 source4/libcli/ndr/libndr.h create mode 100644 source4/libcli/ndr/ndr.c create mode 100644 source4/libcli/ndr/ndr_basic.c create mode 100644 source4/libcli/ndr/ndr_sec.c create mode 100644 source4/libcli/ndr/ndr_sec.h create mode 100644 source4/libcli/rpc/dcerpc.c create mode 100644 source4/libcli/rpc/dcerpc.h delete mode 100644 source4/libcli/rpc/librpc.h delete mode 100644 source4/libcli/rpc/rpc_basic.c delete mode 100644 source4/libcli/rpc/rpc_sec.c delete mode 100644 source4/libcli/rpc/rpc_sec.h delete mode 100644 source4/libcli/rpc/rpcparse.c (limited to 'source4/libcli') diff --git a/source4/libcli/clidcerpc.c b/source4/libcli/clidcerpc.c deleted file mode 100644 index fffd4e0941..0000000000 --- a/source4/libcli/clidcerpc.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - Unix SMB/CIFS implementation. - raw dcerpc operations - - Copyright (C) Tim Potter, 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" - -struct cli_dcerpc_pipe *cli_dcerpc_pipe_init(struct cli_tree *tree) -{ - struct cli_dcerpc_pipe *p; - - TALLOC_CTX *mem_ctx = talloc_init("cli_dcerpc_tree"); - if (mem_ctx == NULL) - return NULL; - - p = talloc_zero(mem_ctx, sizeof(*p)); - if (!p) { - talloc_destroy(mem_ctx); - return NULL; - } - - p->mem_ctx = mem_ctx; - p->tree = tree; - p->tree->reference_count++; - - return p; -} - -void cli_dcerpc_pipe_close(struct cli_dcerpc_pipe *p) -{ - if (!p) return; - p->reference_count--; - if (p->reference_count <= 0) { - cli_tree_close(p->tree); - talloc_destroy(p->mem_ctx); - } -} - -static void init_dcerpc_hdr(struct dcerpc_hdr *hdr, uint8 ptype, - uint8 pfc_flags, uint32 call_id) -{ - hdr->rpc_vers = 5; - hdr->rpc_vers_minor = 0; - hdr->ptype = ptype; - hdr->pfc_flags = pfc_flags; - hdr->drep[0] = 0x10; /* Little endian */ - hdr->call_id = call_id; -} - -struct syntax_id trans_synt_v2 = -{ - { - 0x8a885d04, 0x1ceb, 0x11c9, - { 0x9f, 0xe8, 0x08, 0x00, - 0x2b, 0x10, 0x48, 0x60 } - }, 0x02 -}; - -struct syntax_id synt_netlogon_v2 = -{ - { - 0x8a885d04, 0x1ceb, 0x11c9, - { 0x9f, 0xe8, 0x08, 0x00, - 0x2b, 0x10, 0x48, 0x60 } - }, 0x02 -}; - -struct syntax_id synt_wkssvc_v1 = -{ - { - 0x6bffd098, 0xa112, 0x3610, - { 0x98, 0x33, 0x46, 0xc3, - 0xf8, 0x7e, 0x34, 0x5a } - }, 0x01 -}; - -struct syntax_id synt_srvsvc_v3 = -{ - { - 0x4b324fc8, 0x1670, 0x01d3, - { 0x12, 0x78, 0x5a, 0x47, - 0xbf, 0x6e, 0xe1, 0x88 } - }, 0x03 -}; - -struct syntax_id synt_lsarpc_v0 = -{ - { - 0x12345778, 0x1234, 0xabcd, - { 0xef, 0x00, 0x01, 0x23, - 0x45, 0x67, 0x89, 0xab } - }, 0x00 -}; - -struct syntax_id synt_lsarpc_v0_ds = -{ - { - 0x3919286a, 0xb10c, 0x11d0, - { 0x9b, 0xa8, 0x00, 0xc0, - 0x4f, 0xd9, 0x2e, 0xf5 } - }, 0x00 -}; - -struct syntax_id synt_samr_v1 = -{ - { - 0x12345778, 0x1234, 0xabcd, - { 0xef, 0x00, 0x01, 0x23, - 0x45, 0x67, 0x89, 0xac } - }, 0x01 -}; - -struct syntax_id synt_netlogon_v1 = -{ - { - 0x12345678, 0x1234, 0xabcd, - { 0xef, 0x00, 0x01, 0x23, - 0x45, 0x67, 0xcf, 0xfb } - }, 0x01 -}; - -struct syntax_id synt_winreg_v1 = -{ - { - 0x338cd001, 0x2244, 0x31f1, - { 0xaa, 0xaa, 0x90, 0x00, - 0x38, 0x00, 0x10, 0x03 } - }, 0x01 -}; - -struct syntax_id synt_spoolss_v1 = -{ - { - 0x12345678, 0x1234, 0xabcd, - { 0xef, 0x00, 0x01, 0x23, - 0x45, 0x67, 0x89, 0xab } - }, 0x01 -}; - -struct syntax_id synt_netdfs_v3 = -{ - { - 0x4fc742e0, 0x4a10, 0x11cf, - { 0x82, 0x73, 0x00, 0xaa, - 0x00, 0x4a, 0xe6, 0x73 } - }, 0x03 -}; - -struct known_pipes { - const char *client_pipe; - struct p_ctx_list ctx_list; -}; - -const struct known_pipes known_pipes[] = -{ - { PIPE_LSARPC , { 0, 1, &synt_lsarpc_v0, &trans_synt_v2 }}, - { PIPE_SAMR , { 0, 1, &synt_samr_v1, &trans_synt_v2 }}, - { PIPE_NETLOGON, { 0, 1, &synt_netlogon_v1, &trans_synt_v2 }}, - { PIPE_SRVSVC , { 0, 1, &synt_srvsvc_v3 , &trans_synt_v2 }}, - { PIPE_WKSSVC , { 0, 1, &synt_wkssvc_v1 , &trans_synt_v2 }}, - { PIPE_WINREG , { 0, 1, &synt_winreg_v1 , &trans_synt_v2 }}, - { PIPE_SPOOLSS , { 0, 1, &synt_spoolss_v1, &trans_synt_v2 }}, - { PIPE_NETDFS , { 0, 1, &synt_netdfs_v3 , &trans_synt_v2 }}, - { NULL , { 0, 0, NULL, NULL }} -}; - -/* Perform a bind using the given syntaxes */ - -NTSTATUS cli_dcerpc_bind(struct cli_dcerpc_pipe *p, int num_contexts, - struct p_ctx_list *ctx_list) -{ - TALLOC_CTX *mem_ctx; - struct dcerpc_bind parms; - NTSTATUS status; - - mem_ctx = talloc_init("cli_dcerpc_bind"); - - ZERO_STRUCT(parms); - - init_dcerpc_hdr(&parms.in.hdr, RPC_BIND, RPC_FLG_FIRST|RPC_FLG_LAST, - p->call_id++); - - parms.in.max_xmit_frag = 5680; - parms.in.max_recv_frag = 5680; - parms.in.num_contexts = num_contexts; - parms.in.ctx_list = ctx_list; - - status = dcerpc_raw_bind(p, &parms); - - talloc_destroy(mem_ctx); - - return status; -} - -/* Perform a bind using the given well-known pipe name */ - -NTSTATUS cli_dcerpc_bind_byname(struct cli_dcerpc_pipe *p, - const char *pipe_name) -{ - const struct known_pipes *pi; - - for (pi = known_pipes; pi->client_pipe; pi++) { - if (strequal(&pi->client_pipe[5], pipe_name)) - break; - } - - if (pi->client_pipe == NULL) - return NT_STATUS_UNSUCCESSFUL; - - - return cli_dcerpc_bind(p, 1, &pi->ctx_list); -} - -NTSTATUS cli_dcerpc_request(struct cli_dcerpc_pipe *p, uint16 opnum, - DATA_BLOB stub_data) -{ - TALLOC_CTX *mem_ctx; - struct dcerpc_request parms; - NTSTATUS status; - - mem_ctx = talloc_init("cli_dcerpc_request"); - - ZERO_STRUCT(parms); - - init_dcerpc_hdr(&parms.in.hdr, RPC_REQUEST, - RPC_FLG_FIRST|RPC_FLG_LAST, p->call_id++); - - parms.in.alloc_hint = 0; - parms.in.cont_id = 0; - parms.in.opnum = opnum; - parms.in.stub_data = stub_data; - - status = dcerpc_raw_request(p, &parms); - - talloc_destroy(mem_ctx); - - return status; -} diff --git a/source4/libcli/ndr/libndr.h b/source4/libcli/ndr/libndr.h new file mode 100644 index 0000000000..4369ebeb30 --- /dev/null +++ b/source4/libcli/ndr/libndr.h @@ -0,0 +1,85 @@ +/* + 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_pull { + uint32 flags; /* LIBNDR_FLAG_* */ + char *data; + uint32 data_size; + uint32 offset; + TALLOC_CTX *mem_ctx; +}; + +struct ndr_pull_save { + uint32 data_size; + uint32 offset; +}; + + +/* structure passed to functions that generate NDR formatted data */ +struct ndr_push { + uint32 flags; /* LIBNDR_FLAG_* */ + char *data; + uint32 alloc_size; + uint32 offset; + TALLOC_CTX *mem_ctx; +}; + +#define NDR_BASE_MARSHALL_SIZE 1024 + + + +#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/ndr/ndr.c b/source4/libcli/ndr/ndr.c new file mode 100644 index 0000000000..d9a5ff7735 --- /dev/null +++ b/source4/libcli/ndr/ndr.c @@ -0,0 +1,184 @@ +/* + 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 NDR parsing functions + + see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details + of NDR encoding rules +*/ + +#include "includes.h" + +/* + initialise a ndr parse structure from a data blob +*/ +struct ndr_pull *ndr_pull_init_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx) +{ + struct ndr_pull *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_pull_limit_size(struct ndr_pull *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_pull_advance(struct ndr_pull *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_pull_set_offset(struct ndr_pull *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_pull_save(struct ndr_pull *ndr, struct ndr_pull_save *save) +{ + save->offset = ndr->offset; + save->data_size = ndr->data_size; +} + +/* restore the size/offset of a ndr structure */ +void ndr_pull_restore(struct ndr_pull *ndr, struct ndr_pull_save *save) +{ + ndr->offset = save->offset; + ndr->data_size = save->data_size; +} + + + + +/* create a ndr_push structure, ready for some marshalling */ +struct ndr_push *ndr_push_init(void) +{ + struct ndr_push *ndr; + TALLOC_CTX *mem_ctx = talloc_init("ndr_push_init"); + if (!mem_ctx) return NULL; + + ndr = talloc(mem_ctx, sizeof(*ndr)); + if (!ndr) { + talloc_destroy(mem_ctx); + return NULL; + } + + ndr->mem_ctx = mem_ctx; + ndr->flags = 0; + ndr->alloc_size = NDR_BASE_MARSHALL_SIZE; + ndr->data = talloc(ndr->mem_ctx, ndr->alloc_size); + if (!ndr->data) { + ndr_push_free(ndr); + return NULL; + } + ndr->offset = 0; + + return ndr; +} + +/* free a ndr_push structure */ +void ndr_push_free(struct ndr_push *ndr) +{ + talloc_destroy(ndr->mem_ctx); +} + + +/* return a DATA_BLOB structure for the current ndr_push marshalled data */ +DATA_BLOB ndr_push_blob(struct ndr_push *ndr) +{ + DATA_BLOB blob; + blob.data = ndr->data; + blob.length = ndr->offset; + return blob; +} + + +/* + expand the available space in the buffer to 'size' +*/ +NTSTATUS ndr_push_expand(struct ndr_push *ndr, uint32 size) +{ + if (ndr->alloc_size >= size) { + return NT_STATUS_OK; + } + + ndr->alloc_size = size; + ndr->data = realloc(ndr->data, ndr->alloc_size); + if (!ndr->data) { + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; +} + +/* + set the push offset to 'ofs' +*/ +NTSTATUS ndr_push_set_offset(struct ndr_push *ndr, uint32 ofs) +{ + NDR_CHECK(ndr_push_expand(ndr, ofs)); + ndr->offset = ofs; + return NT_STATUS_OK; +} diff --git a/source4/libcli/ndr/ndr_basic.c b/source4/libcli/ndr/ndr_basic.c new file mode 100644 index 0000000000..736ad0b762 --- /dev/null +++ b/source4/libcli/ndr/ndr_basic.c @@ -0,0 +1,140 @@ +/* + 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_PULL_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_PULL_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_pull_guid(struct ndr_pull *ndr, GUID *guid) +{ + int i; + NDR_PULL_NEED_BYTES(ndr, GUID_SIZE); + for (i=0;iinfo[i] = CVAL(ndr->data, ndr->offset + i); + } + ndr->offset += i; + return NT_STATUS_OK; +} + + +/* + parse a u8 +*/ +NTSTATUS ndr_pull_u8(struct ndr_pull *ndr, uint8 *v) +{ + NDR_PULL_NEED_BYTES(ndr, 1); + *v = CVAL(ndr->data, ndr->offset); + ndr->offset += 1; + return NT_STATUS_OK; +} + + +/* + parse a u16 +*/ +NTSTATUS ndr_pull_u16(struct ndr_pull *ndr, uint16 *v) +{ + NDR_PULL_ALIGN(ndr, 2); + NDR_PULL_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_pull_u32(struct ndr_pull *ndr, uint32 *v) +{ + NDR_PULL_ALIGN(ndr, 4); + NDR_PULL_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; +} + + + +#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, ndr->offset+(n))) + +#define NDR_PUSH_ALIGN(ndr, n) do { \ + ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \ + NDR_CHECK(ndr_push_expand(ndr, ndr->offset)); \ +} while(0) + +/* + push a u8 +*/ +NTSTATUS ndr_push_u8(struct ndr_push *ndr, uint8 v) +{ + NDR_PUSH_NEED_BYTES(ndr, 1); + SCVAL(ndr->data, ndr->offset, v); + ndr->offset += 1; + return NT_STATUS_OK; +} + +/* + push a u16 +*/ +NTSTATUS ndr_push_u16(struct ndr_push *ndr, uint16 v) +{ + NDR_PUSH_ALIGN(ndr, 2); + NDR_PUSH_NEED_BYTES(ndr, 2); + SSVAL(ndr->data, ndr->offset, v); + ndr->offset += 2; + return NT_STATUS_OK; +} + +/* + push a u32 +*/ +NTSTATUS ndr_push_u32(struct ndr_push *ndr, uint32 v) +{ + NDR_PUSH_ALIGN(ndr, 4); + NDR_PUSH_NEED_BYTES(ndr, 4); + SIVAL(ndr->data, ndr->offset, v); + ndr->offset += 4; + return NT_STATUS_OK; +} diff --git a/source4/libcli/ndr/ndr_sec.c b/source4/libcli/ndr/ndr_sec.c new file mode 100644 index 0000000000..6b83a09d7a --- /dev/null +++ b/source4/libcli/ndr/ndr_sec.c @@ -0,0 +1,201 @@ +/* + 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_pull_security_ace(struct ndr_pull *ndr, struct security_ace *ace) +{ + uint16 size; + struct ndr_pull_save save; + + ndr_pull_save(ndr, &save); + + NDR_CHECK(ndr_pull_u8(ndr, &ace->type)); + NDR_CHECK(ndr_pull_u8(ndr, &ace->flags)); + NDR_CHECK(ndr_pull_u16(ndr, &size)); + NDR_CHECK(ndr_pull_limit_size(ndr, size, 4)); + + NDR_CHECK(ndr_pull_u32(ndr, &ace->access_mask)); + + if (sec_ace_object(ace->type)) { + NDR_ALLOC(ndr, ace->obj); + NDR_CHECK(ndr_pull_u32(ndr, &ace->obj->flags)); + if (ace->obj->flags & SEC_ACE_OBJECT_PRESENT) { + NDR_CHECK(ndr_pull_guid(ndr, &ace->obj->object_guid)); + } + if (ace->obj->flags & SEC_ACE_OBJECT_INHERITED_PRESENT) { + NDR_CHECK(ndr_pull_guid(ndr, &ace->obj->inherit_guid)); + } + } + + + NDR_CHECK(ndr_pull_dom_sid(ndr, &ace->trustee)); + + ndr_pull_restore(ndr, &save); + NDR_CHECK(ndr_pull_advance(ndr, size)); + + return NT_STATUS_OK; +} + +/* + parse a security_acl +*/ +NTSTATUS ndr_pull_security_acl(struct ndr_pull *ndr, struct security_acl *acl) +{ + int i; + uint16 size; + struct ndr_pull_save save; + + ndr_pull_save(ndr, &save); + + NDR_CHECK(ndr_pull_u16(ndr, &acl->revision)); + NDR_CHECK(ndr_pull_u16(ndr, &size)); + NDR_CHECK(ndr_pull_limit_size(ndr, size, 4)); + NDR_CHECK(ndr_pull_u32(ndr, &acl->num_aces)); + + NDR_ALLOC_N(ndr, acl->aces, acl->num_aces); + + for (i=0;inum_aces;i++) { + NDR_CHECK(ndr_pull_security_ace(ndr, &acl->aces[i])); + } + + ndr_pull_restore(ndr, &save); + NDR_CHECK(ndr_pull_advance(ndr, size)); + + return NT_STATUS_OK; +} + +/* + parse a security_acl offset and structure +*/ +NTSTATUS ndr_pull_security_acl_ofs(struct ndr_pull *ndr, struct security_acl **acl) +{ + uint32 ofs; + struct ndr_pull_save save; + + NDR_CHECK(ndr_pull_u32(ndr, &ofs)); + if (ofs == 0) { + /* it is valid for an acl ptr to be NULL */ + *acl = NULL; + return NT_STATUS_OK; + } + + ndr_pull_save(ndr, &save); + NDR_CHECK(ndr_pull_set_offset(ndr, ofs)); + NDR_ALLOC(ndr, *acl); + NDR_CHECK(ndr_pull_security_acl(ndr, *acl)); + ndr_pull_restore(ndr, &save); + + return NT_STATUS_OK; +} + + +/* + parse a dom_sid +*/ +NTSTATUS ndr_pull_dom_sid(struct ndr_pull *ndr, struct dom_sid *sid) +{ + int i; + + NDR_CHECK(ndr_pull_u8(ndr, &sid->sid_rev_num)); + NDR_CHECK(ndr_pull_u8(ndr, &sid->num_auths)); + for (i=0;i<6;i++) { + NDR_CHECK(ndr_pull_u8(ndr, &sid->id_auth[i])); + } + + NDR_ALLOC_N(ndr, sid->sub_auths, sid->num_auths); + + for (i=0;inum_auths;i++) { + NDR_CHECK(ndr_pull_u32(ndr, &sid->sub_auths[i])); + } + + return NT_STATUS_OK; +} + +/* + parse a dom_sid offset and structure +*/ +NTSTATUS ndr_pull_dom_sid_ofs(struct ndr_pull *ndr, struct dom_sid **sid) +{ + uint32 ofs; + struct ndr_pull_save save; + + NDR_CHECK(ndr_pull_u32(ndr, &ofs)); + if (ofs == 0) { + /* it is valid for a dom_sid ptr to be NULL */ + *sid = NULL; + return NT_STATUS_OK; + } + + ndr_pull_save(ndr, &save); + NDR_CHECK(ndr_pull_set_offset(ndr, ofs)); + NDR_ALLOC(ndr, *sid); + NDR_CHECK(ndr_pull_dom_sid(ndr, *sid)); + ndr_pull_restore(ndr, &save); + + return NT_STATUS_OK; +} + +/* + parse a security descriptor +*/ +NTSTATUS ndr_pull_security_descriptor(struct ndr_pull *ndr, + struct security_descriptor **sd) +{ + NDR_ALLOC(ndr, *sd); + + NDR_CHECK(ndr_pull_u8(ndr, &(*sd)->revision)); + NDR_CHECK(ndr_pull_u16(ndr, &(*sd)->type)); + NDR_CHECK(ndr_pull_dom_sid_ofs(ndr, &(*sd)->owner_sid)); + NDR_CHECK(ndr_pull_dom_sid_ofs(ndr, &(*sd)->group_sid)); + NDR_CHECK(ndr_pull_security_acl_ofs(ndr, &(*sd)->sacl)); + NDR_CHECK(ndr_pull_security_acl_ofs(ndr, &(*sd)->dacl)); + + return NT_STATUS_OK; +} + +/* + generate a ndr security descriptor +*/ +NTSTATUS ndr_push_security_descriptor(struct ndr_push *ndr, + struct security_descriptor *sd) +{ + uint32 var_offset; + + var_offset = 20; + + NDR_CHECK(ndr_push_u8(ndr, sd->revision)); + NDR_CHECK(ndr_push_u16(ndr, sd->type)); +/* + NDR_CHECK(ndr_push_dom_sid_ofs(ndr, sd->owner_sid, &var_offset)); + NDR_CHECK(ndr_push_dom_sid_ofs(ndr, sd->group_sid, &var_offset)); + NDR_CHECK(ndr_push_security_acl_ofs(ndr, sd->sacl, &var_offset)); + NDR_CHECK(ndr_push_security_acl_ofs(ndr, sd->dacl, &var_offset)); +*/ + return NT_STATUS_OK; +} + diff --git a/source4/libcli/ndr/ndr_sec.h b/source4/libcli/ndr/ndr_sec.h new file mode 100644 index 0000000000..0c9d542006 --- /dev/null +++ b/source4/libcli/ndr/ndr_sec.h @@ -0,0 +1,90 @@ +/* + 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; +}; + +/* set security descriptor */ +struct smb_set_secdesc { + struct { + uint16 fnum; + uint32 secinfo_flags; + struct security_descriptor *sd; + } in; +}; diff --git a/source4/libcli/raw/clisession.c b/source4/libcli/raw/clisession.c index 406491e432..9d154e10cd 100644 --- a/source4/libcli/raw/clisession.c +++ b/source4/libcli/raw/clisession.c @@ -318,8 +318,8 @@ static NTSTATUS smb_raw_session_setup_generic_nt1(struct cli_session *session, s2.nt1.in.os = "Unix"; s2.nt1.in.lanman = "Samba"; - if (session->transport->negotiate.sec_mode & - NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) { + if (s2.nt1.in.user[0] && + (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) { s2.nt1.in.password1 = lanman_blob(parms->generic.in.password, session->transport->negotiate.secblob); s2.nt1.in.password2 = nt_blob(parms->generic.in.password, diff --git a/source4/libcli/raw/rawacl.c b/source4/libcli/raw/rawacl.c index 4cd3338ec5..c45152381d 100644 --- a/source4/libcli/raw/rawacl.c +++ b/source4/libcli/raw/rawacl.c @@ -58,7 +58,7 @@ NTSTATUS smb_raw_query_secdesc_recv(struct cli_request *req, { NTSTATUS status; struct smb_nttrans nt; - struct ndr_parse *rpc; + struct ndr_pull *ndr; status = smb_raw_nttrans_recv(req, mem_ctx, &nt); if (!NT_STATUS_IS_OK(status)) { @@ -73,12 +73,12 @@ NTSTATUS smb_raw_query_secdesc_recv(struct cli_request *req, nt.out.data.length = IVAL(nt.out.params.data, 0); - rpc = ndr_parse_init_blob(&nt.out.data, mem_ctx); - if (!rpc) { + ndr = ndr_pull_init_blob(&nt.out.data, mem_ctx); + if (!ndr) { return NT_STATUS_INVALID_PARAMETER; } - status = ndr_parse_security_descriptor(rpc, &query->out.sd); + status = ndr_pull_security_descriptor(ndr, &query->out.sd); return NT_STATUS_OK; } @@ -95,3 +95,47 @@ NTSTATUS smb_raw_query_secdesc(struct cli_tree *tree, return smb_raw_query_secdesc_recv(req, mem_ctx, query); } + + +/**************************************************************************** +set file ACL (async send) +****************************************************************************/ +struct cli_request *smb_raw_set_secdesc_send(struct cli_tree *tree, + struct smb_set_secdesc *set) +{ + struct smb_nttrans nt; + uint8 params[8]; + struct ndr_push *ndr; + struct cli_request *req; + NTSTATUS status; + + nt.in.max_setup = 0; + nt.in.max_param = 0; + nt.in.max_data = 0; + nt.in.setup_count = 0; + nt.in.function = NT_TRANSACT_SET_SECURITY_DESC; + nt.in.setup = NULL; + + SSVAL(params, 0, set->in.fnum); + SSVAL(params, 2, 0); /* padding */ + SIVAL(params, 4, set->in.secinfo_flags); + + nt.in.params.data = params; + nt.in.params.length = 8; + + ndr = ndr_push_init(); + if (!ndr) return NULL; + +// status = ndr_push_security_descriptor(ndr, set->in.sd); + if (!NT_STATUS_IS_OK(status)) { + ndr_push_free(ndr); + return NULL; + } + + nt.in.data = ndr_push_blob(ndr); + + req = smb_raw_nttrans_send(tree, &nt); + + ndr_push_free(ndr); + return req; +} diff --git a/source4/libcli/raw/rawdcerpc.c b/source4/libcli/raw/rawdcerpc.c index 1cc034de78..4a5159948d 100644 --- a/source4/libcli/raw/rawdcerpc.c +++ b/source4/libcli/raw/rawdcerpc.c @@ -2,7 +2,8 @@ Unix SMB/CIFS implementation. raw dcerpc operations - Copyright (C) Tim Potter, 2003 + 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 @@ -21,202 +22,62 @@ #include "includes.h" -static int put_uuid(char *data, int offset, struct dcerpc_uuid *uuid) -{ - int i; - - SIVAL(data, offset, uuid->time_low); offset += 4; - SSVAL(data, offset, uuid->time_mid); offset += 2; - SSVAL(data, offset, uuid->time_hi_and_version); offset += 2; - for (i = 0; i < 8; i++) - SCVAL(data, offset + i, uuid->remaining[i]); - offset += 8; - - return offset; -} - -DATA_BLOB dcerpc_raw_bind_setup(struct dcerpc_bind *parms) -{ - int i, offset, size; - char *data; - - /* Allocate storage for bind request */ - - size = 28; - for (i = 0; i < parms->in.num_contexts; i++) { - size += 24; /* as header + uuid */ - size += 20 * parms->in.ctx_list[i].num_ts; /* xfer syntaxes */ - } - size += parms->in.auth_verifier.length; - - data = smb_xmalloc(size); - memset(data, 0, size); - - parms->in.hdr.frag_len = size; - - /* Create bind request */ - - SCVAL(data, 0, parms->in.hdr.rpc_vers); - SCVAL(data, 1, parms->in.hdr.rpc_vers_minor); - SCVAL(data, 2, parms->in.hdr.ptype); - SCVAL(data, 3, parms->in.hdr.pfc_flags); - for (i = 0; i < 4; i++) - SCVAL(data, 4 + i, parms->in.hdr.drep[i]); - SSVAL(data, 8, parms->in.hdr.frag_len); - SSVAL(data, 10, parms->in.auth_verifier.length); - SIVAL(data, 12, parms->in.hdr.call_id); - - SSVAL(data, 16, parms->in.max_xmit_frag); - SSVAL(data, 18, parms->in.max_recv_frag); - SIVAL(data, 20, parms->in.assoc_group_id); - SIVAL(data, 24, parms->in.num_contexts); - - offset = 28; - for (i = 0; i < parms->in.num_contexts; i++) { - struct p_ctx_list *ctx = &parms->in.ctx_list[i]; - int j; - - SSVAL(data, offset, ctx->cont_id); offset += 2; - SSVAL(data, offset, ctx->num_ts); offset += 2; - offset = put_uuid(data, offset, &ctx->as->if_uuid); - SIVAL(data, offset, ctx->as->if_version); offset += 4; - for (j = 0; j < ctx->num_ts; j++) { - offset = put_uuid(data, offset, &ctx->ts[i].if_uuid); - SIVAL(data, offset, ctx->ts[i].if_version); - offset += 4; - } - } - - if (parms->in.auth_verifier.length) - memcpy(&data[offset], parms->in.auth_verifier.data, - parms->in.auth_verifier.length); - - return data_blob(data, size); -} - -NTSTATUS dcerpc_raw_bind_send(struct cli_dcerpc_pipe *p, - struct dcerpc_bind *parms) +struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob) { struct smb_trans2 trans; - DATA_BLOB blob; - NTSTATUS result; uint16 setup[2]; + struct cli_request *req; + TALLOC_CTX *mem_ctx; - blob = dcerpc_raw_bind_setup(parms); + mem_ctx = talloc_init("dcerpc_raw_send"); + if (!mem_ctx) return NULL; - ZERO_STRUCT(trans); + trans.in.data = *blob; + trans.in.params = data_blob(NULL, 0); + + setup[0] = TRANSACT_DCERPCCMD; + setup[1] = p->fnum; - trans.in.max_data = blob.length; + trans.in.max_param = 0; + trans.in.max_data = 0x8000; trans.in.setup_count = 2; trans.in.setup = setup; trans.in.trans_name = "\\PIPE\\"; - setup[0] = TRANSACT_DCERPCCMD; - setup[1] = p->fnum; - - trans.in.data = blob; - - result = smb_raw_trans(p->tree, p->mem_ctx, &trans); - - data_blob_free(&blob); + req = smb_raw_trans_send(p->tree, &trans); - return result; -} + talloc_destroy(mem_ctx); -NTSTATUS dcerpc_raw_bind_recv(struct cli_dcerpc_pipe *p, - struct dcerpc_bind *parms) -{ - return NT_STATUS_UNSUCCESSFUL; + return req; } -NTSTATUS dcerpc_raw_bind(struct cli_dcerpc_pipe *p, struct dcerpc_bind *parms) -{ - NTSTATUS result; - - result = dcerpc_raw_bind_send(p, parms); - if (NT_STATUS_IS_ERR(result)) - return result; - return dcerpc_raw_bind_recv(p, parms); -} - -DATA_BLOB dcerpc_raw_request_setup(struct dcerpc_request *parms) -{ - int size, i; - char *data; - - /* Allocate storage for request */ - - size = 24 + parms->in.stub_data.length; - - data = smb_xmalloc(size); - memset(data, 0, size); - - parms->in.hdr.frag_len = size; - parms->in.alloc_hint = parms->in.stub_data.length; - - SCVAL(data, 0, parms->in.hdr.rpc_vers); - SCVAL(data, 1, parms->in.hdr.rpc_vers_minor); - SCVAL(data, 2, parms->in.hdr.ptype); - SCVAL(data, 3, parms->in.hdr.pfc_flags); - for (i = 0; i < 4; i++) - SCVAL(data, 4 + i, parms->in.hdr.drep[i]); - SSVAL(data, 8, parms->in.hdr.frag_len); - SSVAL(data, 10, parms->in.auth_verifier.length); - SIVAL(data, 12, parms->in.hdr.call_id); - - SIVAL(data, 16, parms->in.alloc_hint); - SSVAL(data, 20, parms->in.cont_id); - SSVAL(data, 22, parms->in.opnum); - - if (parms->in.stub_data.length) - memcpy(&data[24], parms->in.stub_data.data, - parms->in.stub_data.length); - - return data_blob(data, size); -} - -NTSTATUS dcerpc_raw_request_send(struct cli_dcerpc_pipe *p, - struct dcerpc_request *parms) +NTSTATUS dcerpc_raw_recv(struct dcerpc_pipe *p, + struct cli_request *req, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob) { struct smb_trans2 trans; - DATA_BLOB blob; - NTSTATUS result; - uint16 setup[2]; - - blob = dcerpc_raw_request_setup(parms); - - ZERO_STRUCT(trans); + NTSTATUS status; - trans.in.max_data = blob.length; - trans.in.setup_count = 2; - trans.in.setup = setup; - trans.in.trans_name = "\\PIPE\\"; - - setup[0] = TRANSACT_DCERPCCMD; - setup[1] = p->fnum; - - trans.in.data = blob; - - result = smb_raw_trans(p->tree, p->mem_ctx, &trans); + status = smb_raw_trans_recv(req, mem_ctx, &trans); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - data_blob_free(&blob); + if (blob) { + *blob = trans.out.data; + } - return result; + return status; } -NTSTATUS dcerpc_raw_request_recv(struct cli_dcerpc_pipe *p, - struct dcerpc_request *parms) +NTSTATUS dcerpc_raw_packet(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + DATA_BLOB *request_blob, + DATA_BLOB *reply_blob) { - return NT_STATUS_UNSUCCESSFUL; -} - -NTSTATUS dcerpc_raw_request(struct cli_dcerpc_pipe *p, - struct dcerpc_request *parms) -{ - NTSTATUS result; - - result = dcerpc_raw_request_send(p, parms); - if (NT_STATUS_IS_ERR(result)) - return result; - return dcerpc_raw_request_recv(p, parms); + struct cli_request *req; + req = dcerpc_raw_send(p, request_blob); + return dcerpc_raw_recv(p, req, mem_ctx, reply_blob); } + diff --git a/source4/libcli/raw/rawsearch.c b/source4/libcli/raw/rawsearch.c index 430cf925a6..4c7da6ec4d 100644 --- a/source4/libcli/raw/rawsearch.c +++ b/source4/libcli/raw/rawsearch.c @@ -307,7 +307,7 @@ static int parse_trans2_search(struct cli_tree *tree, case RAW_SEARCH_FULL_DIRECTORY_INFO: if (blob->length < 69) return -1; - ofs = IVAL(blob->data, 0); + ofs = IVAL(blob->data, 0); data->full_directory_info.file_index = IVAL(blob->data, 4); data->full_directory_info.create_time = cli_pull_nttime(blob->data, 8); data->full_directory_info.access_time = cli_pull_nttime(blob->data, 16); @@ -364,7 +364,7 @@ static int parse_trans2_search(struct cli_tree *tree, case RAW_SEARCH_ID_FULL_DIRECTORY_INFO: if (blob->length < 81) return -1; - ofs = IVAL(blob->data, 0); + ofs = IVAL(blob->data, 0); data->id_full_directory_info.file_index = IVAL(blob->data, 4); data->id_full_directory_info.create_time = cli_pull_nttime(blob->data, 8); data->id_full_directory_info.access_time = cli_pull_nttime(blob->data, 16); @@ -385,7 +385,7 @@ static int parse_trans2_search(struct cli_tree *tree, case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO: if (blob->length < 105) return -1; - ofs = IVAL(blob->data, 0); + ofs = IVAL(blob->data, 0); data->id_both_directory_info.file_index = IVAL(blob->data, 4); data->id_both_directory_info.create_time = cli_pull_nttime(blob->data, 8); data->id_both_directory_info.access_time = cli_pull_nttime(blob->data, 16); @@ -481,7 +481,7 @@ NTSTATUS smb_raw_search_first(struct cli_tree *tree, return status; } - if (p_blob.length != 10) { + if (p_blob.length < 10) { DEBUG(1,("smb_raw_search_first: parms wrong size %d != expected_param_size\n", p_blob.length)); return NT_STATUS_INVALID_PARAMETER; 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;inum_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;inum_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;jctx_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;iin.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;iinfo[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;inum_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;inum_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; -} -- cgit