summaryrefslogtreecommitdiffstats
path: root/source4/libcli
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2003-11-03 06:22:45 +0000
committerAndrew Tridgell <tridge@samba.org>2003-11-03 06:22:45 +0000
commitc5cf47443985c34ad32c44c322901e0fc3a065d7 (patch)
treef7d6abd03304c4f2359a4753aae23e41982c0e17 /source4/libcli
parent7fd381376f88ae99a4bf022d89f21ae497b48c1a (diff)
downloadsamba-c5cf47443985c34ad32c44c322901e0fc3a065d7.tar.gz
samba-c5cf47443985c34ad32c44c322901e0fc3a065d7.tar.xz
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')
-rw-r--r--source4/libcli/clidcerpc.c254
-rw-r--r--source4/libcli/ndr/libndr.h (renamed from source4/libcli/rpc/librpc.h)18
-rw-r--r--source4/libcli/ndr/ndr.c (renamed from source4/libcli/rpc/rpcparse.c)95
-rw-r--r--source4/libcli/ndr/ndr_basic.c (renamed from source4/libcli/rpc/rpc_basic.c)67
-rw-r--r--source4/libcli/ndr/ndr_sec.c201
-rw-r--r--source4/libcli/ndr/ndr_sec.h (renamed from source4/libcli/rpc/rpc_sec.h)9
-rw-r--r--source4/libcli/raw/clisession.c4
-rw-r--r--source4/libcli/raw/rawacl.c52
-rw-r--r--source4/libcli/raw/rawdcerpc.c215
-rw-r--r--source4/libcli/raw/rawsearch.c8
-rw-r--r--source4/libcli/rpc/dcerpc.c644
-rw-r--r--source4/libcli/rpc/dcerpc.h124
-rw-r--r--source4/libcli/rpc/rpc_sec.c179
13 files changed, 1228 insertions, 642 deletions
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/rpc/librpc.h b/source4/libcli/ndr/libndr.h
index f4f7101c90..4369ebeb30 100644
--- a/source4/libcli/rpc/librpc.h
+++ b/source4/libcli/ndr/libndr.h
@@ -31,7 +31,7 @@
are being kept deliberately very simple, and are not tied to a
particular transport
*/
-struct ndr_parse {
+struct ndr_pull {
uint32 flags; /* LIBNDR_FLAG_* */
char *data;
uint32 data_size;
@@ -39,11 +39,25 @@ struct ndr_parse {
TALLOC_CTX *mem_ctx;
};
-struct ndr_parse_save {
+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
diff --git a/source4/libcli/rpc/rpcparse.c b/source4/libcli/ndr/ndr.c
index 41e6919b72..d9a5ff7735 100644
--- a/source4/libcli/rpc/rpcparse.c
+++ b/source4/libcli/ndr/ndr.c
@@ -1,6 +1,8 @@
/*
Unix SMB/CIFS implementation.
+
libndr interface
+
Copyright (C) Andrew Tridgell 2003
This program is free software; you can redistribute it and/or modify
@@ -19,7 +21,10 @@
*/
/*
- this provides the core routines for MSNDR parsing functions
+ 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"
@@ -27,9 +32,9 @@
/*
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_pull *ndr_pull_init_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
{
- struct ndr_parse *ndr;
+ struct ndr_pull *ndr;
ndr = talloc(mem_ctx, sizeof(*ndr));
if (!ndr) return NULL;
@@ -52,7 +57,7 @@ struct ndr_parse *ndr_parse_init_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
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)
+NTSTATUS ndr_pull_limit_size(struct ndr_pull *ndr, uint32 size, uint32 ofs)
{
uint32 new_size;
new_size = ndr->offset + size - ofs;
@@ -69,7 +74,7 @@ NTSTATUS ndr_parse_limit_size(struct ndr_parse *ndr, uint32 size, uint32 ofs)
/*
advance by 'size' bytes
*/
-NTSTATUS ndr_parse_advance(struct ndr_parse *ndr, uint32 size)
+NTSTATUS ndr_pull_advance(struct ndr_pull *ndr, uint32 size)
{
ndr->offset += size;
if (ndr->offset > ndr->data_size) {
@@ -81,7 +86,7 @@ NTSTATUS ndr_parse_advance(struct ndr_parse *ndr, uint32 size)
/*
set the parse offset to 'ofs'
*/
-NTSTATUS ndr_parse_set_offset(struct ndr_parse *ndr, uint32 ofs)
+NTSTATUS ndr_pull_set_offset(struct ndr_pull *ndr, uint32 ofs)
{
ndr->offset = ofs;
if (ndr->offset > ndr->data_size) {
@@ -91,15 +96,89 @@ NTSTATUS ndr_parse_set_offset(struct ndr_parse *ndr, uint32 ofs)
}
/* save the offset/size of the current ndr state */
-void ndr_parse_save(struct ndr_parse *ndr, struct ndr_parse_save *save)
+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_parse_restore(struct ndr_parse *ndr, struct ndr_parse_save *save)
+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/rpc/rpc_basic.c b/source4/libcli/ndr/ndr_basic.c
index 5ff17f9d99..736ad0b762 100644
--- a/source4/libcli/rpc/rpc_basic.c
+++ b/source4/libcli/ndr/ndr_basic.c
@@ -22,13 +22,13 @@
#include "includes.h"
-#define NDR_NEED_BYTES(ndr, n) do { \
+#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_ALIGN(ndr, n) do { \
+#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; \
@@ -38,10 +38,10 @@
/*
parse a GUID
*/
-NTSTATUS ndr_parse_guid(struct ndr_parse *ndr, GUID *guid)
+NTSTATUS ndr_pull_guid(struct ndr_pull *ndr, GUID *guid)
{
int i;
- NDR_NEED_BYTES(ndr, GUID_SIZE);
+ NDR_PULL_NEED_BYTES(ndr, GUID_SIZE);
for (i=0;i<GUID_SIZE;i++) {
guid->info[i] = CVAL(ndr->data, ndr->offset + i);
}
@@ -53,9 +53,9 @@ NTSTATUS ndr_parse_guid(struct ndr_parse *ndr, GUID *guid)
/*
parse a u8
*/
-NTSTATUS ndr_parse_u8(struct ndr_parse *ndr, uint8 *v)
+NTSTATUS ndr_pull_u8(struct ndr_pull *ndr, uint8 *v)
{
- NDR_NEED_BYTES(ndr, 1);
+ NDR_PULL_NEED_BYTES(ndr, 1);
*v = CVAL(ndr->data, ndr->offset);
ndr->offset += 1;
return NT_STATUS_OK;
@@ -65,10 +65,10 @@ NTSTATUS ndr_parse_u8(struct ndr_parse *ndr, uint8 *v)
/*
parse a u16
*/
-NTSTATUS ndr_parse_u16(struct ndr_parse *ndr, uint16 *v)
+NTSTATUS ndr_pull_u16(struct ndr_pull *ndr, uint16 *v)
{
- NDR_ALIGN(ndr, 2);
- NDR_NEED_BYTES(ndr, 2);
+ NDR_PULL_ALIGN(ndr, 2);
+ NDR_PULL_NEED_BYTES(ndr, 2);
if (ndr->flags & LIBNDR_FLAG_BIGENDIAN) {
*v = RSVAL(ndr->data, ndr->offset);
} else {
@@ -82,10 +82,10 @@ NTSTATUS ndr_parse_u16(struct ndr_parse *ndr, uint16 *v)
/*
parse a u32
*/
-NTSTATUS ndr_parse_u32(struct ndr_parse *ndr, uint32 *v)
+NTSTATUS ndr_pull_u32(struct ndr_pull *ndr, uint32 *v)
{
- NDR_ALIGN(ndr, 4);
- NDR_NEED_BYTES(ndr, 4);
+ NDR_PULL_ALIGN(ndr, 4);
+ NDR_PULL_NEED_BYTES(ndr, 4);
if (ndr->flags & LIBNDR_FLAG_BIGENDIAN) {
*v = RIVAL(ndr->data, ndr->offset);
} else {
@@ -95,3 +95,46 @@ NTSTATUS ndr_parse_u32(struct ndr_parse *ndr, uint32 *v)
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;i<acl->num_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;i<sid->num_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/rpc/rpc_sec.h b/source4/libcli/ndr/ndr_sec.h
index 3cda400eb2..0c9d542006 100644
--- a/source4/libcli/rpc/rpc_sec.h
+++ b/source4/libcli/ndr/ndr_sec.h
@@ -79,3 +79,12 @@ struct smb_query_secdesc {
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;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/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;
-}