1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-29 02:50:28 +03:00

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)
This commit is contained in:
Andrew Tridgell 2003-11-03 06:22:45 +00:00
parent 7fd381376f
commit c5cf474439
20 changed files with 1406 additions and 828 deletions

View File

@ -193,7 +193,9 @@ LIBCLIUTIL_OBJ = libcli/util/asn1.o \
libcli/util/doserr.o libcli/util/errormap.o \
libcli/util/pwd_cache.o libcli/util/clierror.o libcli/util/cliutil.o
LIBRAW_RPC_OBJ = libcli/rpc/rpcparse.o libcli/rpc/rpc_basic.o libcli/rpc/rpc_sec.o
LIBRAW_NDR_OBJ = libcli/ndr/ndr.o libcli/ndr/ndr_basic.o libcli/ndr/ndr_sec.o
LIBRAW_RPC_OBJ = libcli/rpc/dcerpc.o
LIBRAW_OBJ = libcli/raw/rawfile.o libcli/raw/smb_signing.o \
libcli/raw/clisocket.o libcli/raw/clitransport.o \
@ -205,13 +207,13 @@ LIBRAW_OBJ = libcli/raw/rawfile.o libcli/raw/smb_signing.o \
libcli/raw/rawnegotiate.o libcli/raw/rawfsinfo.o \
libcli/raw/rawfileinfo.o libcli/raw/rawnotify.o \
libcli/raw/rawioctl.o libcli/raw/rawacl.o libcli/raw/rawdcerpc.o \
$(LIBRAW_RPC_OBJ) $(LIBSAMBA_OBJ) $(LIBCLIUTIL_OBJ) \
$(LIBRAW_NDR_OBJ) $(LIBRAW_RPC_OBJ) $(LIBSAMBA_OBJ) $(LIBCLIUTIL_OBJ) \
$(RPC_PARSE_OBJ1) $(LIBNTLMSSP_OBJ) $(LIBNMB_OBJ) $(KRBCLIENT_OBJ)
LIBSMB_OBJ = libcli/clireadwrite.o libcli/cliconnect.o \
libcli/clifile.o libcli/clilist.o libcli/clitrans2.o \
libcli/clisecdesc.o libcli/climessage.o \
libcli/clideltree.o libcli/clidcerpc.o \
libcli/clideltree.o \
$(LIBRAW_OBJ)
# LIBDFS_OBJ = libcli/clidfs.o
@ -525,10 +527,12 @@ SMBTORTURE_RAW_OBJ = torture/raw/qfsinfo.o torture/raw/qfileinfo.o torture/raw/s
torture/raw/chkpath.o torture/raw/unlink.o torture/raw/read.o torture/raw/context.o \
torture/raw/write.o torture/raw/lock.o torture/raw/rename.o torture/raw/seek.o
SMBTORTURE_RPC_OBJ = torture/rpc/lsa.o
SMBTORTURE_OBJ1 = torture/torture.o torture/torture_util.o torture/nbio.o torture/scanner.o \
torture/utable.o torture/denytest.o torture/mangle_test.o \
torture/aliases.o libcli/raw/clirewrite.o $(SMBTORTURE_RAW_OBJ) \
rpc_parse/parse_lsa.o
$(SMBTORTURE_RPC_OBJ) rpc_parse/parse_lsa.o
SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) \
$(LIBSMB_OBJ) $(LIBDFS_OBJ) $(PARAM_OBJ) $(LIB_OBJ)

View File

