1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-22 05:57:43 +03:00

r10486: This is a merge of Brad Henry's 'net join' rework, to better perform

an ADS join, particularly as a DC.  This represents the bulk of his
Google SOC work, and I'm very pleased to intergrate it into the tree.
(Metze will intergrate the DRSUAPI work later).

Both metze and myself have also put a lot of time into this patch, and
in mentoring Brad in general.  In return, Brad has been a very good
student, and has taken the comments well.

Since it's last appearance on samba-technical@, I have made
correctness and valgrind fixups, as well as adding a new 'BINDING'
mode to the libnet_rpc routines.  This allows the exact binding string
to be passed down from the torture code, including options and exact
target host.

Andrew Bartlett
(This used to be commit d6fa105fdabbeb83a9b0e50dad49d1649afdb2a4)
This commit is contained in:
Andrew Bartlett 2005-09-25 12:26:07 +00:00 committed by Gerald (Jerry) Carter
parent 2fe7c3a34a
commit 5a522b3100
11 changed files with 1078 additions and 400 deletions

View File

@ -17,6 +17,6 @@ ADD_OBJ_FILES = \
libnet/userinfo.o \
libnet/userman.o \
libnet/domain.o
REQUIRED_SUBSYSTEMS = RPC_NDR_SAMR RPC_NDR_LSA RPC_NDR_SRVSVC RPC_NDR_DRSUAPI LIBCLI_COMPOSITE LIBCLI_RESOLVE LIBSAMBA3
REQUIRED_SUBSYSTEMS = RPC_NDR_SAMR RPC_NDR_LSA RPC_NDR_SRVSVC RPC_NDR_DRSUAPI LIBCLI_COMPOSITE LIBCLI_RESOLVE LIBSAMBA3 LIBCLI_CLDAP
# End SUBSYSTEM LIBNET
#################################

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
Copyright (C) Stefan Metzmacher 2004
Copyright (C) Andrew Bartlett <abartlet@samba.org> 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
@ -21,10 +22,23 @@
#include "librpc/gen_ndr/ndr_netlogon.h"
enum libnet_Join_level {
LIBNET_JOIN_AUTOMATIC,
LIBNET_JOIN_SPECIFIED,
};
enum libnet_JoinDomain_level {
LIBNET_JOINDOMAIN_AUTOMATIC,
LIBNET_JOINDOMAIN_SPECIFIED,
};
struct libnet_JoinDomain {
struct {
const char *domain_name;
const char *account_name;
const char *netbios_name;
const char *binding;
enum libnet_JoinDomain_level level;
uint32_t acct_type;
} in;
@ -34,18 +48,30 @@ struct libnet_JoinDomain {
struct dom_sid *domain_sid;
const char *domain_name;
const char *realm;
unsigned int kvno;
const char *domain_dn_str;
const char *account_dn_str;
const char *server_dn_str;
uint32_t kvno; /* msDS-KeyVersionNumber */
struct dcerpc_pipe *lsa_pipe;
struct dcerpc_pipe *samr_pipe;
struct dcerpc_binding *samr_binding;
struct policy_handle *user_handle;
struct dom_sid *account_sid;
} out;
};
struct libnet_Join {
struct {
const char *domain_name;
const char *netbios_name;
enum netr_SchannelType secure_channel_type;
enum libnet_Join_level level;
} in;
struct {
const char *error_string;
const char *join_password;
struct dom_sid *domain_sid;
} out;
};

View File

