wmi-1.3.16 from opsview.com
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
test suite for dcerpc alter_context operations
|
||||
|
||||
Copyright (C) Andrew Tridgell 2005
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_lsa.h"
|
||||
#include "librpc/gen_ndr/ndr_dssetup.h"
|
||||
#include "librpc/rpc/dcerpc.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
BOOL torture_rpc_alter_context(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p, *p2;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
struct policy_handle *handle;
|
||||
struct dcerpc_interface_table tmptbl;
|
||||
struct dcerpc_syntax_id syntax;
|
||||
struct dcerpc_syntax_id transfer_syntax;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_alter_context");
|
||||
|
||||
printf("opening LSA connection\n");
|
||||
status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_lsarpc);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!test_lsa_OpenPolicy2(p, mem_ctx, &handle)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
printf("Opening secondary DSSETUP context\n");
|
||||
status = dcerpc_secondary_context(p, &p2, &dcerpc_table_dssetup);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
printf("dcerpc_alter_context failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
tmptbl = dcerpc_table_dssetup;
|
||||
tmptbl.syntax_id.if_version += 100;
|
||||
printf("Opening bad secondary connection\n");
|
||||
status = dcerpc_secondary_context(p, &p2, &tmptbl);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
printf("dcerpc_alter_context with wrong version should fail\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
printf("testing DSSETUP pipe operations\n");
|
||||
ret &= test_DsRoleGetPrimaryDomainInformation(p2, mem_ctx);
|
||||
|
||||
if (handle) {
|
||||
if (!test_lsa_Close(p, mem_ctx, handle)) {
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
syntax = p->syntax;
|
||||
transfer_syntax = p->transfer_syntax;
|
||||
|
||||
printf("Testing change of primary context\n");
|
||||
status = dcerpc_alter_context(p, mem_ctx, &p2->syntax, &p2->transfer_syntax);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
printf("dcerpc_alter_context failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
printf("testing DSSETUP pipe operations - should fault\n");
|
||||
if (test_DsRoleGetPrimaryDomainInformation(p, mem_ctx)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!test_lsa_OpenPolicy2(p, mem_ctx, &handle)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (handle) {
|
||||
if (!test_lsa_Close(p, mem_ctx, handle)) {
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
printf("testing DSSETUP pipe operations\n");
|
||||
ret &= test_DsRoleGetPrimaryDomainInformation(p2, mem_ctx);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
dcerpc torture tests
|
||||
|
||||
Copyright (C) Andrew Tridgell 2003
|
||||
Copyright (C) Rafal Szczesniak 2006
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "lib/events/events.h"
|
||||
#include "libcli/composite/composite.h"
|
||||
#include "librpc/gen_ndr/ndr_lsa.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
#include "librpc/rpc/dcerpc.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
/*
|
||||
This test initiates multiple rpc bind requests and verifies
|
||||
whether all of them are served.
|
||||
*/
|
||||
|
||||
|
||||
BOOL torture_async_bind(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
struct event_context *evt_ctx;
|
||||
int i;
|
||||
const char *binding_string;
|
||||
struct cli_credentials *creds;
|
||||
extern int torture_numasync;
|
||||
|
||||
struct composite_context **bind_req;
|
||||
struct dcerpc_pipe **pipe;
|
||||
const struct dcerpc_interface_table **table;
|
||||
|
||||
if (!torture_setting_bool(torture, "async", False)) {
|
||||
printf("async bind test disabled - enable async tests to use\n");
|
||||
return True;
|
||||
}
|
||||
|
||||
binding_string = torture_setting_string(torture, "binding", NULL);
|
||||
|
||||
/* talloc context */
|
||||
mem_ctx = talloc_init("torture_async_bind");
|
||||
if (mem_ctx == NULL) return False;
|
||||
|
||||
bind_req = talloc_array(torture, struct composite_context*, torture_numasync);
|
||||
if (bind_req == NULL) return False;
|
||||
pipe = talloc_array(torture, struct dcerpc_pipe*, torture_numasync);
|
||||
if (pipe == NULL) return False;
|
||||
table = talloc_array(torture, const struct dcerpc_interface_table*, torture_numasync);
|
||||
if (table == NULL) return False;
|
||||
|
||||
/* event context */
|
||||
evt_ctx = event_context_init(mem_ctx);
|
||||
if (evt_ctx == NULL) return False;
|
||||
|
||||
/* credentials */
|
||||
creds = cmdline_credentials;
|
||||
|
||||
/* send bind requests */
|
||||
for (i = 0; i < torture_numasync; i++) {
|
||||
table[i] = &dcerpc_table_lsarpc;
|
||||
bind_req[i] = dcerpc_pipe_connect_send(mem_ctx, binding_string,
|
||||
table[i], creds, evt_ctx);
|
||||
}
|
||||
|
||||
/* recv bind requests */
|
||||
for (i = 0; i < torture_numasync; i++) {
|
||||
status = dcerpc_pipe_connect_recv(bind_req[i], mem_ctx, &pipe[i]);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("async rpc connection failed: %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
return True;
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for atsvc rpc 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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_atsvc_c.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
static bool test_JobGetInfo(struct dcerpc_pipe *p, struct torture_context *tctx, uint32_t job_id)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct atsvc_JobGetInfo r;
|
||||
|
||||
r.in.servername = dcerpc_server_name(p);
|
||||
r.in.job_id = job_id;
|
||||
|
||||
status = dcerpc_atsvc_JobGetInfo(p, tctx, &r);
|
||||
|
||||
torture_assert_ntstatus_ok(tctx, status, "JobGetInfo failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_JobDel(struct dcerpc_pipe *p, struct torture_context *tctx, uint32_t min_job_id,
|
||||
uint32_t max_job_id)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct atsvc_JobDel r;
|
||||
|
||||
r.in.servername = dcerpc_server_name(p);
|
||||
r.in.min_job_id = min_job_id;
|
||||
r.in.max_job_id = max_job_id;
|
||||
|
||||
status = dcerpc_atsvc_JobDel(p, tctx, &r);
|
||||
|
||||
torture_assert_ntstatus_ok(tctx, status, "JobDel failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_JobEnum(struct torture_context *tctx, struct dcerpc_pipe *p)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct atsvc_JobEnum r;
|
||||
struct atsvc_enum_ctr ctr;
|
||||
uint32_t resume_handle = 0, i;
|
||||
bool ret = true;
|
||||
|
||||
r.in.servername = dcerpc_server_name(p);
|
||||
ctr.entries_read = 0;
|
||||
ctr.first_entry = NULL;
|
||||
r.in.ctr = r.out.ctr = &ctr;
|
||||
r.in.preferred_max_len = 0xffffffff;
|
||||
r.in.resume_handle = r.out.resume_handle = &resume_handle;
|
||||
|
||||
status = dcerpc_atsvc_JobEnum(p, tctx, &r);
|
||||
|
||||
torture_assert_ntstatus_ok(tctx, status, "JobEnum failed");
|
||||
|
||||
for (i = 0; i < r.out.ctr->entries_read; i++) {
|
||||
if (!test_JobGetInfo(p, tctx, r.out.ctr->first_entry[i].job_id)) {
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool test_JobAdd(struct torture_context *tctx, struct dcerpc_pipe *p)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct atsvc_JobAdd r;
|
||||
struct atsvc_JobInfo info;
|
||||
|
||||
r.in.servername = dcerpc_server_name(p);
|
||||
info.job_time = 0x050ae4c0; /* 11:30pm */
|
||||
info.days_of_month = 0; /* n/a */
|
||||
info.days_of_week = 0x02; /* Tuesday */
|
||||
info.flags = 0x11; /* periodic, non-interactive */
|
||||
info.command = "foo.exe";
|
||||
r.in.job_info = &info;
|
||||
|
||||
status = dcerpc_atsvc_JobAdd(p, tctx, &r);
|
||||
|
||||
torture_assert_ntstatus_ok(tctx, status, "JobAdd failed");
|
||||
|
||||
/* Run EnumJobs again in case there were no jobs to begin with */
|
||||
|
||||
if (!test_JobEnum(tctx, p)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!test_JobGetInfo(p, tctx, *r.out.job_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!test_JobDel(p, tctx, *r.out.job_id, *r.out.job_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct torture_suite *torture_rpc_atsvc(void)
|
||||
{
|
||||
struct torture_suite *suite = torture_suite_create(
|
||||
talloc_autofree_context(),
|
||||
"ATSVC");
|
||||
struct torture_tcase *tcase;
|
||||
|
||||
tcase = torture_suite_add_rpc_iface_tcase(suite, "atsvc",
|
||||
&dcerpc_table_atsvc);
|
||||
|
||||
torture_rpc_tcase_add_test(tcase, "JobEnum", test_JobEnum);
|
||||
torture_rpc_tcase_add_test(tcase, "JobAdd", test_JobAdd);
|
||||
|
||||
return suite;
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
auto-idl scanner
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_drsuapi_c.h"
|
||||
#include "librpc/gen_ndr/ndr_misc.h"
|
||||
#include "librpc/rpc/dcerpc_table.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
|
||||
#if 1
|
||||
/*
|
||||
get a DRSUAPI policy handle
|
||||
*/
|
||||
static BOOL get_policy_handle(struct dcerpc_pipe *p,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct drsuapi_DsBind r;
|
||||
|
||||
ZERO_STRUCT(r);
|
||||
r.out.bind_handle = handle;
|
||||
|
||||
status = dcerpc_drsuapi_DsBind(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("drsuapi_DsBind failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
get a SAMR handle
|
||||
*/
|
||||
static BOOL get_policy_handle(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct samr_Connect r;
|
||||
|
||||
r.in.system_name = 0;
|
||||
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
r.out.connect_handle = handle;
|
||||
|
||||
status = dcerpc_samr_Connect(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("samr_Connect failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void fill_blob_handle(DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle)
|
||||
{
|
||||
DATA_BLOB b2;
|
||||
|
||||
if (blob->length < 20) {
|
||||
return;
|
||||
}
|
||||
|
||||
ndr_push_struct_blob(&b2, mem_ctx, handle, (ndr_push_flags_fn_t)ndr_push_policy_handle);
|
||||
|
||||
memcpy(blob->data, b2.data, 20);
|
||||
}
|
||||
|
||||
static void reopen(TALLOC_CTX *mem_ctx,
|
||||
struct dcerpc_pipe **p,
|
||||
const struct dcerpc_interface_table *iface)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
talloc_free(*p);
|
||||
|
||||
status = torture_rpc_connection(mem_ctx,
|
||||
p, iface);
|
||||
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(mem_ctx, &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, NULL, opnum, False, 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 %s\n", n, dcerpc_errstr(mem_ctx, p->last_fault_code));
|
||||
#endif
|
||||
}
|
||||
if (p->last_fault_code == 5) {
|
||||
reopen(mem_ctx, &p, iface);
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(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(mem_ctx, &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, NULL, opnum, False, 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 %s\n",
|
||||
ofs-min_ofs, dcerpc_errstr(mem_ctx, p->last_fault_code));
|
||||
if (p->last_fault_code == 5) {
|
||||
reopen(mem_ctx, &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);
|
||||
}
|
||||
|
||||
talloc_free(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;
|
||||
struct policy_handle handle;
|
||||
|
||||
reopen(mem_ctx, &p, iface);
|
||||
|
||||
get_policy_handle(p, mem_ctx, &handle);
|
||||
|
||||
/* 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, NULL, opnum, False, mem_ctx, &stub_in, &stub_out);
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
printf("opnum %d min_input %d - output %d\n",
|
||||
opnum, (int)stub_in.length, (int)stub_out.length);
|
||||
dump_data(0, stub_out.data, stub_out.length);
|
||||
talloc_free(p);
|
||||
test_ptr_scan(mem_ctx, iface, opnum, &stub_in, 0, stub_in.length, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
fill_blob_handle(&stub_in, mem_ctx, &handle);
|
||||
|
||||
status = dcerpc_request(p, NULL, opnum, False, mem_ctx, &stub_in, &stub_out);
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
printf("opnum %d min_input %d - output %d (with handle)\n",
|
||||
opnum, (int)stub_in.length, (int)stub_out.length);
|
||||
dump_data(0, stub_out.data, stub_out.length);
|
||||
talloc_free(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 %s\n", opnum, i, dcerpc_errstr(mem_ctx, p->last_fault_code));
|
||||
if (p->last_fault_code == 5) {
|
||||
reopen(mem_ctx, &p, iface);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("opnum %d size %d error %s\n", opnum, i, nt_errstr(status));
|
||||
}
|
||||
|
||||
printf("opnum %d minimum not found!?\n", opnum);
|
||||
talloc_free(p);
|
||||
}
|
||||
|
||||
|
||||
static void test_auto_scan(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface)
|
||||
{
|
||||
test_scan_call(mem_ctx, iface, 2);
|
||||
}
|
||||
|
||||
BOOL torture_rpc_autoidl(struct torture_context *torture)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx;
|
||||
const struct dcerpc_interface_table *iface;
|
||||
|
||||
iface = idl_iface_by_name("drsuapi");
|
||||
if (!iface) {
|
||||
printf("Unknown interface!\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_autoidl");
|
||||
|
||||
printf("\nProbing pipe '%s'\n", iface->name);
|
||||
|
||||
test_auto_scan(mem_ctx, iface);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
return True;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
simple RPC benchmark
|
||||
|
||||
Copyright (C) Andrew Tridgell 2005
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_srvsvc_c.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
/**************************/
|
||||
/* srvsvc_NetShare */
|
||||
/**************************/
|
||||
static BOOL test_NetShareEnumAll(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct srvsvc_NetShareEnumAll r;
|
||||
struct srvsvc_NetShareCtr0 c0;
|
||||
uint32_t levels[] = {0, 1, 2, 501, 502};
|
||||
int i;
|
||||
BOOL ret = True;
|
||||
uint32_t resume_handle;
|
||||
|
||||
ZERO_STRUCT(c0);
|
||||
|
||||
r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
|
||||
r.in.ctr.ctr0 = &c0;
|
||||
r.in.max_buffer = (uint32_t)-1;
|
||||
r.in.resume_handle = &resume_handle;
|
||||
r.out.resume_handle = &resume_handle;
|
||||
|
||||
for (i=0;i<ARRAY_SIZE(levels);i++) {
|
||||
ZERO_STRUCT(r.out);
|
||||
resume_handle = 0;
|
||||
r.in.level = levels[i];
|
||||
status = dcerpc_srvsvc_NetShareEnumAll(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("NetShareEnumAll level %u failed - %s\n", r.in.level, nt_errstr(status));
|
||||
ret = False;
|
||||
continue;
|
||||
}
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("NetShareEnumAll level %u failed - %s\n", r.in.level, win_errstr(r.out.result));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
benchmark srvsvc netshareenumall queries
|
||||
*/
|
||||
static BOOL bench_NetShareEnumAll(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct timeval tv = timeval_current();
|
||||
BOOL ret = True;
|
||||
int timelimit = lp_parm_int(-1, "torture", "timelimit", 10);
|
||||
int count=0;
|
||||
|
||||
printf("Running for %d seconds\n", timelimit);
|
||||
while (timeval_elapsed(&tv) < timelimit) {
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
|
||||
if (!test_NetShareEnumAll(p, tmp_ctx)) break;
|
||||
talloc_free(tmp_ctx);
|
||||
count++;
|
||||
if (count % 50 == 0) {
|
||||
printf("%.1f queries per second \r",
|
||||
count / timeval_elapsed(&tv));
|
||||
}
|
||||
}
|
||||
|
||||
printf("%.1f queries per second \n", count / timeval_elapsed(&tv));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BOOL torture_bench_rpc(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_srvsvc");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx,
|
||||
&p,
|
||||
&dcerpc_table_srvsvc);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!bench_NetShareEnumAll(p, mem_ctx)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
dcerpc torture tests
|
||||
|
||||
Copyright (C) Andrew Tridgell 2003
|
||||
Copyright (C) Andrew Bartlett <abartlet@samba.org 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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_lsa.h"
|
||||
#include "librpc/gen_ndr/ndr_lsa_c.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
#include "librpc/rpc/dcerpc.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
#include "libcli/libcli.h"
|
||||
#include "libcli/composite/composite.h"
|
||||
#include "libcli/smb_composite/smb_composite.h"
|
||||
|
||||
/*
|
||||
This test is 'bogus' in that it doesn't actually perform to the
|
||||
spec. We need to deal with other things inside the DCERPC layer,
|
||||
before we could have multiple binds.
|
||||
|
||||
We should never pass this test, until such details are fixed in our
|
||||
client, and it looks like multible binds are never used anyway.
|
||||
|
||||
*/
|
||||
|
||||
BOOL torture_multi_bind(struct torture_context *torture)
|
||||
{
|
||||
struct dcerpc_pipe *p;
|
||||
struct dcerpc_binding *binding;
|
||||
const char *binding_string = torture_setting_string(torture, "binding", NULL);
|
||||
TALLOC_CTX *mem_ctx;
|
||||
NTSTATUS status;
|
||||
BOOL ret;
|
||||
|
||||
mem_ctx = talloc_init("torture_multi_bind");
|
||||
|
||||
status = dcerpc_parse_binding(mem_ctx, binding_string, &binding);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Failed to parse dcerpc binding '%s'\n", binding_string);
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_lsarpc);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
status = dcerpc_pipe_auth(mem_ctx, &p, binding, &dcerpc_table_lsarpc, cmdline_credentials);
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
printf("(incorrectly) allowed re-bind to uuid %s - %s\n",
|
||||
GUID_string(mem_ctx, &dcerpc_table_lsarpc.syntax_id.uuid), nt_errstr(status));
|
||||
ret = False;
|
||||
} else {
|
||||
printf("\n");
|
||||
ret = True;
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
count number of calls on an interface
|
||||
|
||||
Copyright (C) Andrew Tridgell 2003
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/rpc/dcerpc.h"
|
||||
#include "librpc/rpc/dcerpc_table.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
|
||||
BOOL torture_rpc_countcalls(struct torture_context *torture)
|
||||
{
|
||||
const struct dcerpc_interface_table *iface;
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
int i;
|
||||
const char *iface_name;
|
||||
DATA_BLOB stub_in, stub_out;
|
||||
|
||||
iface_name = lp_parm_string(-1, "countcalls", "interface");
|
||||
if (iface_name == NULL) {
|
||||
printf("You must specify an interface name with countcalls:interface\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
iface = idl_iface_by_name(iface_name);
|
||||
if (!iface) {
|
||||
printf("Unknown interface '%s'\n", iface_name);
|
||||
return False;
|
||||
}
|
||||
|
||||
status = torture_rpc_connection(NULL, &p, iface);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Failed to open '%s' - %s\n", iface->name, nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
stub_in = data_blob_talloc(p, NULL, 0);
|
||||
|
||||
printf("\nScanning pipe '%s'\n", iface->name);
|
||||
|
||||
for (i=0;i<5000;i++) {
|
||||
status = dcerpc_request(p, NULL, i, False, p, &stub_in, &stub_out);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT) &&
|
||||
p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) break;
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_DISCONNECTED)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i==5000) {
|
||||
talloc_free(p);
|
||||
printf("no limit on calls!?\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
printf("Found %d calls\n", i);
|
||||
|
||||
talloc_free(p);
|
||||
|
||||
return True;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for dcom operations
|
||||
|
||||
Copyright (C) Jelmer Vernooij 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"
|
||||
#include "torture/torture.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
#include "librpc/gen_ndr/ndr_oxidresolver.h"
|
||||
|
||||
BOOL torture_rpc_dcom(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_dcom");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_IOXIDResolver);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for rpc dfs operations
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
#include "librpc/gen_ndr/ndr_dfs_c.h"
|
||||
#include "librpc/gen_ndr/ndr_srvsvc_c.h"
|
||||
#include "libnet/libnet.h"
|
||||
#include "libcli/raw/libcliraw.h"
|
||||
#include "torture/util.h"
|
||||
#include "libcli/libcli.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
|
||||
#if 0
|
||||
|
||||
#define SMBTORTURE_DFS_SHARENAME "smbtorture_dfs_share"
|
||||
#define SMBTORTURE_DFS_DIRNAME "\\smbtorture_dfs_dir"
|
||||
#define SMBTORTURE_DFS_PATHNAME "C:"SMBTORTURE_DFS_DIRNAME
|
||||
|
||||
#define IS_DFS_VERSION_UNSUPPORTED_CALL_W2K3(x,y)\
|
||||
if (x == DFS_MANAGER_VERSION_W2K3) {\
|
||||
if (!W_ERROR_EQUAL(y,WERR_NOT_SUPPORTED)) {\
|
||||
printf("expected WERR_NOT_SUPPORTED\n");\
|
||||
return False;\
|
||||
}\
|
||||
return True;\
|
||||
}\
|
||||
|
||||
static BOOL test_NetShareAdd(TALLOC_CTX *mem_ctx, const char *host, const char *sharename, const char *dir)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct srvsvc_NetShareInfo2 i;
|
||||
struct libnet_context* libnetctx;
|
||||
struct libnet_AddShare r;
|
||||
|
||||
printf("Creating share %s\n", sharename);
|
||||
|
||||
if (!(libnetctx = libnet_context_init(NULL))) {
|
||||
return False;
|
||||
}
|
||||
|
||||
libnetctx->cred = cmdline_credentials;
|
||||
|
||||
i.name = sharename;
|
||||
i.type = STYPE_DISKTREE;
|
||||
i.path = dir;
|
||||
i.max_users = (uint32_t) -1;
|
||||
i.comment = "created by smbtorture";
|
||||
i.password = NULL;
|
||||
i.permissions = 0x0;
|
||||
i.current_users = 0x0;
|
||||
|
||||
r.level = 2;
|
||||
r.in.server_name = host;
|
||||
r.in.share = i;
|
||||
|
||||
status = libnet_AddShare(libnetctx, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
d_printf("Failed to add new share: %s (%s)\n",
|
||||
nt_errstr(status), r.out.error_string);
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_NetShareDel(TALLOC_CTX *mem_ctx, const char *host, const char *sharename)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct libnet_context* libnetctx;
|
||||
struct libnet_DelShare r;
|
||||
|
||||
printf("Deleting share %s\n", sharename);
|
||||
|
||||
if (!(libnetctx = libnet_context_init(NULL))) {
|
||||
return False;
|
||||
}
|
||||
|
||||
libnetctx->cred = cmdline_credentials;
|
||||
|
||||
r.in.share_name = sharename;
|
||||
r.in.server_name = host;
|
||||
|
||||
status = libnet_DelShare(libnetctx, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
d_printf("Failed to delete share: %s (%s)\n",
|
||||
nt_errstr(status), r.out.error_string);
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_CreateDir(TALLOC_CTX *mem_ctx,
|
||||
struct smbcli_state **cli,
|
||||
const char *host,
|
||||
const char *share,
|
||||
const char *dir)
|
||||
{
|
||||
printf("Creating directory %s\n", dir);
|
||||
|
||||
if (!torture_open_connection_share(mem_ctx, cli, host, share, NULL)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!torture_setup_dir(*cli, dir)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_DeleteDir(struct smbcli_state *cli, const char *dir)
|
||||
{
|
||||
printf("Deleting directory %s\n", dir);
|
||||
|
||||
if (smbcli_deltree(cli->tree, dir) == -1) {
|
||||
printf("Unable to delete dir %s - %s\n", dir, smbcli_errstr(cli->tree));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_GetManagerVersion(struct torture_context *tctx, struct dcerpc_pipe *p, enum dfs_ManagerVersion *version)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dfs_GetManagerVersion r;
|
||||
|
||||
r.out.version = version;
|
||||
|
||||
status = dcerpc_dfs_GetManagerVersion(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status, "GetManagerVersion failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static BOOL test_ManagerInitialize(struct torture_context *tctx, struct dcerpc_pipe *p, const char *host)
|
||||
{
|
||||
NTSTATUS status;
|
||||
enum dfs_ManagerVersion version;
|
||||
struct dfs_ManagerInitialize r;
|
||||
|
||||
printf("Testing ManagerInitialize\n");
|
||||
|
||||
if (!test_GetManagerVersion(tctx, p, &version)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
r.in.servername = host;
|
||||
r.in.flags = 0;
|
||||
|
||||
status = dcerpc_dfs_ManagerInitialize(p, tctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("ManagerInitialize failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("dfs_ManagerInitialize failed - %s\n", win_errstr(r.out.result));
|
||||
IS_DFS_VERSION_UNSUPPORTED_CALL_W2K3(version, r.out.result);
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_GetInfoLevel(struct torture_context *tctx, struct dcerpc_pipe *p, uint16_t level, const char *root)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dfs_GetInfo r;
|
||||
|
||||
torture_comment(tctx,
|
||||
talloc_asprintf(tctx, "Testing GetInfo level %u on '%s'\n", level, root));
|
||||
|
||||
r.in.dfs_entry_path = talloc_strdup(tctx, root);
|
||||
r.in.servername = NULL;
|
||||
r.in.sharename = NULL;
|
||||
r.in.level = level;
|
||||
|
||||
status = dcerpc_dfs_GetInfo(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status, "Info failed");
|
||||
torture_assert(tctx, W_ERROR_IS_OK(r.out.result) ||
|
||||
W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, r.out.result),
|
||||
talloc_asprintf(tctx,
|
||||
"dfs_GetInfo failed - %s", win_errstr(r.out.result)));
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static bool test_Info(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p, const char *root)
|
||||
{
|
||||
BOOL ret = True;
|
||||
/* 103, 104, 105, 106 is only available on Set */
|
||||
uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 100, 101, 102, 103, 104, 105, 106};
|
||||
int i;
|
||||
|
||||
for (i=0;i<ARRAY_SIZE(levels);i++) {
|
||||
if (!test_GetInfoLevel(tctx, p, levels[i], root)) {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool test_EnumLevel(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p, uint16_t level)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dfs_EnumEx rex;
|
||||
uint32_t total=0;
|
||||
struct dfs_EnumStruct e;
|
||||
struct dfs_Info1 s;
|
||||
struct dfs_EnumArray1 e1;
|
||||
BOOL ret = True;
|
||||
|
||||
rex.in.level = level;
|
||||
rex.in.bufsize = (uint32_t)-1;
|
||||
rex.in.total = &total;
|
||||
rex.in.info = &e;
|
||||
rex.in.dfs_name = dfs_name;
|
||||
|
||||
e.level = rex.in.level;
|
||||
e.e.info1 = &e1;
|
||||
e.e.info1->count = 0;
|
||||
e.e.info1->s = &s;
|
||||
s.path = NULL;
|
||||
|
||||
printf("Testing EnumEx level %u on '%s'\n", level, dfs_name);
|
||||
|
||||
status = dcerpc_dfs_EnumEx(p, mem_ctx, &rex);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("EnumEx failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (level == 1 && rex.out.total) {
|
||||
int i;
|
||||
for (i=0;i<*rex.out.total;i++) {
|
||||
const char *root = talloc_strdup(mem_ctx, rex.out.info->e.info1->s[i].path);
|
||||
if (!test_GetInfo(p, mem_ctx, root)) {
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (level == 300 && rex.out.total) {
|
||||
int i,k;
|
||||
for (i=0;i<*rex.out.total;i++) {
|
||||
uint16_t levels[] = {1, 2, 3, 4, 200}; /* 300 */
|
||||
const char *root = talloc_strdup(mem_ctx, rex.out.info->e.info300->s[i].dom_root);
|
||||
for (k=0;k<ARRAY_SIZE(levels);k++) {
|
||||
if (!test_EnumLevelEx(p, mem_ctx, levels[k], root)) {
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
if (!test_GetInfo(p, mem_ctx, root)) {
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static BOOL test_EnumLevel(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, uint16_t level)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dfs_Enum r;
|
||||
uint32_t total=0;
|
||||
struct dfs_EnumStruct e;
|
||||
struct dfs_Info1 s;
|
||||
struct dfs_EnumArray1 e1;
|
||||
BOOL ret = True;
|
||||
|
||||
r.in.level = level;
|
||||
r.in.bufsize = (uint32_t)-1;
|
||||
r.in.total = &total;
|
||||
r.in.info = &e;
|
||||
|
||||
e.level = r.in.level;
|
||||
e.e.info1 = &e1;
|
||||
e.e.info1->count = 0;
|
||||
e.e.info1->s = &s;
|
||||
s.path = NULL;
|
||||
|
||||
status = dcerpc_dfs_Enum(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status, "Enum failed - %s\n",
|
||||
nt_errstr(status));
|
||||
torture_assert(tctx, W_ERROR_IS_OK(r.out.result) ||
|
||||
W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, r.out.result),
|
||||
"dfs_Enum failed - %s", win_errstr(r.out.result));
|
||||
|
||||
if (level == 1 && r.out.total) {
|
||||
int i;
|
||||
for (i=0;i<*r.out.total;i++) {
|
||||
const char *root = r.out.info->e.info1->s[i].path;
|
||||
if (!test_GetInfo(tctx, p, root)) {
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static bool test_Enum(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
BOOL ret = True;
|
||||
uint16_t levels[] = {1, 2, 3, 4, 200, 300};
|
||||
int i;
|
||||
|
||||
for (i=0;i<ARRAY_SIZE(levels);i++) {
|
||||
if (!test_EnumLevel(tctx, p, levels[i])) {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL test_EnumEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *host)
|
||||
{
|
||||
BOOL ret = True;
|
||||
uint16_t levels[] = {1, 2, 3, 4, 200, 300};
|
||||
int i;
|
||||
|
||||
for (i=0;i<ARRAY_SIZE(levels);i++) {
|
||||
if (!test_EnumLevelEx(p, mem_ctx, levels[i], host)) {
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL test_RemoveStdRoot(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *host, const char *sharename)
|
||||
{
|
||||
struct dfs_RemoveStdRoot r;
|
||||
NTSTATUS status;
|
||||
|
||||
printf("Testing RemoveStdRoot\n");
|
||||
|
||||
r.in.servername = host;
|
||||
r.in.rootshare = sharename;
|
||||
r.in.flags = 0;
|
||||
|
||||
status = dcerpc_dfs_RemoveStdRoot(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("RemoveStdRoot failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("dfs_RemoveStdRoot failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_AddStdRoot(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *host, const char *sharename)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dfs_AddStdRoot r;
|
||||
|
||||
printf("Testing AddStdRoot\n");
|
||||
|
||||
r.in.servername = host;
|
||||
r.in.rootshare = sharename;
|
||||
r.in.comment = "standard dfs standalone DFS root created by smbtorture (dfs_AddStdRoot)";
|
||||
r.in.flags = 0;
|
||||
|
||||
status = dcerpc_dfs_AddStdRoot(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("AddStdRoot failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("dfs_AddStdRoot failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_AddStdRootForced(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *host, const char *sharename)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dfs_AddStdRootForced r;
|
||||
enum dfs_ManagerVersion version;
|
||||
|
||||
printf("Testing AddStdRootForced\n");
|
||||
|
||||
if (!test_GetManagerVersion(p, mem_ctx, &version)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
r.in.servername = host;
|
||||
r.in.rootshare = sharename;
|
||||
r.in.comment = "standard dfs forced standalone DFS root created by smbtorture (dfs_AddStdRootForced)";
|
||||
r.in.store = SMBTORTURE_DFS_PATHNAME;
|
||||
|
||||
status = dcerpc_dfs_AddStdRootForced(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("AddStdRootForced failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("dfs_AddStdRootForced failed - %s\n", win_errstr(r.out.result));
|
||||
IS_DFS_VERSION_UNSUPPORTED_CALL_W2K3(version, r.out.result);
|
||||
return False;
|
||||
}
|
||||
|
||||
return test_RemoveStdRoot(p, mem_ctx, host, sharename);
|
||||
}
|
||||
|
||||
static void test_cleanup_stdroot(struct dcerpc_pipe *p,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *host,
|
||||
const char *sharename,
|
||||
const char *dir)
|
||||
{
|
||||
struct smbcli_state *cli;
|
||||
|
||||
printf("Cleaning up StdRoot\n");
|
||||
|
||||
test_RemoveStdRoot(p, mem_ctx, host, sharename);
|
||||
test_NetShareDel(mem_ctx, host, sharename);
|
||||
torture_open_connection_share(mem_ctx, &cli, host, "C$", NULL);
|
||||
test_DeleteDir(cli, dir);
|
||||
torture_close_connection(cli);
|
||||
}
|
||||
|
||||
static BOOL test_StdRoot(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *host)
|
||||
{
|
||||
const char *sharename = SMBTORTURE_DFS_SHARENAME;
|
||||
const char *dir = SMBTORTURE_DFS_DIRNAME;
|
||||
const char *path = SMBTORTURE_DFS_PATHNAME;
|
||||
struct smbcli_state *cli;
|
||||
BOOL ret;
|
||||
|
||||
printf("Testing StdRoot\n");
|
||||
|
||||
test_cleanup_stdroot(p, mem_ctx, host, sharename, dir);
|
||||
|
||||
ret &= test_CreateDir(mem_ctx, &cli, host, "C$", dir);
|
||||
ret &= test_NetShareAdd(mem_ctx, host, sharename, path);
|
||||
ret &= test_AddStdRoot(p, mem_ctx, host, sharename);
|
||||
ret &= test_RemoveStdRoot(p, mem_ctx, host, sharename);
|
||||
ret &= test_AddStdRootForced(p, mem_ctx, host, sharename);
|
||||
ret &= test_NetShareDel(mem_ctx, host, sharename);
|
||||
ret &= test_DeleteDir(cli, dir);
|
||||
|
||||
torture_close_connection(cli);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct torture_suite *torture_rpc_dfs(void)
|
||||
{
|
||||
struct torture_suite *suite = torture_suite_create(
|
||||
talloc_autofree_context(), "RPC-DFS");
|
||||
|
||||
#if 0
|
||||
struct torture_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
|
||||
"dfs", &dcerpc_table_netdfs);
|
||||
|
||||
torture_rpc_tcase_add_test(tcase, "GetManagerVersion",
|
||||
test_GetManagerVersion);
|
||||
|
||||
#if 0
|
||||
torture_rpc_tcase_add_test(tcase, "Add",
|
||||
test_Add);
|
||||
#endif
|
||||
|
||||
torture_rpc_tcase_add_test(tcase, "Enum", test_Enum);
|
||||
torture_rpc_tcase_add_test(tcase, "EnumEx", test_EnumEx);
|
||||
torture_rpc_tcase_add_test(tcase, "ManagerInitialize",
|
||||
test_ManagerInitialize);
|
||||
torture_rpc_tcase_add_test(tcase, "StdRoot",
|
||||
test_StdRoot);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
#endif
|
||||
|
||||
return suite;
|
||||
}
|
||||
@@ -0,0 +1,709 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
DRSUapi tests
|
||||
|
||||
Copyright (C) Andrew Tridgell 2003
|
||||
Copyright (C) Stefan (metze) Metzmacher 2004
|
||||
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_drsuapi_c.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
#define TEST_MACHINE_NAME "torturetest"
|
||||
|
||||
BOOL test_DsBind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct DsPrivate *priv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct drsuapi_DsBind r;
|
||||
BOOL ret = True;
|
||||
|
||||
GUID_from_string(DRSUAPI_DS_BIND_GUID, &priv->bind_guid);
|
||||
|
||||
r.in.bind_guid = &priv->bind_guid;
|
||||
r.in.bind_info = NULL;
|
||||
r.out.bind_handle = &priv->bind_handle;
|
||||
|
||||
printf("testing DsBind\n");
|
||||
|
||||
status = dcerpc_drsuapi_DsBind(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsBind failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsBind failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL test_DsGetDCInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct DsPrivate *priv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct drsuapi_DsGetDomainControllerInfo r;
|
||||
BOOL ret = True;
|
||||
|
||||
if (lp_parm_bool(-1, "torture", "samba4", False)) {
|
||||
printf("skipping DsGetDCInfo test against Samba4\n");
|
||||
return True;
|
||||
}
|
||||
|
||||
r.in.bind_handle = &priv->bind_handle;
|
||||
r.in.level = 1;
|
||||
|
||||
r.in.req.req1.domain_name = talloc_strdup(mem_ctx, lp_realm());
|
||||
r.in.req.req1.level = 1;
|
||||
|
||||
printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
|
||||
r.in.req.req1.level, r.in.req.req1.domain_name);
|
||||
|
||||
status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
|
||||
" with dns domain failed - %s\n",
|
||||
r.in.req.req1.level, errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsGetDomainControllerInfo level %d\n"
|
||||
" with dns domain failed - %s\n",
|
||||
r.in.req.req1.level, win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
r.in.req.req1.level = 2;
|
||||
|
||||
printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
|
||||
r.in.req.req1.level, r.in.req.req1.domain_name);
|
||||
|
||||
status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
|
||||
" with dns domain failed - %s\n",
|
||||
r.in.req.req1.level, errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsGetDomainControllerInfo level %d\n"
|
||||
" with dns domain failed - %s\n",
|
||||
r.in.req.req1.level, win_errstr(r.out.result));
|
||||
ret = False;
|
||||
} else {
|
||||
if (r.out.ctr.ctr2.count > 0) {
|
||||
priv->dcinfo = r.out.ctr.ctr2.array[0];
|
||||
}
|
||||
}
|
||||
|
||||
r.in.req.req1.level = -1;
|
||||
|
||||
printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
|
||||
r.in.req.req1.level, r.in.req.req1.domain_name);
|
||||
|
||||
status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
|
||||
" with dns domain failed - %s\n",
|
||||
r.in.req.req1.level, errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsGetDomainControllerInfo level %d\n"
|
||||
" with dns domain failed - %s\n",
|
||||
r.in.req.req1.level, win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
r.in.req.req1.domain_name = talloc_strdup(mem_ctx, lp_workgroup());
|
||||
r.in.req.req1.level = 2;
|
||||
|
||||
printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
|
||||
r.in.req.req1.level, r.in.req.req1.domain_name);
|
||||
|
||||
status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
|
||||
" with netbios domain failed - %s\n",
|
||||
r.in.req.req1.level, errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsGetDomainControllerInfo level %d\n"
|
||||
" with netbios domain failed - %s\n",
|
||||
r.in.req.req1.level, win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
r.in.req.req1.domain_name = "__UNKNOWN_DOMAIN__";
|
||||
r.in.req.req1.level = 2;
|
||||
|
||||
printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
|
||||
r.in.req.req1.level, r.in.req.req1.domain_name);
|
||||
|
||||
status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
|
||||
" with invalid domain failed - %s\n",
|
||||
r.in.req.req1.level, errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_EQUAL(r.out.result, WERR_DS_OBJ_NOT_FOUND)) {
|
||||
printf("DsGetDomainControllerInfo level %d\n"
|
||||
" with invalid domain not expected error (WERR_DS_OBJ_NOT_FOUND) - %s\n",
|
||||
r.in.req.req1.level, win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL test_DsWriteAccountSpn(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct DsPrivate *priv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct drsuapi_DsWriteAccountSpn r;
|
||||
struct drsuapi_DsNameString names[2];
|
||||
BOOL ret = True;
|
||||
|
||||
r.in.bind_handle = &priv->bind_handle;
|
||||
r.in.level = 1;
|
||||
|
||||
printf("testing DsWriteAccountSpn\n");
|
||||
|
||||
r.in.req.req1.operation = DRSUAPI_DS_SPN_OPERATION_ADD;
|
||||
r.in.req.req1.unknown1 = 0;
|
||||
r.in.req.req1.object_dn = priv->dcinfo.computer_dn;
|
||||
r.in.req.req1.count = 2;
|
||||
r.in.req.req1.spn_names = names;
|
||||
names[0].str = talloc_asprintf(mem_ctx, "smbtortureSPN/%s",priv->dcinfo.netbios_name);
|
||||
names[1].str = talloc_asprintf(mem_ctx, "smbtortureSPN/%s",priv->dcinfo.dns_name);
|
||||
|
||||
status = dcerpc_drsuapi_DsWriteAccountSpn(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
r.in.req.req1.operation = DRSUAPI_DS_SPN_OPERATION_DELETE;
|
||||
r.in.req.req1.unknown1 = 0;
|
||||
|
||||
status = dcerpc_drsuapi_DsWriteAccountSpn(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL test_DsReplicaGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct DsPrivate *priv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct drsuapi_DsReplicaGetInfo r;
|
||||
BOOL ret = True;
|
||||
int i;
|
||||
struct {
|
||||
int32_t level;
|
||||
int32_t infotype;
|
||||
const char *obj_dn;
|
||||
} array[] = {
|
||||
{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO,
|
||||
DRSUAPI_DS_REPLICA_INFO_NEIGHBORS,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO,
|
||||
DRSUAPI_DS_REPLICA_INFO_CURSORS,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO,
|
||||
DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO,
|
||||
DRSUAPI_DS_REPLICA_INFO_KCC_DSA_CONNECT_FAILURES,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO,
|
||||
DRSUAPI_DS_REPLICA_INFO_KCC_DSA_LINK_FAILURES,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO,
|
||||
DRSUAPI_DS_REPLICA_INFO_PENDING_OPS,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO2,
|
||||
DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO2,
|
||||
DRSUAPI_DS_REPLICA_INFO_CURSORS2,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO2,
|
||||
DRSUAPI_DS_REPLICA_INFO_CURSORS3,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO2,
|
||||
DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA2,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO2,
|
||||
DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA2,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO2,
|
||||
DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO2,
|
||||
DRSUAPI_DS_REPLICA_INFO_CONNECTIONS04,
|
||||
"__IGNORED__"
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO2,
|
||||
DRSUAPI_DS_REPLICA_INFO_CURSURS05,
|
||||
NULL
|
||||
},{
|
||||
DRSUAPI_DS_REPLICA_GET_INFO2,
|
||||
DRSUAPI_DS_REPLICA_INFO_06,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
if (lp_parm_bool(-1, "torture", "samba4", False)) {
|
||||
printf("skipping DsGetDCInfo test against Samba4\n");
|
||||
return True;
|
||||
}
|
||||
|
||||
r.in.bind_handle = &priv->bind_handle;
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(array); i++) {
|
||||
const char *object_dn;
|
||||
|
||||
printf("testing DsReplicaGetInfo level %d infotype %d\n",
|
||||
array[i].level, array[i].infotype);
|
||||
|
||||
object_dn = (array[i].obj_dn ? array[i].obj_dn : priv->domain_obj_dn);
|
||||
|
||||
r.in.level = array[i].level;
|
||||
switch(r.in.level) {
|
||||
case DRSUAPI_DS_REPLICA_GET_INFO:
|
||||
r.in.req.req1.info_type = array[i].infotype;
|
||||
r.in.req.req1.object_dn = object_dn;
|
||||
ZERO_STRUCT(r.in.req.req1.guid1);
|
||||
break;
|
||||
case DRSUAPI_DS_REPLICA_GET_INFO2:
|
||||
r.in.req.req2.info_type = array[i].infotype;
|
||||
r.in.req.req2.object_dn = object_dn;
|
||||
ZERO_STRUCT(r.in.req.req1.guid1);
|
||||
r.in.req.req2.unknown1 = 0;
|
||||
r.in.req.req2.string1 = NULL;
|
||||
r.in.req.req2.string2 = NULL;
|
||||
r.in.req.req2.unknown2 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
status = dcerpc_drsuapi_DsReplicaGetInfo(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
if (p->last_fault_code != DCERPC_FAULT_INVALID_TAG) {
|
||||
printf("dcerpc_drsuapi_DsReplicaGetInfo failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else {
|
||||
printf("DsReplicaGetInfo level %d and/or infotype %d not supported by server\n",
|
||||
array[i].level, array[i].infotype);
|
||||
}
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsReplicaGetInfo failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL test_DsReplicaSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct DsPrivate *priv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
BOOL ret = True;
|
||||
int i;
|
||||
struct drsuapi_DsReplicaSync r;
|
||||
struct drsuapi_DsReplicaObjectIdentifier nc;
|
||||
struct GUID null_guid;
|
||||
struct dom_sid null_sid;
|
||||
struct {
|
||||
int32_t level;
|
||||
} array[] = {
|
||||
{
|
||||
1
|
||||
}
|
||||
};
|
||||
|
||||
if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
|
||||
printf("DsReplicaSync disabled - enable dangerous tests to use\n");
|
||||
return True;
|
||||
}
|
||||
|
||||
if (lp_parm_bool(-1, "torture", "samba4", False)) {
|
||||
printf("skipping DsReplicaSync test against Samba4\n");
|
||||
return True;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(null_guid);
|
||||
ZERO_STRUCT(null_sid);
|
||||
|
||||
r.in.bind_handle = &priv->bind_handle;
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(array); i++) {
|
||||
printf("testing DsReplicaSync level %d\n",
|
||||
array[i].level);
|
||||
|
||||
r.in.level = array[i].level;
|
||||
switch(r.in.level) {
|
||||
case 1:
|
||||
nc.guid = null_guid;
|
||||
nc.sid = null_sid;
|
||||
nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
|
||||
|
||||
r.in.req.req1.naming_context = &nc;
|
||||
r.in.req.req1.guid1 = priv->dcinfo.ntds_guid;
|
||||
r.in.req.req1.string1 = NULL;
|
||||
r.in.req.req1.options = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
status = dcerpc_drsuapi_DsReplicaSync(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsReplicaSync failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsReplicaSync failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL test_DsReplicaUpdateRefs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct DsPrivate *priv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
BOOL ret = True;
|
||||
int i;
|
||||
struct drsuapi_DsReplicaUpdateRefs r;
|
||||
struct drsuapi_DsReplicaObjectIdentifier nc;
|
||||
struct GUID null_guid;
|
||||
struct dom_sid null_sid;
|
||||
struct {
|
||||
int32_t level;
|
||||
} array[] = {
|
||||
{
|
||||
1
|
||||
}
|
||||
};
|
||||
|
||||
if (lp_parm_bool(-1, "torture", "samba4", False)) {
|
||||
printf("skipping DsReplicaUpdateRefs test against Samba4\n");
|
||||
return True;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(null_guid);
|
||||
ZERO_STRUCT(null_sid);
|
||||
|
||||
r.in.bind_handle = &priv->bind_handle;
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(array); i++) {
|
||||
printf("testing DsReplicaUpdateRefs level %d\n",
|
||||
array[i].level);
|
||||
|
||||
r.in.level = array[i].level;
|
||||
switch(r.in.level) {
|
||||
case 1:
|
||||
nc.guid = null_guid;
|
||||
nc.sid = null_sid;
|
||||
nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
|
||||
|
||||
r.in.req.req1.naming_context = &nc;
|
||||
r.in.req.req1.dest_dsa_dns_name = talloc_asprintf(mem_ctx, "__some_dest_dsa_guid_string._msdn.%s",
|
||||
priv->domain_dns_name);
|
||||
r.in.req.req1.dest_dsa_guid = null_guid;
|
||||
r.in.req.req1.options = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
status = dcerpc_drsuapi_DsReplicaUpdateRefs(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsReplicaUpdateRefs failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsReplicaUpdateRefs failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL test_DsGetNCChanges(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct DsPrivate *priv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
BOOL ret = True;
|
||||
int i;
|
||||
struct drsuapi_DsGetNCChanges r;
|
||||
struct drsuapi_DsReplicaObjectIdentifier nc;
|
||||
struct GUID null_guid;
|
||||
struct dom_sid null_sid;
|
||||
struct {
|
||||
int32_t level;
|
||||
} array[] = {
|
||||
{
|
||||
5
|
||||
},
|
||||
{
|
||||
8
|
||||
}
|
||||
};
|
||||
|
||||
if (lp_parm_bool(-1, "torture", "samba4", False)) {
|
||||
printf("skipping DsGetNCChanges test against Samba4\n");
|
||||
return True;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(null_guid);
|
||||
ZERO_STRUCT(null_sid);
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(array); i++) {
|
||||
printf("testing DsGetNCChanges level %d\n",
|
||||
array[i].level);
|
||||
|
||||
r.in.bind_handle = &priv->bind_handle;
|
||||
r.in.level = array[i].level;
|
||||
|
||||
switch (r.in.level) {
|
||||
case 5:
|
||||
nc.guid = null_guid;
|
||||
nc.sid = null_sid;
|
||||
nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
|
||||
|
||||
r.in.req.req5.destination_dsa_guid = GUID_random();
|
||||
r.in.req.req5.source_dsa_invocation_id = null_guid;
|
||||
r.in.req.req5.naming_context = &nc;
|
||||
r.in.req.req5.highwatermark.tmp_highest_usn = 0;
|
||||
r.in.req.req5.highwatermark.reserved_usn = 0;
|
||||
r.in.req.req5.highwatermark.highest_usn = 0;
|
||||
r.in.req.req5.uptodateness_vector = NULL;
|
||||
r.in.req.req5.replica_flags = 0;
|
||||
if (lp_parm_bool(-1, "drsuapi","compression", False)) {
|
||||
r.in.req.req5.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
|
||||
}
|
||||
r.in.req.req5.max_object_count = 0;
|
||||
r.in.req.req5.max_ndr_size = 0;
|
||||
r.in.req.req5.unknown4 = 0;
|
||||
r.in.req.req5.h1 = 0;
|
||||
|
||||
break;
|
||||
case 8:
|
||||
nc.guid = null_guid;
|
||||
nc.sid = null_sid;
|
||||
nc.dn = priv->domain_obj_dn?priv->domain_obj_dn:"";
|
||||
|
||||
r.in.req.req8.destination_dsa_guid = GUID_random();
|
||||
r.in.req.req8.source_dsa_invocation_id = null_guid;
|
||||
r.in.req.req8.naming_context = &nc;
|
||||
r.in.req.req8.highwatermark.tmp_highest_usn = 0;
|
||||
r.in.req.req8.highwatermark.reserved_usn = 0;
|
||||
r.in.req.req8.highwatermark.highest_usn = 0;
|
||||
r.in.req.req8.uptodateness_vector = NULL;
|
||||
r.in.req.req8.replica_flags = 0;
|
||||
if (lp_parm_bool(-1,"drsuapi","compression",False)) {
|
||||
r.in.req.req8.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
|
||||
}
|
||||
if (lp_parm_bool(-1,"drsuapi","neighbour_writeable",True)) {
|
||||
r.in.req.req8.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE;
|
||||
}
|
||||
r.in.req.req8.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
|
||||
| DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
|
||||
| DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS
|
||||
| DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
|
||||
;
|
||||
r.in.req.req8.max_object_count = 402;
|
||||
r.in.req.req8.max_ndr_size = 402116;
|
||||
r.in.req.req8.unknown4 = 0;
|
||||
r.in.req.req8.h1 = 0;
|
||||
r.in.req.req8.unique_ptr1 = 0;
|
||||
r.in.req.req8.unique_ptr2 = 0;
|
||||
r.in.req.req8.ctr12.count = 0;
|
||||
r.in.req.req8.ctr12.array = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
status = dcerpc_drsuapi_DsGetNCChanges(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsGetNCChanges failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsGetNCChanges failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL test_DsUnbind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct DsPrivate *priv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct drsuapi_DsUnbind r;
|
||||
BOOL ret = True;
|
||||
|
||||
r.in.bind_handle = &priv->bind_handle;
|
||||
r.out.bind_handle = &priv->bind_handle;
|
||||
|
||||
printf("testing DsUnbind\n");
|
||||
|
||||
status = dcerpc_drsuapi_DsUnbind(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsUnbind failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsBind failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL torture_rpc_drsuapi(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
struct DsPrivate priv;
|
||||
struct cli_credentials *machine_credentials;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_drsuapi");
|
||||
|
||||
printf("Connected to DRAUAPI pipe\n");
|
||||
|
||||
ZERO_STRUCT(priv);
|
||||
|
||||
priv.join = torture_join_domain(TEST_MACHINE_NAME, ACB_SVRTRUST,
|
||||
&machine_credentials);
|
||||
if (!priv.join) {
|
||||
talloc_free(mem_ctx);
|
||||
printf("Failed to join as BDC\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
status = torture_rpc_connection(mem_ctx,
|
||||
&p,
|
||||
&dcerpc_table_drsuapi);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
torture_leave_domain(priv.join);
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
ret &= test_DsBind(p, mem_ctx, &priv);
|
||||
|
||||
ret &= test_DsGetDCInfo(p, mem_ctx, &priv);
|
||||
|
||||
ret &= test_DsCrackNames(p, mem_ctx, &priv, TEST_MACHINE_NAME);
|
||||
|
||||
ret &= test_DsWriteAccountSpn(p, mem_ctx, &priv);
|
||||
|
||||
ret &= test_DsReplicaGetInfo(p, mem_ctx, &priv);
|
||||
|
||||
ret &= test_DsReplicaSync(p, mem_ctx, &priv);
|
||||
|
||||
ret &= test_DsReplicaUpdateRefs(p, mem_ctx, &priv);
|
||||
|
||||
ret &= test_DsGetNCChanges(p, mem_ctx, &priv);
|
||||
|
||||
ret &= test_DsUnbind(p, mem_ctx, &priv);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
torture_leave_domain(priv.join);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
DRSUapi tests
|
||||
|
||||
Copyright (C) Andrew Tridgell 2003
|
||||
Copyright (C) Stefan (metze) Metzmacher 2004
|
||||
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
|
||||
|
||||
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 "librpc/gen_ndr/drsuapi.h"
|
||||
|
||||
struct DsPrivate {
|
||||
struct policy_handle bind_handle;
|
||||
struct GUID bind_guid;
|
||||
const char *domain_obj_dn;
|
||||
const char *domain_guid_str;
|
||||
const char *domain_dns_name;
|
||||
struct GUID domain_guid;
|
||||
struct drsuapi_DsGetDCInfo2 dcinfo;
|
||||
struct test_join *join;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,831 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
DRSUapi tests
|
||||
|
||||
Copyright (C) Andrew Tridgell 2003
|
||||
Copyright (C) Stefan (metze) Metzmacher 2004
|
||||
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_drsuapi_c.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
#include "ldb/include/ldb.h"
|
||||
#include "libcli/security/security.h"
|
||||
|
||||
static BOOL test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct DsPrivate *priv, const char *dn,
|
||||
const char *user_principal_name, const char *service_principal_name)
|
||||
{
|
||||
|
||||
|
||||
NTSTATUS status;
|
||||
BOOL ret = True;
|
||||
struct drsuapi_DsCrackNames r;
|
||||
enum drsuapi_DsNameFormat formats[] = {
|
||||
DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
|
||||
DRSUAPI_DS_NAME_FORMAT_DISPLAY,
|
||||
DRSUAPI_DS_NAME_FORMAT_GUID,
|
||||
DRSUAPI_DS_NAME_FORMAT_CANONICAL,
|
||||
DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
|
||||
DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
|
||||
DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
|
||||
DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN
|
||||
};
|
||||
struct drsuapi_DsNameString names[ARRAY_SIZE(formats)];
|
||||
int i, j;
|
||||
|
||||
const char *n_matrix[ARRAY_SIZE(formats)][ARRAY_SIZE(formats)];
|
||||
const char *n_from[ARRAY_SIZE(formats)];
|
||||
|
||||
ZERO_STRUCT(r);
|
||||
r.in.bind_handle = &priv->bind_handle;
|
||||
r.in.level = 1;
|
||||
r.in.req.req1.unknown1 = 0x000004e4;
|
||||
r.in.req.req1.unknown2 = 0x00000407;
|
||||
r.in.req.req1.count = 1;
|
||||
r.in.req.req1.names = names;
|
||||
r.in.req.req1.format_flags = DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
|
||||
|
||||
n_matrix[0][0] = dn;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(formats); i++) {
|
||||
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
|
||||
r.in.req.req1.format_desired = formats[i];
|
||||
names[0].str = dn;
|
||||
printf("testing DsCrackNames (matrix prep) with name '%s' from format: %d desired format:%d ",
|
||||
names[0].str, r.in.req.req1.format_offered, r.in.req.req1.format_desired);
|
||||
|
||||
status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
switch (formats[i]) {
|
||||
case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL:
|
||||
if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE) {
|
||||
printf(__location__ ": Unexpected error (%d): This name lookup should fail\n",
|
||||
r.out.ctr.ctr1->array[0].status);
|
||||
return False;
|
||||
}
|
||||
printf ("(expected) error\n");
|
||||
break;
|
||||
case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL:
|
||||
if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_NO_MAPPING) {
|
||||
printf(__location__ ": Unexpected error (%d): This name lookup should fail\n",
|
||||
r.out.ctr.ctr1->array[0].status);
|
||||
return False;
|
||||
}
|
||||
printf ("(expected) error\n");
|
||||
break;
|
||||
case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN:
|
||||
case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY:
|
||||
if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR) {
|
||||
printf(__location__ ": Unexpected error (%d): This name lookup should fail\n",
|
||||
r.out.ctr.ctr1->array[0].status);
|
||||
return False;
|
||||
}
|
||||
printf ("(expected) error\n");
|
||||
break;
|
||||
default:
|
||||
if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
|
||||
printf("Error: %d\n", r.out.ctr.ctr1->array[0].status);
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
switch (formats[i]) {
|
||||
case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL:
|
||||
n_from[i] = user_principal_name;
|
||||
break;
|
||||
case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL:
|
||||
n_from[i] = service_principal_name;
|
||||
break;
|
||||
case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY:
|
||||
case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN:
|
||||
n_from[i] = NULL;
|
||||
break;
|
||||
default:
|
||||
n_from[i] = r.out.ctr.ctr1->array[0].result_name;
|
||||
printf("%s\n", n_from[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(formats); i++) {
|
||||
for (j = 0; j < ARRAY_SIZE(formats); j++) {
|
||||
r.in.req.req1.format_offered = formats[i];
|
||||
r.in.req.req1.format_desired = formats[j];
|
||||
if (!n_from[i]) {
|
||||
n_matrix[i][j] = NULL;
|
||||
continue;
|
||||
}
|
||||
names[0].str = n_from[i];
|
||||
status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("testing DsCrackNames (matrix) with name '%s' from format: %d desired format:%d failed - %s",
|
||||
names[0].str, r.in.req.req1.format_offered, r.in.req.req1.format_desired, errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("testing DsCrackNames (matrix) with name '%s' from format: %d desired format:%d failed - %s",
|
||||
names[0].str, r.in.req.req1.format_offered, r.in.req.req1.format_desired,
|
||||
win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
if (r.out.ctr.ctr1->array[0].status == DRSUAPI_DS_NAME_STATUS_OK) {
|
||||
n_matrix[i][j] = r.out.ctr.ctr1->array[0].result_name;
|
||||
} else {
|
||||
n_matrix[i][j] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(formats); i++) {
|
||||
for (j = 0; j < ARRAY_SIZE(formats); j++) {
|
||||
if (n_matrix[i][j] == n_from[j]) {
|
||||
|
||||
/* We don't have a from name for these yet (and we can't map to them to find it out) */
|
||||
} else if (n_matrix[i][j] == NULL && n_from[i] == NULL) {
|
||||
|
||||
/* we can't map to these two */
|
||||
} else if (n_matrix[i][j] == NULL && formats[j] == DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL) {
|
||||
} else if (n_matrix[i][j] == NULL && formats[j] == DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL) {
|
||||
} else if (n_matrix[i][j] == NULL && n_from[j] != NULL) {
|
||||
printf("dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s\n", formats[i], formats[j], n_matrix[i][j], n_from[j]);
|
||||
ret = False;
|
||||
} else if (n_matrix[i][j] != NULL && n_from[j] == NULL) {
|
||||
printf("dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s\n", formats[i], formats[j], n_matrix[i][j], n_from[j]);
|
||||
ret = False;
|
||||
} else if (strcmp(n_matrix[i][j], n_from[j]) != 0) {
|
||||
printf("dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s\n", formats[i], formats[j], n_matrix[i][j], n_from[j]);
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct DsPrivate *priv, const char *test_dc)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct drsuapi_DsCrackNames r;
|
||||
struct drsuapi_DsNameString names[1];
|
||||
BOOL ret = True;
|
||||
const char *dns_domain;
|
||||
const char *nt4_domain;
|
||||
const char *FQDN_1779_name;
|
||||
struct ldb_context *ldb;
|
||||
struct ldb_dn *FQDN_1779_dn;
|
||||
struct ldb_dn *realm_dn;
|
||||
const char *realm_dn_str;
|
||||
const char *realm_canonical;
|
||||
const char *realm_canonical_ex;
|
||||
const char *user_principal_name;
|
||||
char *user_principal_name_short;
|
||||
const char *service_principal_name;
|
||||
const char *canonical_name;
|
||||
const char *canonical_ex_name;
|
||||
const char *dc_sid;
|
||||
|
||||
ZERO_STRUCT(r);
|
||||
r.in.bind_handle = &priv->bind_handle;
|
||||
r.in.level = 1;
|
||||
r.in.req.req1.unknown1 = 0x000004e4;
|
||||
r.in.req.req1.unknown2 = 0x00000407;
|
||||
r.in.req.req1.count = 1;
|
||||
r.in.req.req1.names = names;
|
||||
r.in.req.req1.format_flags = DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
|
||||
|
||||
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
|
||||
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
|
||||
|
||||
dc_sid = dom_sid_string(mem_ctx, torture_join_sid(priv->join));
|
||||
|
||||
names[0].str = dc_sid;
|
||||
|
||||
printf("testing DsCrackNames with name '%s' desired format:%d\n",
|
||||
names[0].str, r.in.req.req1.format_desired);
|
||||
|
||||
status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
} else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
|
||||
printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
dns_domain = r.out.ctr.ctr1->array[0].dns_domain_name;
|
||||
nt4_domain = r.out.ctr.ctr1->array[0].result_name;
|
||||
|
||||
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_GUID;
|
||||
|
||||
printf("testing DsCrackNames with name '%s' desired format:%d\n",
|
||||
names[0].str, r.in.req.req1.format_desired);
|
||||
|
||||
status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
} else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
|
||||
printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->domain_dns_name = r.out.ctr.ctr1->array[0].dns_domain_name;
|
||||
priv->domain_guid_str = r.out.ctr.ctr1->array[0].result_name;
|
||||
GUID_from_string(priv->domain_guid_str, &priv->domain_guid);
|
||||
|
||||
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
|
||||
|
||||
printf("testing DsCrackNames with name '%s' desired format:%d\n",
|
||||
names[0].str, r.in.req.req1.format_desired);
|
||||
|
||||
status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
} else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
|
||||
printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ldb = ldb_init(mem_ctx);
|
||||
|
||||
realm_dn_str = r.out.ctr.ctr1->array[0].result_name;
|
||||
realm_dn = ldb_dn_new(mem_ctx, ldb, realm_dn_str);
|
||||
realm_canonical = ldb_dn_canonical_string(mem_ctx, realm_dn);
|
||||
|
||||
if (strcmp(realm_canonical,
|
||||
talloc_asprintf(mem_ctx, "%s/", dns_domain))!= 0) {
|
||||
printf("local Round trip on canonical name failed: %s != %s!\n",
|
||||
realm_canonical,
|
||||
talloc_asprintf(mem_ctx, "%s/", dns_domain));
|
||||
return False;
|
||||
};
|
||||
|
||||
realm_canonical_ex = ldb_dn_canonical_ex_string(mem_ctx, realm_dn);
|
||||
|
||||
if (strcmp(realm_canonical_ex,
|
||||
talloc_asprintf(mem_ctx, "%s\n", dns_domain))!= 0) {
|
||||
printf("local Round trip on canonical ex name failed: %s != %s!\n",
|
||||
realm_canonical,
|
||||
talloc_asprintf(mem_ctx, "%s\n", dns_domain));
|
||||
return False;
|
||||
};
|
||||
|
||||
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
|
||||
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
|
||||
names[0].str = nt4_domain;
|
||||
|
||||
printf("testing DsCrackNames with name '%s' desired format:%d\n",
|
||||
names[0].str, r.in.req.req1.format_desired);
|
||||
|
||||
status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
} else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
|
||||
printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->domain_obj_dn = r.out.ctr.ctr1->array[0].result_name;
|
||||
|
||||
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
|
||||
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
|
||||
names[0].str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, test_dc);
|
||||
|
||||
printf("testing DsCrackNames with name '%s' desired format:%d\n",
|
||||
names[0].str, r.in.req.req1.format_desired);
|
||||
|
||||
status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
} else if (r.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
|
||||
printf("DsCrackNames failed on name - %d\n", r.out.ctr.ctr1->array[0].status);
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
FQDN_1779_name = r.out.ctr.ctr1->array[0].result_name;
|
||||
|
||||
FQDN_1779_dn = ldb_dn_new(mem_ctx, ldb, FQDN_1779_name);
|
||||
|
||||
canonical_name = ldb_dn_canonical_string(mem_ctx, FQDN_1779_dn);
|
||||
canonical_ex_name = ldb_dn_canonical_ex_string(mem_ctx, FQDN_1779_dn);
|
||||
|
||||
user_principal_name = talloc_asprintf(mem_ctx, "%s$@%s", test_dc, dns_domain);
|
||||
|
||||
/* form up a user@DOMAIN */
|
||||
user_principal_name_short = talloc_asprintf(mem_ctx, "%s$@%s", test_dc, nt4_domain);
|
||||
/* variable nt4_domain includs a trailing \ */
|
||||
user_principal_name_short[strlen(user_principal_name_short) - 1] = '\0';
|
||||
|
||||
service_principal_name = talloc_asprintf(mem_ctx, "HOST/%s", test_dc);
|
||||
{
|
||||
|
||||
struct {
|
||||
enum drsuapi_DsNameFormat format_offered;
|
||||
enum drsuapi_DsNameFormat format_desired;
|
||||
const char *comment;
|
||||
const char *str;
|
||||
const char *expected_str;
|
||||
enum drsuapi_DsNameStatus status;
|
||||
enum drsuapi_DsNameFlags flags;
|
||||
} crack[] = {
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = user_principal_name,
|
||||
.expected_str = FQDN_1779_name,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = user_principal_name_short,
|
||||
.expected_str = FQDN_1779_name,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = service_principal_name,
|
||||
.expected_str = FQDN_1779_name,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = talloc_asprintf(mem_ctx, "cifs/%s.%s", test_dc, dns_domain),
|
||||
.comment = "ServicePrincipal Name",
|
||||
.expected_str = FQDN_1779_name,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL,
|
||||
.str = FQDN_1779_name,
|
||||
.expected_str = canonical_name,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
|
||||
.str = FQDN_1779_name,
|
||||
.expected_str = canonical_ex_name,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL,
|
||||
.str = FQDN_1779_name,
|
||||
.comment = "DN to cannoical syntactial only",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK,
|
||||
.expected_str = canonical_name,
|
||||
.flags = DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
|
||||
.str = FQDN_1779_name,
|
||||
.comment = "DN to cannoical EX syntactial only",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK,
|
||||
.expected_str = canonical_ex_name,
|
||||
.flags = DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_DISPLAY,
|
||||
.str = FQDN_1779_name,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_GUID,
|
||||
.str = FQDN_1779_name,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
|
||||
.str = priv->domain_guid_str,
|
||||
.comment = "Domain GUID to NT4 ACCOUNT",
|
||||
.expected_str = nt4_domain,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL,
|
||||
.str = priv->domain_guid_str,
|
||||
.comment = "Domain GUID to Canonical",
|
||||
.expected_str = talloc_asprintf(mem_ctx, "%s/", dns_domain),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
|
||||
.str = priv->domain_guid_str,
|
||||
.comment = "Domain GUID to Canonical EX",
|
||||
.expected_str = talloc_asprintf(mem_ctx, "%s\n", dns_domain),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_DISPLAY,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = "CN=Microsoft Corporation,L=Redmond,S=Washington,C=US",
|
||||
.comment = "display name for Microsoft Support Account",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = GUID_string2(mem_ctx, &priv->dcinfo.site_guid),
|
||||
.comment = "Site GUID",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
|
||||
.str = GUID_string2(mem_ctx, &priv->dcinfo.computer_guid),
|
||||
.comment = "Computer GUID",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = GUID_string2(mem_ctx, &priv->dcinfo.server_guid),
|
||||
.comment = "Server GUID",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = GUID_string2(mem_ctx, &priv->dcinfo.ntds_guid),
|
||||
.comment = "NTDS GUID",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = SID_BUILTIN,
|
||||
.comment = "BUILTIN domain SID",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_DISPLAY,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = test_dc,
|
||||
.comment = "DISLPAY NAME search for DC short name",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = talloc_asprintf(mem_ctx, "krbtgt/%s", dns_domain),
|
||||
.comment = "Looking for KRBTGT as a serivce principal",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = talloc_asprintf(mem_ctx, "krbtgt"),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.comment = "Looking for the kadmin/changepw service as a serivce principal",
|
||||
.str = talloc_asprintf(mem_ctx, "kadmin/changepw"),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK,
|
||||
.expected_str = talloc_asprintf(mem_ctx, "CN=krbtgt,CN=Users,%s", realm_dn_str)
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = talloc_asprintf(mem_ctx, "cifs/%s.%s@%s",
|
||||
test_dc, dns_domain,
|
||||
dns_domain),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = talloc_asprintf(mem_ctx, "cifs/%s.%s@%s",
|
||||
test_dc, dns_domain,
|
||||
"BOGUS"),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = talloc_asprintf(mem_ctx, "cifs/%s.%s@%s",
|
||||
test_dc, "REALLY",
|
||||
"BOGUS"),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = talloc_asprintf(mem_ctx, "cifs/%s.%s",
|
||||
test_dc, dns_domain),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = talloc_asprintf(mem_ctx, "cifs/%s",
|
||||
test_dc),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = "NOT A GUID",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = "NOT A SID",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = "NOT AN NT4 NAME",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_GUID,
|
||||
.comment = "Unparsable DN",
|
||||
.str = "NOT A DN",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.comment = "Unparsable user principal",
|
||||
.str = "NOT A PRINCIPAL",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.comment = "Unparsable service principal",
|
||||
.str = "NOT A SERVICE PRINCIPAL",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_GUID,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.comment = "BIND GUID (ie, not in the directory)",
|
||||
.str = GUID_string2(mem_ctx, &priv->bind_guid),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.comment = "Unqualified Machine account as user principal",
|
||||
.str = talloc_asprintf(mem_ctx, "%s$", test_dc),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.comment = "Machine account as service principal",
|
||||
.str = talloc_asprintf(mem_ctx, "%s$", test_dc),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.comment = "Full Machine account as service principal",
|
||||
.str = user_principal_name,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.comment = "Realm as an NT4 domain lookup",
|
||||
.str = talloc_asprintf(mem_ctx, "%s\\", dns_domain),
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
|
||||
.comment = "BUITIN SID -> NT4 account",
|
||||
.str = SID_BUILTIN,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = SID_BUILTIN_ADMINISTRATORS,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
|
||||
.str = SID_BUILTIN_ADMINISTRATORS,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.comment = "DC SID -> DN",
|
||||
.str = dc_sid,
|
||||
.expected_str = FQDN_1779_name,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
|
||||
.comment = "DC SID -> NT4 account",
|
||||
.str = dc_sid,
|
||||
.status = DRSUAPI_DS_NAME_STATUS_OK
|
||||
},
|
||||
{
|
||||
.format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
|
||||
.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
|
||||
.str = "foo@bar",
|
||||
.status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY
|
||||
},
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(crack); i++) {
|
||||
r.in.req.req1.format_flags = crack[i].flags;
|
||||
r.in.req.req1.format_offered = crack[i].format_offered;
|
||||
r.in.req.req1.format_desired = crack[i].format_desired;
|
||||
names[0].str = crack[i].str;
|
||||
|
||||
if (crack[i].comment) {
|
||||
printf("testing DsCrackNames '%s' with name '%s' desired format:%d\n",
|
||||
crack[i].comment, names[0].str, r.in.req.req1.format_desired);
|
||||
} else {
|
||||
printf("testing DsCrackNames with name '%s' desired format:%d\n",
|
||||
names[0].str, r.in.req.req1.format_desired);
|
||||
}
|
||||
status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
} else if (r.out.ctr.ctr1->array[0].status != crack[i].status) {
|
||||
printf("DsCrackNames unexpected status %d, wanted %d on name: %s\n",
|
||||
r.out.ctr.ctr1->array[0].status,
|
||||
crack[i].status,
|
||||
crack[i].str);
|
||||
ret = False;
|
||||
} else if (crack[i].expected_str
|
||||
&& (strcmp(r.out.ctr.ctr1->array[0].result_name,
|
||||
crack[i].expected_str) != 0)) {
|
||||
printf("DsCrackNames failed - got %s, expected %s\n",
|
||||
r.out.ctr.ctr1->array[0].result_name,
|
||||
crack[i].expected_str);
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!test_DsCrackNamesMatrix(p, mem_ctx, priv, FQDN_1779_name,
|
||||
user_principal_name, service_principal_name)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL torture_rpc_drsuapi_cracknames(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
struct DsPrivate priv;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_drsuapi");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx,
|
||||
&p,
|
||||
&dcerpc_table_drsuapi);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
printf("Connected to DRSUAPI pipe\n");
|
||||
|
||||
ZERO_STRUCT(priv);
|
||||
|
||||
ret &= test_DsBind(p, mem_ctx, &priv);
|
||||
|
||||
ret &= test_DsCrackNames(p, mem_ctx, &priv,
|
||||
torture_setting_string(torture, "host", NULL));
|
||||
|
||||
ret &= test_DsUnbind(p, mem_ctx, &priv);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
test suite for dssetup rpc operations
|
||||
|
||||
Copyright (C) Andrew Tridgell 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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_dssetup_c.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
|
||||
BOOL test_DsRoleGetPrimaryDomainInformation(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct dssetup_DsRoleGetPrimaryDomainInformation r;
|
||||
NTSTATUS status;
|
||||
BOOL ret = True;
|
||||
int i;
|
||||
|
||||
printf("\ntesting DsRoleGetPrimaryDomainInformation\n");
|
||||
|
||||
for (i=DS_ROLE_BASIC_INFORMATION; i <= DS_ROLE_OP_STATUS; i++) {
|
||||
r.in.level = i;
|
||||
|
||||
status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_dssetup_DsRoleGetPrimaryDomainInformation level %d failed - %s\n",
|
||||
i, errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsRoleGetPrimaryDomainInformation level %d failed - %s\n",
|
||||
i, win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL torture_rpc_dssetup(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_dssetup");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_dssetup);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
ret &= test_DsRoleGetPrimaryDomainInformation(p, mem_ctx);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,582 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
DsGetNCChanges replication test
|
||||
|
||||
Copyright (C) Stefan (metze) Metzmacher 2005
|
||||
Copyright (C) Brad Henry 2005
|
||||
|
||||
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"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
#include "librpc/gen_ndr/ndr_drsuapi_c.h"
|
||||
#include "libcli/cldap/cldap.h"
|
||||
#include "libcli/ldap/ldap_client.h"
|
||||
#include "torture/torture.h"
|
||||
#include "torture/ldap/proto.h"
|
||||
|
||||
struct DsSyncBindInfo {
|
||||
struct dcerpc_pipe *pipe;
|
||||
struct drsuapi_DsBind req;
|
||||
struct GUID bind_guid;
|
||||
struct drsuapi_DsBindInfoCtr our_bind_info_ctr;
|
||||
struct drsuapi_DsBindInfo28 our_bind_info28;
|
||||
struct drsuapi_DsBindInfo28 peer_bind_info28;
|
||||
struct policy_handle bind_handle;
|
||||
};
|
||||
|
||||
struct DsSyncLDAPInfo {
|
||||
struct ldap_connection *conn;
|
||||
};
|
||||
|
||||
struct DsSyncTest {
|
||||
struct dcerpc_binding *drsuapi_binding;
|
||||
|
||||
const char *ldap_url;
|
||||
const char *site_name;
|
||||
|
||||
const char *domain_dn;
|
||||
|
||||
/* what we need to do as 'Administrator' */
|
||||
struct {
|
||||
struct cli_credentials *credentials;
|
||||
struct DsSyncBindInfo drsuapi;
|
||||
struct DsSyncLDAPInfo ldap;
|
||||
} admin;
|
||||
|
||||
/* what we need to do as the new dc machine account */
|
||||
struct {
|
||||
struct cli_credentials *credentials;
|
||||
struct DsSyncBindInfo drsuapi;
|
||||
struct drsuapi_DsGetDCInfo2 dc_info2;
|
||||
struct GUID invocation_id;
|
||||
struct GUID object_guid;
|
||||
} new_dc;
|
||||
|
||||
/* info about the old dc */
|
||||
struct {
|
||||
struct drsuapi_DsGetDomainControllerInfo dc_info;
|
||||
} old_dc;
|
||||
};
|
||||
|
||||
static struct DsSyncTest *test_create_context(TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct DsSyncTest *ctx;
|
||||
struct drsuapi_DsBindInfo28 *our_bind_info28;
|
||||
struct drsuapi_DsBindInfoCtr *our_bind_info_ctr;
|
||||
const char *binding = lp_parm_string(-1, "torture", "binding");
|
||||
ctx = talloc_zero(mem_ctx, struct DsSyncTest);
|
||||
if (!ctx) return NULL;
|
||||
|
||||
status = dcerpc_parse_binding(ctx, binding, &ctx->drsuapi_binding);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Bad binding string %s\n", binding);
|
||||
return NULL;
|
||||
}
|
||||
ctx->drsuapi_binding->flags |= DCERPC_SIGN | DCERPC_SEAL;
|
||||
|
||||
ctx->ldap_url = talloc_asprintf(ctx, "ldap://%s/", ctx->drsuapi_binding->host);
|
||||
|
||||
/* ctx->admin ...*/
|
||||
ctx->admin.credentials = cmdline_credentials;
|
||||
|
||||
our_bind_info28 = &ctx->admin.drsuapi.our_bind_info28;
|
||||
our_bind_info28->supported_extensions = 0xFFFFFFFF;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
|
||||
our_bind_info28->site_guid = GUID_zero();
|
||||
our_bind_info28->u1 = 0;
|
||||
our_bind_info28->repl_epoch = 1;
|
||||
|
||||
our_bind_info_ctr = &ctx->admin.drsuapi.our_bind_info_ctr;
|
||||
our_bind_info_ctr->length = 28;
|
||||
our_bind_info_ctr->info.info28 = *our_bind_info28;
|
||||
|
||||
GUID_from_string(DRSUAPI_DS_BIND_GUID, &ctx->admin.drsuapi.bind_guid);
|
||||
|
||||
ctx->admin.drsuapi.req.in.bind_guid = &ctx->admin.drsuapi.bind_guid;
|
||||
ctx->admin.drsuapi.req.in.bind_info = our_bind_info_ctr;
|
||||
ctx->admin.drsuapi.req.out.bind_handle = &ctx->admin.drsuapi.bind_handle;
|
||||
|
||||
/* ctx->new_dc ...*/
|
||||
|
||||
our_bind_info28 = &ctx->new_dc.drsuapi.our_bind_info28;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
|
||||
if (lp_parm_bool(-1,"dssync","xpress",False)) {
|
||||
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
|
||||
}
|
||||
our_bind_info28->site_guid = GUID_zero();
|
||||
our_bind_info28->u1 = 508;
|
||||
our_bind_info28->repl_epoch = 0;
|
||||
|
||||
our_bind_info_ctr = &ctx->new_dc.drsuapi.our_bind_info_ctr;
|
||||
our_bind_info_ctr->length = 28;
|
||||
our_bind_info_ctr->info.info28 = *our_bind_info28;
|
||||
|
||||
GUID_from_string(DRSUAPI_DS_BIND_GUID_W2K3, &ctx->new_dc.drsuapi.bind_guid);
|
||||
|
||||
ctx->new_dc.drsuapi.req.in.bind_guid = &ctx->new_dc.drsuapi.bind_guid;
|
||||
ctx->new_dc.drsuapi.req.in.bind_info = our_bind_info_ctr;
|
||||
ctx->new_dc.drsuapi.req.out.bind_handle = &ctx->new_dc.drsuapi.bind_handle;
|
||||
|
||||
ctx->new_dc.invocation_id = ctx->new_dc.drsuapi.bind_guid;
|
||||
|
||||
/* ctx->old_dc ...*/
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static BOOL _test_DsBind(struct DsSyncTest *ctx, struct cli_credentials *credentials, struct DsSyncBindInfo *b)
|
||||
{
|
||||
NTSTATUS status;
|
||||
BOOL ret = True;
|
||||
struct event_context *event = NULL;
|
||||
|
||||
status = dcerpc_pipe_connect_b(ctx,
|
||||
&b->pipe, ctx->drsuapi_binding,
|
||||
&dcerpc_table_drsuapi,
|
||||
credentials, event);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Failed to connect to server as a BDC: %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
status = dcerpc_drsuapi_DsBind(b->pipe, ctx, &b->req);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(ctx, b->pipe->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsBind failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(b->req.out.result)) {
|
||||
printf("DsBind failed - %s\n", win_errstr(b->req.out.result));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(b->peer_bind_info28);
|
||||
if (b->req.out.bind_info) {
|
||||
switch (b->req.out.bind_info->length) {
|
||||
case 24: {
|
||||
struct drsuapi_DsBindInfo24 *info24;
|
||||
info24 = &b->req.out.bind_info->info.info24;
|
||||
b->peer_bind_info28.supported_extensions= info24->supported_extensions;
|
||||
b->peer_bind_info28.site_guid = info24->site_guid;
|
||||
b->peer_bind_info28.u1 = info24->u1;
|
||||
b->peer_bind_info28.repl_epoch = 0;
|
||||
break;
|
||||
}
|
||||
case 28:
|
||||
b->peer_bind_info28 = b->req.out.bind_info->info.info28;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL test_LDAPBind(struct DsSyncTest *ctx, struct cli_credentials *credentials, struct DsSyncLDAPInfo *l)
|
||||
{
|
||||
NTSTATUS status;
|
||||
BOOL ret = True;
|
||||
|
||||
status = torture_ldap_connection(ctx, &l->conn, ctx->ldap_url);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("failed to connect to LDAP: %s\n", ctx->ldap_url);
|
||||
return False;
|
||||
}
|
||||
|
||||
printf("connected to LDAP: %s\n", ctx->ldap_url);
|
||||
|
||||
status = torture_ldap_bind_sasl(l->conn, credentials);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("failed to bind to LDAP:\n");
|
||||
return False;
|
||||
}
|
||||
printf("bound to LDAP.\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL test_GetInfo(struct DsSyncTest *ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct drsuapi_DsCrackNames r;
|
||||
struct drsuapi_DsNameString names[1];
|
||||
BOOL ret = True;
|
||||
|
||||
struct cldap_socket *cldap = cldap_socket_init(ctx, NULL);
|
||||
struct cldap_netlogon search;
|
||||
|
||||
r.in.bind_handle = &ctx->admin.drsuapi.bind_handle;
|
||||
r.in.level = 1;
|
||||
r.in.req.req1.unknown1 = 0x000004e4;
|
||||
r.in.req.req1.unknown2 = 0x00000407;
|
||||
r.in.req.req1.count = 1;
|
||||
r.in.req.req1.names = names;
|
||||
r.in.req.req1.format_flags = DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
|
||||
r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
|
||||
r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
|
||||
names[0].str = talloc_asprintf(ctx, "%s\\", lp_workgroup());
|
||||
|
||||
status = dcerpc_drsuapi_DsCrackNames(ctx->admin.drsuapi.pipe, ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(ctx, ctx->admin.drsuapi.pipe->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
|
||||
return False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
ctx->domain_dn = r.out.ctr.ctr1->array[0].result_name;
|
||||
|
||||
ZERO_STRUCT(search);
|
||||
search.in.dest_address = ctx->drsuapi_binding->host;
|
||||
search.in.acct_control = -1;
|
||||
search.in.version = 6;
|
||||
status = cldap_netlogon(cldap, ctx, &search);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
ctx->site_name = talloc_asprintf(ctx, "%s", "Default-First-Site-Name");
|
||||
printf("cldap_netlogon() returned %s. Defaulting to Site-Name: %s\n", errstr, ctx->site_name);
|
||||
} else {
|
||||
ctx->site_name = talloc_steal(ctx, search.out.netlogon.logon5.client_site);
|
||||
printf("cldap_netlogon() returned Client Site-Name: %s.\n",ctx->site_name);
|
||||
printf("cldap_netlogon() returned Server Site-Name: %s.\n",search.out.netlogon.logon5.server_site);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void test_analyse_objects(struct DsSyncTest *ctx,
|
||||
struct drsuapi_DsReplicaObjectListItemEx *cur)
|
||||
{
|
||||
if (!lp_parm_bool(-1,"dssync","print_pwd_blobs",False)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (; cur; cur = cur->next_object) {
|
||||
const char *dn;
|
||||
BOOL dn_printed = False;
|
||||
uint32_t i;
|
||||
|
||||
if (!cur->object.identifier) continue;
|
||||
|
||||
dn = cur->object.identifier->dn;
|
||||
|
||||
for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
|
||||
const char *name = NULL;
|
||||
DATA_BLOB *data = NULL;
|
||||
struct drsuapi_DsReplicaAttribute *attr;
|
||||
attr = &cur->object.attribute_ctr.attributes[i];
|
||||
|
||||
switch (attr->attid) {
|
||||
case DRSUAPI_ATTRIBUTE_dBCSPwd:
|
||||
name = "dBCSPwd";
|
||||
break;
|
||||
case DRSUAPI_ATTRIBUTE_unicodePwd:
|
||||
name = "unicodePwd";
|
||||
break;
|
||||
case DRSUAPI_ATTRIBUTE_ntPwdHistory:
|
||||
name = "ntPwdHistory";
|
||||
break;
|
||||
case DRSUAPI_ATTRIBUTE_lmPwdHistory:
|
||||
name = "lmPwdHistory";
|
||||
break;
|
||||
case DRSUAPI_ATTRIBUTE_supplementalCredentials:
|
||||
name = "supplementalCredentials";
|
||||
break;
|
||||
case DRSUAPI_ATTRIBUTE_priorValue:
|
||||
name = "priorValue";
|
||||
break;
|
||||
case DRSUAPI_ATTRIBUTE_currentValue:
|
||||
name = "currentValue";
|
||||
break;
|
||||
case DRSUAPI_ATTRIBUTE_trustAuthOutgoing:
|
||||
name = "trustAuthOutgoing";
|
||||
break;
|
||||
case DRSUAPI_ATTRIBUTE_trustAuthIncoming:
|
||||
name = "trustAuthIncoming";
|
||||
break;
|
||||
case DRSUAPI_ATTRIBUTE_initialAuthOutgoing:
|
||||
name = "initialAuthOutgoing";
|
||||
break;
|
||||
case DRSUAPI_ATTRIBUTE_initialAuthIncoming:
|
||||
name = "initialAuthIncoming";
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (attr->value_ctr.data_blob.num_values != 1) continue;
|
||||
|
||||
if (!attr->value_ctr.data_blob.values[0].data) continue;
|
||||
|
||||
data = attr->value_ctr.data_blob.values[0].data;
|
||||
|
||||
if (!dn_printed) {
|
||||
DEBUG(0,("DN: %s\n", dn));
|
||||
dn_printed = True;
|
||||
}
|
||||
DEBUGADD(0,("ATTR: %s data_blob.length=%lu\n",
|
||||
name, (long)data->length));
|
||||
dump_data(0,data->data, data->length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL test_FetchData(struct DsSyncTest *ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
BOOL ret = True;
|
||||
int i, y = 0;
|
||||
uint64_t highest_usn = 0;
|
||||
const char *partition = NULL;
|
||||
struct drsuapi_DsGetNCChanges r;
|
||||
struct drsuapi_DsReplicaObjectIdentifier nc;
|
||||
struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
|
||||
struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
|
||||
int32_t out_level = 0;
|
||||
struct GUID null_guid;
|
||||
struct dom_sid null_sid;
|
||||
struct {
|
||||
int32_t level;
|
||||
} array[] = {
|
||||
/* {
|
||||
5
|
||||
},
|
||||
*/ {
|
||||
8
|
||||
}
|
||||
};
|
||||
|
||||
ZERO_STRUCT(null_guid);
|
||||
ZERO_STRUCT(null_sid);
|
||||
|
||||
partition = lp_parm_string(-1, "dssync", "partition");
|
||||
if (partition == NULL) {
|
||||
partition = ctx->domain_dn;
|
||||
printf("dssync:partition not specified, defaulting to %s.\n", ctx->domain_dn);
|
||||
}
|
||||
|
||||
highest_usn = lp_parm_int(-1, "dssync", "highest_usn", 0);
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(array); i++) {
|
||||
printf("testing DsGetNCChanges level %d\n",
|
||||
array[i].level);
|
||||
|
||||
r.in.bind_handle = &ctx->new_dc.drsuapi.bind_handle;
|
||||
r.in.level = array[i].level;
|
||||
|
||||
switch (r.in.level) {
|
||||
case 5:
|
||||
nc.guid = null_guid;
|
||||
nc.sid = null_sid;
|
||||
nc.dn = partition;
|
||||
|
||||
r.in.req.req5.destination_dsa_guid = ctx->new_dc.invocation_id;
|
||||
r.in.req.req5.source_dsa_invocation_id = null_guid;
|
||||
r.in.req.req5.naming_context = &nc;
|
||||
r.in.req.req5.highwatermark.tmp_highest_usn = highest_usn;
|
||||
r.in.req.req5.highwatermark.reserved_usn = 0;
|
||||
r.in.req.req5.highwatermark.highest_usn = highest_usn;
|
||||
r.in.req.req5.uptodateness_vector = NULL;
|
||||
r.in.req.req5.replica_flags = 0;
|
||||
if (lp_parm_bool(-1,"dssync","compression",False)) {
|
||||
r.in.req.req5.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
|
||||
}
|
||||
if (lp_parm_bool(-1,"dssync","neighbour_writeable",True)) {
|
||||
r.in.req.req5.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE;
|
||||
}
|
||||
r.in.req.req5.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
|
||||
| DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
|
||||
| DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS
|
||||
| DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
|
||||
;
|
||||
r.in.req.req5.max_object_count = 133;
|
||||
r.in.req.req5.max_ndr_size = 1336770;
|
||||
r.in.req.req5.unknown4 = 0;
|
||||
r.in.req.req5.h1 = 0;
|
||||
|
||||
break;
|
||||
case 8:
|
||||
nc.guid = null_guid;
|
||||
nc.sid = null_sid;
|
||||
nc.dn = partition;
|
||||
/* nc.dn can be set to any other ad partition */
|
||||
|
||||
r.in.req.req8.destination_dsa_guid = ctx->new_dc.invocation_id;
|
||||
r.in.req.req8.source_dsa_invocation_id = null_guid;
|
||||
r.in.req.req8.naming_context = &nc;
|
||||
r.in.req.req8.highwatermark.tmp_highest_usn = highest_usn;
|
||||
r.in.req.req8.highwatermark.reserved_usn = 0;
|
||||
r.in.req.req8.highwatermark.highest_usn = highest_usn;
|
||||
r.in.req.req8.uptodateness_vector = NULL;
|
||||
r.in.req.req8.replica_flags = 0;
|
||||
if (lp_parm_bool(-1,"dssync","compression",False)) {
|
||||
r.in.req.req8.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
|
||||
}
|
||||
if (lp_parm_bool(-1,"dssync","neighbour_writeable",True)) {
|
||||
r.in.req.req8.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE;
|
||||
}
|
||||
r.in.req.req8.replica_flags |= DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
|
||||
| DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
|
||||
| DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS
|
||||
| DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
|
||||
;
|
||||
r.in.req.req8.max_object_count = 402;
|
||||
r.in.req.req8.max_ndr_size = 402116;
|
||||
|
||||
r.in.req.req8.unknown4 = 0;
|
||||
r.in.req.req8.h1 = 0;
|
||||
r.in.req.req8.unique_ptr1 = 0;
|
||||
r.in.req.req8.unique_ptr2 = 0;
|
||||
r.in.req.req8.ctr12.count = 0;
|
||||
r.in.req.req8.ctr12.array = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Dumping AD partition: %s\n", nc.dn);
|
||||
for (y=0; ;y++) {
|
||||
ZERO_STRUCT(r.out);
|
||||
|
||||
if (r.in.level == 5) {
|
||||
DEBUG(0,("start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",y,
|
||||
(long long)r.in.req.req5.highwatermark.tmp_highest_usn,
|
||||
(long long)r.in.req.req5.highwatermark.highest_usn));
|
||||
}
|
||||
|
||||
if (r.in.level == 8) {
|
||||
DEBUG(0,("start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",y,
|
||||
(long long)r.in.req.req8.highwatermark.tmp_highest_usn,
|
||||
(long long)r.in.req.req8.highwatermark.highest_usn));
|
||||
}
|
||||
|
||||
status = dcerpc_drsuapi_DsGetNCChanges(ctx->new_dc.drsuapi.pipe, ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
const char *errstr = nt_errstr(status);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
|
||||
errstr = dcerpc_errstr(ctx, ctx->new_dc.drsuapi.pipe->last_fault_code);
|
||||
}
|
||||
printf("dcerpc_drsuapi_DsGetNCChanges failed - %s\n", errstr);
|
||||
ret = False;
|
||||
} else if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DsGetNCChanges failed - %s\n", win_errstr(r.out.result));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (ret == True && r.out.level == 1) {
|
||||
out_level = 1;
|
||||
ctr1 = &r.out.ctr.ctr1;
|
||||
} else if (ret == True && r.out.level == 2) {
|
||||
out_level = 1;
|
||||
ctr1 = r.out.ctr.ctr2.ctr.mszip1.ctr1;
|
||||
}
|
||||
|
||||
if (out_level == 1) {
|
||||
DEBUG(0,("end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",y,
|
||||
(long long)ctr1->new_highwatermark.tmp_highest_usn,
|
||||
(long long)ctr1->new_highwatermark.highest_usn));
|
||||
|
||||
test_analyse_objects(ctx, ctr1->first_object);
|
||||
|
||||
if (ctr1->new_highwatermark.tmp_highest_usn > ctr1->new_highwatermark.highest_usn) {
|
||||
r.in.req.req5.highwatermark = ctr1->new_highwatermark;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == True && r.out.level == 6) {
|
||||
out_level = 6;
|
||||
ctr6 = &r.out.ctr.ctr6;
|
||||
} else if (ret == True && r.out.level == 7
|
||||
&& r.out.ctr.ctr7.level == 6
|
||||
&& r.out.ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP) {
|
||||
out_level = 6;
|
||||
ctr6 = r.out.ctr.ctr7.ctr.mszip6.ctr6;
|
||||
}
|
||||
|
||||
if (out_level == 6) {
|
||||
DEBUG(0,("end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",y,
|
||||
(long long)ctr6->new_highwatermark.tmp_highest_usn,
|
||||
(long long)ctr6->new_highwatermark.highest_usn));
|
||||
|
||||
test_analyse_objects(ctx, ctr6->first_object);
|
||||
|
||||
if (ctr6->new_highwatermark.tmp_highest_usn > ctr6->new_highwatermark.highest_usn) {
|
||||
r.in.req.req8.highwatermark = ctr6->new_highwatermark;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL torture_rpc_dssync(struct torture_context *torture)
|
||||
{
|
||||
BOOL ret = True;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
struct DsSyncTest *ctx;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_dssync");
|
||||
ctx = test_create_context(mem_ctx);
|
||||
|
||||
ret &= _test_DsBind(ctx, ctx->admin.credentials, &ctx->admin.drsuapi);
|
||||
ret &= test_LDAPBind(ctx, ctx->admin.credentials, &ctx->admin.ldap);
|
||||
ret &= test_GetInfo(ctx);
|
||||
ret &= _test_DsBind(ctx, ctx->admin.credentials, &ctx->new_dc.drsuapi);
|
||||
ret &= test_FetchData(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for echo rpc operations
|
||||
|
||||
Copyright (C) Andrew Tridgell 2003
|
||||
Copyright (C) Stefan (metze) Metzmacher 2005
|
||||
Copyright (C) Jelmer Vernooij 2005
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
#include "lib/events/events.h"
|
||||
#include "librpc/gen_ndr/ndr_echo_c.h"
|
||||
|
||||
|
||||
/*
|
||||
test the AddOne interface
|
||||
*/
|
||||
#define TEST_ADDONE(tctx, value) do { \
|
||||
n = i = value; \
|
||||
r.in.in_data = n; \
|
||||
r.out.out_data = &n; \
|
||||
status = dcerpc_echo_AddOne(p, tctx, &r); \
|
||||
torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "AddOne(%d) failed", i)); \
|
||||
torture_assert (tctx, n == i+1, talloc_asprintf(tctx, "%d + 1 != %u (should be %u)\n", i, n, i+1)); \
|
||||
torture_comment (tctx, "%d + 1 = %u\n", i, n); \
|
||||
} while(0)
|
||||
|
||||
static bool test_addone(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
uint32_t i;
|
||||
NTSTATUS status;
|
||||
uint32_t n;
|
||||
struct echo_AddOne r;
|
||||
|
||||
for (i=0;i<10;i++) {
|
||||
TEST_ADDONE(tctx, i);
|
||||
}
|
||||
|
||||
TEST_ADDONE(tctx, 0x7FFFFFFE);
|
||||
TEST_ADDONE(tctx, 0xFFFFFFFE);
|
||||
TEST_ADDONE(tctx, 0xFFFFFFFF);
|
||||
TEST_ADDONE(tctx, random() & 0xFFFFFFFF);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
test the EchoData interface
|
||||
*/
|
||||
static bool test_echodata(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
int i;
|
||||
NTSTATUS status;
|
||||
uint8_t *data_in, *data_out;
|
||||
int len;
|
||||
struct echo_EchoData r;
|
||||
|
||||
if (torture_setting_bool(tctx, "quick", false) &&
|
||||
(p->conn->flags & DCERPC_DEBUG_VALIDATE_BOTH)) {
|
||||
len = 1 + (random() % 500);
|
||||
} else {
|
||||
len = 1 + (random() % 5000);
|
||||
}
|
||||
|
||||
data_in = talloc_size(tctx, len);
|
||||
data_out = talloc_size(tctx, len);
|
||||
for (i=0;i<len;i++) {
|
||||
data_in[i] = i;
|
||||
}
|
||||
|
||||
r.in.len = len;
|
||||
r.in.in_data = data_in;
|
||||
|
||||
status = dcerpc_echo_EchoData(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx,
|
||||
"EchoData(%d) failed\n", len));
|
||||
|
||||
data_out = r.out.out_data;
|
||||
|
||||
for (i=0;i<len;i++) {
|
||||
if (data_in[i] != data_out[i]) {
|
||||
torture_comment(tctx, "Bad data returned for len %d at offset %d\n",
|
||||
len, i);
|
||||
torture_comment(tctx, "in:\n");
|
||||
dump_data(0, data_in+i, MIN(len-i, 16));
|
||||
torture_comment(tctx, "out:\n");
|
||||
dump_data(0, data_out+i, MIN(len-1, 16));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
test the SourceData interface
|
||||
*/
|
||||
static bool test_sourcedata(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
int i;
|
||||
NTSTATUS status;
|
||||
int len;
|
||||
struct echo_SourceData r;
|
||||
|
||||
if (torture_setting_bool(tctx, "quick", false) &&
|
||||
(p->conn->flags & DCERPC_DEBUG_VALIDATE_BOTH)) {
|
||||
len = 100 + (random() % 500);
|
||||
} else {
|
||||
len = 200000 + (random() % 5000);
|
||||
}
|
||||
|
||||
r.in.len = len;
|
||||
|
||||
status = dcerpc_echo_SourceData(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx,
|
||||
"SourceData(%d) failed", len));
|
||||
|
||||
for (i=0;i<len;i++) {
|
||||
uint8_t *v = (uint8_t *)r.out.data;
|
||||
torture_assert(tctx, v[i] == (i & 0xFF),
|
||||
talloc_asprintf(tctx,
|
||||
"bad data 0x%x at %d\n", (uint8_t)r.out.data[i], i));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
test the SinkData interface
|
||||
*/
|
||||
static bool test_sinkdata(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
int i;
|
||||
NTSTATUS status;
|
||||
uint8_t *data_in;
|
||||
int len;
|
||||
struct echo_SinkData r;
|
||||
|
||||
if (torture_setting_bool(tctx, "quick", false) &&
|
||||
(p->conn->flags & DCERPC_DEBUG_VALIDATE_BOTH)) {
|
||||
len = 100 + (random() % 5000);
|
||||
} else {
|
||||
len = 200000 + (random() % 5000);
|
||||
}
|
||||
|
||||
data_in = talloc_size(tctx, len);
|
||||
for (i=0;i<len;i++) {
|
||||
data_in[i] = i+1;
|
||||
}
|
||||
|
||||
r.in.len = len;
|
||||
r.in.data = data_in;
|
||||
|
||||
status = dcerpc_echo_SinkData(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx,
|
||||
"SinkData(%d) failed",
|
||||
len));
|
||||
|
||||
torture_comment(tctx, "sunk %d bytes\n", len);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
test the testcall interface
|
||||
*/
|
||||
static bool test_testcall(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct echo_TestCall r;
|
||||
const char *s = NULL;
|
||||
|
||||
r.in.s1 = "input string";
|
||||
r.out.s2 = &s;
|
||||
|
||||
status = dcerpc_echo_TestCall(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status, "TestCall failed");
|
||||
|
||||
torture_assert_str_equal(tctx, s, "input string", "Didn't receive back same string");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
test the testcall interface
|
||||
*/
|
||||
static bool test_testcall2(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct echo_TestCall2 r;
|
||||
int i;
|
||||
|
||||
for (i=1;i<=7;i++) {
|
||||
r.in.level = i;
|
||||
r.out.info = talloc(tctx, union echo_Info);
|
||||
|
||||
torture_comment(tctx, "Testing TestCall2 level %d\n", i);
|
||||
status = dcerpc_echo_TestCall2(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status, "TestCall2 failed");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
test the TestSleep interface
|
||||
*/
|
||||
static bool test_sleep(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
int i;
|
||||
NTSTATUS status;
|
||||
#define ASYNC_COUNT 3
|
||||
struct rpc_request *req[ASYNC_COUNT];
|
||||
struct echo_TestSleep r[ASYNC_COUNT];
|
||||
BOOL done[ASYNC_COUNT];
|
||||
struct timeval snd[ASYNC_COUNT];
|
||||
struct timeval rcv[ASYNC_COUNT];
|
||||
struct timeval diff[ASYNC_COUNT];
|
||||
struct event_context *ctx;
|
||||
int total_done = 0;
|
||||
|
||||
if (torture_setting_bool(tctx, "quick", false)) {
|
||||
torture_skip(tctx, "TestSleep disabled - use \"torture:quick=no\" to enable\n");
|
||||
}
|
||||
torture_comment(tctx, "Testing TestSleep - use \"torture:quick=no\" to disable\n");
|
||||
|
||||
for (i=0;i<ASYNC_COUNT;i++) {
|
||||
done[i] = False;
|
||||
snd[i] = timeval_current();
|
||||
rcv[i] = timeval_zero();
|
||||
r[i].in.seconds = ASYNC_COUNT-i;
|
||||
req[i] = dcerpc_echo_TestSleep_send(p, tctx, &r[i]);
|
||||
torture_assert(tctx, req[i], "Failed to send async sleep request\n");
|
||||
}
|
||||
|
||||
ctx = dcerpc_event_context(p);
|
||||
while (total_done < ASYNC_COUNT) {
|
||||
torture_assert(tctx, event_loop_once(ctx) == 0,
|
||||
"Event context loop failed");
|
||||
for (i=0;i<ASYNC_COUNT;i++) {
|
||||
if (done[i] == False && req[i]->state == RPC_REQUEST_DONE) {
|
||||
int rounded_tdiff;
|
||||
total_done++;
|
||||
done[i] = True;
|
||||
rcv[i] = timeval_current();
|
||||
diff[i] = timeval_until(&snd[i], &rcv[i]);
|
||||
rounded_tdiff = (int)(0.5 + diff[i].tv_sec + (1.0e-6*diff[i].tv_usec));
|
||||
status = dcerpc_ndr_request_recv(req[i]);
|
||||
printf("rounded_tdiff=%d\n", rounded_tdiff);
|
||||
torture_assert_ntstatus_ok(tctx, status,
|
||||
talloc_asprintf(tctx, "TestSleep(%d) failed", i));
|
||||
torture_assert(tctx, r[i].out.result == r[i].in.seconds,
|
||||
talloc_asprintf(tctx, "Failed - Asked to sleep for %u seconds (server replied with %u seconds and the reply takes only %u seconds)",
|
||||
r[i].out.result, r[i].in.seconds, (uint_t)diff[i].tv_sec));
|
||||
torture_assert(tctx, r[i].out.result <= rounded_tdiff,
|
||||
talloc_asprintf(tctx, "Failed - Slept for %u seconds (but reply takes only %u.%06u seconds)",
|
||||
r[i].out.result, (uint_t)diff[i].tv_sec, (uint_t)diff[i].tv_usec));
|
||||
if (r[i].out.result+1 == rounded_tdiff) {
|
||||
torture_comment(tctx, "Slept for %u seconds (but reply takes %u.%06u seconds - busy server?)\n",
|
||||
r[i].out.result, (uint_t)diff[i].tv_sec, (uint_t)diff[i].tv_usec);
|
||||
} else if (r[i].out.result == rounded_tdiff) {
|
||||
torture_comment(tctx, "Slept for %u seconds (reply takes %u.%06u seconds - ok)\n",
|
||||
r[i].out.result, (uint_t)diff[i].tv_sec, (uint_t)diff[i].tv_usec);
|
||||
} else {
|
||||
torture_comment(tctx, "(Failed) - Not async - Slept for %u seconds (but reply takes %u.%06u seconds)",
|
||||
r[i].out.result, (uint_t)diff[i].tv_sec, (uint_t)diff[i].tv_usec);
|
||||
/* TODO: let the test fail here, when we support async rpc on ncacn_np */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
test enum handling
|
||||
*/
|
||||
static bool test_enum(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct echo_TestEnum r;
|
||||
enum echo_Enum1 v = ECHO_ENUM1;
|
||||
struct echo_Enum2 e2;
|
||||
union echo_Enum3 e3;
|
||||
|
||||
r.in.foo1 = &v;
|
||||
r.in.foo2 = &e2;
|
||||
r.in.foo3 = &e3;
|
||||
r.out.foo1 = &v;
|
||||
r.out.foo2 = &e2;
|
||||
r.out.foo3 = &e3;
|
||||
|
||||
e2.e1 = 76;
|
||||
e2.e2 = ECHO_ENUM1_32;
|
||||
e3.e1 = ECHO_ENUM2;
|
||||
|
||||
status = dcerpc_echo_TestEnum(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status, "TestEnum failed");
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
test surrounding conformant array handling
|
||||
*/
|
||||
static bool test_surrounding(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct echo_TestSurrounding r;
|
||||
|
||||
ZERO_STRUCT(r);
|
||||
r.in.data = talloc(tctx, struct echo_Surrounding);
|
||||
|
||||
r.in.data->x = 20;
|
||||
r.in.data->surrounding = talloc_zero_array(tctx, uint16_t, r.in.data->x);
|
||||
|
||||
r.out.data = talloc(tctx, struct echo_Surrounding);
|
||||
|
||||
status = dcerpc_echo_TestSurrounding(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status, "TestSurrounding failed");
|
||||
|
||||
torture_assert(tctx, r.out.data->x == 2 * r.in.data->x,
|
||||
"TestSurrounding did not make the array twice as large");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
test multiple levels of pointers
|
||||
*/
|
||||
static bool test_doublepointer(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct echo_TestDoublePointer r;
|
||||
uint16_t value = 12;
|
||||
uint16_t *pvalue = &value;
|
||||
uint16_t **ppvalue = &pvalue;
|
||||
|
||||
ZERO_STRUCT(r);
|
||||
r.in.data = &ppvalue;
|
||||
|
||||
status = dcerpc_echo_TestDoublePointer(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status, "TestDoublePointer failed");
|
||||
|
||||
torture_assert_int_equal(tctx, value, r.out.result,
|
||||
"TestDoublePointer did not return original value");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
test request timeouts
|
||||
*/
|
||||
static bool test_timeout(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct rpc_request *req;
|
||||
struct echo_TestSleep r;
|
||||
int timeout_saved = p->request_timeout;
|
||||
|
||||
if (torture_setting_bool(tctx, "quick", false)) {
|
||||
torture_skip(tctx, "timeout testing disabled - use \"torture:quick=no\" to enable\n");
|
||||
}
|
||||
|
||||
torture_comment(tctx, "testing request timeouts\n");
|
||||
r.in.seconds = 2;
|
||||
p->request_timeout = 1;
|
||||
|
||||
torture_assert(tctx, req = dcerpc_echo_TestSleep_send(p, tctx, &r),
|
||||
"Failed to send async sleep request");
|
||||
|
||||
status = dcerpc_ndr_request_recv(req);
|
||||
torture_assert_ntstatus_equal(tctx, status, NT_STATUS_IO_TIMEOUT,
|
||||
"request should have timed out");
|
||||
|
||||
torture_comment(tctx, "testing request destruction\n");
|
||||
req = dcerpc_echo_TestSleep_send(p, tctx, &r);
|
||||
if (!req) {
|
||||
torture_comment(tctx, "Failed to send async sleep request\n");
|
||||
goto failed;
|
||||
}
|
||||
talloc_free(req);
|
||||
|
||||
req = dcerpc_echo_TestSleep_send(p, tctx, &r);
|
||||
if (!req) {
|
||||
torture_comment(tctx, "Failed to send async sleep request\n");
|
||||
goto failed;
|
||||
}
|
||||
status = dcerpc_ndr_request_recv(req);
|
||||
torture_assert_ntstatus_equal(tctx, status, NT_STATUS_IO_TIMEOUT,
|
||||
"request should have timed out");
|
||||
|
||||
p->request_timeout = timeout_saved;
|
||||
|
||||
return test_addone(tctx, p);
|
||||
|
||||
failed:
|
||||
p->request_timeout = timeout_saved;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
struct torture_suite *torture_rpc_echo(void)
|
||||
{
|
||||
struct torture_suite *suite = torture_suite_create(
|
||||
talloc_autofree_context(), "ECHO");
|
||||
struct torture_tcase *tcase;
|
||||
|
||||
tcase = torture_suite_add_rpc_iface_tcase(suite, "echo",
|
||||
&dcerpc_table_rpcecho);
|
||||
|
||||
torture_rpc_tcase_add_test(tcase, "addone", test_addone);
|
||||
torture_rpc_tcase_add_test(tcase, "sinkdata", test_sinkdata);
|
||||
torture_rpc_tcase_add_test(tcase, "echodata", test_echodata);
|
||||
torture_rpc_tcase_add_test(tcase, "sourcedata", test_sourcedata);
|
||||
torture_rpc_tcase_add_test(tcase, "testcall", test_testcall);
|
||||
torture_rpc_tcase_add_test(tcase, "testcall2", test_testcall2);
|
||||
torture_rpc_tcase_add_test(tcase, "enum", test_enum);
|
||||
torture_rpc_tcase_add_test(tcase, "surrounding", test_surrounding);
|
||||
torture_rpc_tcase_add_test(tcase, "doublepointer", test_doublepointer);
|
||||
torture_rpc_tcase_add_test(tcase, "sleep", test_sleep);
|
||||
torture_rpc_tcase_add_test(tcase, "timeout", test_timeout);
|
||||
|
||||
return suite;
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for epmapper rpc operations
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_epmapper_c.h"
|
||||
#include "librpc/rpc/dcerpc_table.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
|
||||
/*
|
||||
display any protocol tower
|
||||
*/
|
||||
static void display_tower(TALLOC_CTX *mem_ctx, struct epm_tower *twr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<twr->num_floors;i++) {
|
||||
printf(" %s", epm_floor_string(mem_ctx, &twr->floors[i]));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
static BOOL test_Map(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct epm_twr_t *twr)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct epm_Map r;
|
||||
struct GUID uuid;
|
||||
struct policy_handle handle;
|
||||
int i;
|
||||
struct dcerpc_syntax_id syntax;
|
||||
|
||||
ZERO_STRUCT(uuid);
|
||||
ZERO_STRUCT(handle);
|
||||
|
||||
r.in.object = &uuid;
|
||||
r.in.map_tower = twr;
|
||||
r.in.entry_handle = &handle;
|
||||
r.out.entry_handle = &handle;
|
||||
r.in.max_towers = 100;
|
||||
|
||||
dcerpc_floor_get_lhs_data(&twr->tower.floors[0], &syntax);
|
||||
|
||||
printf("epm_Map results for '%s':\n",
|
||||
idl_pipe_name(&syntax.uuid, syntax.if_version));
|
||||
|
||||
twr->tower.floors[2].lhs.protocol = EPM_PROTOCOL_NCACN;
|
||||
twr->tower.floors[2].lhs.lhs_data = data_blob(NULL, 0);
|
||||
twr->tower.floors[2].rhs.ncacn.minor_version = 0;
|
||||
|
||||
twr->tower.floors[3].lhs.protocol = EPM_PROTOCOL_TCP;
|
||||
twr->tower.floors[3].lhs.lhs_data = data_blob(NULL, 0);
|
||||
twr->tower.floors[3].rhs.tcp.port = 0;
|
||||
|
||||
twr->tower.floors[4].lhs.protocol = EPM_PROTOCOL_IP;
|
||||
twr->tower.floors[4].lhs.lhs_data = data_blob(NULL, 0);
|
||||
twr->tower.floors[4].rhs.ip.ipaddr = "0.0.0.0";
|
||||
|
||||
status = dcerpc_epm_Map(p, mem_ctx, &r);
|
||||
if (NT_STATUS_IS_OK(status) && r.out.result == 0) {
|
||||
for (i=0;i<*r.out.num_towers;i++) {
|
||||
if (r.out.towers[i].twr) {
|
||||
display_tower(mem_ctx, &r.out.towers[i].twr->tower);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
twr->tower.floors[3].lhs.protocol = EPM_PROTOCOL_HTTP;
|
||||
twr->tower.floors[3].lhs.lhs_data = data_blob(NULL, 0);
|
||||
twr->tower.floors[3].rhs.http.port = 0;
|
||||
|
||||
status = dcerpc_epm_Map(p, mem_ctx, &r);
|
||||
if (NT_STATUS_IS_OK(status) && r.out.result == 0) {
|
||||
for (i=0;i<*r.out.num_towers;i++) {
|
||||
if (r.out.towers[i].twr) {
|
||||
display_tower(mem_ctx, &r.out.towers[i].twr->tower);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
twr->tower.floors[3].lhs.protocol = EPM_PROTOCOL_UDP;
|
||||
twr->tower.floors[3].lhs.lhs_data = data_blob(NULL, 0);
|
||||
twr->tower.floors[3].rhs.http.port = 0;
|
||||
|
||||
status = dcerpc_epm_Map(p, mem_ctx, &r);
|
||||
if (NT_STATUS_IS_OK(status) && r.out.result == 0) {
|
||||
for (i=0;i<*r.out.num_towers;i++) {
|
||||
if (r.out.towers[i].twr) {
|
||||
display_tower(mem_ctx, &r.out.towers[i].twr->tower);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
twr->tower.floors[3].lhs.protocol = EPM_PROTOCOL_SMB;
|
||||
twr->tower.floors[3].lhs.lhs_data = data_blob(NULL, 0);
|
||||
twr->tower.floors[3].rhs.smb.unc = "";
|
||||
|
||||
twr->tower.floors[4].lhs.protocol = EPM_PROTOCOL_NETBIOS;
|
||||
twr->tower.floors[4].lhs.lhs_data = data_blob(NULL, 0);
|
||||
twr->tower.floors[4].rhs.netbios.name = "";
|
||||
|
||||
status = dcerpc_epm_Map(p, mem_ctx, &r);
|
||||
if (NT_STATUS_IS_OK(status) && r.out.result == 0) {
|
||||
for (i=0;i<*r.out.num_towers;i++) {
|
||||
if (r.out.towers[i].twr) {
|
||||
display_tower(mem_ctx, &r.out.towers[i].twr->tower);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: Extend to do other protocols as well (ncacn_unix_stream, ncalrpc) */
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_Lookup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct epm_Lookup r;
|
||||
struct GUID uuid;
|
||||
struct rpc_if_id_t iface;
|
||||
struct policy_handle handle;
|
||||
|
||||
ZERO_STRUCT(handle);
|
||||
|
||||
r.in.inquiry_type = 0;
|
||||
r.in.object = &uuid;
|
||||
r.in.interface_id = &iface;
|
||||
r.in.vers_option = 0;
|
||||
r.in.entry_handle = &handle;
|
||||
r.out.entry_handle = &handle;
|
||||
r.in.max_ents = 10;
|
||||
|
||||
do {
|
||||
int i;
|
||||
|
||||
ZERO_STRUCT(uuid);
|
||||
ZERO_STRUCT(iface);
|
||||
|
||||
status = dcerpc_epm_Lookup(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status) || r.out.result != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
printf("epm_Lookup returned %d events GUID %s\n",
|
||||
*r.out.num_ents, GUID_string(mem_ctx, &handle.uuid));
|
||||
|
||||
for (i=0;i<*r.out.num_ents;i++) {
|
||||
printf("\nFound '%s'\n", r.out.entries[i].annotation);
|
||||
display_tower(mem_ctx, &r.out.entries[i].tower->tower);
|
||||
if (r.out.entries[i].tower->tower.num_floors == 5) {
|
||||
test_Map(p, mem_ctx, r.out.entries[i].tower);
|
||||
}
|
||||
}
|
||||
} while (NT_STATUS_IS_OK(status) &&
|
||||
r.out.result == 0 &&
|
||||
*r.out.num_ents == r.in.max_ents &&
|
||||
!policy_handle_empty(&handle));
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Lookup failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_Delete(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct epm_entry_t *entries)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct epm_Delete r;
|
||||
|
||||
r.in.num_ents = 1;
|
||||
r.in.entries = entries;
|
||||
|
||||
status = dcerpc_epm_Delete(p, mem_ctx, &r);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
printf("Delete failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (r.out.result != 0) {
|
||||
printf("Delete failed - %d\n", r.out.result);
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_Insert(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct epm_Insert r;
|
||||
struct dcerpc_binding *bd;
|
||||
|
||||
r.in.num_ents = 1;
|
||||
|
||||
r.in.entries = talloc_array(mem_ctx, struct epm_entry_t, 1);
|
||||
ZERO_STRUCT(r.in.entries[0].object);
|
||||
r.in.entries[0].annotation = "smbtorture endpoint";
|
||||
status = dcerpc_parse_binding(mem_ctx, "ncalrpc:[SMBTORTURE]", &bd);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
printf("Unable to generate dcerpc_binding struct\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
r.in.entries[0].tower = talloc(mem_ctx, struct epm_twr_t);
|
||||
|
||||
status = dcerpc_binding_build_tower(mem_ctx, bd, &r.in.entries[0].tower->tower);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
printf("Unable to build tower from binding struct\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
r.in.replace = 0;
|
||||
|
||||
status = dcerpc_epm_Insert(p, mem_ctx, &r);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
printf("Insert failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (r.out.result != 0) {
|
||||
printf("Insert failed - %d\n", r.out.result);
|
||||
printf("NOT CONSIDERING AS A FAILURE\n");
|
||||
return True;
|
||||
}
|
||||
|
||||
if (!test_Delete(p, mem_ctx, r.in.entries)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_InqObject(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct epm_InqObject r;
|
||||
|
||||
r.in.epm_object = talloc(mem_ctx, struct GUID);
|
||||
*r.in.epm_object = dcerpc_table_epmapper.syntax_id.uuid;
|
||||
|
||||
status = dcerpc_epm_InqObject(p, mem_ctx, &r);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
printf("InqObject failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL torture_rpc_epmapper(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_epmapper");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_epmapper);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!test_Lookup(p, mem_ctx)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!test_Insert(p, mem_ctx)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!test_InqObject(p, mem_ctx)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for eventlog rpc operations
|
||||
|
||||
Copyright (C) Tim Potter 2003,2005
|
||||
Copyright (C) Jelmer Vernooij 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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_eventlog.h"
|
||||
#include "librpc/gen_ndr/ndr_eventlog_c.h"
|
||||
#include "librpc/gen_ndr/ndr_lsa.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
static void init_lsa_String(struct lsa_String *name, const char *s)
|
||||
{
|
||||
name->string = s;
|
||||
name->length = 2*strlen_m(s);
|
||||
name->size = name->length;
|
||||
}
|
||||
|
||||
static bool get_policy_handle(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p,
|
||||
struct policy_handle *handle)
|
||||
{
|
||||
struct eventlog_OpenEventLogW r;
|
||||
struct eventlog_OpenUnknown0 unknown0;
|
||||
|
||||
unknown0.unknown0 = 0x005c;
|
||||
unknown0.unknown1 = 0x0001;
|
||||
|
||||
r.in.unknown0 = &unknown0;
|
||||
init_lsa_String(&r.in.logname, "dns server");
|
||||
init_lsa_String(&r.in.servername, NULL);
|
||||
r.in.unknown2 = 0x00000001;
|
||||
r.in.unknown3 = 0x00000001;
|
||||
r.out.handle = handle;
|
||||
|
||||
torture_assert_ntstatus_ok(tctx,
|
||||
dcerpc_eventlog_OpenEventLogW(p, tctx, &r),
|
||||
"OpenEventLog failed");
|
||||
|
||||
torture_assert_ntstatus_ok(tctx, r.out.result, "OpenEventLog failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool test_GetNumRecords(struct torture_context *tctx, struct dcerpc_pipe *p)
|
||||
{
|
||||
struct eventlog_GetNumRecords r;
|
||||
struct eventlog_CloseEventLog cr;
|
||||
struct policy_handle handle;
|
||||
|
||||
if (!get_policy_handle(tctx, p, &handle))
|
||||
return false;
|
||||
|
||||
r.in.handle = &handle;
|
||||
|
||||
torture_assert_ntstatus_ok(tctx,
|
||||
dcerpc_eventlog_GetNumRecords(p, tctx, &r),
|
||||
"GetNumRecords failed");
|
||||
|
||||
torture_comment(tctx, talloc_asprintf(tctx, "%d records\n", *r.out.number));
|
||||
|
||||
cr.in.handle = cr.out.handle = &handle;
|
||||
|
||||
torture_assert_ntstatus_ok(tctx,
|
||||
dcerpc_eventlog_CloseEventLog(p, tctx, &cr),
|
||||
"CloseEventLog failed");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_ReadEventLog(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct eventlog_ReadEventLogW r;
|
||||
struct eventlog_CloseEventLog cr;
|
||||
struct policy_handle handle;
|
||||
|
||||
if (!get_policy_handle(tctx, p, &handle))
|
||||
return false;
|
||||
|
||||
r.in.offset = 0;
|
||||
r.in.handle = &handle;
|
||||
r.in.flags = EVENTLOG_BACKWARDS_READ|EVENTLOG_SEQUENTIAL_READ;
|
||||
|
||||
while (1) {
|
||||
DATA_BLOB blob;
|
||||
struct eventlog_Record rec;
|
||||
struct ndr_pull *ndr;
|
||||
|
||||
/* Read first for number of bytes in record */
|
||||
|
||||
r.in.number_of_bytes = 0;
|
||||
r.out.data = NULL;
|
||||
|
||||
status = dcerpc_eventlog_ReadEventLogW(p, tctx, &r);
|
||||
|
||||
if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_END_OF_FILE)) {
|
||||
break;
|
||||
}
|
||||
|
||||
torture_assert_ntstatus_ok(tctx, status, "ReadEventLog failed");
|
||||
|
||||
torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_BUFFER_TOO_SMALL,
|
||||
"ReadEventLog failed");
|
||||
|
||||
/* Now read the actual record */
|
||||
|
||||
r.in.number_of_bytes = *r.out.real_size;
|
||||
r.out.data = talloc_size(tctx, r.in.number_of_bytes);
|
||||
|
||||
status = dcerpc_eventlog_ReadEventLogW(p, tctx, &r);
|
||||
|
||||
torture_assert_ntstatus_ok(tctx, status, "ReadEventLog failed");
|
||||
|
||||
/* Decode a user-marshalled record */
|
||||
|
||||
blob.length = *r.out.sent_size;
|
||||
blob.data = talloc_steal(tctx, r.out.data);
|
||||
|
||||
ndr = ndr_pull_init_blob(&blob, tctx);
|
||||
|
||||
status = ndr_pull_eventlog_Record(
|
||||
ndr, NDR_SCALARS|NDR_BUFFERS, &rec);
|
||||
|
||||
NDR_PRINT_DEBUG(eventlog_Record, &rec);
|
||||
|
||||
torture_assert_ntstatus_ok(tctx, status,
|
||||
"ReadEventLog failed parsing event log record");
|
||||
|
||||
r.in.offset++;
|
||||
}
|
||||
|
||||
cr.in.handle = cr.out.handle = &handle;
|
||||
|
||||
torture_assert_ntstatus_ok(tctx,
|
||||
dcerpc_eventlog_CloseEventLog(p, tctx, &cr),
|
||||
"CloseEventLog failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_FlushEventLog(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
struct eventlog_FlushEventLog r;
|
||||
struct eventlog_CloseEventLog cr;
|
||||
struct policy_handle handle;
|
||||
|
||||
if (!get_policy_handle(tctx, p, &handle))
|
||||
return false;
|
||||
|
||||
r.in.handle = &handle;
|
||||
|
||||
/* Huh? Does this RPC always return access denied? */
|
||||
torture_assert_ntstatus_equal(tctx,
|
||||
dcerpc_eventlog_FlushEventLog(p, tctx, &r),
|
||||
NT_STATUS_ACCESS_DENIED,
|
||||
"FlushEventLog failed");
|
||||
|
||||
cr.in.handle = cr.out.handle = &handle;
|
||||
|
||||
torture_assert_ntstatus_ok(tctx,
|
||||
dcerpc_eventlog_CloseEventLog(p, tctx, &cr),
|
||||
"CloseEventLog failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_ClearEventLog(struct dcerpc_pipe *p, TALLOC_CTX *tctx)
|
||||
{
|
||||
struct eventlog_ClearEventLogW r;
|
||||
struct eventlog_CloseEventLog cr;
|
||||
struct policy_handle handle;
|
||||
|
||||
if (!get_policy_handle(tctx, p, &handle))
|
||||
return false;
|
||||
|
||||
r.in.handle = &handle;
|
||||
r.in.unknown = NULL;
|
||||
|
||||
torture_assert_ntstatus_ok(tctx,
|
||||
dcerpc_eventlog_ClearEventLogW(p, tctx, &r),
|
||||
"ClearEventLog failed");
|
||||
|
||||
cr.in.handle = cr.out.handle = &handle;
|
||||
|
||||
torture_assert_ntstatus_ok(tctx,
|
||||
dcerpc_eventlog_CloseEventLog(p, tctx, &cr),
|
||||
"CloseEventLog failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_OpenEventLog(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
struct policy_handle handle;
|
||||
struct eventlog_CloseEventLog cr;
|
||||
|
||||
if (!get_policy_handle(tctx, p, &handle))
|
||||
return false;
|
||||
|
||||
cr.in.handle = cr.out.handle = &handle;
|
||||
|
||||
torture_assert_ntstatus_ok(tctx,
|
||||
dcerpc_eventlog_CloseEventLog(p, tctx, &cr),
|
||||
"CloseEventLog failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct torture_suite *torture_rpc_eventlog(void)
|
||||
{
|
||||
struct torture_suite *suite;
|
||||
struct torture_tcase *tcase;
|
||||
|
||||
suite = torture_suite_create(talloc_autofree_context(), "EVENTLOG");
|
||||
tcase = torture_suite_add_rpc_iface_tcase(suite, "eventlog",
|
||||
&dcerpc_table_eventlog);
|
||||
|
||||
torture_rpc_tcase_add_test(tcase, "OpenEventLog", test_OpenEventLog);
|
||||
|
||||
#if 0
|
||||
/* Destructive test */
|
||||
torture_rpc_tcase_add_test(tcase, "ClearEventLog", test_ClearEventLog);
|
||||
#endif
|
||||
|
||||
torture_rpc_tcase_add_test(tcase, "GetNumRecords", test_GetNumRecords);
|
||||
torture_rpc_tcase_add_test(tcase, "ReadEventLog", test_ReadEventLog);
|
||||
torture_rpc_tcase_add_test(tcase, "FlushEventLog", test_FlushEventLog);
|
||||
|
||||
return suite;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for initshutdown operations
|
||||
|
||||
Copyright (C) Tim Potter 2003
|
||||
Copyright (C) Jelmer Vernooij 2004-2005
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_initshutdown_c.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
static void init_initshutdown_String(TALLOC_CTX *mem_ctx, struct initshutdown_String *name, const char *s)
|
||||
{
|
||||
name->name = talloc(mem_ctx, struct initshutdown_String_sub);
|
||||
name->name->name = s;
|
||||
}
|
||||
|
||||
static BOOL test_Init(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
const char *msg, uint32_t timeout)
|
||||
{
|
||||
struct initshutdown_Init r;
|
||||
NTSTATUS status;
|
||||
uint16_t hostname = 0x0;
|
||||
|
||||
r.in.hostname = &hostname;
|
||||
r.in.message = talloc(mem_ctx, struct initshutdown_String);
|
||||
init_initshutdown_String(mem_ctx, r.in.message, msg);
|
||||
r.in.force_apps = 1;
|
||||
r.in.timeout = timeout;
|
||||
r.in.reboot = 1;
|
||||
|
||||
status = dcerpc_initshutdown_Init(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("initshutdown_Init failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("initshutdown_Init failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_InitEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
const char *msg, uint32_t timeout)
|
||||
{
|
||||
struct initshutdown_InitEx r;
|
||||
NTSTATUS status;
|
||||
uint16_t hostname = 0x0;
|
||||
|
||||
r.in.hostname = &hostname;
|
||||
r.in.message = talloc(mem_ctx, struct initshutdown_String);
|
||||
init_initshutdown_String(mem_ctx, r.in.message, msg);
|
||||
r.in.force_apps = 1;
|
||||
r.in.timeout = timeout;
|
||||
r.in.reboot = 1;
|
||||
r.in.reason = 0;
|
||||
|
||||
status = dcerpc_initshutdown_InitEx(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("initshutdown_InitEx failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("initshutdown_InitEx failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_Abort(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct initshutdown_Abort r;
|
||||
NTSTATUS status;
|
||||
uint16_t server = 0x0;
|
||||
|
||||
r.in.server = &server;
|
||||
|
||||
status = dcerpc_initshutdown_Abort(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("initshutdown_Abort failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("initshutdown_Abort failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL torture_rpc_initshutdown(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_initshutdown");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_initshutdown);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!torture_setting_bool(torture, "dangerous", False)) {
|
||||
printf("initshutdown tests disabled - enable dangerous tests to use\n");
|
||||
} else {
|
||||
ret &= test_Init(p, mem_ctx, "spottyfood", 30);
|
||||
ret &= test_Abort(p, mem_ctx);
|
||||
ret &= test_InitEx(p, mem_ctx, "spottyfood", 30);
|
||||
ret &= test_Abort(p, mem_ctx);
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "includes.h"
|
||||
#include "libnet/libnet.h"
|
||||
#include "libcli/libcli.h"
|
||||
|
||||
#include "auth/credentials/credentials.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
#define TORTURE_NETBIOS_NAME "smbtorturejoin"
|
||||
|
||||
|
||||
BOOL torture_rpc_join(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct test_join *tj;
|
||||
struct cli_credentials *machine_account;
|
||||
struct smbcli_state *cli;
|
||||
const char *host = lp_parm_string(-1, "torture", "host");
|
||||
|
||||
/* Join domain as a member server. */
|
||||
tj = torture_join_domain(TORTURE_NETBIOS_NAME,
|
||||
ACB_WSTRUST,
|
||||
&machine_account);
|
||||
|
||||
if (!tj) {
|
||||
DEBUG(0, ("%s failed to join domain as workstation\n",
|
||||
TORTURE_NETBIOS_NAME));
|
||||
return False;
|
||||
}
|
||||
|
||||
status = smbcli_full_connection(tj, &cli, host,
|
||||
"IPC$", NULL,
|
||||
machine_account,
|
||||
NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0, ("%s failed to connect to IPC$ with workstation credentials\n",
|
||||
TORTURE_NETBIOS_NAME));
|
||||
return False;
|
||||
}
|
||||
smbcli_tdis(cli);
|
||||
|
||||
/* Leave domain. */
|
||||
torture_leave_domain(tj);
|
||||
|
||||
/* Join domain as a domain controller. */
|
||||
tj = torture_join_domain(TORTURE_NETBIOS_NAME,
|
||||
ACB_SVRTRUST,
|
||||
&machine_account);
|
||||
if (!tj) {
|
||||
DEBUG(0, ("%s failed to join domain as domain controller\n",
|
||||
TORTURE_NETBIOS_NAME));
|
||||
return False;
|
||||
}
|
||||
|
||||
status = smbcli_full_connection(tj, &cli, host,
|
||||
"IPC$", NULL,
|
||||
machine_account,
|
||||
NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0, ("%s failed to connect to IPC$ with workstation credentials\n",
|
||||
TORTURE_NETBIOS_NAME));
|
||||
return False;
|
||||
}
|
||||
|
||||
smbcli_tdis(cli);
|
||||
|
||||
/* Leave domain. */
|
||||
torture_leave_domain(tj);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for lsa rpc lookup operations
|
||||
|
||||
Copyright (C) Volker Lendecke 2006
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "lib/events/events.h"
|
||||
#include "libnet/libnet_join.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
#include "librpc/gen_ndr/ndr_lsa_c.h"
|
||||
#include "libcli/security/security.h"
|
||||
|
||||
static BOOL open_policy(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p,
|
||||
struct policy_handle **handle)
|
||||
{
|
||||
struct lsa_ObjectAttribute attr;
|
||||
struct lsa_QosInfo qos;
|
||||
struct lsa_OpenPolicy2 r;
|
||||
NTSTATUS status;
|
||||
|
||||
*handle = talloc(mem_ctx, struct policy_handle);
|
||||
if (!*handle) {
|
||||
return False;
|
||||
}
|
||||
|
||||
qos.len = 0;
|
||||
qos.impersonation_level = 2;
|
||||
qos.context_mode = 1;
|
||||
qos.effective_only = 0;
|
||||
|
||||
attr.len = 0;
|
||||
attr.root_dir = NULL;
|
||||
attr.object_name = NULL;
|
||||
attr.attributes = 0;
|
||||
attr.sec_desc = NULL;
|
||||
attr.sec_qos = &qos;
|
||||
|
||||
r.in.system_name = "\\";
|
||||
r.in.attr = &attr;
|
||||
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
r.out.handle = *handle;
|
||||
|
||||
status = dcerpc_lsa_OpenPolicy2(p, mem_ctx, &r);
|
||||
|
||||
return NT_STATUS_IS_OK(status);
|
||||
}
|
||||
|
||||
static BOOL get_domainsid(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p,
|
||||
struct policy_handle *handle,
|
||||
struct dom_sid **sid)
|
||||
{
|
||||
struct lsa_QueryInfoPolicy r;
|
||||
NTSTATUS status;
|
||||
|
||||
r.in.level = LSA_POLICY_INFO_DOMAIN;
|
||||
r.in.handle = handle;
|
||||
|
||||
status = dcerpc_lsa_QueryInfoPolicy(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) return False;
|
||||
|
||||
*sid = r.out.info->domain.sid;
|
||||
return True;
|
||||
}
|
||||
|
||||
static NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, uint16_t level,
|
||||
struct dcerpc_pipe *p,
|
||||
struct policy_handle *handle,
|
||||
struct dom_sid **sids, uint32_t num_sids,
|
||||
struct lsa_TransNameArray *names)
|
||||
{
|
||||
struct lsa_LookupSids r;
|
||||
struct lsa_SidArray sidarray;
|
||||
uint32_t count = 0;
|
||||
uint32_t i;
|
||||
|
||||
names->count = 0;
|
||||
names->names = NULL;
|
||||
|
||||
sidarray.num_sids = num_sids;
|
||||
sidarray.sids = talloc_array(mem_ctx, struct lsa_SidPtr, num_sids);
|
||||
|
||||
for (i=0; i<num_sids; i++) {
|
||||
sidarray.sids[i].sid = sids[i];
|
||||
}
|
||||
|
||||
r.in.handle = handle;
|
||||
r.in.sids = &sidarray;
|
||||
r.in.names = names;
|
||||
r.in.level = level;
|
||||
r.in.count = &count;
|
||||
r.out.names = names;
|
||||
r.out.count = &count;
|
||||
|
||||
return dcerpc_lsa_LookupSids(p, mem_ctx, &r);
|
||||
}
|
||||
|
||||
static const char *sid_type_lookup(enum lsa_SidType r)
|
||||
{
|
||||
switch (r) {
|
||||
case SID_NAME_USE_NONE: return "SID_NAME_USE_NONE"; break;
|
||||
case SID_NAME_USER: return "SID_NAME_USER"; break;
|
||||
case SID_NAME_DOM_GRP: return "SID_NAME_DOM_GRP"; break;
|
||||
case SID_NAME_DOMAIN: return "SID_NAME_DOMAIN"; break;
|
||||
case SID_NAME_ALIAS: return "SID_NAME_ALIAS"; break;
|
||||
case SID_NAME_WKN_GRP: return "SID_NAME_WKN_GRP"; break;
|
||||
case SID_NAME_DELETED: return "SID_NAME_DELETED"; break;
|
||||
case SID_NAME_INVALID: return "SID_NAME_INVALID"; break;
|
||||
case SID_NAME_UNKNOWN: return "SID_NAME_UNKNOWN"; break;
|
||||
}
|
||||
return "Invalid sid type\n";
|
||||
}
|
||||
|
||||
static BOOL test_lookupsids(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p,
|
||||
struct policy_handle *handle,
|
||||
struct dom_sid **sids, uint32_t num_sids,
|
||||
int level, NTSTATUS expected_result,
|
||||
enum lsa_SidType *types)
|
||||
{
|
||||
struct lsa_TransNameArray names;
|
||||
NTSTATUS status;
|
||||
uint32_t i;
|
||||
BOOL ret = True;
|
||||
|
||||
status = lookup_sids(mem_ctx, level, p, handle, sids, num_sids,
|
||||
&names);
|
||||
if (!NT_STATUS_EQUAL(status, expected_result)) {
|
||||
printf("For level %d expected %s, got %s\n",
|
||||
level, nt_errstr(expected_result),
|
||||
nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_EQUAL(status, NT_STATUS_OK) &&
|
||||
!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
|
||||
return True;
|
||||
}
|
||||
|
||||
for (i=0; i<num_sids; i++) {
|
||||
if (names.names[i].sid_type != types[i]) {
|
||||
printf("In level %d, for sid %s expected %s, "
|
||||
"got %s\n", level,
|
||||
dom_sid_string(mem_ctx, sids[i]),
|
||||
sid_type_lookup(types[i]),
|
||||
sid_type_lookup(names.names[i].sid_type));
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL get_downleveltrust(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p,
|
||||
struct policy_handle *handle,
|
||||
struct dom_sid **sid)
|
||||
{
|
||||
struct lsa_EnumTrustDom r;
|
||||
uint32_t resume_handle = 0;
|
||||
struct lsa_DomainList domains;
|
||||
NTSTATUS status;
|
||||
int i;
|
||||
|
||||
r.in.handle = handle;
|
||||
r.in.resume_handle = &resume_handle;
|
||||
r.in.max_size = 1000;
|
||||
r.out.domains = &domains;
|
||||
r.out.resume_handle = &resume_handle;
|
||||
|
||||
status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r);
|
||||
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
|
||||
printf("no trusts\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
if (domains.count == 0) {
|
||||
printf("no trusts\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
for (i=0; i<domains.count; i++) {
|
||||
struct lsa_QueryTrustedDomainInfoBySid q;
|
||||
|
||||
if (domains.domains[i].sid == NULL)
|
||||
continue;
|
||||
|
||||
q.in.handle = handle;
|
||||
q.in.dom_sid = domains.domains[i].sid;
|
||||
q.in.level = 6;
|
||||
status = dcerpc_lsa_QueryTrustedDomainInfoBySid(p, mem_ctx, &q);
|
||||
if (!NT_STATUS_IS_OK(status)) continue;
|
||||
|
||||
if ((q.out.info->info_ex.trust_direction & 2) &&
|
||||
(q.out.info->info_ex.trust_type == 1)) {
|
||||
*sid = domains.domains[i].sid;
|
||||
return True;
|
||||
}
|
||||
}
|
||||
|
||||
printf("I need a AD DC with an outgoing trust to NT4\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
#define NUM_SIDS 8
|
||||
|
||||
BOOL torture_rpc_lsa_lookup(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
struct policy_handle *handle;
|
||||
struct dom_sid *dom_sid;
|
||||
struct dom_sid *trusted_sid;
|
||||
struct dom_sid *sids[NUM_SIDS];
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_lsa");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_lsarpc);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ret = False;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret &= open_policy(mem_ctx, p, &handle);
|
||||
if (!ret) goto done;
|
||||
|
||||
ret &= get_domainsid(mem_ctx, p, handle, &dom_sid);
|
||||
if (!ret) goto done;
|
||||
|
||||
ret &= get_downleveltrust(mem_ctx, p, handle, &trusted_sid);
|
||||
if (!ret) goto done;
|
||||
|
||||
printf("domain sid: %s\n", dom_sid_string(mem_ctx, dom_sid));
|
||||
|
||||
sids[0] = dom_sid_parse_talloc(mem_ctx, "S-1-1-0");
|
||||
sids[1] = dom_sid_parse_talloc(mem_ctx, "S-1-5-4");
|
||||
sids[2] = dom_sid_parse_talloc(mem_ctx, "S-1-5-32");
|
||||
sids[3] = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-545");
|
||||
sids[4] = dom_sid_dup(mem_ctx, dom_sid);
|
||||
sids[5] = dom_sid_add_rid(mem_ctx, dom_sid, 512);
|
||||
sids[6] = dom_sid_dup(mem_ctx, trusted_sid);
|
||||
sids[7] = dom_sid_add_rid(mem_ctx, trusted_sid, 512);
|
||||
|
||||
ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 0,
|
||||
NT_STATUS_INVALID_PARAMETER, NULL);
|
||||
|
||||
{
|
||||
enum lsa_SidType types[NUM_SIDS] =
|
||||
{ SID_NAME_WKN_GRP, SID_NAME_WKN_GRP, SID_NAME_DOMAIN,
|
||||
SID_NAME_ALIAS, SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
|
||||
SID_NAME_DOMAIN, SID_NAME_DOM_GRP };
|
||||
|
||||
ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 1,
|
||||
NT_STATUS_OK, types);
|
||||
}
|
||||
|
||||
{
|
||||
enum lsa_SidType types[NUM_SIDS] =
|
||||
{ SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
|
||||
SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
|
||||
SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
|
||||
SID_NAME_DOMAIN, SID_NAME_DOM_GRP };
|
||||
ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 2,
|
||||
STATUS_SOME_UNMAPPED, types);
|
||||
}
|
||||
|
||||
{
|
||||
enum lsa_SidType types[NUM_SIDS] =
|
||||
{ SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
|
||||
SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
|
||||
SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
|
||||
SID_NAME_UNKNOWN, SID_NAME_UNKNOWN };
|
||||
ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 3,
|
||||
STATUS_SOME_UNMAPPED, types);
|
||||
}
|
||||
|
||||
{
|
||||
enum lsa_SidType types[NUM_SIDS] =
|
||||
{ SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
|
||||
SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
|
||||
SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
|
||||
SID_NAME_UNKNOWN, SID_NAME_UNKNOWN };
|
||||
ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 4,
|
||||
STATUS_SOME_UNMAPPED, types);
|
||||
}
|
||||
|
||||
ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 5,
|
||||
NT_STATUS_NONE_MAPPED, NULL);
|
||||
|
||||
{
|
||||
enum lsa_SidType types[NUM_SIDS] =
|
||||
{ SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
|
||||
SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
|
||||
SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
|
||||
SID_NAME_UNKNOWN, SID_NAME_UNKNOWN };
|
||||
ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 6,
|
||||
STATUS_SOME_UNMAPPED, types);
|
||||
}
|
||||
|
||||
ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 7,
|
||||
NT_STATUS_INVALID_PARAMETER, NULL);
|
||||
ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 8,
|
||||
NT_STATUS_INVALID_PARAMETER, NULL);
|
||||
ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 9,
|
||||
NT_STATUS_INVALID_PARAMETER, NULL);
|
||||
ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 10,
|
||||
NT_STATUS_INVALID_PARAMETER, NULL);
|
||||
|
||||
done:
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for mgmt rpc operations
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_mgmt_c.h"
|
||||
#include "auth/gensec/gensec.h"
|
||||
#include "librpc/rpc/dcerpc_table.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
|
||||
/*
|
||||
ask the server what interface IDs are available on this endpoint
|
||||
*/
|
||||
static BOOL test_inq_if_ids(struct dcerpc_pipe *p,
|
||||
TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct mgmt_inq_if_ids r;
|
||||
int i;
|
||||
|
||||
status = dcerpc_mgmt_inq_if_ids(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("inq_if_ids failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("inq_if_ids gave error code %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!r.out.if_id_vector) {
|
||||
printf("inq_if_ids gave NULL if_id_vector\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
for (i=0;i<r.out.if_id_vector->count;i++) {
|
||||
struct dcerpc_syntax_id *id = r.out.if_id_vector->if_id[i].id;
|
||||
if (!id) continue;
|
||||
|
||||
printf("\tuuid %s version 0x%08x '%s'\n",
|
||||
GUID_string(mem_ctx, &id->uuid),
|
||||
id->if_version, idl_pipe_name(&id->uuid, id->if_version));
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_inq_stats(struct dcerpc_pipe *p,
|
||||
TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct mgmt_inq_stats r;
|
||||
|
||||
r.in.max_count = MGMT_STATS_ARRAY_MAX_SIZE;
|
||||
r.in.unknown = 0;
|
||||
|
||||
status = dcerpc_mgmt_inq_stats(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("inq_stats failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (r.out.statistics.count != MGMT_STATS_ARRAY_MAX_SIZE) {
|
||||
printf("Unexpected array size %d\n", r.out.statistics.count);
|
||||
return False;
|
||||
}
|
||||
|
||||
printf("\tcalls_in %6d calls_out %6d\n\tpkts_in %6d pkts_out %6d\n",
|
||||
r.out.statistics.statistics[MGMT_STATS_CALLS_IN],
|
||||
r.out.statistics.statistics[MGMT_STATS_CALLS_OUT],
|
||||
r.out.statistics.statistics[MGMT_STATS_PKTS_IN],
|
||||
r.out.statistics.statistics[MGMT_STATS_PKTS_OUT]);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_inq_princ_name(struct dcerpc_pipe *p,
|
||||
TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct mgmt_inq_princ_name r;
|
||||
int i;
|
||||
BOOL ret = False;
|
||||
|
||||
for (i=0;i<100;i++) {
|
||||
r.in.authn_proto = i; /* DCERPC_AUTH_TYPE_* */
|
||||
r.in.princ_name_size = 100;
|
||||
|
||||
status = dcerpc_mgmt_inq_princ_name(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
continue;
|
||||
}
|
||||
if (W_ERROR_IS_OK(r.out.result)) {
|
||||
const char *name = gensec_get_name_by_authtype(i);
|
||||
ret = True;
|
||||
if (name) {
|
||||
printf("\tprinciple name for proto %u (%s) is '%s'\n",
|
||||
i, name, r.out.princ_name);
|
||||
} else {
|
||||
printf("\tprinciple name for proto %u is '%s'\n",
|
||||
i, r.out.princ_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
printf("\tno principle names?\n");
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_is_server_listening(struct dcerpc_pipe *p,
|
||||
TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct mgmt_is_server_listening r;
|
||||
|
||||
status = dcerpc_mgmt_is_server_listening(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("is_server_listening failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (r.out.status != 0 || r.out.result == 0) {
|
||||
printf("\tserver is NOT listening\n");
|
||||
} else {
|
||||
printf("\tserver is listening\n");
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_stop_server_listening(struct dcerpc_pipe *p,
|
||||
TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct mgmt_stop_server_listening r;
|
||||
|
||||
status = dcerpc_mgmt_stop_server_listening(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("stop_server_listening failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("\tserver refused to stop listening - %s\n", win_errstr(r.out.result));
|
||||
} else {
|
||||
printf("\tserver allowed a stop_server_listening request\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
BOOL torture_rpc_mgmt(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx, *loop_ctx;
|
||||
BOOL ret = True;
|
||||
const char *binding = torture_setting_string(torture, "binding", NULL);
|
||||
const struct dcerpc_interface_list *l;
|
||||
struct dcerpc_binding *b;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_mgmt");
|
||||
|
||||
if (!binding) {
|
||||
printf("You must supply a ncacn binding string\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
status = dcerpc_parse_binding(mem_ctx, binding, &b);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
printf("Failed to parse binding '%s'\n", binding);
|
||||
return False;
|
||||
}
|
||||
|
||||
for (l=librpc_dcerpc_pipes();l;l=l->next) {
|
||||
loop_ctx = talloc_named(mem_ctx, 0, "torture_rpc_mgmt loop context");
|
||||
|
||||
/* some interfaces are not mappable */
|
||||
if (l->table->num_calls == 0 ||
|
||||
strcmp(l->table->name, "mgmt") == 0) {
|
||||
talloc_free(loop_ctx);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\nTesting pipe '%s'\n", l->table->name);
|
||||
|
||||
if (b->transport == NCACN_IP_TCP) {
|
||||
status = dcerpc_epm_map_binding(loop_ctx, b, l->table, NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Failed to map port for uuid %s\n",
|
||||
GUID_string(loop_ctx, &l->table->syntax_id.uuid));
|
||||
talloc_free(loop_ctx);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
b->endpoint = talloc_strdup(b, l->table->name);
|
||||
}
|
||||
|
||||
lp_set_cmdline("torture:binding", dcerpc_binding_string(loop_ctx, b));
|
||||
|
||||
status = torture_rpc_connection(loop_ctx, &p, &dcerpc_table_mgmt);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(loop_ctx);
|
||||
ret = False;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!test_is_server_listening(p, loop_ctx)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!test_stop_server_listening(p, loop_ctx)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!test_inq_stats(p, loop_ctx)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!test_inq_princ_name(p, loop_ctx)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!test_inq_if_ids(p, loop_ctx)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for oxidresolve operations
|
||||
|
||||
Copyright (C) Jelmer Vernooij 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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_oxidresolver_c.h"
|
||||
#include "librpc/gen_ndr/ndr_remact_c.h"
|
||||
#include "librpc/gen_ndr/epmapper.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
#include "librpc/gen_ndr/ndr_dcom.h"
|
||||
|
||||
#define CLSID_IMAGEDOC "02B01C80-E03D-101A-B294-00DD010F2BF9"
|
||||
|
||||
static int test_RemoteActivation(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, uint64_t *oxid, struct GUID *oid)
|
||||
{
|
||||
struct RemoteActivation r;
|
||||
NTSTATUS status;
|
||||
struct GUID iids[2];
|
||||
uint16_t protseq[3] = { EPM_PROTOCOL_TCP, EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_UUID };
|
||||
|
||||
ZERO_STRUCT(r.in);
|
||||
r.in.this.version.MajorVersion = 5;
|
||||
r.in.this.version.MinorVersion = 1;
|
||||
r.in.this.cid = GUID_random();
|
||||
GUID_from_string(CLSID_IMAGEDOC, &r.in.Clsid);
|
||||
r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY;
|
||||
r.in.num_protseqs = 3;
|
||||
r.in.protseq = protseq;
|
||||
r.in.Interfaces = 1;
|
||||
iids[0] = dcerpc_table_IUnknown.syntax_id.uuid;
|
||||
r.in.pIIDs = iids;
|
||||
r.out.pOxid = oxid;
|
||||
r.out.ipidRemUnknown = oid;
|
||||
|
||||
status = dcerpc_RemoteActivation(p, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
fprintf(stderr, "RemoteActivation: %s\n", nt_errstr(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(r.out.result)) {
|
||||
fprintf(stderr, "RemoteActivation: %s\n", win_errstr(r.out.result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(*r.out.hr)) {
|
||||
fprintf(stderr, "RemoteActivation: %s\n", win_errstr(*r.out.hr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(r.out.results[0])) {
|
||||
fprintf(stderr, "RemoteActivation: %s\n", win_errstr(r.out.results[0]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_SimplePing(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, uint64_t setid)
|
||||
{
|
||||
struct SimplePing r;
|
||||
NTSTATUS status;
|
||||
|
||||
r.in.SetId = &setid;
|
||||
|
||||
status = dcerpc_SimplePing(p, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
fprintf(stderr, "SimplePing: %s\n", nt_errstr(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(r.out.result)) {
|
||||
fprintf(stderr, "SimplePing: %s\n", win_errstr(r.out.result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_ComplexPing(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, uint64_t *setid, struct GUID oid)
|
||||
{
|
||||
struct ComplexPing r;
|
||||
NTSTATUS status;
|
||||
|
||||
*setid = 0;
|
||||
ZERO_STRUCT(r.in);
|
||||
|
||||
r.in.SequenceNum = 0;
|
||||
r.in.SetId = setid;
|
||||
r.in.cAddToSet = 1;
|
||||
r.in.AddToSet = &oid;
|
||||
|
||||
status = dcerpc_ComplexPing(p, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
fprintf(stderr, "ComplexPing: %s\n", nt_errstr(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(r.out.result)) {
|
||||
fprintf(stderr, "ComplexPing: %s\n", win_errstr(r.out.result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_ServerAlive(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct ServerAlive r;
|
||||
NTSTATUS status;
|
||||
|
||||
status = dcerpc_ServerAlive(p, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
fprintf(stderr, "ServerAlive: %s\n", nt_errstr(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(r.out.result)) {
|
||||
fprintf(stderr, "ServerAlive: %s\n", win_errstr(r.out.result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_ResolveOxid(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, uint64_t oxid)
|
||||
{
|
||||
struct ResolveOxid r;
|
||||
NTSTATUS status;
|
||||
uint16_t protseq[2] = { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB };
|
||||
|
||||
r.in.pOxid = oxid;
|
||||
r.in.cRequestedProtseqs = 2;
|
||||
r.in.arRequestedProtseqs = protseq;
|
||||
|
||||
status = dcerpc_ResolveOxid(p, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
fprintf(stderr, "ResolveOxid: %s\n", nt_errstr(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(r.out.result)) {
|
||||
fprintf(stderr, "ResolveOxid: %s\n", win_errstr(r.out.result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_ResolveOxid2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, uint64_t oxid)
|
||||
{
|
||||
struct ResolveOxid2 r;
|
||||
NTSTATUS status;
|
||||
uint16_t protseq[2] = { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB };
|
||||
|
||||
r.in.pOxid = oxid;
|
||||
r.in.cRequestedProtseqs = 2;
|
||||
r.in.arRequestedProtseqs = protseq;
|
||||
|
||||
status = dcerpc_ResolveOxid2(p, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
fprintf(stderr, "ResolveOxid2: %s\n", nt_errstr(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(r.out.result)) {
|
||||
fprintf(stderr, "ResolveOxid2: %s\n", win_errstr(r.out.result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Remote server versions: %d, %d\n", r.out.ComVersion->MajorVersion, r.out.ComVersion->MinorVersion);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int test_ServerAlive2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct ServerAlive2 r;
|
||||
NTSTATUS status;
|
||||
|
||||
status = dcerpc_ServerAlive2(p, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
fprintf(stderr, "ServerAlive2: %s\n", nt_errstr(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(r.out.result)) {
|
||||
fprintf(stderr, "ServerAlive2: %s\n", win_errstr(r.out.result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL torture_rpc_oxidresolve(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p, *premact;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
uint64_t setid;
|
||||
uint64_t oxid;
|
||||
struct GUID oid;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_oxidresolve");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx,
|
||||
&premact,
|
||||
&dcerpc_table_IRemoteActivation);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
status = torture_rpc_connection(mem_ctx,
|
||||
&p,
|
||||
&dcerpc_table_IOXIDResolver);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
if(!test_ServerAlive(p, mem_ctx))
|
||||
ret = False;
|
||||
|
||||
if(!test_ServerAlive2(p, mem_ctx))
|
||||
ret = False;
|
||||
|
||||
if(!test_RemoteActivation(premact, mem_ctx, &oxid, &oid))
|
||||
return False;
|
||||
|
||||
if(!test_ComplexPing(p, mem_ctx, &setid, oid))
|
||||
ret = False;
|
||||
|
||||
if(!test_SimplePing(p, mem_ctx, setid))
|
||||
ret = False;
|
||||
|
||||
if(!test_ResolveOxid(p, mem_ctx, oxid))
|
||||
ret = False;
|
||||
|
||||
if(!test_ResolveOxid2(p, mem_ctx, oxid))
|
||||
ret = False;
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for remoteactivation operations
|
||||
|
||||
Copyright (C) Jelmer Vernooij 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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_remact_c.h"
|
||||
#include "librpc/gen_ndr/ndr_epmapper_c.h"
|
||||
#include "librpc/gen_ndr/ndr_dcom.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
#define CLSID_IMAGEDOC "02B01C80-E03D-101A-B294-00DD010F2BF9"
|
||||
|
||||
static int test_RemoteActivation(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct RemoteActivation r;
|
||||
NTSTATUS status;
|
||||
struct GUID iids[1];
|
||||
uint16_t protseq[3] = { EPM_PROTOCOL_TCP, EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_UUID };
|
||||
|
||||
ZERO_STRUCT(r.in);
|
||||
r.in.this.version.MajorVersion = 5;
|
||||
r.in.this.version.MinorVersion = 1;
|
||||
r.in.this.cid = GUID_random();
|
||||
GUID_from_string(CLSID_IMAGEDOC, &r.in.Clsid);
|
||||
r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY;
|
||||
r.in.num_protseqs = 3;
|
||||
r.in.protseq = protseq;
|
||||
r.in.Interfaces = 1;
|
||||
GUID_from_string(DCERPC_IUNKNOWN_UUID, &iids[0]);
|
||||
r.in.pIIDs = iids;
|
||||
|
||||
status = dcerpc_RemoteActivation(p, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
printf("RemoteActivation: %s\n", nt_errstr(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("RemoteActivation: %s\n", win_errstr(r.out.result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(*r.out.hr)) {
|
||||
printf("RemoteActivation: %s\n", win_errstr(*r.out.hr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(r.out.results[0])) {
|
||||
printf("RemoteActivation: %s\n", win_errstr(r.out.results[0]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
GUID_from_string(DCERPC_ICLASSFACTORY_UUID, &iids[0]);
|
||||
r.in.Interfaces = 1;
|
||||
r.in.Mode = MODE_GET_CLASS_OBJECT;
|
||||
|
||||
status = dcerpc_RemoteActivation(p, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
printf("RemoteActivation(GetClassObject): %s\n", nt_errstr(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("RemoteActivation(GetClassObject): %s\n", win_errstr(r.out.result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(*r.out.hr)) {
|
||||
printf("RemoteActivation(GetClassObject): %s\n", win_errstr(*r.out.hr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!W_ERROR_IS_OK(r.out.results[0])) {
|
||||
printf("RemoteActivation(GetClassObject): %s\n", win_errstr(r.out.results[0]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL torture_rpc_remact(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_remact");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx,
|
||||
&p,
|
||||
&dcerpc_table_IRemoteActivation);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
if(!test_RemoteActivation(p, mem_ctx))
|
||||
ret = False;
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for the running object table
|
||||
|
||||
Copyright (C) Jelmer Vernooij 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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_rot.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
BOOL torture_rpc_rot(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_rot");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx,
|
||||
&p,
|
||||
&dcerpc_table_rot);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
SMB torture tester
|
||||
Copyright (C) Andrew Tridgell 1997-2003
|
||||
Copyright (C) Jelmer Vernooij 2006
|
||||
|
||||
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"
|
||||
#include "auth/credentials/credentials.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
#include "librpc/rpc/dcerpc.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/rpc/dcerpc_table.h"
|
||||
#include "lib/util/dlinklist.h"
|
||||
|
||||
/* open a rpc connection to the chosen binding string */
|
||||
_PUBLIC_ NTSTATUS torture_rpc_connection(TALLOC_CTX *parent_ctx,
|
||||
struct dcerpc_pipe **p,
|
||||
const struct dcerpc_interface_table *table)
|
||||
{
|
||||
NTSTATUS status;
|
||||
const char *binding = lp_parm_string(-1, "torture", "binding");
|
||||
|
||||
if (!binding) {
|
||||
printf("You must specify a ncacn binding string\n");
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
status = dcerpc_pipe_connect(parent_ctx,
|
||||
p, binding, table,
|
||||
cmdline_credentials, NULL);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Failed to connect to remote server: %s %s\n", binding, nt_errstr(status));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* open a rpc connection to a specific transport */
|
||||
NTSTATUS torture_rpc_connection_transport(TALLOC_CTX *parent_ctx,
|
||||
struct dcerpc_pipe **p,
|
||||
const struct dcerpc_interface_table *table,
|
||||
enum dcerpc_transport_t transport)
|
||||
{
|
||||
NTSTATUS status;
|
||||
const char *binding = lp_parm_string(-1, "torture", "binding");
|
||||
struct dcerpc_binding *b;
|
||||
TALLOC_CTX *mem_ctx = talloc_named(parent_ctx, 0, "torture_rpc_connection_smb");
|
||||
|
||||
if (!binding) {
|
||||
printf("You must specify a ncacn binding string\n");
|
||||
talloc_free(mem_ctx);
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
status = dcerpc_parse_binding(mem_ctx, binding, &b);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("Failed to parse dcerpc binding '%s'\n", binding));
|
||||
talloc_free(mem_ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
b->transport = transport;
|
||||
|
||||
status = dcerpc_pipe_connect_b(mem_ctx, p, b, table,
|
||||
cmdline_credentials, NULL);
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
*p = talloc_reference(parent_ctx, *p);
|
||||
} else {
|
||||
*p = NULL;
|
||||
}
|
||||
talloc_free(mem_ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
static bool torture_rpc_setup (struct torture_context *tctx, void **data)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
status = torture_rpc_connection(tctx,
|
||||
(struct dcerpc_pipe **)data,
|
||||
(const struct dcerpc_interface_table *)tctx->active_tcase->data);
|
||||
|
||||
torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool torture_rpc_teardown (struct torture_context *tcase, void *data)
|
||||
{
|
||||
talloc_free(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
_PUBLIC_ struct torture_tcase *torture_suite_add_rpc_iface_tcase(struct torture_suite *suite,
|
||||
const char *name,
|
||||
const struct dcerpc_interface_table *table)
|
||||
{
|
||||
struct torture_tcase *tcase = torture_suite_add_tcase(suite, name);
|
||||
|
||||
tcase->setup = torture_rpc_setup;
|
||||
tcase->teardown = torture_rpc_teardown;
|
||||
tcase->data = table;
|
||||
|
||||
return tcase;
|
||||
}
|
||||
|
||||
static bool torture_rpc_wrap_test(struct torture_context *tctx,
|
||||
struct torture_tcase *tcase,
|
||||
struct torture_test *test)
|
||||
{
|
||||
bool (*fn) (struct torture_context *, struct dcerpc_pipe *);
|
||||
|
||||
fn = test->fn;
|
||||
|
||||
return fn(tctx, (struct dcerpc_pipe *)tcase->data);
|
||||
}
|
||||
|
||||
_PUBLIC_ struct torture_test *torture_rpc_tcase_add_test(
|
||||
struct torture_tcase *tcase,
|
||||
const char *name,
|
||||
bool (*fn) (struct torture_context *, struct dcerpc_pipe *))
|
||||
{
|
||||
struct torture_test *test;
|
||||
|
||||
test = talloc(tcase, struct torture_test);
|
||||
|
||||
test->name = talloc_strdup(test, name);
|
||||
test->description = NULL;
|
||||
test->run = torture_rpc_wrap_test;
|
||||
test->dangerous = false;
|
||||
test->data = NULL;
|
||||
test->fn = fn;
|
||||
|
||||
DLIST_ADD(tcase->tests, test);
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
NTSTATUS torture_rpc_init(void)
|
||||
{
|
||||
struct torture_suite *suite = torture_suite_create(
|
||||
talloc_autofree_context(),
|
||||
"RPC");
|
||||
dcerpc_init();
|
||||
|
||||
dcerpc_table_init();
|
||||
|
||||
torture_suite_add_simple_test(suite, "LSA", torture_rpc_lsa);
|
||||
torture_suite_add_simple_test(suite, "LSALOOKUP", torture_rpc_lsa_lookup);
|
||||
torture_suite_add_simple_test(suite, "LSA-GETUSER", torture_rpc_lsa_get_user);
|
||||
torture_suite_add_simple_test(suite, "SECRETS", torture_rpc_lsa_secrets);
|
||||
torture_suite_add_suite(suite, torture_rpc_echo());
|
||||
torture_suite_add_suite(suite, torture_rpc_dfs());
|
||||
torture_suite_add_suite(suite, torture_rpc_unixinfo());
|
||||
torture_suite_add_suite(suite, torture_rpc_eventlog());
|
||||
torture_suite_add_suite(suite, torture_rpc_atsvc());
|
||||
torture_suite_add_suite(suite, torture_rpc_wkssvc());
|
||||
torture_suite_add_simple_test(suite, "SPOOLSS", torture_rpc_spoolss);
|
||||
torture_suite_add_simple_test(suite, "SAMR", torture_rpc_samr);
|
||||
torture_suite_add_simple_test(suite, "SAMR-USERS", torture_rpc_samr_users);
|
||||
torture_suite_add_simple_test(suite, "SAMR-PASSWORDS", torture_rpc_samr_passwords);
|
||||
torture_suite_add_simple_test(suite, "NETLOGON", torture_rpc_netlogon);
|
||||
torture_suite_add_simple_test(suite, "SAMLOGON", torture_rpc_samlogon);
|
||||
torture_suite_add_simple_test(suite, "SAMSYNC", torture_rpc_samsync);
|
||||
torture_suite_add_simple_test(suite, "SCHANNEL", torture_rpc_schannel);
|
||||
torture_suite_add_simple_test(suite, "SRVSVC", torture_rpc_srvsvc);
|
||||
torture_suite_add_simple_test(suite, "SVCCTL", torture_rpc_svcctl);
|
||||
torture_suite_add_simple_test(suite, "EPMAPPER", torture_rpc_epmapper);
|
||||
torture_suite_add_simple_test(suite, "WINREG", torture_rpc_winreg);
|
||||
torture_suite_add_simple_test(suite, "INITSHUTDOWN", torture_rpc_initshutdown);
|
||||
torture_suite_add_simple_test(suite, "OXIDRESOLVE", torture_rpc_oxidresolve);
|
||||
torture_suite_add_simple_test(suite, "REMACT", torture_rpc_remact);
|
||||
torture_suite_add_simple_test(suite, "MGMT", torture_rpc_mgmt);
|
||||
torture_suite_add_simple_test(suite, "SCANNER", torture_rpc_scanner);
|
||||
torture_suite_add_simple_test(suite, "AUTOIDL", torture_rpc_autoidl);
|
||||
torture_suite_add_simple_test(suite, "COUNTCALLS", torture_rpc_countcalls);
|
||||
torture_suite_add_simple_test(suite, "MULTIBIND", torture_multi_bind);
|
||||
torture_suite_add_simple_test(suite, "AUTHCONTEXT", torture_bind_authcontext);
|
||||
torture_suite_add_simple_test(suite, "BINDSAMBA3", torture_bind_samba3);
|
||||
torture_suite_add_simple_test(suite, "NETLOGSAMBA3", torture_netlogon_samba3);
|
||||
torture_suite_add_simple_test(suite, "SAMBA3SESSIONKEY", torture_samba3_sessionkey);
|
||||
torture_suite_add_simple_test(suite, "SAMBA3-SRVSVC", torture_samba3_rpc_srvsvc);
|
||||
torture_suite_add_simple_test(suite, "SAMBA3-SHARESEC",
|
||||
torture_samba3_rpc_sharesec);
|
||||
torture_suite_add_simple_test(suite, "SAMBA3-GETUSERNAME",
|
||||
torture_samba3_rpc_getusername);
|
||||
torture_suite_add_simple_test(suite, "SAMBA3-LSA", torture_samba3_rpc_lsa);
|
||||
torture_suite_add_simple_test(suite, "SAMBA3-SPOOLSS", torture_samba3_rpc_spoolss);
|
||||
torture_suite_add_simple_test(suite, "SAMBA3-WKSSVC", torture_samba3_rpc_wkssvc);
|
||||
torture_suite_add_simple_test(suite, "RPC-SAMBA3-WINREG", torture_samba3_rpc_winreg);
|
||||
torture_suite_add_simple_test(suite, "DRSUAPI", torture_rpc_drsuapi);
|
||||
torture_suite_add_simple_test(suite, "CRACKNAMES", torture_rpc_drsuapi_cracknames);
|
||||
torture_suite_add_simple_test(suite, "ROT", torture_rpc_rot);
|
||||
torture_suite_add_simple_test(suite, "DSSETUP", torture_rpc_dssetup);
|
||||
torture_suite_add_simple_test(suite, "ALTERCONTEXT", torture_rpc_alter_context);
|
||||
torture_suite_add_simple_test(suite, "JOIN", torture_rpc_join);
|
||||
torture_suite_add_simple_test(suite, "DSSYNC", torture_rpc_dssync);
|
||||
torture_suite_add_simple_test(suite, "BENCH-RPC", torture_bench_rpc);
|
||||
torture_suite_add_simple_test(suite, "ASYNCBIND", torture_async_bind);
|
||||
|
||||
suite->description = talloc_strdup(suite,
|
||||
"DCE/RPC protocol and interface tests");
|
||||
|
||||
torture_register_suite(suite);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
SMB torture tester
|
||||
Copyright (C) Andrew Tridgell 1997-2003
|
||||
Copyright (C) Jelmer Vernooij 2006
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __TORTURE_RPC_H__
|
||||
#define __TORTURE_RPC_H__
|
||||
|
||||
#include "torture/torture.h"
|
||||
#include "auth/credentials/credentials.h"
|
||||
#include "torture/rpc/drsuapi.h"
|
||||
#include "libnet/libnet_join.h"
|
||||
#include "librpc/rpc/dcerpc.h"
|
||||
#include "libcli/raw/libcliraw.h"
|
||||
#include "torture/rpc/proto.h"
|
||||
#include "torture/ui.h"
|
||||
|
||||
#endif /* __TORTURE_RPC_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
scanner for rpc calls
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_mgmt_c.h"
|
||||
#include "librpc/rpc/dcerpc_table.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
/*
|
||||
work out how many calls there are for an interface
|
||||
*/
|
||||
static BOOL test_num_calls(const struct dcerpc_interface_table *iface,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct dcerpc_syntax_id *id)
|
||||
{
|
||||
struct dcerpc_pipe *p;
|
||||
NTSTATUS status;
|
||||
int i;
|
||||
DATA_BLOB stub_in, stub_out;
|
||||
int idl_calls;
|
||||
struct dcerpc_interface_table tbl;
|
||||
|
||||
/* FIXME: This should be fixed when torture_rpc_connection
|
||||
* takes a dcerpc_syntax_id */
|
||||
tbl.name = iface->name;
|
||||
tbl.syntax_id = *id;
|
||||
|
||||
status = torture_rpc_connection(mem_ctx, &p, iface);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
char *uuid_str = GUID_string(mem_ctx, &id->uuid);
|
||||
printf("Failed to connect to '%s' on '%s' - %s\n",
|
||||
uuid_str, iface->name, nt_errstr(status));
|
||||
talloc_free(uuid_str);
|
||||
return False;
|
||||
}
|
||||
|
||||
/* make null calls */
|
||||
stub_in = data_blob(NULL, 1000);
|
||||
memset(stub_in.data, 0xFF, stub_in.length);
|
||||
|
||||
for (i=0;i<200;i++) {
|
||||
status = dcerpc_request(p, NULL, False, i, mem_ctx, &stub_in, &stub_out);
|
||||
if (!NT_STATUS_IS_OK(status) &&
|
||||
p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status) && p->last_fault_code == 5) {
|
||||
printf("\tpipe disconnected at %d\n", i);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status) && p->last_fault_code == 0x80010111) {
|
||||
printf("\terr 0x80010111 at %d\n", i);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\t%d calls available\n", i);
|
||||
idl_calls = idl_num_calls(&id->uuid, id->if_version);
|
||||
if (idl_calls == -1) {
|
||||
printf("\tinterface not known in local IDL\n");
|
||||
} else if (i != idl_calls) {
|
||||
printf("\tWARNING: local IDL defines %u calls\n", idl_calls);
|
||||
} else {
|
||||
printf("\tOK: matches num_calls in local IDL\n");
|
||||
}
|
||||
|
||||
done:
|
||||
talloc_free(p);
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
ask the server what interface IDs are available on this endpoint
|
||||
*/
|
||||
static BOOL test_inq_if_ids(struct dcerpc_pipe *p,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const struct dcerpc_interface_table *iface)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct mgmt_inq_if_ids r;
|
||||
int i;
|
||||
|
||||
status = dcerpc_mgmt_inq_if_ids(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("inq_if_ids failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("inq_if_ids gave error code %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!r.out.if_id_vector) {
|
||||
printf("inq_if_ids gave NULL if_id_vector\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
for (i=0;i<r.out.if_id_vector->count;i++) {
|
||||
const char *uuid;
|
||||
struct dcerpc_syntax_id *id = r.out.if_id_vector->if_id[i].id;
|
||||
if (!id) continue;
|
||||
|
||||
uuid = GUID_string(mem_ctx, &id->uuid),
|
||||
|
||||
printf("\n\tuuid %s version 0x%08x '%s'\n",
|
||||
uuid,
|
||||
id->if_version, idl_pipe_name(&id->uuid, id->if_version));
|
||||
|
||||
test_num_calls(iface, mem_ctx, id);
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
BOOL torture_rpc_scanner(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx, *loop_ctx;
|
||||
BOOL ret = True;
|
||||
const struct dcerpc_interface_list *l;
|
||||
const char *binding = torture_setting_string(torture, "binding", NULL);
|
||||
struct dcerpc_binding *b;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_scanner");
|
||||
|
||||
if (!binding) {
|
||||
talloc_free(mem_ctx);
|
||||
printf("You must supply a ncacn binding string\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
status = dcerpc_parse_binding(mem_ctx, binding, &b);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
printf("Failed to parse binding '%s'\n", binding);
|
||||
return False;
|
||||
}
|
||||
|
||||
for (l=librpc_dcerpc_pipes();l;l=l->next) {
|
||||
loop_ctx = talloc_named(mem_ctx, 0, "torture_rpc_scanner loop context");
|
||||
/* some interfaces are not mappable */
|
||||
if (l->table->num_calls == 0 ||
|
||||
strcmp(l->table->name, "mgmt") == 0) {
|
||||
talloc_free(loop_ctx);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\nTesting pipe '%s'\n", l->table->name);
|
||||
|
||||
if (b->transport == NCACN_IP_TCP) {
|
||||
status = dcerpc_epm_map_binding(mem_ctx, b, l->table, NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Failed to map port for uuid %s\n",
|
||||
GUID_string(loop_ctx, &l->table->syntax_id.uuid));
|
||||
talloc_free(loop_ctx);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
b->endpoint = talloc_strdup(b, l->table->name);
|
||||
}
|
||||
|
||||
lp_set_cmdline("torture:binding", dcerpc_binding_string(mem_ctx, b));
|
||||
|
||||
status = torture_rpc_connection(loop_ctx, &p, &dcerpc_table_mgmt);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(loop_ctx);
|
||||
ret = False;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!test_inq_if_ids(p, mem_ctx, l->table)) {
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
test suite for schannel operations
|
||||
|
||||
Copyright (C) Andrew Tridgell 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"
|
||||
#include "librpc/gen_ndr/ndr_netlogon_c.h"
|
||||
#include "librpc/gen_ndr/ndr_lsa_c.h"
|
||||
#include "librpc/gen_ndr/ndr_samr_c.h"
|
||||
#include "auth/credentials/credentials.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
#include "auth/gensec/schannel_proto.h"
|
||||
#include "libcli/auth/libcli_auth.h"
|
||||
#include "libcli/security/security.h"
|
||||
|
||||
#define TEST_MACHINE_NAME "schannel"
|
||||
|
||||
/*
|
||||
try a netlogon SamLogon
|
||||
*/
|
||||
BOOL test_netlogon_ex_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct cli_credentials *credentials,
|
||||
struct creds_CredentialState *creds)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct netr_LogonSamLogonEx r;
|
||||
struct netr_NetworkInfo ninfo;
|
||||
DATA_BLOB names_blob, chal, lm_resp, nt_resp;
|
||||
int i;
|
||||
BOOL ret = True;
|
||||
int flags = CLI_CRED_NTLM_AUTH;
|
||||
if (lp_client_lanman_auth()) {
|
||||
flags |= CLI_CRED_LANMAN_AUTH;
|
||||
}
|
||||
|
||||
if (lp_client_ntlmv2_auth()) {
|
||||
flags |= CLI_CRED_NTLMv2_AUTH;
|
||||
}
|
||||
|
||||
cli_credentials_get_ntlm_username_domain(cmdline_credentials, mem_ctx,
|
||||
&ninfo.identity_info.account_name.string,
|
||||
&ninfo.identity_info.domain_name.string);
|
||||
|
||||
generate_random_buffer(ninfo.challenge,
|
||||
sizeof(ninfo.challenge));
|
||||
chal = data_blob_const(ninfo.challenge,
|
||||
sizeof(ninfo.challenge));
|
||||
|
||||
names_blob = NTLMv2_generate_names_blob(mem_ctx, cli_credentials_get_workstation(credentials),
|
||||
cli_credentials_get_domain(credentials));
|
||||
|
||||
status = cli_credentials_get_ntlm_response(cmdline_credentials, mem_ctx,
|
||||
&flags,
|
||||
chal,
|
||||
names_blob,
|
||||
&lm_resp, &nt_resp,
|
||||
NULL, NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("cli_credentials_get_ntlm_response failed: %s\n",
|
||||
nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
ninfo.lm.data = lm_resp.data;
|
||||
ninfo.lm.length = lm_resp.length;
|
||||
|
||||
ninfo.nt.data = nt_resp.data;
|
||||
ninfo.nt.length = nt_resp.length;
|
||||
|
||||
ninfo.identity_info.parameter_control = 0;
|
||||
ninfo.identity_info.logon_id_low = 0;
|
||||
ninfo.identity_info.logon_id_high = 0;
|
||||
ninfo.identity_info.workstation.string = cli_credentials_get_workstation(credentials);
|
||||
|
||||
r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
|
||||
r.in.computer_name = cli_credentials_get_workstation(credentials);
|
||||
r.in.logon_level = 2;
|
||||
r.in.logon.network = &ninfo;
|
||||
r.in.flags = 0;
|
||||
|
||||
printf("Testing LogonSamLogonEx with name %s\n", ninfo.identity_info.account_name.string);
|
||||
|
||||
for (i=2;i<3;i++) {
|
||||
r.in.validation_level = i;
|
||||
|
||||
status = dcerpc_netr_LogonSamLogonEx(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("LogonSamLogon failed: %s\n",
|
||||
nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
do some samr ops using the schannel connection
|
||||
*/
|
||||
static BOOL test_samr_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct samr_GetDomPwInfo r;
|
||||
struct samr_Connect connect;
|
||||
struct samr_OpenDomain opendom;
|
||||
int i;
|
||||
struct lsa_String name;
|
||||
struct policy_handle handle;
|
||||
struct policy_handle domain_handle;
|
||||
|
||||
name.string = lp_workgroup();
|
||||
r.in.domain_name = &name;
|
||||
|
||||
connect.in.system_name = 0;
|
||||
connect.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
connect.out.connect_handle = &handle;
|
||||
|
||||
printf("Testing Connect and OpenDomain on BUILTIN\n");
|
||||
|
||||
status = dcerpc_samr_Connect(p, mem_ctx, &connect);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
|
||||
printf("Connect failed (expected, schannel mapped to anonymous): %s\n",
|
||||
nt_errstr(status));
|
||||
} else {
|
||||
printf("Connect failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
} else {
|
||||
opendom.in.connect_handle = &handle;
|
||||
opendom.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
opendom.in.sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32");
|
||||
opendom.out.domain_handle = &domain_handle;
|
||||
|
||||
status = dcerpc_samr_OpenDomain(p, mem_ctx, &opendom);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("OpenDomain failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
|
||||
|
||||
/* do several ops to test credential chaining */
|
||||
for (i=0;i<5;i++) {
|
||||
status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
|
||||
printf("GetDomPwInfo op %d failed - %s\n", i, nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
do some lsa ops using the schannel connection
|
||||
*/
|
||||
static BOOL test_lsa_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct lsa_GetUserName r;
|
||||
NTSTATUS status;
|
||||
BOOL ret = True;
|
||||
struct lsa_StringPointer authority_name_p;
|
||||
|
||||
printf("\nTesting GetUserName\n");
|
||||
|
||||
r.in.system_name = "\\";
|
||||
r.in.account_name = NULL;
|
||||
r.in.authority_name = &authority_name_p;
|
||||
authority_name_p.string = NULL;
|
||||
|
||||
/* do several ops to test credential chaining and various operations */
|
||||
status = dcerpc_lsa_GetUserName(p, mem_ctx, &r);
|
||||
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED)) {
|
||||
printf("not considering %s to be an error\n", nt_errstr(status));
|
||||
} else if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("GetUserName failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
} else {
|
||||
if (!r.out.account_name) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if (strcmp(r.out.account_name->string, "ANONYMOUS LOGON") != 0) {
|
||||
printf("GetUserName returned wrong user: %s, expected %s\n",
|
||||
r.out.account_name->string, "ANONYMOUS LOGON");
|
||||
return False;
|
||||
}
|
||||
if (!r.out.authority_name || !r.out.authority_name->string) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if (strcmp(r.out.authority_name->string->string, "NT AUTHORITY") != 0) {
|
||||
printf("GetUserName returned wrong user: %s, expected %s\n",
|
||||
r.out.authority_name->string->string, "NT AUTHORITY");
|
||||
return False;
|
||||
}
|
||||
}
|
||||
if (!test_many_LookupSids(p, mem_ctx, NULL)) {
|
||||
printf("LsaLookupSids3 failed!\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
test a schannel connection with the given flags
|
||||
*/
|
||||
static BOOL test_schannel(TALLOC_CTX *mem_ctx,
|
||||
uint16_t acct_flags, uint32_t dcerpc_flags,
|
||||
int i)
|
||||
{
|
||||
BOOL ret = True;
|
||||
|
||||
struct test_join *join_ctx;
|
||||
NTSTATUS status;
|
||||
const char *binding = lp_parm_string(-1, "torture", "binding");
|
||||
struct dcerpc_binding *b;
|
||||
struct dcerpc_pipe *p = NULL;
|
||||
struct dcerpc_pipe *p_netlogon = NULL;
|
||||
struct dcerpc_pipe *p_netlogon2 = NULL;
|
||||
struct dcerpc_pipe *p_netlogon3 = NULL;
|
||||
struct dcerpc_pipe *p_samr2 = NULL;
|
||||
struct dcerpc_pipe *p_lsa = NULL;
|
||||
struct creds_CredentialState *creds;
|
||||
struct cli_credentials *credentials;
|
||||
|
||||
TALLOC_CTX *test_ctx = talloc_named(mem_ctx, 0, "test_schannel context");
|
||||
|
||||
join_ctx = torture_join_domain(talloc_asprintf(mem_ctx, "%s%d", TEST_MACHINE_NAME, i),
|
||||
acct_flags, &credentials);
|
||||
if (!join_ctx) {
|
||||
printf("Failed to join domain with acct_flags=0x%x\n", acct_flags);
|
||||
talloc_free(test_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
status = dcerpc_parse_binding(test_ctx, binding, &b);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Bad binding string %s\n", binding);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
b->flags &= ~DCERPC_AUTH_OPTIONS;
|
||||
b->flags |= dcerpc_flags;
|
||||
|
||||
status = dcerpc_pipe_connect_b(test_ctx, &p, b, &dcerpc_table_samr,
|
||||
credentials, NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Failed to connect with schannel: %s\n", nt_errstr(status));
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (!test_samr_ops(p, test_ctx)) {
|
||||
printf("Failed to process schannel secured SAMR ops\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
/* Also test that when we connect to the netlogon pipe, that
|
||||
* the credentials we setup on the first pipe are valid for
|
||||
* the second */
|
||||
|
||||
/* Swap the binding details from SAMR to NETLOGON */
|
||||
status = dcerpc_epm_map_binding(test_ctx, b, &dcerpc_table_netlogon, NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
status = dcerpc_secondary_connection(p, &p_netlogon,
|
||||
b);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
status = dcerpc_bind_auth(p_netlogon, &dcerpc_table_netlogon,
|
||||
credentials, DCERPC_AUTH_TYPE_SCHANNEL,
|
||||
dcerpc_auth_level(p->conn),
|
||||
NULL);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
status = dcerpc_schannel_creds(p_netlogon->conn->security_state.generic_state, test_ctx, &creds);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* do a couple of logins */
|
||||
if (!test_netlogon_ops(p_netlogon, test_ctx, credentials, creds)) {
|
||||
printf("Failed to process schannel secured NETLOGON ops\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!test_netlogon_ex_ops(p_netlogon, test_ctx, credentials, creds)) {
|
||||
printf("Failed to process schannel secured NETLOGON EX ops\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
/* Swap the binding details from SAMR to LSARPC */
|
||||
status = dcerpc_epm_map_binding(test_ctx, b, &dcerpc_table_lsarpc, NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
status = dcerpc_secondary_connection(p, &p_lsa,
|
||||
b);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
status = dcerpc_bind_auth(p_lsa, &dcerpc_table_lsarpc,
|
||||
credentials, DCERPC_AUTH_TYPE_SCHANNEL,
|
||||
dcerpc_auth_level(p->conn),
|
||||
NULL);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (!test_lsa_ops(p_lsa, test_ctx)) {
|
||||
printf("Failed to process schannel secured LSA ops\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
/* Drop the socket, we want to start from scratch */
|
||||
talloc_free(p);
|
||||
p = NULL;
|
||||
|
||||
/* Now see what we are still allowed to do */
|
||||
|
||||
status = dcerpc_parse_binding(test_ctx, binding, &b);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Bad binding string %s\n", binding);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
b->flags &= ~DCERPC_AUTH_OPTIONS;
|
||||
b->flags |= dcerpc_flags;
|
||||
|
||||
status = dcerpc_pipe_connect_b(test_ctx, &p_samr2, b, &dcerpc_table_samr,
|
||||
credentials, NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Failed to connect with schannel: %s\n", nt_errstr(status));
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* do a some SAMR operations. We have *not* done a new serverauthenticate */
|
||||
if (!test_samr_ops(p_samr2, test_ctx)) {
|
||||
printf("Failed to process schannel secured SAMR ops (on fresh connection)\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Swap the binding details from SAMR to NETLOGON */
|
||||
status = dcerpc_epm_map_binding(test_ctx, b, &dcerpc_table_netlogon, NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
status = dcerpc_secondary_connection(p_samr2, &p_netlogon2,
|
||||
b);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* and now setup an SCHANNEL bind on netlogon */
|
||||
status = dcerpc_bind_auth(p_netlogon2, &dcerpc_table_netlogon,
|
||||
credentials, DCERPC_AUTH_TYPE_SCHANNEL,
|
||||
dcerpc_auth_level(p_samr2->conn),
|
||||
NULL);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Try the schannel-only SamLogonEx operation */
|
||||
if (!test_netlogon_ex_ops(p_netlogon2, test_ctx, credentials, creds)) {
|
||||
printf("Failed to process schannel secured NETLOGON EX ops (on fresh connection)\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
/* And the more traditional style, proving that the
|
||||
* credentials chaining state is fully present */
|
||||
if (!test_netlogon_ops(p_netlogon2, test_ctx, credentials, creds)) {
|
||||
printf("Failed to process schannel secured NETLOGON ops (on fresh connection)\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
/* Drop the socket, we want to start from scratch (again) */
|
||||
talloc_free(p_samr2);
|
||||
|
||||
/* We don't want schannel for this test */
|
||||
b->flags &= ~DCERPC_AUTH_OPTIONS;
|
||||
|
||||
status = dcerpc_pipe_connect_b(test_ctx, &p_netlogon3, b, &dcerpc_table_netlogon,
|
||||
credentials, NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Failed to connect without schannel: %s\n", nt_errstr(status));
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (test_netlogon_ex_ops(p_netlogon3, test_ctx, credentials, creds)) {
|
||||
printf("Processed NOT schannel secured NETLOGON EX ops without SCHANNEL (unsafe)\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!test_netlogon_ops(p_netlogon3, test_ctx, credentials, creds)) {
|
||||
printf("Failed to processed NOT schannel secured NETLOGON ops without new ServerAuth\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
torture_leave_domain(join_ctx);
|
||||
talloc_free(test_ctx);
|
||||
return ret;
|
||||
|
||||
failed:
|
||||
torture_leave_domain(join_ctx);
|
||||
talloc_free(test_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
/*
|
||||
a schannel test suite
|
||||
*/
|
||||
BOOL torture_rpc_schannel(struct torture_context *torture)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
struct {
|
||||
uint16_t acct_flags;
|
||||
uint32_t dcerpc_flags;
|
||||
} tests[] = {
|
||||
{ ACB_WSTRUST, DCERPC_SCHANNEL | DCERPC_SIGN},
|
||||
{ ACB_WSTRUST, DCERPC_SCHANNEL | DCERPC_SEAL},
|
||||
{ ACB_WSTRUST, DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128},
|
||||
{ ACB_WSTRUST, DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_128 },
|
||||
{ ACB_SVRTRUST, DCERPC_SCHANNEL | DCERPC_SIGN },
|
||||
{ ACB_SVRTRUST, DCERPC_SCHANNEL | DCERPC_SEAL },
|
||||
{ ACB_SVRTRUST, DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128 },
|
||||
{ ACB_SVRTRUST, DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_128 }
|
||||
};
|
||||
int i;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_schannel");
|
||||
|
||||
for (i=0;i<ARRAY_SIZE(tests);i++) {
|
||||
if (!test_schannel(mem_ctx,
|
||||
tests[i].acct_flags, tests[i].dcerpc_flags,
|
||||
i)) {
|
||||
printf("Failed with acct_flags=0x%x dcerpc_flags=0x%x \n",
|
||||
tests[i].acct_flags, tests[i].dcerpc_flags);
|
||||
ret = False;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for lsa rpc operations
|
||||
|
||||
Copyright (C) Andrew Tridgell 2003
|
||||
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_lsa_c.h"
|
||||
|
||||
#include "libcli/auth/libcli_auth.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
static void init_lsa_String(struct lsa_String *name, const char *s)
|
||||
{
|
||||
name->string = s;
|
||||
}
|
||||
|
||||
static BOOL test_CreateSecret_basic(struct dcerpc_pipe *p,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct lsa_CreateSecret r;
|
||||
struct lsa_SetSecret r3;
|
||||
struct lsa_QuerySecret r4;
|
||||
struct policy_handle sec_handle;
|
||||
struct lsa_Delete d;
|
||||
struct lsa_DATA_BUF buf1;
|
||||
struct lsa_DATA_BUF_PTR bufp1;
|
||||
DATA_BLOB enc_key;
|
||||
BOOL ret = True;
|
||||
DATA_BLOB session_key;
|
||||
NTTIME old_mtime, new_mtime;
|
||||
DATA_BLOB blob1, blob2;
|
||||
const char *secret1 = "abcdef12345699qwerty";
|
||||
char *secret2;
|
||||
char *secname;
|
||||
|
||||
secname = talloc_asprintf(mem_ctx, "torturesecret-%u", (uint_t)random());
|
||||
|
||||
printf("Testing CreateSecret of %s\n", secname);
|
||||
|
||||
init_lsa_String(&r.in.name, secname);
|
||||
|
||||
r.in.handle = handle;
|
||||
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
r.out.sec_handle = &sec_handle;
|
||||
|
||||
status = dcerpc_lsa_CreateSecret(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("CreateSecret failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
status = dcerpc_fetch_session_key(p, &session_key);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("dcerpc_fetch_session_key failed - %s\n", nt_errstr(status));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
enc_key = sess_encrypt_string(secret1, &session_key);
|
||||
|
||||
r3.in.sec_handle = &sec_handle;
|
||||
r3.in.new_val = &buf1;
|
||||
r3.in.old_val = NULL;
|
||||
r3.in.new_val->data = enc_key.data;
|
||||
r3.in.new_val->length = enc_key.length;
|
||||
r3.in.new_val->size = enc_key.length;
|
||||
|
||||
printf("Testing SetSecret\n");
|
||||
|
||||
status = dcerpc_lsa_SetSecret(p, mem_ctx, &r3);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("SetSecret failed - %s\n", nt_errstr(status));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
r3.in.sec_handle = &sec_handle;
|
||||
r3.in.new_val = &buf1;
|
||||
r3.in.old_val = NULL;
|
||||
r3.in.new_val->data = enc_key.data;
|
||||
r3.in.new_val->length = enc_key.length;
|
||||
r3.in.new_val->size = enc_key.length;
|
||||
|
||||
/* break the encrypted data */
|
||||
enc_key.data[0]++;
|
||||
|
||||
printf("Testing SetSecret with broken key\n");
|
||||
|
||||
status = dcerpc_lsa_SetSecret(p, mem_ctx, &r3);
|
||||
if (!NT_STATUS_EQUAL(status, NT_STATUS_UNKNOWN_REVISION)) {
|
||||
printf("SetSecret should have failed UNKNOWN_REVISION - %s\n", nt_errstr(status));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
data_blob_free(&enc_key);
|
||||
|
||||
ZERO_STRUCT(new_mtime);
|
||||
ZERO_STRUCT(old_mtime);
|
||||
|
||||
/* fetch the secret back again */
|
||||
r4.in.sec_handle = &sec_handle;
|
||||
r4.in.new_val = &bufp1;
|
||||
r4.in.new_mtime = &new_mtime;
|
||||
r4.in.old_val = NULL;
|
||||
r4.in.old_mtime = NULL;
|
||||
|
||||
bufp1.buf = NULL;
|
||||
|
||||
printf("Testing QuerySecret\n");
|
||||
status = dcerpc_lsa_QuerySecret(p, mem_ctx, &r4);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("QuerySecret failed - %s\n", nt_errstr(status));
|
||||
ret = False;
|
||||
} else {
|
||||
if (r4.out.new_val == NULL || r4.out.new_val->buf == NULL) {
|
||||
printf("No secret buffer returned\n");
|
||||
ret = False;
|
||||
} else {
|
||||
blob1.data = r4.out.new_val->buf->data;
|
||||
blob1.length = r4.out.new_val->buf->size;
|
||||
|
||||
blob2 = data_blob_talloc(mem_ctx, NULL, blob1.length);
|
||||
|
||||
secret2 = sess_decrypt_string(mem_ctx, &blob1, &session_key);
|
||||
|
||||
if (strcmp(secret1, secret2) != 0) {
|
||||
printf("Returned secret '%s' doesn't match '%s'\n",
|
||||
secret2, secret1);
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d.in.handle = &sec_handle;
|
||||
status = dcerpc_lsa_Delete(p, mem_ctx, &d);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("delete should have returned OKINVALID_HANDLE - %s\n", nt_errstr(status));
|
||||
ret = False;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* TEST session key correctness by pushing and pulling secrets */
|
||||
|
||||
BOOL torture_rpc_lsa_secrets(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
struct policy_handle *handle;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_lsa_secrets");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx,
|
||||
&p,
|
||||
&dcerpc_table_lsarpc);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (test_lsa_OpenPolicy2(p, mem_ctx, &handle)) {
|
||||
if (!handle) {
|
||||
printf("OpenPolicy2 failed. This test cannot run against this server\n");
|
||||
ret = False;
|
||||
} else if (!test_CreateSecret_basic(p, mem_ctx, handle)) {
|
||||
ret = False;
|
||||
}
|
||||
} else {
|
||||
return False;
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for srvsvc rpc operations
|
||||
|
||||
Copyright (C) Jelmer Vernooij 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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_svcctl_c.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
static BOOL test_EnumServicesStatus(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *h)
|
||||
{
|
||||
struct svcctl_EnumServicesStatusW r;
|
||||
int i;
|
||||
NTSTATUS status;
|
||||
uint32_t resume_handle = 0;
|
||||
struct ENUM_SERVICE_STATUS *service = NULL;
|
||||
|
||||
r.in.handle = h;
|
||||
r.in.type = SERVICE_TYPE_WIN32;
|
||||
r.in.state = SERVICE_STATE_ALL;
|
||||
r.in.buf_size = 0;
|
||||
r.in.resume_handle = &resume_handle;
|
||||
r.out.service = NULL;
|
||||
r.out.resume_handle = &resume_handle;
|
||||
r.out.services_returned = 0;
|
||||
r.out.bytes_needed = 0;
|
||||
|
||||
status = dcerpc_svcctl_EnumServicesStatusW(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("ËnumServicesStatus failed!\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
|
||||
r.in.buf_size = r.out.bytes_needed;
|
||||
r.out.service = talloc_size(mem_ctx, r.out.bytes_needed);
|
||||
|
||||
status = dcerpc_svcctl_EnumServicesStatusW(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("ËnumServicesStatus failed!\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("EnumServicesStatus failed\n");
|
||||
return False;
|
||||
}
|
||||
service = (struct ENUM_SERVICE_STATUS *)r.out.service;
|
||||
}
|
||||
|
||||
for(i = 0; i < r.out.services_returned; i++) {
|
||||
printf("Type: %d, State: %d\n", service[i].status.type, service[i].status.state);
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_OpenSCManager(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *h)
|
||||
{
|
||||
struct svcctl_OpenSCManagerW r;
|
||||
NTSTATUS status;
|
||||
|
||||
r.in.MachineName = NULL;
|
||||
r.in.DatabaseName = NULL;
|
||||
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
r.out.handle = h;
|
||||
|
||||
status = dcerpc_svcctl_OpenSCManagerW(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("OpenSCManager failed!\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_CloseServiceHandle(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *h)
|
||||
{
|
||||
struct svcctl_CloseServiceHandle r;
|
||||
NTSTATUS status;
|
||||
r.in.handle = h;
|
||||
r.out.handle = h;
|
||||
status = dcerpc_svcctl_CloseServiceHandle(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("CloseServiceHandle failed\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL torture_rpc_svcctl(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
struct policy_handle h;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
|
||||
mem_ctx = talloc_init("torture_rpc_svcctl");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_svcctl);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!test_OpenSCManager(p, mem_ctx, &h)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!test_EnumServicesStatus(p, mem_ctx, &h)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!test_CloseServiceHandle(p, mem_ctx, &h)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for unixinfo rpc operations
|
||||
|
||||
Copyright (C) Volker Lendecke 2005
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
#include "librpc/gen_ndr/ndr_unixinfo_c.h"
|
||||
#include "libcli/security/security.h"
|
||||
|
||||
/**
|
||||
test the SidToUid interface
|
||||
*/
|
||||
static BOOL test_sidtouid(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct unixinfo_SidToUid r;
|
||||
struct dom_sid *sid;
|
||||
|
||||
sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1234-5432");
|
||||
r.in.sid = *sid;
|
||||
|
||||
status = dcerpc_unixinfo_SidToUid(p, mem_ctx, &r);
|
||||
if (NT_STATUS_EQUAL(NT_STATUS_NONE_MAPPED, status)) {
|
||||
} else if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("SidToUid failed == %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
test the UidToSid interface
|
||||
*/
|
||||
static bool test_uidtosid(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
struct unixinfo_UidToSid r;
|
||||
struct dom_sid sid;
|
||||
|
||||
r.in.uid = 1000;
|
||||
r.out.sid = &sid;
|
||||
|
||||
torture_assert_ntstatus_ok(tctx, dcerpc_unixinfo_UidToSid(p, tctx, &r),
|
||||
"UidToSid failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_getpwuid(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
uint64_t uids[512];
|
||||
uint32_t num_uids = ARRAY_SIZE(uids);
|
||||
uint32_t i;
|
||||
struct unixinfo_GetPWUid r;
|
||||
NTSTATUS result;
|
||||
|
||||
for (i=0; i<num_uids; i++) {
|
||||
uids[i] = i;
|
||||
}
|
||||
|
||||
r.in.count = &num_uids;
|
||||
r.in.uids = uids;
|
||||
r.out.count = &num_uids;
|
||||
r.out.infos = talloc_array(tctx, struct unixinfo_GetPWUidInfo, num_uids);
|
||||
|
||||
result = dcerpc_unixinfo_GetPWUid(p, tctx, &r);
|
||||
|
||||
torture_assert_ntstatus_ok(tctx, result, "GetPWUid failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
test the SidToGid interface
|
||||
*/
|
||||
static BOOL test_sidtogid(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct unixinfo_SidToGid r;
|
||||
struct dom_sid *sid;
|
||||
|
||||
sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1234-5432");
|
||||
r.in.sid = *sid;
|
||||
|
||||
status = dcerpc_unixinfo_SidToGid(p, mem_ctx, &r);
|
||||
if (NT_STATUS_EQUAL(NT_STATUS_NONE_MAPPED, status)) {
|
||||
} else if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("SidToGid failed == %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
test the GidToSid interface
|
||||
*/
|
||||
static BOOL test_gidtosid(struct torture_context *tctx, struct dcerpc_pipe *p)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct unixinfo_GidToSid r;
|
||||
struct dom_sid sid;
|
||||
|
||||
r.in.gid = 1000;
|
||||
r.out.sid = &sid;
|
||||
|
||||
status = dcerpc_unixinfo_GidToSid(p, tctx, &r);
|
||||
if (NT_STATUS_EQUAL(NT_STATUS_NO_SUCH_GROUP, status)) {
|
||||
} else torture_assert_ntstatus_ok(tctx, status, "GidToSid failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct torture_suite *torture_rpc_unixinfo(void)
|
||||
{
|
||||
struct torture_suite *suite;
|
||||
struct torture_tcase *tcase;
|
||||
|
||||
suite = torture_suite_create(talloc_autofree_context(), "UNIXINFO");
|
||||
tcase = torture_suite_add_rpc_iface_tcase(suite, "unixinfo",
|
||||
&dcerpc_table_unixinfo);
|
||||
|
||||
torture_rpc_tcase_add_test(tcase, "uidtosid", test_uidtosid);
|
||||
torture_rpc_tcase_add_test(tcase, "getpwuid", test_getpwuid);
|
||||
torture_rpc_tcase_add_test(tcase, "gidtosid", test_gidtosid);
|
||||
|
||||
return suite;
|
||||
}
|
||||
@@ -0,0 +1,846 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for winreg rpc operations
|
||||
|
||||
Copyright (C) Tim Potter 2003
|
||||
Copyright (C) Jelmer Vernooij 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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_winreg_c.h"
|
||||
#include "librpc/gen_ndr/ndr_security.h"
|
||||
#include "libcli/security/security.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
#define TEST_KEY_BASE "smbtorture test"
|
||||
#define TEST_KEY1 TEST_KEY_BASE "\\spottyfoot"
|
||||
#define TEST_KEY2 TEST_KEY_BASE "\\with a SD (#1)"
|
||||
|
||||
static void init_initshutdown_String(TALLOC_CTX *mem_ctx, struct initshutdown_String *name, const char *s)
|
||||
{
|
||||
name->name = talloc(mem_ctx, struct initshutdown_String_sub);
|
||||
name->name->name = s;
|
||||
}
|
||||
|
||||
static void init_winreg_String(struct winreg_String *name, const char *s)
|
||||
{
|
||||
name->name = s;
|
||||
if (s) {
|
||||
name->name_len = 2 * (strlen_m(s) + 1);
|
||||
name->name_size = name->name_len;
|
||||
} else {
|
||||
name->name_len = 0;
|
||||
name->name_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL test_GetVersion(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct winreg_GetVersion r;
|
||||
uint32_t v;
|
||||
printf("\ntesting GetVersion\n");
|
||||
|
||||
ZERO_STRUCT(r);
|
||||
r.in.handle = handle;
|
||||
r.out.version = &v;
|
||||
|
||||
status = dcerpc_winreg_GetVersion(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("GetVersion failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("GetVersion failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_NotifyChangeKeyValue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle)
|
||||
{
|
||||
struct winreg_NotifyChangeKeyValue r;
|
||||
NTSTATUS status;
|
||||
|
||||
printf("\ntesting NotifyChangeKeyValue\n");
|
||||
|
||||
r.in.handle = handle;
|
||||
r.in.watch_subtree = 1;
|
||||
r.in.notify_filter = 0;
|
||||
r.in.unknown = r.in.unknown2 = 0;
|
||||
init_winreg_String(&r.in.string1, NULL);
|
||||
init_winreg_String(&r.in.string2, NULL);
|
||||
|
||||
status = dcerpc_winreg_NotifyChangeKeyValue(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("NotifyChangeKeyValue failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("NotifyChangeKeyValue failed - %s - not considering\n", win_errstr(r.out.result));
|
||||
return True;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_CreateKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle, const char *name,
|
||||
const char *class)
|
||||
{
|
||||
struct winreg_CreateKey r;
|
||||
struct policy_handle newhandle;
|
||||
NTSTATUS status;
|
||||
enum winreg_CreateAction action_taken = 0;
|
||||
|
||||
printf("\ntesting CreateKey\n");
|
||||
|
||||
r.in.handle = handle;
|
||||
r.out.new_handle = &newhandle;
|
||||
init_winreg_String(&r.in.name, name);
|
||||
init_winreg_String(&r.in.keyclass, class);
|
||||
r.in.options = 0x0;
|
||||
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
r.in.action_taken = r.out.action_taken = &action_taken;
|
||||
r.in.secdesc = NULL;
|
||||
|
||||
status = dcerpc_winreg_CreateKey(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("CreateKey failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("CreateKey failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
createkey testing with a SD
|
||||
*/
|
||||
static BOOL test_CreateKey_sd(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle, const char *name,
|
||||
const char *class, struct policy_handle *newhandle)
|
||||
{
|
||||
struct winreg_CreateKey r;
|
||||
NTSTATUS status;
|
||||
enum winreg_CreateAction action_taken = 0;
|
||||
struct security_descriptor *sd;
|
||||
DATA_BLOB sdblob;
|
||||
struct winreg_SecBuf secbuf;
|
||||
|
||||
sd = security_descriptor_create(mem_ctx,
|
||||
NULL, NULL,
|
||||
SID_NT_AUTHENTICATED_USERS,
|
||||
SEC_ACE_TYPE_ACCESS_ALLOWED,
|
||||
SEC_GENERIC_ALL,
|
||||
SEC_ACE_FLAG_OBJECT_INHERIT,
|
||||
NULL);
|
||||
|
||||
status = ndr_push_struct_blob(&sdblob, mem_ctx, sd,
|
||||
(ndr_push_flags_fn_t)ndr_push_security_descriptor);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("Failed to push security_descriptor ?!\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
secbuf.sd.data = sdblob.data;
|
||||
secbuf.sd.len = sdblob.length;
|
||||
secbuf.sd.size = sdblob.length;
|
||||
secbuf.length = sdblob.length-10;
|
||||
secbuf.inherit = 0;
|
||||
|
||||
printf("\ntesting CreateKey with sd\n");
|
||||
|
||||
r.in.handle = handle;
|
||||
r.out.new_handle = newhandle;
|
||||
init_winreg_String(&r.in.name, name);
|
||||
init_winreg_String(&r.in.keyclass, class);
|
||||
r.in.options = 0x0;
|
||||
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
r.in.action_taken = r.out.action_taken = &action_taken;
|
||||
r.in.secdesc = &secbuf;
|
||||
|
||||
status = dcerpc_winreg_CreateKey(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("CreateKey with sd failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("CreateKey with sd failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_GetKeySecurity(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct winreg_GetKeySecurity r;
|
||||
struct security_descriptor sd;
|
||||
DATA_BLOB sdblob;
|
||||
|
||||
printf("\ntesting GetKeySecurity\n");
|
||||
|
||||
ZERO_STRUCT(r);
|
||||
|
||||
r.in.handle = handle;
|
||||
r.in.sd = r.out.sd = talloc_zero(mem_ctx, struct KeySecurityData);
|
||||
r.in.sd->size = 0x1000;
|
||||
r.in.sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
|
||||
|
||||
status = dcerpc_winreg_GetKeySecurity(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("GetKeySecurity failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("GetKeySecurity failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
sdblob.data = r.out.sd->data;
|
||||
sdblob.length = r.out.sd->len;
|
||||
|
||||
status = ndr_pull_struct_blob(&sdblob, mem_ctx, &sd,
|
||||
(ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("pull_security_descriptor failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
if (p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
|
||||
NDR_PRINT_DEBUG(security_descriptor, &sd);
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_CloseKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct winreg_CloseKey r;
|
||||
|
||||
printf("\ntesting CloseKey\n");
|
||||
|
||||
r.in.handle = r.out.handle = handle;
|
||||
|
||||
status = dcerpc_winreg_CloseKey(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("CloseKey failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("CloseKey failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_FlushKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct winreg_FlushKey r;
|
||||
|
||||
printf("\ntesting FlushKey\n");
|
||||
|
||||
r.in.handle = handle;
|
||||
|
||||
status = dcerpc_winreg_FlushKey(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("FlushKey failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("FlushKey failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_OpenKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *hive_handle,
|
||||
const char *keyname, struct policy_handle *key_handle)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct winreg_OpenKey r;
|
||||
|
||||
printf("\ntesting OpenKey\n");
|
||||
|
||||
r.in.parent_handle = hive_handle;
|
||||
init_winreg_String(&r.in.keyname, keyname);
|
||||
r.in.unknown = 0x00000000;
|
||||
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
r.out.handle = key_handle;
|
||||
|
||||
status = dcerpc_winreg_OpenKey(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("OpenKey failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("OpenKey failed - %s\n", win_errstr(r.out.result));
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_Cleanup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle, const char *key)
|
||||
{
|
||||
struct winreg_DeleteKey r;
|
||||
|
||||
r.in.handle = handle;
|
||||
|
||||
init_winreg_String(&r.in.key, key);
|
||||
dcerpc_winreg_DeleteKey(p, mem_ctx, &r);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
static BOOL test_DeleteKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle, const char *key)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct winreg_DeleteKey r;
|
||||
|
||||
printf("\ntesting DeleteKey\n");
|
||||
|
||||
r.in.handle = handle;
|
||||
init_winreg_String(&r.in.key, key);
|
||||
|
||||
status = dcerpc_winreg_DeleteKey(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("DeleteKey failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("DeleteKey failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_QueryInfoKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle, char *class)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct winreg_QueryInfoKey r;
|
||||
uint32_t num_subkeys, max_subkeylen, max_subkeysize,
|
||||
num_values, max_valnamelen, max_valbufsize,
|
||||
secdescsize;
|
||||
NTTIME last_changed_time;
|
||||
|
||||
printf("\ntesting QueryInfoKey\n");
|
||||
|
||||
ZERO_STRUCT(r);
|
||||
r.in.handle = handle;
|
||||
r.out.num_subkeys = &num_subkeys;
|
||||
r.out.max_subkeylen = &max_subkeylen;
|
||||
r.out.max_subkeysize = &max_subkeysize;
|
||||
r.out.num_values = &num_values;
|
||||
r.out.max_valnamelen = &max_valnamelen;
|
||||
r.out.max_valbufsize = &max_valbufsize;
|
||||
r.out.secdescsize = &secdescsize;
|
||||
r.out.last_changed_time = &last_changed_time;
|
||||
|
||||
init_winreg_String(&r.in.class_in, class);
|
||||
|
||||
status = dcerpc_winreg_QueryInfoKey(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("QueryInfoKey failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("QueryInfoKey failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_key(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle, int depth);
|
||||
|
||||
static BOOL test_EnumKey(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle, int depth)
|
||||
{
|
||||
struct winreg_EnumKey r;
|
||||
struct winreg_StringBuf class, name;
|
||||
NTSTATUS status;
|
||||
NTTIME t = 0;
|
||||
|
||||
printf("Testing EnumKey\n\n");
|
||||
|
||||
class.name = "";
|
||||
class.size = 1024;
|
||||
|
||||
r.in.handle = handle;
|
||||
r.in.enum_index = 0;
|
||||
r.in.name = &name;
|
||||
r.in.keyclass = &class;
|
||||
r.out.name = &name;
|
||||
r.in.last_changed_time = &t;
|
||||
|
||||
do {
|
||||
name.name = NULL;
|
||||
name.size = 1024;
|
||||
|
||||
status = dcerpc_winreg_EnumKey(p, mem_ctx, &r);
|
||||
|
||||
if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
|
||||
struct policy_handle key_handle;
|
||||
|
||||
printf("EnumKey: %d: %s\n", r.in.enum_index, r.out.name->name);
|
||||
|
||||
if (!test_OpenKey(
|
||||
p, mem_ctx, handle, r.out.name->name,
|
||||
&key_handle)) {
|
||||
} else {
|
||||
test_key(p, mem_ctx, &key_handle, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
r.in.enum_index++;
|
||||
|
||||
} while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result));
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("EnumKey failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result) && !W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
|
||||
printf("EnumKey failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_QueryMultipleValues(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle, const char *valuename)
|
||||
{
|
||||
struct winreg_QueryMultipleValues r;
|
||||
NTSTATUS status;
|
||||
uint32_t bufsize=0;
|
||||
|
||||
printf("Testing QueryMultipleValues\n");
|
||||
|
||||
r.in.key_handle = handle;
|
||||
r.in.values = r.out.values = talloc_array(mem_ctx, struct QueryMultipleValue, 1);
|
||||
r.in.values[0].name = talloc(mem_ctx, struct winreg_String);
|
||||
r.in.values[0].name->name = valuename;
|
||||
r.in.values[0].offset = 0;
|
||||
r.in.values[0].length = 0;
|
||||
r.in.values[0].type = 0;
|
||||
|
||||
r.in.num_values = 1;
|
||||
r.in.buffer_size = r.out.buffer_size = talloc(mem_ctx, uint32_t);
|
||||
*r.in.buffer_size = bufsize;
|
||||
do {
|
||||
*r.in.buffer_size = bufsize;
|
||||
r.in.buffer = r.out.buffer = talloc_zero_array(mem_ctx, uint8_t,
|
||||
*r.in.buffer_size);
|
||||
|
||||
status = dcerpc_winreg_QueryMultipleValues(p, mem_ctx, &r);
|
||||
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
printf("QueryMultipleValues failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
talloc_free(r.in.buffer);
|
||||
bufsize += 0x20;
|
||||
} while (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA));
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("QueryMultipleValues failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_QueryValue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle, const char *valuename)
|
||||
{
|
||||
struct winreg_QueryValue r;
|
||||
NTSTATUS status;
|
||||
enum winreg_Type zero_type = 0;
|
||||
uint32_t offered = 0xfff;
|
||||
uint32_t zero = 0;
|
||||
|
||||
printf("Testing QueryValue\n");
|
||||
|
||||
r.in.handle = handle;
|
||||
r.in.data = NULL;
|
||||
r.in.value_name.name = valuename;
|
||||
r.in.type = &zero_type;
|
||||
r.in.size = &offered;
|
||||
r.in.length = &zero;
|
||||
|
||||
status = dcerpc_winreg_QueryValue(p, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
printf("QueryValue failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("QueryValue failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_EnumValue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle, int max_valnamelen, int max_valbufsize)
|
||||
{
|
||||
struct winreg_EnumValue r;
|
||||
enum winreg_Type type = 0;
|
||||
uint32_t size = max_valbufsize, zero = 0;
|
||||
BOOL ret = True;
|
||||
uint8_t buf8;
|
||||
struct winreg_StringBuf name;
|
||||
|
||||
printf("testing EnumValue\n");
|
||||
|
||||
name.name = "";
|
||||
name.size = 1024;
|
||||
|
||||
r.in.handle = handle;
|
||||
r.in.enum_index = 0;
|
||||
r.in.name = &name;
|
||||
r.out.name = &name;
|
||||
r.in.type = &type;
|
||||
r.in.value = &buf8;
|
||||
r.in.length = &zero;
|
||||
r.in.size = &size;
|
||||
|
||||
do {
|
||||
NTSTATUS status = dcerpc_winreg_EnumValue(p, mem_ctx, &r);
|
||||
if(NT_STATUS_IS_ERR(status)) {
|
||||
printf("EnumValue failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (W_ERROR_IS_OK(r.out.result)) {
|
||||
ret &= test_QueryValue(p, mem_ctx, handle, r.out.name->name);
|
||||
ret &= test_QueryMultipleValues(p, mem_ctx, handle, r.out.name->name);
|
||||
}
|
||||
|
||||
r.in.enum_index++;
|
||||
} while (W_ERROR_IS_OK(r.out.result));
|
||||
|
||||
if(!W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
|
||||
printf("EnumValue failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL test_InitiateSystemShutdown(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
const char *msg, uint32_t timeout)
|
||||
{
|
||||
struct winreg_InitiateSystemShutdown r;
|
||||
NTSTATUS status;
|
||||
uint16_t hostname = 0x0;
|
||||
|
||||
r.in.hostname = &hostname;
|
||||
r.in.message = talloc(mem_ctx, struct initshutdown_String);
|
||||
init_initshutdown_String(mem_ctx, r.in.message, msg);
|
||||
r.in.force_apps = 1;
|
||||
r.in.timeout = timeout;
|
||||
r.in.reboot = 1;
|
||||
|
||||
status = dcerpc_winreg_InitiateSystemShutdown(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("InitiateSystemShutdown failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("InitiateSystemShutdown failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_InitiateSystemShutdownEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
const char *msg, uint32_t timeout)
|
||||
{
|
||||
struct winreg_InitiateSystemShutdownEx r;
|
||||
NTSTATUS status;
|
||||
uint16_t hostname = 0x0;
|
||||
|
||||
r.in.hostname = &hostname;
|
||||
r.in.message = talloc(mem_ctx, struct initshutdown_String);
|
||||
init_initshutdown_String(mem_ctx, r.in.message, msg);
|
||||
r.in.force_apps = 1;
|
||||
r.in.timeout = timeout;
|
||||
r.in.reboot = 1;
|
||||
r.in.reason = 0;
|
||||
|
||||
status = dcerpc_winreg_InitiateSystemShutdownEx(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("InitiateSystemShutdownEx failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("InitiateSystemShutdownEx failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_AbortSystemShutdown(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct winreg_AbortSystemShutdown r;
|
||||
NTSTATUS status;
|
||||
uint16_t server = 0x0;
|
||||
|
||||
r.in.server = &server;
|
||||
|
||||
status = dcerpc_winreg_AbortSystemShutdown(p, mem_ctx, &r);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("AbortSystemShutdown failed - %s\n", nt_errstr(status));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("AbortSystemShutdown failed - %s\n", win_errstr(r.out.result));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
#define MAX_DEPTH 2 /* Only go this far down the tree */
|
||||
|
||||
static BOOL test_key(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
struct policy_handle *handle, int depth)
|
||||
{
|
||||
if (depth == MAX_DEPTH)
|
||||
return True;
|
||||
|
||||
if (!test_QueryInfoKey(p, mem_ctx, handle, NULL)) {
|
||||
}
|
||||
|
||||
|
||||
if (!test_NotifyChangeKeyValue(p, mem_ctx, handle)) {
|
||||
}
|
||||
|
||||
if (!test_GetKeySecurity(p, mem_ctx, handle)) {
|
||||
}
|
||||
|
||||
if (!test_EnumKey(p, mem_ctx, handle, depth)) {
|
||||
}
|
||||
|
||||
if (!test_EnumValue(p, mem_ctx, handle, 0xFF, 0xFFFF)) {
|
||||
}
|
||||
|
||||
|
||||
test_CloseKey(p, mem_ctx, handle);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
typedef NTSTATUS (*winreg_open_fn)(struct dcerpc_pipe *, TALLOC_CTX *, void *);
|
||||
|
||||
static BOOL test_Open(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
|
||||
const char *name, winreg_open_fn open_fn)
|
||||
{
|
||||
struct policy_handle handle, newhandle;
|
||||
BOOL ret = True, created = False, created2 = False, deleted = False;
|
||||
struct winreg_OpenHKLM r;
|
||||
NTSTATUS status;
|
||||
|
||||
printf("Testing %s\n", name);
|
||||
|
||||
r.in.system_name = 0;
|
||||
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
r.out.handle = &handle;
|
||||
|
||||
status = open_fn(p, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
test_Cleanup(p, mem_ctx, &handle, TEST_KEY1);
|
||||
test_Cleanup(p, mem_ctx, &handle, TEST_KEY2);
|
||||
test_Cleanup(p, mem_ctx, &handle, TEST_KEY_BASE);
|
||||
|
||||
if (!test_CreateKey(p, mem_ctx, &handle, TEST_KEY1, NULL)) {
|
||||
printf("CreateKey failed - not considering a failure\n");
|
||||
} else {
|
||||
created = True;
|
||||
}
|
||||
|
||||
if (created && !test_FlushKey(p, mem_ctx, &handle)) {
|
||||
printf("FlushKey failed\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (created && !test_OpenKey(p, mem_ctx, &handle, TEST_KEY1, &newhandle)) {
|
||||
printf("CreateKey failed (OpenKey after Create didn't work)\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (created && !test_DeleteKey(p, mem_ctx, &handle, TEST_KEY1)) {
|
||||
printf("DeleteKey failed\n");
|
||||
ret = False;
|
||||
} else {
|
||||
deleted = True;
|
||||
}
|
||||
|
||||
if (created && !test_FlushKey(p, mem_ctx, &handle)) {
|
||||
printf("FlushKey failed\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (created && deleted &&
|
||||
test_OpenKey(p, mem_ctx, &handle, TEST_KEY1, &newhandle)) {
|
||||
printf("DeleteKey failed (OpenKey after Delete didn't work)\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!test_GetVersion(p, mem_ctx, &handle)) {
|
||||
printf("GetVersion failed\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (created && test_CreateKey_sd(p, mem_ctx, &handle, TEST_KEY2,
|
||||
NULL, &newhandle)) {
|
||||
created2 = True;
|
||||
}
|
||||
|
||||
if (created2 && !test_GetKeySecurity(p, mem_ctx, &newhandle)) {
|
||||
printf("GetKeySecurity failed\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (created2 && !test_CloseKey(p, mem_ctx, &newhandle)) {
|
||||
printf("CloseKey failed\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (created && !test_DeleteKey(p, mem_ctx, &handle, TEST_KEY2)) {
|
||||
printf("DeleteKey failed\n");
|
||||
ret = False;
|
||||
}
|
||||
|
||||
/* The HKCR hive has a very large fanout */
|
||||
|
||||
if (open_fn == (void *)dcerpc_winreg_OpenHKCR) {
|
||||
if(!test_key(p, mem_ctx, &handle, MAX_DEPTH - 1)) {
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
|
||||
if(!test_key(p, mem_ctx, &handle, 0)) {
|
||||
ret = False;
|
||||
}
|
||||
|
||||
test_Cleanup(p, mem_ctx, &handle, TEST_KEY_BASE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL torture_rpc_winreg(struct torture_context *torture)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
BOOL ret = True;
|
||||
struct {
|
||||
const char *name;
|
||||
winreg_open_fn fn;
|
||||
} open_fns[] = {{"OpenHKLM", (winreg_open_fn)dcerpc_winreg_OpenHKLM },
|
||||
{"OpenHKU", (winreg_open_fn)dcerpc_winreg_OpenHKU },
|
||||
{"OpenHKCR", (winreg_open_fn)dcerpc_winreg_OpenHKCR },
|
||||
{"OpenHKCU", (winreg_open_fn)dcerpc_winreg_OpenHKCU }};
|
||||
int i;
|
||||
mem_ctx = talloc_init("torture_rpc_winreg");
|
||||
|
||||
status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_winreg);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!torture_setting_bool(torture, "dangerous", False)) {
|
||||
printf("winreg_InitiateShutdown disabled - enable dangerous tests to use\n");
|
||||
} else {
|
||||
ret &= test_InitiateSystemShutdown(p, mem_ctx, "spottyfood", 30);
|
||||
ret &= test_AbortSystemShutdown(p, mem_ctx);
|
||||
ret &= test_InitiateSystemShutdownEx(p, mem_ctx, "spottyfood", 30);
|
||||
ret &= test_AbortSystemShutdown(p, mem_ctx);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
|
||||
if (!test_Open(p, mem_ctx, open_fns[i].name, open_fns[i].fn))
|
||||
ret = False;
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
test suite for wkssvc rpc operations
|
||||
|
||||
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"
|
||||
#include "torture/torture.h"
|
||||
#include "librpc/gen_ndr/ndr_wkssvc_c.h"
|
||||
#include "torture/rpc/rpc.h"
|
||||
|
||||
static bool test_NetWkstaGetInfo(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct wkssvc_NetWkstaGetInfo r;
|
||||
union wkssvc_NetWkstaInfo info;
|
||||
uint16_t levels[] = {100, 101, 102, 502};
|
||||
int i;
|
||||
|
||||
r.in.server_name = dcerpc_server_name(p);
|
||||
r.out.info = &info;
|
||||
|
||||
for (i=0;i<ARRAY_SIZE(levels);i++) {
|
||||
r.in.level = levels[i];
|
||||
torture_comment(tctx, talloc_asprintf(tctx, "testing NetWkstaGetInfo level %u\n", r.in.level));
|
||||
status = dcerpc_wkssvc_NetWkstaGetInfo(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status,
|
||||
talloc_asprintf(tctx, "NetWkstaGetInfo level %u failed", r.in.level));
|
||||
torture_assert_werr_ok(tctx, r.out.result,
|
||||
talloc_asprintf(tctx, "NetWkstaGetInfo level %u failed", r.in.level));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool test_NetWkstaTransportEnum(struct torture_context *tctx,
|
||||
struct dcerpc_pipe *p)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct wkssvc_NetWkstaTransportEnum r;
|
||||
uint32_t resume_handle = 0;
|
||||
union wkssvc_NetWkstaTransportCtr ctr;
|
||||
struct wkssvc_NetWkstaTransportCtr0 ctr0;
|
||||
|
||||
ZERO_STRUCT(ctr0);
|
||||
ctr.ctr0 = &ctr0;
|
||||
|
||||
r.in.server_name = dcerpc_server_name(p);
|
||||
r.in.level = 0;
|
||||
r.in.ctr = &ctr;
|
||||
r.in.max_buffer = (uint32_t)-1;
|
||||
r.in.resume_handle = &resume_handle;
|
||||
r.out.ctr = &ctr;
|
||||
r.out.resume_handle = &resume_handle;
|
||||
|
||||
status = dcerpc_wkssvc_NetWkstaTransportEnum(p, tctx, &r);
|
||||
torture_assert_ntstatus_ok(tctx, status, "NetWkstaTransportEnum failed");
|
||||
torture_assert_werr_ok(tctx, r.out.result,
|
||||
talloc_asprintf(tctx,
|
||||
"NetWkstaTransportEnum level %u failed", r.in.level));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct torture_suite *torture_rpc_wkssvc(void)
|
||||
{
|
||||
struct torture_suite *suite;
|
||||
struct torture_tcase *tcase;
|
||||
|
||||
suite = torture_suite_create(talloc_autofree_context(), "WKSSVC");
|
||||
tcase = torture_suite_add_rpc_iface_tcase(suite, "wkssvc",
|
||||
&dcerpc_table_wkssvc);
|
||||
|
||||
torture_rpc_tcase_add_test(tcase, "NetWkstaGetInfo", test_NetWkstaGetInfo);
|
||||
torture_rpc_tcase_add_test(tcase, "NetWkstaTransportEnum",
|
||||
test_NetWkstaTransportEnum);
|
||||
return suite;
|
||||
}
|
||||
Reference in New Issue
Block a user