@ -1,93 +0,0 @@
/*
Unix SMB/CIFS implementation.
DCERPC interface structures
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.
*/
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_len; /* Total length of fragment */
uint32 call_id; /* Call identifier */
};
struct dcerpc_uuid {
uint32 time_low;
uint16 time_mid;
uint16 time_hi_and_version;
uint8 remaining[8];
};
struct syntax_id {
struct dcerpc_uuid if_uuid;
uint32 if_version;
};
struct p_ctx_list {
uint16 cont_id; /* Context id */
uint8 num_ts; /* Number of transfer syntaxes */
struct syntax_id *as; /* Abstract syntax */
struct syntax_id *ts; /* Transfer syntaxes */
};
struct dcerpc_bind {
struct {
struct dcerpc_hdr hdr; /* Header */
uint16 max_xmit_frag; /* Max transmit frag size */
uint16 max_recv_frag; /* Max receive frag size */
uint32 assoc_group_id; /* Association group */
uint8 num_contexts; /* Number of presentation contexts */
struct p_ctx_list *ctx_list; /* Presentation context list */
DATA_BLOB auth_verifier;
} in;
struct {
struct dcerpc_hdr hdr; /* Header */
uint16 max_xmit_frag; /* Max transmit frag size */
uint16 max_recv_frag; /* Max receive frag size */
uint32 assoc_group_id; /* Association group */
DATA_BLOB auth_verifier;
} out;
};
struct dcerpc_request {
struct {
struct dcerpc_hdr hdr;
uint32 alloc_hint; /* Allocation hint */
uint16 cont_id; /* Context id */
uint16 opnum; /* Operation number */
DATA_BLOB stub_data;
DATA_BLOB auth_verifier;
} in;
struct {
struct dcerpc_hdr hdr;
uint32 alloc_hint; /* Allocation hint */
uint8 cancel_count; /* Context id */
DATA_BLOB stub_data;
DATA_BLOB auth_verifier;
} out;
};
struct cli_dcerpc_pipe {
TALLOC_CTX *mem_ctx;
uint16 fnum;
int reference_count;
uint32 call_id;
struct cli_tree *tree;
};

View File

@ -776,8 +776,9 @@ extern int errno;
#include "mutex.h"
#include "libcli/rpc/librpc.h"
#include "libcli/rpc/rpc_sec.h"
#include "libcli/ndr/libndr.h"
#include "libcli/ndr/ndr_sec.h"
#include "libcli/rpc/dcerpc.h"
/*
* Type for wide character dirent structure.

View File

@ -430,7 +430,6 @@ struct vuid_cache {
#include "events.h"
#include "context.h"
#include "smb_interfaces.h"
#include "dcerpc_interfaces.h"
#include "ntvfs.h"
typedef struct smb_vfs_handle_struct

View File

@ -1610,7 +1610,7 @@ struct smb_trans2 {
uint32 timeout;
uint8 setup_count;
uint16 *setup;
char *trans_name; /* SMBtrans only */
const char *trans_name; /* SMBtrans only */
DATA_BLOB params;
DATA_BLOB data;
} in;

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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,

View File

@ -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;
}

View File

@ -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;
req = smb_raw_trans_send(p->tree, &trans);
trans.in.data = blob;
talloc_destroy(mem_ctx);
result = smb_raw_trans(p->tree, p->mem_ctx, &trans);
data_blob_free(&blob);
return result;
return req;
}
NTSTATUS dcerpc_raw_bind_recv(struct cli_dcerpc_pipe *p,
struct dcerpc_bind *parms)
NTSTATUS dcerpc_raw_recv(struct dcerpc_pipe *p,
struct cli_request *req,
TALLOC_CTX *mem_ctx,
DATA_BLOB *blob)
{
return NT_STATUS_UNSUCCESSFUL;
struct smb_trans2 trans;
NTSTATUS status;
status = smb_raw_trans_recv(req, mem_ctx, &trans);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
if (blob) {
*blob = trans.out.data;
}
return status;
}
NTSTATUS dcerpc_raw_bind(struct cli_dcerpc_pipe *p, struct dcerpc_bind *parms)
NTSTATUS dcerpc_raw_packet(struct dcerpc_pipe *p,
TALLOC_CTX *mem_ctx,
DATA_BLOB *request_blob,
DATA_BLOB *reply_blob)
{
NTSTATUS result;
result = dcerpc_raw_bind_send(p, parms);
if (NT_STATUS_IS_ERR(result))
return result;
return dcerpc_raw_bind_recv(p, parms);
struct cli_request *req;
req = dcerpc_raw_send(p, request_blob);
return dcerpc_raw_recv(p, req, mem_ctx, reply_blob);
}
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)
{
struct smb_trans2 trans;
DATA_BLOB blob;
NTSTATUS result;
uint16 setup[2];
blob = dcerpc_raw_request_setup(parms);
ZERO_STRUCT(trans);
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);
data_blob_free(&blob);
return result;
}
NTSTATUS dcerpc_raw_request_recv(struct cli_dcerpc_pipe *p,
struct dcerpc_request *parms)
{
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);
}