@ -36,8 +36,14 @@ static NTSTATUS libnet_RpcConnectSrv(struct libnet_context *ctx, TALLOC_CTX *mem
{
NTSTATUS status;
const char *binding = NULL;
binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", r->in.domain_name);
switch (r->level) {
case LIBNET_RPC_CONNECT_SERVER:
binding = talloc_asprintf(mem_ctx, "ncacn_np:%s", r->in.domain_name);
break;
case LIBNET_RPC_CONNECT_BINDING:
binding = r->in.binding;
break;
}
status = dcerpc_pipe_connect(mem_ctx, &r->out.dcerpc_pipe,
binding, r->in.dcerpc_iface_uuid,r->in.dcerpc_iface_version,
@ -115,6 +121,8 @@ NTSTATUS libnet_RpcConnect(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru
switch (r->level) {
case LIBNET_RPC_CONNECT_SERVER:
return libnet_RpcConnectSrv(ctx, mem_ctx, r);
case LIBNET_RPC_CONNECT_BINDING:
return libnet_RpcConnectSrv(ctx, mem_ctx, r);
case LIBNET_RPC_CONNECT_PDC:
return libnet_RpcConnectPdc(ctx, mem_ctx, r);
}

View File

@ -25,7 +25,8 @@
enum libnet_RpcConnect_level {
LIBNET_RPC_CONNECT_SERVER, /* connect to a standalone rpc server */
LIBNET_RPC_CONNECT_PDC /* connect to a domain pdc */
LIBNET_RPC_CONNECT_PDC, /* connect to a domain pdc */
LIBNET_RPC_CONNECT_BINDING /* specified binding string */
};
struct libnet_RpcConnect {
@ -33,6 +34,7 @@ struct libnet_RpcConnect {
struct {
const char *domain_name;
const char *binding;
const char *dcerpc_iface_name;
const char *dcerpc_iface_uuid;
uint32_t dcerpc_iface_version;

View File

@ -71,6 +71,7 @@ REQUIRED_SUBSYSTEMS = \
# Start SUBSYSTEM TORTURE_RPC
[SUBSYSTEM::TORTURE_RPC]
ADD_OBJ_FILES = \
torture/rpc/join.o \
torture/rpc/lsa.o \
torture/rpc/session_key.o \
torture/rpc/echo.o \

View File

@ -217,7 +217,7 @@ static BOOL nbt_test_ntlogon(TALLOC_CTX *mem_ctx,
const char *password;
const char *dom_sid;
join_ctx = torture_join_domain(TEST_NAME, lp_workgroup(),
join_ctx = torture_join_domain(TEST_NAME,
ACB_WSTRUST, &password);
if (join_ctx == NULL) {
printf("Failed to join domain %s as %s\n", lp_workgroup(), TEST_NAME);

View File

@ -1361,7 +1361,7 @@ BOOL torture_rpc_netlogon(void)
mem_ctx = talloc_init("torture_rpc_netlogon");
join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST,
join_ctx = torture_join_domain(TEST_MACHINE_NAME, ACB_SVRTRUST,
&machine_password);
if (!join_ctx) {
talloc_free(mem_ctx);

View File

@ -29,10 +29,15 @@
#include "librpc/gen_ndr/ndr_samr.h"
#include "system/time.h"
#include "lib/crypto/crypto.h"
#include "libnet/libnet.h"
#include "lib/cmdline/popt_common.h"
#include "lib/ldb/include/ldb.h"
struct test_join {
struct dcerpc_pipe *p;
struct policy_handle user_handle;
struct libnet_JoinDomain *libnet_r;
const char *dom_sid;
};
@ -272,13 +277,59 @@ failed:
struct test_join *torture_join_domain(const char *machine_name,
const char *domain,
uint16_t acct_flags,
uint32_t acct_flags,
const char **machine_password)
{
char *username = talloc_asprintf(NULL, "%s$", machine_name);
struct test_join *tj = torture_create_testuser(username, domain, acct_flags, machine_password);
talloc_free(username);
NTSTATUS status;
struct libnet_context *libnet_ctx;
struct libnet_JoinDomain *libnet_r;
struct test_join *tj;
tj = talloc(NULL, struct test_join);
if (!tj) return NULL;
libnet_r = talloc(tj, struct libnet_JoinDomain);
if (!libnet_r) {
talloc_free(tj);
return NULL;
}
libnet_ctx = libnet_context_init(NULL);
if (!libnet_ctx) {
talloc_free(tj);
return NULL;
}
tj->libnet_r = libnet_r;
libnet_ctx->cred = cmdline_credentials;
libnet_r->in.binding = lp_parm_string(-1, "torture", "binding");
libnet_r->in.level = LIBNET_JOINDOMAIN_SPECIFIED;
libnet_r->in.netbios_name = machine_name;
libnet_r->in.account_name = talloc_asprintf(libnet_r, "%s$", machine_name);
if (!libnet_r->in.account_name) {
talloc_free(tj);
return NULL;
}
libnet_r->in.acct_type = acct_flags;
status = libnet_JoinDomain(libnet_ctx, libnet_r, libnet_r);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Domain join failed - %s.\n", nt_errstr(status)));
talloc_free(tj);
return NULL;
}
tj->p = libnet_r->out.samr_pipe;
tj->user_handle = *libnet_r->out.user_handle;
tj->dom_sid = dom_sid_string(tj, libnet_r->out.domain_sid);
*machine_password = libnet_r->out.join_password;
DEBUG(0, ("%s joined domain %s (%s).\n",
libnet_r->in.netbios_name,
libnet_r->out.domain_name,
tj->dom_sid));
return tj;
}
@ -292,24 +343,94 @@ struct policy_handle *torture_join_samr_user_policy(struct test_join *join)
return &join->user_handle;
}
NTSTATUS torture_leave_ads_domain(TALLOC_CTX *mem_ctx, struct libnet_JoinDomain *libnet_r)
{
NTSTATUS status;
int rtn;
TALLOC_CTX *tmp_ctx;
struct ldb_dn *server_dn;
struct ldb_context *ldb_ctx;
char *remote_ldb_url;
/* Check if we are a domain controller. If not, exit. */
if (!libnet_r->out.server_dn_str) {
return NT_STATUS_OK;
}
tmp_ctx = talloc_named(mem_ctx, 0, "torture_leave temporary context");
if (!tmp_ctx) {
libnet_r->out.error_string = NULL;
return NT_STATUS_NO_MEMORY;
}
ldb_ctx = ldb_init(tmp_ctx);
if (!ldb_ctx) {
libnet_r->out.error_string = NULL;
talloc_free(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
/* Remove CN=Servers,... entry from the AD. */
server_dn = ldb_dn_explode(tmp_ctx, libnet_r->out.server_dn_str);
if (!server_dn) {
libnet_r->out.error_string = NULL;
talloc_free(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
remote_ldb_url = talloc_asprintf(tmp_ctx, "ldap://%s", libnet_r->out.samr_binding->host);
if (!remote_ldb_url) {
libnet_r->out.error_string = NULL;
talloc_free(tmp_ctx);
return NT_STATUS_NO_MEMORY;
}
rtn = ldb_connect(ldb_ctx, remote_ldb_url, 0, NULL);
if (rtn != 0) {
libnet_r->out.error_string = NULL;
talloc_free(tmp_ctx);
return NT_STATUS_UNSUCCESSFUL;
}
rtn = ldb_delete(ldb_ctx, server_dn);
if (rtn != 0) {
libnet_r->out.error_string = NULL;
talloc_free(tmp_ctx);
return NT_STATUS_UNSUCCESSFUL;
}
DEBUG(0, ("%s removed successfully.\n", libnet_r->out.server_dn_str));
talloc_free(tmp_ctx);
return status;
}
/*
leave the domain, deleting the machine acct
*/
void torture_leave_domain(struct test_join *join)
{
struct samr_DeleteUser d;
NTSTATUS status;
if (!GUID_all_zero(&join->user_handle.uuid)) {
d.in.user_handle = &join->user_handle;
d.out.user_handle = &join->user_handle;
status = dcerpc_samr_DeleteUser(join->p, join, &d);
if (!NT_STATUS_IS_OK(status)) {
printf("Delete of machine account failed\n");
}
d.in.user_handle = &join->user_handle;
d.out.user_handle = &join->user_handle;
/* Delete machine account */
status = dcerpc_samr_DeleteUser(join->p, join, &d);
if (!NT_STATUS_IS_OK(status)) {
printf("Delete of machine account failed\n");
} else {
printf("Delete of machine account was successful.\n");
}
if (join->libnet_r) {
status = torture_leave_ads_domain(join, join->libnet_r);
}
talloc_free(join);
}
@ -337,7 +458,7 @@ struct test_join_ads_dc *torture_join_domain_ads_dc(const char *machine_name,
return NULL;
}
join->join = torture_join_domain(machine_name, domain,
join->join = torture_join_domain(machine_name,
ACB_SVRTRUST,
machine_password);

View File

@ -2312,6 +2312,7 @@ static struct {
{"RPC-ROT", torture_rpc_rot, 0},
{"RPC-DSSETUP", torture_rpc_dssetup, 0},
{"RPC-ALTERCONTEXT", torture_rpc_alter_context, 0},
{"RPC-JOIN", torture_rpc_join, 0},
/* local (no server) testers */
{"LOCAL-NTLMSSP", torture_ntlmssp_self_check, 0},

View File

@ -29,7 +29,7 @@ int net_join(struct net_context *ctx, int argc, const char **argv)
{
NTSTATUS status;
struct libnet_context *libnetctx;
struct libnet_Join r;
struct libnet_Join *r;
char *tmp;
const char *domain_name;
enum netr_SchannelType secure_channel_type = SEC_CHAN_WKSTA;
@ -62,23 +62,29 @@ int net_join(struct net_context *ctx, int argc, const char **argv)
return -1;
}
libnetctx->cred = ctx->credentials;
r = talloc(ctx->mem_ctx, struct libnet_Join);
if (!r) {
return -1;
}
/* prepare password change */
r.in.domain_name = domain_name;
r.in.secure_channel_type = secure_channel_type;
r.out.error_string = NULL;
r->in.netbios_name = lp_netbios_name();
r->in.domain_name = domain_name;
r->in.secure_channel_type = secure_channel_type;
r->in.level = LIBNET_JOIN_AUTOMATIC;
r->out.error_string = NULL;
/* do the domain join */
status = libnet_Join(libnetctx, ctx->mem_ctx, &r);
status = libnet_Join(libnetctx, r, r);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("libnet_Join returned %s: %s\n",
nt_errstr(status),
r.out.error_string));
r->out.error_string));
talloc_free(r);
talloc_free(libnetctx);
return -1;
}
talloc_free(libnetctx);
return 0;
}