diff options
-rw-r--r-- | source4/librpc/config.m4 | 1 | ||||
-rw-r--r-- | source4/librpc/idl/drsuapi.idl | 117 | ||||
-rw-r--r-- | source4/torture/config.mk | 1 | ||||
-rw-r--r-- | source4/torture/rpc/drsuapi.c | 230 | ||||
-rw-r--r-- | source4/torture/torture.c | 2 |
5 files changed, 350 insertions, 1 deletions
diff --git a/source4/librpc/config.m4 b/source4/librpc/config.m4 index 7e0f92b3cc..c360a8f89d 100644 --- a/source4/librpc/config.m4 +++ b/source4/librpc/config.m4 @@ -12,6 +12,7 @@ SMB_SUBSYSTEM(LIBNDR_RAW,[], librpc/gen_ndr/ndr_lsa.o librpc/gen_ndr/ndr_lsads.o librpc/gen_ndr/ndr_dfs.o + librpc/gen_ndr/ndr_drsuapi.o librpc/gen_ndr/ndr_samr.o librpc/gen_ndr/ndr_spoolss.o librpc/gen_ndr/ndr_wkssvc.o diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl new file mode 100644 index 0000000000..a139c60726 --- /dev/null +++ b/source4/librpc/idl/drsuapi.idl @@ -0,0 +1,117 @@ +#include "idl_types.h" + +[ + uuid(e3514235-4b06-11d1-ab04-00c04fc2dcd2), + version(4.0), + endpoints(drsuapi,TCP-0), + pointer_default(unique) +] +interface drsuapi +{ + /*****************/ + /* Function 0x00 */ + void DRSUAPI_BIND( + /* [in] 8-60 bytes are possible + * but I saw 56 bytes + */ + [in] uint8 blob[56], + /* [out] 60 bytes */ + [out] uint8 blob[60] + ); + + /*****************/ + /* Function 0x01 */ + void DRSUAPI_UNBIND(); + + /*****************/ + /* Function 0x02 */ + void DRSUAPI_REPLICA_SYNC(); + + /*****************/ + /* Function 0x03 */ + void DRSUAPI_GET_NC_CHANGES(); + + /*****************/ + /* Function 0x04 */ + void DRSUAPI_UPDATE_REFS(); + + /*****************/ + /* Function 0x05 */ + void DRSUAPI_REPLICA_ADD(); + + /*****************/ + /* Function 0x06 */ + void DRSUAPI_REPLICA_DEL(); + + /*****************/ + /* Function 0x07 */ + void DRSUAPI_REPLICA_MODIFY(); + + /*****************/ + /* Function 0x08 */ + void DRSUAPI_VERIFY_NAMES(); + + /*****************/ + /* Function 0x09 */ + void DRSUAPI_GET_MEMBERSHIPS(); + + /*****************/ + /* Function 0x0a */ + void DRSUAPI_INTER_DOMAIN_MOVE(); + + /*****************/ + /* Function 0x0b */ + void DRSUAPI_GET_NT4_CHANGELOG(); + + /*****************/ + /* Function 0x0c */ + void DRSUAPI_CRACKNAMES(); + + /*****************/ + /* Function 0x0d */ + void DRSUAPI_WRITE_SPN(); + + /*****************/ + /* Function 0x0e */ + void DRSUAPI_REMOVE_DS_SERVER(); + + /*****************/ + /* Function 0x0f */ + void DRSUAPI_REMOVE_DS_DOMAIN(); + + /*****************/ + /* Function 0x10 */ + void DRSUAPI_DOMAIN_CONTROLLER_INFO(); + + /*****************/ + /* Function 0x11 */ + void DRSUAPI_ADD_ENTRY(); + + /*****************/ + /* Function 0x12 */ + void DRSUAPI_EXECUTE_KCC(); + + /*****************/ + /* Function 0x13 */ + void DRSUAPI_GET_REPL_INFO(); + + /*****************/ + /* Function 0x14 */ + void DRSUAPI_ADD_SID_HISTORY(); + + /*****************/ + /* Function 0x15 */ + void DRSUAPI_GET_MEMBERSHIPS2(); + + /*****************/ + /* Function 0x16 */ + void DRSUAPI_REPLICA_VERIFY_OBJECTS(); + + /*****************/ + /* Function 0x17 */ + void DRSUAPI_GET_OBJECT_EXISTENCE(); + + /*****************/ + /* Function 0x18 */ + void DRSUAPI_QUERY_SITES_BY_COST(); +} diff --git a/source4/torture/config.mk b/source4/torture/config.mk index 12b69d9745..de24d10617 100644 --- a/source4/torture/config.mk +++ b/source4/torture/config.mk @@ -50,6 +50,7 @@ ADD_OBJ_FILES = \ torture/rpc/lsa.o \ torture/rpc/echo.o \ torture/rpc/dfs.o \ + torture/rpc/drsuapi.o \ torture/rpc/spoolss.o \ torture/rpc/samr.o \ torture/rpc/wkssvc.o \ diff --git a/source4/torture/rpc/drsuapi.c b/source4/torture/rpc/drsuapi.c new file mode 100644 index 0000000000..a2f3eb6104 --- /dev/null +++ b/source4/torture/rpc/drsuapi.c @@ -0,0 +1,230 @@ +/* + Unix SMB/CIFS implementation. + + DRSUapi tests + + Copyright (C) Andrew Tridgell 2003 + Copyright (C) Stefan (metze) Metzmacher 2004 + + 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" + + +static void reopen(struct dcerpc_pipe **p, const struct dcerpc_interface_table *iface) +{ + NTSTATUS status; + + if (*p) { + dcerpc_pipe_close(*p); + } + + status = torture_rpc_connection(p, iface->endpoints->names[0], iface->uuid, iface->if_version); + if (!NT_STATUS_IS_OK(status)) { + printf("Failed to reopen '%s' - %s\n", iface->name, nt_errstr(status)); + exit(1); + } +} + +static void print_depth(int depth) +{ + int i; + for (i=0;i<depth;i++) { + printf(" "); + } +} + +static void test_ptr_scan(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface, + int opnum, DATA_BLOB *base_in, int min_ofs, int max_ofs, int depth); + +static void try_expand(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface, + int opnum, DATA_BLOB *base_in, int insert_ofs, int depth) +{ + DATA_BLOB stub_in, stub_out; + int n; + NTSTATUS status; + struct dcerpc_pipe *p = NULL; + + reopen(&p, iface); + + /* work out how much to expand to get a non fault */ + for (n=0;n<2000;n++) { + stub_in = data_blob(NULL, base_in->length + n); + data_blob_clear(&stub_in); + memcpy(stub_in.data, base_in->data, insert_ofs); + memcpy(stub_in.data+insert_ofs+n, base_in->data+insert_ofs, base_in->length-insert_ofs); + + status = dcerpc_request(p, opnum, mem_ctx, &stub_in, &stub_out); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { + print_depth(depth); + printf("expand by %d gives %s\n", n, nt_errstr(status)); + if (n >= 4) { + test_ptr_scan(mem_ctx, iface, opnum, &stub_in, + insert_ofs, insert_ofs+n, depth+1); + } + return; + } else { +#if 0 + print_depth(depth); + printf("expand by %d gives fault 0x%x\n", n, p->last_fault_code); +#endif + } + if (p->last_fault_code == 5) { + reopen(&p, iface); + } + } + + dcerpc_pipe_close(p); +} + + +static void test_ptr_scan(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface, + int opnum, DATA_BLOB *base_in, int min_ofs, int max_ofs, int depth) +{ + DATA_BLOB stub_in, stub_out; + int ofs; + NTSTATUS status; + struct dcerpc_pipe *p = NULL; + + reopen(&p, iface); + + stub_in = data_blob(NULL, base_in->length); + memcpy(stub_in.data, base_in->data, base_in->length); + + /* work out which elements are pointers */ + for (ofs=min_ofs;ofs<=max_ofs-4;ofs+=4) { + SIVAL(stub_in.data, ofs, 1); + status = dcerpc_request(p, opnum, mem_ctx, &stub_in, &stub_out); + + if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { + print_depth(depth); + printf("possible ptr at ofs %d - fault 0x%08x\n", + ofs-min_ofs, p->last_fault_code); + if (p->last_fault_code == 5) { + reopen(&p, iface); + } + if (depth == 0) { + try_expand(mem_ctx, iface, opnum, &stub_in, ofs+4, depth+1); + } else { + try_expand(mem_ctx, iface, opnum, &stub_in, max_ofs, depth+1); + } + SIVAL(stub_in.data, ofs, 0); + continue; + } + SIVAL(stub_in.data, ofs, 0); + } + + dcerpc_pipe_close(p); +} + + +static void test_scan_call(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface, int opnum) +{ + DATA_BLOB stub_in, stub_out; + int i; + NTSTATUS status; + struct dcerpc_pipe *p = NULL; + + reopen(&p, iface); + + /* work out the minimum amount of input data */ + for (i=0;i<2000;i++) { + stub_in = data_blob(NULL, i); + data_blob_clear(&stub_in); + + + status = dcerpc_request(p, opnum, mem_ctx, &stub_in, &stub_out); + + if (NT_STATUS_IS_OK(status)) { + printf("opnum %d min_input %d - output %d\n", + opnum, stub_in.length, stub_out.length); + dump_data(0, stub_out.data, stub_out.length); + dcerpc_pipe_close(p); + test_ptr_scan(mem_ctx, iface, opnum, &stub_in, 0, stub_in.length, 0); + return; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { + printf("opnum %d size %d fault 0x%08x\n", opnum, i, p->last_fault_code); + if (p->last_fault_code == 5) { + reopen(&p, iface); + } + continue; + } + + printf("opnum %d size %d error %s\n", opnum, i, nt_errstr(status)); + } + + printf("opnum %d minimum not found!?\n", opnum); + dcerpc_pipe_close(p); +} + + +static BOOL test_scan(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) +{ + test_scan_call(mem_ctx, &dcerpc_table_drsuapi, 0x0); + return True; +} + +static BOOL test_DRSBind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + struct DRSUAPI_BIND r; + BOOL ret = True; + + ZERO_STRUCT(r.in.blob); + + status = dcerpc_DRSUAPI_BIND(p, mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("DRSUAPI_BIND level failed - %s\n", nt_errstr(status)); + ret = False; + } + + return ret; +} + +BOOL torture_rpc_drsuapi(int dummy) +{ + NTSTATUS status; + struct dcerpc_pipe *p; + TALLOC_CTX *mem_ctx; + BOOL ret = True; + + mem_ctx = talloc_init("torture_rpc_srvsvc"); + + status = torture_rpc_connection(&p, + DCERPC_DRSUAPI_NAME, + DCERPC_DRSUAPI_UUID, + DCERPC_DRSUAPI_VERSION); + if (!NT_STATUS_IS_OK(status)) { + return False; + } + + if (!test_DRSBind(p, mem_ctx)) { + ret = False; + } + + if (!test_scan(p, mem_ctx)) { + ret = False; + } + + talloc_destroy(mem_ctx); + + torture_rpc_close(p); + + return ret; +} diff --git a/source4/torture/torture.c b/source4/torture/torture.c index d48d10a504..8f72b63e6c 100644 --- a/source4/torture/torture.c +++ b/source4/torture/torture.c @@ -4217,7 +4217,7 @@ static struct { {"RPC-SCANNER", torture_rpc_scanner, 0}, {"RPC-AUTOIDL", torture_rpc_autoidl, 0}, {"RPC-MULTIBIND", torture_multi_bind, 0}, - {"RAP-RAW", torture_raw_rap, 0}, + {"RPC-DRSUAPI", torture_rpc_drsuapi, 0}, {"NTLMSSP-SELFCHECK", torture_ntlmssp_self_check, 0}, {NULL, NULL, 0}}; |