View File

@ -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;

644
source4/libcli/rpc/dcerpc.c Normal file
View File

@ -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;
}

124
source4/libcli/rpc/dcerpc.h Normal file
View File

@ -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;
};

View File

@ -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;
}

79
source4/torture/rpc/lsa.c Normal file
View File

@ -0,0 +1,79 @@
/*
Unix SMB/CIFS implementation.
test suite for lsa rpc 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"
/* Helper function for RPC-OPEN test */
static DATA_BLOB blob_lsa_open_policy_req(TALLOC_CTX *mem_ctx, BOOL sec_qos,
uint32 des_access)
{
prs_struct qbuf;
LSA_Q_OPEN_POL q;
LSA_SEC_QOS qos;
ZERO_STRUCT(q);
/* Initialise parse structures */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
/* Initialise input parameters */
if (sec_qos) {
init_lsa_sec_qos(&qos, 2, 1, 0);
init_q_open_pol(&q, '\\', 0, des_access, &qos);
} else {
init_q_open_pol(&q, '\\', 0, des_access, NULL);
}
if (lsa_io_q_open_pol("", &q, &qbuf, 0))
return data_blob_talloc(
mem_ctx, prs_data_p(&qbuf), prs_offset(&qbuf));
return data_blob(NULL, 0);
}
BOOL torture_rpc_lsa(int dummy)
{
NTSTATUS status;
struct dcerpc_pipe *p;
DATA_BLOB request;
TALLOC_CTX *mem_ctx;
mem_ctx = talloc_init("torture_rpc_lsa");
status = torture_rpc_connection(&p, "lsarpc");
if (!NT_STATUS_IS_OK(status)) {
return False;
}
request = blob_lsa_open_policy_req(mem_ctx, True,
SEC_RIGHTS_MAXIMUM_ALLOWED);
status = cli_dcerpc_request(p, LSA_OPENPOLICY, mem_ctx, &request, NULL);
if (!NT_STATUS_IS_OK(status)) {
d_printf("Failed to LSA_OPENPOLICY - %s\n", nt_errstr(status));
}
torture_rpc_close(p);
return NT_STATUS_IS_OK(status);
}

View File

