mirror of
https://github.com/samba-team/samba.git
synced 2025-10-21 03:33:16 +03:00
r20353: Restructure the DRSUAPI DsGetDomainControllerInfo test, because as
usual things are more complex than they appear. Also remove the incorrect server-side implementation, which blindly assumed some sense of consistancy across the API switch levels. Andrew Bartlett
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
929fd1beee
commit
79941adbff
@@ -1065,13 +1065,13 @@ interface drsuapi
|
||||
} drsuapi_DsGetDCInfoCtr2;
|
||||
|
||||
typedef struct {
|
||||
uint32 unknown1;
|
||||
[flag(BIG_ENDIAN)] ipv4address last_logon_ipv4_ip;
|
||||
uint32 unknown2;
|
||||
uint32 unknown3;
|
||||
uint32 unknown4;
|
||||
uint32 unknown5;
|
||||
uint32 unknown6;
|
||||
[charset(UTF16),string] uint16 *server_nt4_account;
|
||||
[charset(UTF16),string] uint16 *nt4_account;
|
||||
} drsuapi_DsGetDCInfo01;
|
||||
|
||||
typedef struct {
|
||||
|
@@ -374,7 +374,6 @@ static WERROR drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_state *b_s
|
||||
struct ldb_dn *sites_dn;
|
||||
struct ldb_result *res;
|
||||
|
||||
const char *attrs_account_01[] = { "samAccountName", NULL };
|
||||
const char *attrs_account_1[] = { "cn", "dnsHostName", NULL };
|
||||
const char *attrs_account_2[] = { "cn", "dnsHostName", "objectGUID", NULL };
|
||||
|
||||
@@ -384,12 +383,10 @@ static WERROR drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_state *b_s
|
||||
|
||||
const char *attrs_ntds[] = { "options", "objectGUID", NULL };
|
||||
|
||||
const char *attrs_01[] = { "serverReference", NULL };
|
||||
const char *attrs_1[] = { "serverReference", "cn", "dnsHostName", NULL };
|
||||
const char *attrs_2[] = { "serverReference", "cn", "dnsHostName", "objectGUID", NULL };
|
||||
const char **attrs;
|
||||
|
||||
struct drsuapi_DsGetDCInfoCtr01 *ctr01;
|
||||
struct drsuapi_DsGetDCInfoCtr1 *ctr1;
|
||||
struct drsuapi_DsGetDCInfoCtr2 *ctr2;
|
||||
|
||||
@@ -408,8 +405,8 @@ static WERROR drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_state *b_s
|
||||
|
||||
switch (r->out.level_out) {
|
||||
case -1:
|
||||
attrs = attrs_01;
|
||||
break;
|
||||
/* this level is not like the others */
|
||||
return WERR_UNKNOWN_LEVEL;
|
||||
case 1:
|
||||
attrs = attrs_1;
|
||||
break;
|
||||
@@ -428,29 +425,6 @@ static WERROR drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_state *b_s
|
||||
}
|
||||
|
||||
switch (r->out.level_out) {
|
||||
case -1:
|
||||
ctr01 = &r->out.ctr.ctr01;
|
||||
ctr01->count = res->count;
|
||||
ctr01->array = talloc_zero_array(mem_ctx,
|
||||
struct drsuapi_DsGetDCInfo01,
|
||||
res->count);
|
||||
for (i=0; i < res->count; i++) {
|
||||
struct ldb_result *res_account;
|
||||
struct ldb_dn *ref_dn
|
||||
= ldb_msg_find_attr_as_dn(b_state->sam_ctx,
|
||||
mem_ctx, res->msgs[i],
|
||||
"serverReference");
|
||||
ret = ldb_search_exp_fmt(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
|
||||
LDB_SCOPE_BASE, attrs_account_01, "objectClass=computer");
|
||||
if (ret) {
|
||||
return WERR_GENERAL_FAILURE;
|
||||
}
|
||||
if (res_account->count == 1) {
|
||||
ctr01->array[i].server_nt4_account
|
||||
= ldb_msg_find_attr_as_string(res_account->msgs[0], "samAccountName", NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
ctr1 = &r->out.ctr.ctr1;
|
||||
ctr1->count = res->count;
|
||||
|
@@ -253,6 +253,26 @@ NTSTATUS ejs_push_string(struct ejs_rpc *ejs,
|
||||
return mprSetVar(v, name, mprString(s));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
pull a ipv4address (internally a string)
|
||||
*/
|
||||
NTSTATUS ejs_pull_ipv4address(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const char **s)
|
||||
{
|
||||
return ejs_pull_string(ejs, v, name, s);
|
||||
}
|
||||
|
||||
/*
|
||||
push a ipv4address (internally a string)
|
||||
*/
|
||||
NTSTATUS ejs_push_ipv4address(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, char * const *s)
|
||||
{
|
||||
return ejs_push_string(ejs, v, name, *s);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS ejs_pull_dom_sid(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, struct dom_sid *r)
|
||||
{
|
||||
|
@@ -93,6 +93,10 @@ NTSTATUS ejs_pull_string(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const char **s);
|
||||
NTSTATUS ejs_push_string(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const char *s);
|
||||
NTSTATUS ejs_pull_ipv4address(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const char **s);
|
||||
NTSTATUS ejs_push_ipv4address(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, char * const *s);
|
||||
void ejs_set_constant_int(int eid, const char *name, int value);
|
||||
void ejs_set_constant_string(int eid, const char *name, const char *value);
|
||||
|
||||
|
@@ -66,63 +66,118 @@ static BOOL test_DsGetDomainControllerInfo(struct dcerpc_pipe *p, TALLOC_CTX *me
|
||||
NTSTATUS status;
|
||||
struct drsuapi_DsGetDomainControllerInfo r;
|
||||
BOOL ret = True;
|
||||
BOOL found = False;
|
||||
int i, 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
|
||||
},
|
||||
};
|
||||
int levels[] = {1, 2};
|
||||
int level;
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(levels); i++) {
|
||||
for (j=0; j < ARRAY_SIZE(names); j++) {
|
||||
level = levels[i];
|
||||
r.in.bind_handle = &priv->bind_handle;
|
||||
r.in.level = 1;
|
||||
|
||||
r.in.req.req1.domain_name = names[j].name;
|
||||
r.in.req.req1.level = level;
|
||||
|
||||
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_EQUAL(r.out.result, names[j].expected)) {
|
||||
printf("DsGetDomainControllerInfo level %d\n"
|
||||
" with dns domain failed - %s, expected %s\n",
|
||||
r.in.req.req1.level, win_errstr(r.out.result),
|
||||
win_errstr(names[j].expected));
|
||||
ret = False;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
/* If this was an error, we can't read the result structure */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r.in.req.req1.level != r.out.level_out) {
|
||||
printf("dcerpc_drsuapi_DsGetDomainControllerInfo level in (%d) != out (%d)\n",
|
||||
r.in.req.req1.level, r.out.level_out);
|
||||
ret = False;
|
||||
/* We can't safely read the result structure */
|
||||
continue;
|
||||
}
|
||||
switch (level) {
|
||||
case 1:
|
||||
for (k=0; k < r.out.ctr.ctr1.count; k++) {
|
||||
if (strcasecmp_m(r.out.ctr.ctr1.array[k].netbios_name,
|
||||
torture_join_netbios_name(priv->join))) {
|
||||
found = True;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (r.out.ctr.ctr2.count > 0) {
|
||||
priv->dcinfo = r.out.ctr.ctr2.array[0];
|
||||
}
|
||||
for (k=0; k < r.out.ctr.ctr2.count; k++) {
|
||||
if (strcasecmp_m(r.out.ctr.ctr2.array[k].netbios_name,
|
||||
torture_join_netbios_name(priv->join))) {
|
||||
found = True;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d: Failed to find the domain controller (%s) we just created during the join\n",
|
||||
r.in.req.req1.level,
|
||||
torture_join_netbios_name(priv->join));
|
||||
ret = False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lp_parm_bool(-1, "torture", "samba4", False)) {
|
||||
printf("skipping DsGetDomainControllerInfo level -1 test against Samba4\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
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.domain_name = "__UNKNOWN_DOMAIN__"; /* This is clearly ignored for this level */
|
||||
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);
|
||||
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)) {
|
||||
@@ -131,62 +186,35 @@ static BOOL test_DsGetDomainControllerInfo(struct dcerpc_pipe *p, TALLOC_CTX *me
|
||||
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);
|
||||
" 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));
|
||||
" 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);
|
||||
{
|
||||
const char *dc_account = talloc_asprintf(mem_ctx, "%s\\%s$",
|
||||
torture_join_dom_netbios_name(priv->join),
|
||||
priv->dcinfo.netbios_name);
|
||||
for (k=0; k < r.out.ctr.ctr1.count; k++) {
|
||||
if (strcasecmp_m(r.out.ctr.ctr01.array[k].nt4_account,
|
||||
dc_account)) {
|
||||
found = True;
|
||||
}
|
||||
}
|
||||
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);
|
||||
if (!found) {
|
||||
printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d: Failed to find the domain controller (%s) in last logon records\n",
|
||||
r.in.req.req1.level,
|
||||
dc_account);
|
||||
ret = False;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user