summaryrefslogtreecommitdiff
path: root/source4/torture/rpc/testjoin.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/torture/rpc/testjoin.c')
-rw-r--r--source4/torture/rpc/testjoin.c277
1 files changed, 277 insertions, 0 deletions
diff --git a/source4/torture/rpc/testjoin.c b/source4/torture/rpc/testjoin.c
new file mode 100644
index 0000000000..aab08c3a56
--- /dev/null
+++ b/source4/torture/rpc/testjoin.c
@@ -0,0 +1,277 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ utility code to join/leave a domain
+
+ 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.
+*/
+
+/*
+ this code is used by other torture modules to join/leave a domain
+ as either a member, bdc or thru a trust relationship
+*/
+
+#include "includes.h"
+
+struct test_join {
+ TALLOC_CTX *mem_ctx;
+ struct dcerpc_pipe *p;
+ const char *machine_password;
+ struct policy_handle acct_handle;
+};
+
+
+static NTSTATUS DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+ struct policy_handle *handle, const char *name)
+{
+ NTSTATUS status;
+ struct samr_DeleteUser d;
+ struct policy_handle acct_handle;
+ uint32_t rid;
+ struct samr_LookupNames n;
+ struct samr_Name sname;
+ struct samr_OpenUser r;
+
+ sname.name = name;
+
+ n.in.handle = handle;
+ n.in.num_names = 1;
+ n.in.names = &sname;
+
+ status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
+ if (NT_STATUS_IS_OK(status)) {
+ rid = n.out.rids.ids[0];
+ } else {
+ return status;
+ }
+
+ r.in.handle = handle;
+ r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ r.in.rid = rid;
+ r.out.acct_handle = &acct_handle;
+
+ status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("OpenUser(%s) failed - %s\n", name, nt_errstr(status));
+ return status;
+ }
+
+ d.in.handle = &acct_handle;
+ d.out.handle = &acct_handle;
+ status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*
+ join the domain as a test machine
+ an opaque pointer is returned. Pass it to torture_leave_domain()
+ when finished
+*/
+void *torture_join_domain(const char *machine_name,
+ const char *domain,
+ uint16 acct_flags,
+ const char **machine_password)
+{
+ NTSTATUS status;
+ struct samr_Connect c;
+ struct samr_CreateUser2 r;
+ struct samr_OpenDomain o;
+ struct samr_LookupDomain l;
+ struct samr_GetUserPwInfo pwp;
+ struct samr_SetUserInfo s;
+ union samr_UserInfo u;
+ struct policy_handle handle;
+ struct policy_handle domain_handle;
+ uint32_t access_granted;
+ uint32_t rid;
+ DATA_BLOB session_key;
+ struct samr_Name name;
+ int policy_min_pw_len = 0;
+ struct test_join *join;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_init("torture_join_domain");
+ if (!mem_ctx) {
+ return NULL;
+ }
+
+ join = talloc_p(mem_ctx, struct test_join);
+ if (join == NULL) {
+ talloc_destroy(mem_ctx);
+ return NULL;
+ }
+
+ ZERO_STRUCTP(join);
+
+ join->mem_ctx = mem_ctx;
+
+ printf("Connecting to SAMR\n");
+
+ status = torture_rpc_connection(&join->p,
+ DCERPC_SAMR_NAME,
+ DCERPC_SAMR_UUID,
+ DCERPC_SAMR_VERSION);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto failed;
+ }
+
+ c.in.system_name = NULL;
+ c.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ c.out.handle = &handle;
+
+ status = dcerpc_samr_Connect(join->p, mem_ctx, &c);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("samr_Connect failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ printf("Opening domain %s\n", domain);
+
+ name.name = domain;
+ l.in.handle = &handle;
+ l.in.domain = &name;
+
+ status = dcerpc_samr_LookupDomain(join->p, mem_ctx, &l);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("LookupDomain failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ o.in.handle = &handle;
+ o.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ o.in.sid = l.out.sid;
+ o.out.domain_handle = &domain_handle;
+
+ status = dcerpc_samr_OpenDomain(join->p, mem_ctx, &o);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("OpenDomain failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ printf("Creating machine account %s\n", machine_name);
+
+again:
+ name.name = talloc_asprintf(mem_ctx, "%s$", machine_name);
+ r.in.handle = &domain_handle;
+ r.in.account_name = &name;
+ r.in.acct_flags = acct_flags;
+ r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ r.out.acct_handle = &join->acct_handle;
+ r.out.access_granted = &access_granted;
+ r.out.rid = &rid;
+
+ status = dcerpc_samr_CreateUser2(join->p, mem_ctx, &r);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
+ status = DeleteUser_byname(join->p, mem_ctx, &domain_handle, name.name);
+ if (NT_STATUS_IS_OK(status)) {
+ goto again;
+ }
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("CreateUser2 failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ pwp.in.handle = &join->acct_handle;
+
+ status = dcerpc_samr_GetUserPwInfo(join->p, mem_ctx, &pwp);
+ if (NT_STATUS_IS_OK(status)) {
+ policy_min_pw_len = pwp.out.info.min_password_len;
+ }
+
+ join->machine_password = generate_random_str(mem_ctx, MAX(8, policy_min_pw_len));
+
+ printf("Setting machine account password '%s'\n", join->machine_password);
+
+ s.in.handle = &join->acct_handle;
+ s.in.info = &u;
+ s.in.level = 24;
+
+ encode_pw_buffer(u.info24.password.data, join->machine_password, STR_UNICODE);
+ u.info24.pw_len = strlen(join->machine_password);
+
+ status = dcerpc_fetch_session_key(join->p, &session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo level %u - no session key - %s\n",
+ s.in.level, nt_errstr(status));
+ torture_leave_domain(&join);
+ goto failed;
+ }
+
+ arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
+
+ status = dcerpc_samr_SetUserInfo(join->p, mem_ctx, &s);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ s.in.handle = &join->acct_handle;
+ s.in.info = &u;
+ s.in.level = 16;
+
+ u.info16.acct_flags = acct_flags;
+
+ printf("Resetting ACB flags\n");
+
+ status = dcerpc_samr_SetUserInfo(join->p, mem_ctx, &s);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("SetUserInfo failed - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ *machine_password = join->machine_password;
+
+ return join;
+
+failed:
+ torture_leave_domain(join);
+ return NULL;
+}
+
+
+/*
+ leave the domain, deleting the machine acct
+*/
+void torture_leave_domain(void *join_ctx)
+{
+ struct test_join *join = join_ctx;
+ struct samr_DeleteUser d;
+ NTSTATUS status;
+
+ if (!uuid_all_zero(&join->acct_handle.uuid)) {
+ d.in.handle = &join->acct_handle;
+ d.out.handle = &join->acct_handle;
+
+ status = dcerpc_samr_DeleteUser(join->p, join->mem_ctx, &d);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Delete of machine account failed\n");
+ }
+ }
+
+ if (join->p) {
+ torture_rpc_close(join->p);
+ }
+
+ talloc_destroy(join->mem_ctx);
+}