@ -98,11 +98,11 @@ BOOL torture_open_connection(struct cli_state **c)
if (use_kerberos)
flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
status = cli_full_connection(c, lp_netbios_name(),
host, NULL,
share, "?????",
username, lp_workgroup(),
username, username[0]?lp_workgroup():"",
password, flags, &retry);
if (!NT_STATUS_IS_OK(status)) {
printf("Failed to open connection - %s\n", nt_errstr(status));
@ -131,6 +131,87 @@ BOOL torture_close_connection(struct cli_state *c)
return ret;
}
/* open a rpc connection to a named pipe */
NTSTATUS torture_rpc_connection(struct dcerpc_pipe **p, const char *pipe_name)
{
struct cli_state *cli;
int fnum;
NTSTATUS status;
char *name = NULL;
union smb_open open_parms;
TALLOC_CTX *mem_ctx;
if (!torture_open_connection(&cli)) {
return NT_STATUS_UNSUCCESSFUL;
}
asprintf(&name, "\\%s", pipe_name);
if (!name) {
return NT_STATUS_NO_MEMORY;
}
open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
open_parms.ntcreatex.in.flags = 0;
open_parms.ntcreatex.in.root_fid = 0;
open_parms.ntcreatex.in.access_mask =
STD_RIGHT_READ_CONTROL_ACCESS |
SA_RIGHT_FILE_WRITE_ATTRIBUTES |
SA_RIGHT_FILE_WRITE_EA |
GENERIC_RIGHTS_FILE_READ;
open_parms.ntcreatex.in.file_attr = 0;
open_parms.ntcreatex.in.alloc_size = 0;
open_parms.ntcreatex.in.share_access =
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
open_parms.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
open_parms.ntcreatex.in.create_options = 0;
open_parms.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
open_parms.ntcreatex.in.security_flags = 0;
open_parms.ntcreatex.in.fname = name;
mem_ctx = talloc_init("torture_rpc_connection");
status = smb_raw_open(cli->tree, mem_ctx, &open_parms);
free(name);
talloc_destroy(mem_ctx);
if (!NT_STATUS_IS_OK(status)) {
printf("Open of pipe %s failed with error (%s)\n",
pipe_name, nt_errstr(status));
return status;
}
if (!(*p = dcerpc_pipe_init(cli->tree))) {
return NT_STATUS_NO_MEMORY;
}
(*p)->fnum = open_parms.ntcreatex.out.fnum;
status = cli_dcerpc_bind_byname(*p, pipe_name);
if (!NT_STATUS_IS_OK(status)) {
cli_close(cli, fnum);
dcerpc_pipe_close(*p);
}
return status;
}
/* close a rpc connection to a named pipe */
NTSTATUS torture_rpc_close(struct dcerpc_pipe *p)
{
union smb_close io;
NTSTATUS status;
io.close.level = RAW_CLOSE_CLOSE;
io.close.in.fnum = p->fnum;
io.close.in.write_time = 0;
status = smb_raw_close(p->tree, &io);
dcerpc_pipe_close(p);
return status;
}
/* check if the server produced the expected error code */
static BOOL check_error(int line, struct cli_state *c,
@ -3755,85 +3836,6 @@ static BOOL run_deny3test(int dummy)
return True;
}
/* Helper function for RPC-OPEN test */
static DATA_BLOB blob_lsa_open_policy_req(TALLOC_CTX *mem_ctx, BOOL sec_qos,
uint32 des_access)
{
prs_struct qbuf;
LSA_Q_OPEN_POL q;
LSA_SEC_QOS qos;
ZERO_STRUCT(q);
/* Initialise parse structures */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
/* Initialise input parameters */
if (sec_qos) {
init_lsa_sec_qos(&qos, 2, 1, 0);
init_q_open_pol(&q, '\\', 0, des_access, &qos);
} else {
init_q_open_pol(&q, '\\', 0, des_access, NULL);
}
if (lsa_io_q_open_pol("", &q, &qbuf, 0))
return data_blob_talloc(
mem_ctx, prs_data_p(&qbuf), prs_offset(&qbuf));
return data_blob(NULL, 0);
}
static BOOL torture_rpc_open(int dummy)
{
struct cli_state *cli;
const char *pipe_name = "\\lsarpc";
int fnum;
TALLOC_CTX *mem_ctx;
NTSTATUS status;
struct cli_dcerpc_pipe *p;
DATA_BLOB request;
mem_ctx = talloc_init("rpc_open");
printf("starting rpc test\n");
if (!torture_open_connection(&cli))
return False;
fnum = cli_nt_create_full(cli, pipe_name, 0, SA_RIGHT_FILE_READ_DATA,
FILE_ATTRIBUTE_NORMAL,
NTCREATEX_SHARE_ACCESS_READ|
NTCREATEX_SHARE_ACCESS_WRITE,
NTCREATEX_DISP_OPEN_IF, 0, 0);
if (fnum == -1) {
printf("Open of pipe %s failed with error (%s)\n",
pipe_name, cli_errstr(cli));
return False;
}
if (!(p = cli_dcerpc_pipe_init(cli->tree)))
return False;
p->fnum = fnum;
status = cli_dcerpc_bind_byname(p, pipe_name);
request = blob_lsa_open_policy_req(mem_ctx, True,
SEC_RIGHTS_MAXIMUM_ALLOWED);
status = cli_dcerpc_request(p, LSA_OPENPOLICY, request);
talloc_destroy(mem_ctx);
torture_close_connection(cli);
return True;
}
static void sigcont(void)
{
}
@ -4023,7 +4025,7 @@ static struct {
{"SCAN-NTTRANS", torture_nttrans_scan, 0},
{"SCAN-ALIASES", torture_trans2_aliases, 0},
{"SCAN-SMB", torture_smb_scan, 0},
{"RPC-OPEN", torture_rpc_open, 0},
{"RPC-LSA", torture_rpc_lsa, 0},
{NULL, NULL, 0}};