mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
6ded4f5230
These are marked as known_fail pending the next patch ("Extend DsBind and DsGetDomainControllerInfo to work with w2k8"). Signed-off-by: Dirk Godau <voidswitch@gmail.com> Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> Reviewed-by: Garming Sam <garming@catalyst.net.nz>
335 lines
11 KiB
C
335 lines
11 KiB
C
/*
|
|
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-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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "librpc/gen_ndr/ndr_drsuapi_c.h"
|
|
#include "torture/rpc/torture_rpc.h"
|
|
#include "param/param.h"
|
|
|
|
#define TEST_MACHINE_NAME "torturetest"
|
|
|
|
/*
|
|
* DsBind as sent from W2K8 Client.
|
|
* This should work regardless of functional level, and accept
|
|
* any info <=48
|
|
*/
|
|
bool test_DsBind_w2k8(struct torture_context *tctx,
|
|
struct DsPrivate_w2k8 *priv)
|
|
{
|
|
NTSTATUS status;
|
|
struct dcerpc_pipe *p = priv->drs_pipe;
|
|
struct drsuapi_DsBind r;
|
|
struct drsuapi_DsBindInfo48 *bind_info48;
|
|
struct drsuapi_DsBindInfoCtr bind_info_ctr;
|
|
|
|
/* We send info48 */
|
|
ZERO_STRUCT(bind_info_ctr);
|
|
bind_info_ctr.length = 48;
|
|
|
|
bind_info48 = &bind_info_ctr.info.info48;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
|
|
bind_info48->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
|
|
|
|
/*
|
|
* We wish for DRSUAPI_SUPPORTED_EXTENSION_LH_BETA2,
|
|
* needed for DsGetDomainControllerInfo level 3
|
|
*/
|
|
bind_info48->supported_extensions_ext |= DRSUAPI_SUPPORTED_EXTENSION_LH_BETA2;
|
|
|
|
GUID_from_string(DRSUAPI_DS_BIND_GUID, &priv->bind_guid);
|
|
|
|
r.in.bind_guid = &priv->bind_guid;
|
|
r.in.bind_info = &bind_info_ctr;
|
|
r.out.bind_handle = &priv->bind_handle;
|
|
|
|
torture_comment(tctx, "Testing DsBind W2K8\n");
|
|
|
|
status = dcerpc_drsuapi_DsBind_r(p->binding_handle, tctx, &r);
|
|
torture_drsuapi_assert_call(tctx, p, status, &r, "dcerpc_drsuapi_DsBind");
|
|
|
|
torture_assert_not_null(tctx, r.out.bind_info,
|
|
"DsBind with info48 results in NULL");
|
|
|
|
/* cache server supported extensions, i.e. bind_info */
|
|
priv->srv_bind_info = *r.out.bind_info;
|
|
|
|
/*
|
|
* We do not check for length here, because it should be valid to return
|
|
* any valid info
|
|
*/
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool test_DsGetDomainControllerInfo_w2k8(struct torture_context *tctx,
|
|
struct DsPrivate_w2k8 *priv)
|
|
{
|
|
NTSTATUS status;
|
|
struct dcerpc_pipe *p = priv->drs_pipe;
|
|
struct drsuapi_DsGetDomainControllerInfo r;
|
|
union drsuapi_DsGetDCInfoCtr ctr;
|
|
int32_t level_out = 0;
|
|
uint32_t supported_extensions_ext = 0;
|
|
bool found = false;
|
|
int j, k;
|
|
|
|
struct {
|
|
const char *name;
|
|
WERROR expected;
|
|
} names[] = {
|
|
{
|
|
.name = torture_join_dom_netbios_name(priv->join),
|
|
.expected = WERR_OK
|
|
},
|
|
{
|
|
.name = torture_join_dom_dns_name(priv->join),
|
|
.expected = WERR_OK
|
|
},
|
|
{
|
|
.name = "__UNKNOWN_DOMAIN__",
|
|
.expected = WERR_DS_OBJ_NOT_FOUND
|
|
},
|
|
{
|
|
.name = "unknown.domain.samba.example.com",
|
|
.expected = WERR_DS_OBJ_NOT_FOUND
|
|
},
|
|
};
|
|
|
|
/* Levels 1 and 2 are tested in standard drsuapi tests */
|
|
int level = 3;
|
|
|
|
/* Do Bind first. */
|
|
if (!test_DsBind_w2k8(tctx, priv)) {
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* We used DsBind_w2k8, so DRSUAPI_SUPPORTED_EXTENSION_LH_BETA2
|
|
* should mean support for level 3
|
|
*/
|
|
|
|
/*
|
|
* We are looking for an extension found in info32 and later
|
|
*/
|
|
switch (priv->srv_bind_info.length) {
|
|
case 32:
|
|
supported_extensions_ext = priv->srv_bind_info.info.info32.supported_extensions_ext;
|
|
break;
|
|
case 48:
|
|
supported_extensions_ext = priv->srv_bind_info.info.info48.supported_extensions_ext;
|
|
break;
|
|
default:
|
|
supported_extensions_ext = 0;
|
|
break;
|
|
}
|
|
|
|
supported_extensions_ext &= DRSUAPI_SUPPORTED_EXTENSION_LH_BETA2;
|
|
torture_assert(tctx, (supported_extensions_ext > 0),
|
|
"Server does not support DRSUAPI_SUPPORTED_EXTENSION_LH_BETA2");
|
|
|
|
for (j=0; j < ARRAY_SIZE(names); j++) {
|
|
union drsuapi_DsGetDCInfoRequest req;
|
|
r.in.bind_handle = &priv->bind_handle;
|
|
r.in.level = 1;
|
|
r.in.req = &req;
|
|
|
|
r.in.req->req1.domain_name = names[j].name;
|
|
r.in.req->req1.level = level;
|
|
|
|
r.out.ctr = &ctr;
|
|
r.out.level_out = &level_out;
|
|
|
|
torture_comment(tctx,
|
|
"Testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
|
|
r.in.req->req1.level, r.in.req->req1.domain_name);
|
|
|
|
status = dcerpc_drsuapi_DsGetDomainControllerInfo_r(p->binding_handle, tctx, &r);
|
|
torture_assert_ntstatus_ok(tctx, status,
|
|
"dcerpc_drsuapi_DsGetDomainControllerInfo with dns domain failed");
|
|
torture_assert_werr_equal(tctx, r.out.result, names[j].expected,
|
|
"DsGetDomainControllerInfo level with dns domain failed");
|
|
|
|
if (!W_ERROR_IS_OK(r.out.result)) {
|
|
/* If this was an error, we can't read the result structure */
|
|
continue;
|
|
}
|
|
|
|
torture_assert_int_equal(tctx, r.in.req->req1.level, *r.out.level_out,
|
|
"dcerpc_drsuapi_DsGetDomainControllerInfo in/out level differs");
|
|
|
|
for (k=0; k < r.out.ctr->ctr3.count; k++) {
|
|
if (strcasecmp_m(r.out.ctr->ctr3.array[k].netbios_name,
|
|
torture_join_netbios_name(priv->join)) == 0) {
|
|
found = true;
|
|
priv->dcinfo = r.out.ctr->ctr3.array[k];
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
torture_assert(tctx, found,
|
|
"dcerpc_drsuapi_DsGetDomainControllerInfo: Failed to find the domain controller we just created during the join");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool test_DsUnbind_w2k8(struct torture_context *tctx,
|
|
struct DsPrivate_w2k8 *priv)
|
|
{
|
|
NTSTATUS status;
|
|
struct dcerpc_pipe *p = priv->drs_pipe;
|
|
struct drsuapi_DsUnbind r;
|
|
|
|
r.in.bind_handle = &priv->bind_handle;
|
|
r.out.bind_handle = &priv->bind_handle;
|
|
|
|
torture_comment(tctx, "Testing DsUnbind W2K8\n");
|
|
|
|
status = dcerpc_drsuapi_DsUnbind_r(p->binding_handle, tctx, &r);
|
|
torture_drsuapi_assert_call(tctx, p, status, &r, "dcerpc_drsuapi_DsUnbind");
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Common test case setup function to be used
|
|
* in DRS suit of test when appropriate
|
|
*/
|
|
bool torture_drsuapi_w2k8_tcase_setup_common(struct torture_context *tctx,
|
|
struct DsPrivate_w2k8 *priv)
|
|
{
|
|
NTSTATUS status;
|
|
int rnd = rand() % 1000;
|
|
char *name = talloc_asprintf(tctx, "%s%d", TEST_MACHINE_NAME, rnd);
|
|
struct cli_credentials *machine_credentials;
|
|
|
|
torture_assert(tctx, priv, "Invalid argument");
|
|
|
|
torture_comment(tctx, "Create DRSUAPI pipe\n");
|
|
status = torture_rpc_connection(tctx,
|
|
&priv->drs_pipe,
|
|
&ndr_table_drsuapi);
|
|
torture_assert(tctx, NT_STATUS_IS_OK(status), "Unable to connect to DRSUAPI pipe");
|
|
|
|
torture_comment(tctx, "About to join domain with name %s\n", name);
|
|
priv->join = torture_join_domain(tctx, name, ACB_SVRTRUST,
|
|
&machine_credentials);
|
|
torture_assert(tctx, priv->join, "Failed to join as BDC");
|
|
|
|
/*
|
|
* After that every test should use DsBind and DsGetDomainControllerInfo
|
|
*/
|
|
if (!test_DsBind_w2k8(tctx, priv)) {
|
|
/* clean up */
|
|
torture_drsuapi_w2k8_tcase_teardown_common(tctx, priv);
|
|
torture_fail(tctx, "Failed execute test_DsBind_w2k8()");
|
|
}
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Common test case teardown function to be used
|
|
* in DRS suit of test when appropriate
|
|
*/
|
|
bool torture_drsuapi_w2k8_tcase_teardown_common(struct torture_context *tctx,
|
|
struct DsPrivate_w2k8 *priv)
|
|
{
|
|
if (priv->join) {
|
|
torture_leave_domain(tctx, priv->join);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Test case setup for DRSUAPI test case
|
|
*/
|
|
static bool torture_drsuapi_w2k8_tcase_setup(struct torture_context *tctx, void **data)
|
|
{
|
|
struct DsPrivate_w2k8 *priv;
|
|
|
|
*data = priv = talloc_zero(tctx, struct DsPrivate_w2k8);
|
|
|
|
return torture_drsuapi_w2k8_tcase_setup_common(tctx, priv);
|
|
}
|
|
|
|
/**
|
|
* Test case tear-down for DRSUAPI test case
|
|
*/
|
|
static bool torture_drsuapi_w2k8_tcase_teardown(struct torture_context *tctx, void *data)
|
|
{
|
|
bool ret;
|
|
struct DsPrivate_w2k8 *priv = talloc_get_type(data, struct DsPrivate_w2k8);
|
|
|
|
ret = torture_drsuapi_w2k8_tcase_teardown_common(tctx, priv);
|
|
|
|
talloc_free(priv);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* DRSUAPI test case implementation
|
|
*/
|
|
void torture_rpc_drsuapi_w2k8_tcase(struct torture_suite *suite)
|
|
{
|
|
typedef bool (*run_func) (struct torture_context *test, void *tcase_data);
|
|
|
|
struct torture_tcase *tcase = torture_suite_add_tcase(suite, "drsuapi_w2k8");
|
|
|
|
torture_tcase_set_fixture(tcase, torture_drsuapi_w2k8_tcase_setup,
|
|
torture_drsuapi_w2k8_tcase_teardown);
|
|
|
|
torture_tcase_add_simple_test(tcase, "DsBind_W2K8", (run_func)test_DsBind_w2k8);
|
|
torture_tcase_add_simple_test(tcase, "DsGetDomainControllerInfo_W2K8", (run_func)test_DsGetDomainControllerInfo_w2k8);
|
|
}
|