s4:torture: Migrate smbtorture to new cmdline option parser
[samba.git] / source4 / torture / rpc / testjoin.c
index 3f58b53e61504a6cf14d12505950b54610cb1fcd..0a3c96f55ea8382b1ca87eb6da614c8d32a03ffd 100644 (file)
@@ -7,7 +7,7 @@
    
    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
+   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,
@@ -16,8 +16,7 @@
    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.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 /*
 */
 
 #include "includes.h"
-#include "torture/torture.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"
+#include "lib/cmdline/cmdline.h"
+#include "librpc/gen_ndr/ndr_lsa_c.h"
 #include "librpc/gen_ndr/ndr_samr_c.h"
 
 #include "libcli/auth/libcli_auth.h"
-#include "torture/rpc/rpc.h"
+#include "torture/rpc/torture_rpc.h"
 #include "libcli/security/security.h"
+#include "param/param.h"
+#include "source3/rpc_client/init_samr.h"
 
 struct test_join {
        struct dcerpc_pipe *p;
        struct policy_handle user_handle;
+       struct policy_handle domain_handle;
        struct libnet_JoinDomain *libnet_r;
        struct dom_sid *dom_sid;
+       const char *dom_netbios_name;
+       const char *dom_dns_name;
        struct dom_sid *user_sid;
+       struct GUID user_guid;
+       const char *netbios_name;
 };
 
 
-static NTSTATUS DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+static NTSTATUS DeleteUser_byname(struct torture_context *tctx,
+                                 struct dcerpc_binding_handle *b,
+                                 TALLOC_CTX *mem_ctx,
                                  struct policy_handle *handle, const char *name)
 {
        NTSTATUS status;
@@ -55,6 +61,7 @@ static NTSTATUS DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        struct policy_handle user_handle;
        uint32_t rid;
        struct samr_LookupNames n;
+       struct samr_Ids rids, types;
        struct lsa_String sname;
        struct samr_OpenUser r;
 
@@ -63,31 +70,43 @@ static NTSTATUS DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        n.in.domain_handle = handle;
        n.in.num_names = 1;
        n.in.names = &sname;
+       n.out.rids = &rids;
+       n.out.types = &types;
 
-       status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
-       if (NT_STATUS_IS_OK(status)) {
-               rid = n.out.rids.ids[0];
-       } else {
+       status = dcerpc_samr_LookupNames_r(b, mem_ctx, &n);
+       if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
+       if (NT_STATUS_IS_OK(n.out.result)) {
+               rid = n.out.rids->ids[0];
+       } else {
+               return n.out.result;
+       }
 
        r.in.domain_handle = handle;
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        r.in.rid = rid;
        r.out.user_handle = &user_handle;
 
-       status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+       status = dcerpc_samr_OpenUser_r(b, mem_ctx, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenUser(%s) failed - %s\n", name, nt_errstr(status));
+               torture_comment(tctx, "OpenUser(%s) failed - %s\n", name, nt_errstr(status));
                return status;
        }
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_comment(tctx, "OpenUser(%s) failed - %s\n", name, nt_errstr(r.out.result));
+               return r.out.result;
+       }
 
        d.in.user_handle = &user_handle;
        d.out.user_handle = &user_handle;
-       status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
+       status = dcerpc_samr_DeleteUser_r(b, mem_ctx, &d);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
+       if (!NT_STATUS_IS_OK(d.out.result)) {
+               return d.out.result;
+       }
 
        return NT_STATUS_OK;
 }
@@ -98,21 +117,24 @@ static NTSTATUS DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
   when finished
 */
 
-struct test_join *torture_create_testuser(const char *username, 
-                                         const char *domain,
-                                         uint16_t acct_type,
-                                         const char **random_password)
+struct test_join *torture_create_testuser_max_pwlen(struct torture_context *tctx,
+                                                   const char *username,
+                                                   const char *domain,
+                                                   uint16_t acct_type,
+                                                   const char **random_password,
+                                                   int max_pw_len)
 {
        NTSTATUS status;
        struct samr_Connect c;
        struct samr_CreateUser2 r;
        struct samr_OpenDomain o;
        struct samr_LookupDomain l;
+       struct dom_sid2 *sid = NULL;
        struct samr_GetUserPwInfo pwp;
+       struct samr_PwInfo info;
        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;
@@ -121,7 +143,8 @@ struct test_join *torture_create_testuser(const char *username,
        int policy_min_pw_len = 0;
        struct test_join *join;
        char *random_pw;
-
+       const char *dc_binding = torture_setting_string(tctx, "dc_binding", NULL);
+       struct dcerpc_binding_handle *b = NULL;
        join = talloc(NULL, struct test_join);
        if (join == NULL) {
                return NULL;
@@ -129,60 +152,139 @@ struct test_join *torture_create_testuser(const char *username,
 
        ZERO_STRUCTP(join);
 
-       printf("Connecting to SAMR\n");
-
-       status = torture_rpc_connection(join, 
-                                       &join->p, 
-                                       &dcerpc_table_samr);
+       torture_comment(tctx, "Connecting to SAMR\n");
+       
+       if (dc_binding) {
+               status = dcerpc_pipe_connect(join,
+                                            &join->p,
+                                            dc_binding,
+                                            &ndr_table_samr,
+                                            samba_cmdline_get_creds(),
+                                       NULL, tctx->lp_ctx);
+                                            
+       } else {
+               status = torture_rpc_connection(tctx,
+                                               &join->p, 
+                                               &ndr_table_samr);
+       }
        if (!NT_STATUS_IS_OK(status)) {
                return NULL;
        }
+       b = join->p->binding_handle;
 
        c.in.system_name = NULL;
        c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        c.out.connect_handle = &handle;
 
-       status = dcerpc_samr_Connect(join->p, join, &c);
+       status = dcerpc_samr_Connect_r(b, join, &c);
        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(join, join->p->last_fault_code);
-               }
-               printf("samr_Connect failed - %s\n", errstr);
+               torture_comment(tctx, "samr_Connect failed - %s\n", errstr);
+               return NULL;
+       }
+       if (!NT_STATUS_IS_OK(c.out.result)) {
+               const char *errstr = nt_errstr(c.out.result);
+               torture_comment(tctx, "samr_Connect failed - %s\n", errstr);
                return NULL;
        }
 
-       printf("Opening domain %s\n", domain);
+       if (domain) {
+               torture_comment(tctx, "Opening domain %s\n", domain);
 
-       name.string = domain;
-       l.in.connect_handle = &handle;
-       l.in.domain_name = &name;
+               name.string = domain;
+               l.in.connect_handle = &handle;
+               l.in.domain_name = &name;
+               l.out.sid = &sid;
 
-       status = dcerpc_samr_LookupDomain(join->p, join, &l);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("LookupDomain failed - %s\n", nt_errstr(status));
-               goto failed;
+               status = dcerpc_samr_LookupDomain_r(b, join, &l);
+               if (!NT_STATUS_IS_OK(status)) {
+                       torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(status));
+                       goto failed;
+               }
+               if (!NT_STATUS_IS_OK(l.out.result)) {
+                       torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(l.out.result));
+                       goto failed;
+               }
+       } else {
+               struct samr_EnumDomains e;
+               uint32_t resume_handle = 0, num_entries;
+               struct samr_SamArray *sam;
+               int i;
+
+               e.in.connect_handle = &handle;
+               e.in.buf_size = (uint32_t)-1;
+               e.in.resume_handle = &resume_handle;
+               e.out.sam = &sam;
+               e.out.num_entries = &num_entries;
+               e.out.resume_handle = &resume_handle;
+
+               status = dcerpc_samr_EnumDomains_r(b, join, &e);
+               if (!NT_STATUS_IS_OK(status)) {
+                       torture_comment(tctx, "EnumDomains failed - %s\n", nt_errstr(status));
+                       goto failed;
+               }
+               if (!NT_STATUS_IS_OK(e.out.result)) {
+                       torture_comment(tctx, "EnumDomains failed - %s\n", nt_errstr(e.out.result));
+                       goto failed;
+               }
+               if ((num_entries != 2) || (sam && sam->count != 2)) {
+                       torture_comment(tctx, "unexpected number of domains\n");
+                       goto failed;
+               }
+               for (i=0; i < 2; i++) {
+                       if (!strequal(sam->entries[i].name.string, "builtin")) {
+                               domain = sam->entries[i].name.string;
+                               break;
+                       }
+               }
+               if (domain) {
+                       torture_comment(tctx, "Opening domain %s\n", domain);
+
+                       name.string = domain;
+                       l.in.connect_handle = &handle;
+                       l.in.domain_name = &name;
+                       l.out.sid = &sid;
+
+                       status = dcerpc_samr_LookupDomain_r(b, join, &l);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(status));
+                               goto failed;
+                       }
+                       if (!NT_STATUS_IS_OK(l.out.result)) {
+                               torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(l.out.result));
+                               goto failed;
+                       }
+               } else {
+                       torture_comment(tctx, "cannot proceed without domain name\n");
+                       goto failed;
+               }
        }
 
-       talloc_steal(join, l.out.sid);
-       join->dom_sid = l.out.sid;
+       talloc_steal(join, *l.out.sid);
+       join->dom_sid = *l.out.sid;
+       join->dom_netbios_name = talloc_strdup(join, domain);
+       if (!join->dom_netbios_name) goto failed;
 
        o.in.connect_handle = &handle;
        o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
-       o.in.sid = l.out.sid;
-       o.out.domain_handle = &domain_handle;
+       o.in.sid = *l.out.sid;
+       o.out.domain_handle = &join->domain_handle;
 
-       status = dcerpc_samr_OpenDomain(join->p, join, &o);
+       status = dcerpc_samr_OpenDomain_r(b, join, &o);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenDomain failed - %s\n", nt_errstr(status));
+               torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(status));
+               goto failed;
+       }
+       if (!NT_STATUS_IS_OK(o.out.result)) {
+               torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(o.out.result));
                goto failed;
        }
 
-       printf("Creating account %s\n", username);
+       torture_comment(tctx, "Creating account %s\n", username);
 
 again:
        name.string = username;
-       r.in.domain_handle = &domain_handle;
+       r.in.domain_handle = &join->domain_handle;
        r.in.account_name = &name;
        r.in.acct_flags = acct_type;
        r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
@@ -190,53 +292,67 @@ again:
        r.out.access_granted = &access_granted;
        r.out.rid = &rid;
 
-       status = dcerpc_samr_CreateUser2(join->p, join, &r);
+       status = dcerpc_samr_CreateUser2_r(b, join, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               torture_comment(tctx, "CreateUser2 failed - %s\n", nt_errstr(status));
+               goto failed;
+       }
 
-       if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
-               status = DeleteUser_byname(join->p, join, &domain_handle, name.string);
+       if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
+               status = DeleteUser_byname(tctx, b, join, &join->domain_handle, name.string);
                if (NT_STATUS_IS_OK(status)) {
                        goto again;
                }
        }
 
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("CreateUser2 failed - %s\n", nt_errstr(status));
+       if (!NT_STATUS_IS_OK(r.out.result)) {
+               torture_comment(tctx, "CreateUser2 failed - %s\n", nt_errstr(r.out.result));
                goto failed;
        }
 
        join->user_sid = dom_sid_add_rid(join, join->dom_sid, rid);
 
        pwp.in.user_handle = &join->user_handle;
+       pwp.out.info = &info;
 
-       status = dcerpc_samr_GetUserPwInfo(join->p, join, &pwp);
-       if (NT_STATUS_IS_OK(status)) {
-               policy_min_pw_len = pwp.out.info.min_password_length;
+       status = dcerpc_samr_GetUserPwInfo_r(b, join, &pwp);
+       if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(pwp.out.result)) {
+               policy_min_pw_len = pwp.out.info->min_password_length;
        }
 
-       random_pw = generate_random_str(join, MAX(8, policy_min_pw_len));
+       random_pw = generate_random_password(join, MAX(8, policy_min_pw_len), max_pw_len);
 
-       printf("Setting account password '%s'\n", random_pw);
+       torture_comment(tctx, "Setting account password '%s'\n", random_pw);
 
+       ZERO_STRUCT(u);
        s.in.user_handle = &join->user_handle;
        s.in.info = &u;
        s.in.level = 24;
 
-       encode_pw_buffer(u.info24.password.data, random_pw, STR_UNICODE);
-       u.info24.pw_len = strlen(random_pw);
+       u.info24.password_expired = 0;
 
        status = dcerpc_fetch_session_key(join->p, &session_key);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u - no session key - %s\n",
+               torture_comment(tctx, "SetUserInfo level %u - no session key - %s\n",
                       s.in.level, nt_errstr(status));
-               torture_leave_domain(join);
+               torture_leave_domain(tctx, join);
                goto failed;
        }
 
-       arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
+       status = init_samr_CryptPassword(random_pw,
+                                        &session_key,
+                                        &u.info24.password);
+       torture_assert_ntstatus_ok(tctx,
+                                  status,
+                                  "init_samr_CryptPassword failed");
 
-       status = dcerpc_samr_SetUserInfo(join->p, join, &s);
+       status = dcerpc_samr_SetUserInfo_r(b, join, &s);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo failed - %s\n", nt_errstr(status));
+               torture_comment(tctx, "SetUserInfo failed - %s\n", nt_errstr(status));
+               goto failed;
+       }
+       if (!NT_STATUS_IS_OK(s.out.result)) {
+               torture_comment(tctx, "SetUserInfo failed - %s\n", nt_errstr(s.out.result));
                goto failed;
        }
 
@@ -245,7 +361,7 @@ again:
        s.in.info = &u;
        s.in.level = 21;
 
-       u.info21.acct_flags = acct_type;
+       u.info21.acct_flags = acct_type | ACB_PWNOEXP;
        u.info21.fields_present = SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME;
 
        u.info21.comment.string = talloc_asprintf(join, 
@@ -258,13 +374,18 @@ again:
        
        u.info21.description.string = talloc_asprintf(join, 
                                         "Samba4 torture account created by host %s: %s", 
-                                        lp_netbios_name(), timestring(join, time(NULL)));
+                                        lpcfg_netbios_name(tctx->lp_ctx),
+                                        timestring(join, time(NULL)));
 
-       printf("Resetting ACB flags, force pw change time\n");
+       torture_comment(tctx, "Resetting ACB flags, force pw change time\n");
 
-       status = dcerpc_samr_SetUserInfo(join->p, join, &s);
+       status = dcerpc_samr_SetUserInfo_r(b, join, &s);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo failed - %s\n", nt_errstr(status));
+               torture_comment(tctx, "SetUserInfo failed - %s\n", nt_errstr(status));
+               goto failed;
+       }
+       if (!NT_STATUS_IS_OK(s.out.result)) {
+               torture_comment(tctx, "SetUserInfo failed - %s\n", nt_errstr(s.out.result));
                goto failed;
        }
 
@@ -275,12 +396,110 @@ again:
        return join;
 
 failed:
-       torture_leave_domain(join);
+       torture_leave_domain(tctx, join);
        return NULL;
 }
 
+/*
+ * Set privileges on an account.
+ */
+
+static void init_lsa_StringLarge(struct lsa_StringLarge *name, const char *s)
+{
+       name->string = s;
+}
+static void init_lsa_String(struct lsa_String *name, const char *s)
+{
+       name->string = s;
+}
+
+bool torture_setup_privs(struct torture_context *tctx,
+                       struct dcerpc_pipe *p,
+                       uint32_t num_privs,
+                       const char **privs,
+                       const struct dom_sid *user_sid)
+{
+       struct dcerpc_binding_handle *b = p->binding_handle;
+       struct policy_handle *handle;
+       int i;
+
+       torture_assert(tctx,
+               test_lsa_OpenPolicy2(b, tctx, &handle),
+               "failed to open policy");
+
+       for (i=0; i < num_privs; i++) {
+               struct lsa_LookupPrivValue r;
+               struct lsa_LUID luid;
+               struct lsa_String name;
+
+               init_lsa_String(&name, privs[i]);
+
+               r.in.handle = handle;
+               r.in.name = &name;
+               r.out.luid = &luid;
+
+               torture_assert_ntstatus_ok(tctx,
+                       dcerpc_lsa_LookupPrivValue_r(b, tctx, &r),
+                       "lsa_LookupPrivValue failed");
+               if (!NT_STATUS_IS_OK(r.out.result)) {
+                       torture_comment(tctx, "lsa_LookupPrivValue failed for '%s' with %s\n",
+                               privs[i], nt_errstr(r.out.result));
+                       return false;
+               }
+       }
+
+       {
+               struct lsa_AddAccountRights r;
+               struct lsa_RightSet rights;
+
+               rights.count = num_privs;
+               rights.names = talloc_zero_array(tctx, struct lsa_StringLarge, rights.count);
+               for (i=0; i < rights.count; i++) {
+                       init_lsa_StringLarge(&rights.names[i], privs[i]);
+               }
+
+               r.in.handle = handle;
+               r.in.sid = discard_const_p(struct dom_sid, user_sid);
+               r.in.rights = &rights;
+
+               torture_assert_ntstatus_ok(tctx,
+                       dcerpc_lsa_AddAccountRights_r(b, tctx, &r),
+                       "lsa_AddAccountRights failed");
+               torture_assert_ntstatus_ok(tctx, r.out.result,
+                       "lsa_AddAccountRights failed");
+       }
+
+       test_lsa_Close(b, tctx, handle);
+
+       return true;
+}
+
+struct test_join *torture_create_testuser(struct torture_context *torture,
+                                         const char *username,
+                                         const char *domain,
+                                         uint16_t acct_type,
+                                         const char **random_password)
+{
+       return torture_create_testuser_max_pwlen(torture, username, domain, acct_type, random_password, 255);
+}
 
-_PUBLIC_ struct test_join *torture_join_domain(const char *machine_name, 
+NTSTATUS torture_delete_testuser(struct torture_context *torture,
+                                struct test_join *join,
+                                const char *username)
+{
+       NTSTATUS status;
+
+       status = DeleteUser_byname(torture,
+                                  join->p->binding_handle,
+                                  torture,
+                                  &join->domain_handle,
+                                  username);
+
+       return status;
+}
+
+_PUBLIC_ struct test_join *torture_join_domain(struct torture_context *tctx,
+                                              const char *machine_name, 
                                      uint32_t acct_flags,
                                      struct cli_credentials **machine_credentials)
 {
@@ -290,17 +509,43 @@ _PUBLIC_ struct test_join *torture_join_domain(const char *machine_name,
        struct test_join *tj;
        struct samr_SetUserInfo s;
        union samr_UserInfo u;
-       
-       tj = talloc(NULL, struct test_join);
+       const char *binding_str = NULL;
+       struct dcerpc_binding *binding = NULL;
+       enum dcerpc_transport_t transport;
+
+       tj = talloc_zero(tctx, struct test_join);
        if (!tj) return NULL;
 
-       libnet_r = talloc(tj, struct libnet_JoinDomain);
+       binding_str = torture_setting_string(tctx, "binding", NULL);
+       if (binding_str == NULL) {
+               const char *host = torture_setting_string(tctx, "host", NULL);
+               binding_str = talloc_asprintf(tj, "ncacn_np:%s", host);
+       }
+       status = dcerpc_parse_binding(tj, binding_str, &binding);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("dcerpc_parse_binding(%s) failed - %s\n",
+                         binding_str, nt_errstr(status)));
+               talloc_free(tj);
+               return NULL;
+       }
+       transport = dcerpc_binding_get_transport(binding);
+       switch (transport) {
+       case NCALRPC:
+       case NCACN_UNIX_STREAM:
+               break;
+       default:
+               dcerpc_binding_set_transport(binding, NCACN_NP);
+               dcerpc_binding_set_flags(binding, 0, DCERPC_AUTH_OPTIONS);
+               break;
+       }
+
+       libnet_r = talloc_zero(tj, struct libnet_JoinDomain);
        if (!libnet_r) {
                talloc_free(tj);
                return NULL;
        }
        
-       libnet_ctx = libnet_context_init(NULL); 
+       libnet_ctx = libnet_context_init(tctx->ev, tctx->lp_ctx);
        if (!libnet_ctx) {
                talloc_free(tj);
                return NULL;
@@ -308,10 +553,11 @@ _PUBLIC_ struct test_join *torture_join_domain(const char *machine_name,
        
        tj->libnet_r = libnet_r;
                
-       libnet_ctx->cred = cmdline_credentials;
-       libnet_r->in.binding = lp_parm_string(-1, "torture", "binding");
-       if (!libnet_r->in.binding) {
-               libnet_r->in.binding = talloc_asprintf(libnet_r, "ncacn_np:%s", lp_parm_string(-1, "torture", "host"));
+       libnet_ctx->cred = samba_cmdline_get_creds();
+       libnet_r->in.binding = dcerpc_binding_string(libnet_r, binding);
+       if (libnet_r->in.binding == NULL) {
+               talloc_free(tj);
+               return NULL;
        }
        libnet_r->in.level = LIBNET_JOINDOMAIN_SPECIFIED;
        libnet_r->in.netbios_name = machine_name;
@@ -322,7 +568,7 @@ _PUBLIC_ struct test_join *torture_join_domain(const char *machine_name,
        }
        
        libnet_r->in.acct_type = acct_flags;
-       libnet_r->in.recreate_account = True;
+       libnet_r->in.recreate_account = true;
 
        status = libnet_JoinDomain(libnet_ctx, libnet_r, libnet_r);
        if (!NT_STATUS_IS_OK(status)) {
@@ -338,6 +584,16 @@ _PUBLIC_ struct test_join *torture_join_domain(const char *machine_name,
        tj->user_handle = *libnet_r->out.user_handle;
        tj->dom_sid = libnet_r->out.domain_sid;
        talloc_steal(tj, libnet_r->out.domain_sid);
+       tj->dom_netbios_name    = libnet_r->out.domain_name;
+       talloc_steal(tj, libnet_r->out.domain_name);
+       tj->dom_dns_name        = libnet_r->out.realm;
+       talloc_steal(tj, libnet_r->out.realm);
+       tj->user_guid = libnet_r->out.account_guid;
+       tj->netbios_name = talloc_strdup(tj, machine_name);
+       if (!tj->netbios_name) {
+               talloc_free(tj);
+               return NULL;
+       }
 
        ZERO_STRUCT(u);
        s.in.user_handle = &tj->user_handle;
@@ -354,15 +610,18 @@ _PUBLIC_ struct test_join *torture_join_domain(const char *machine_name,
        
        u.info21.description.string = talloc_asprintf(tj, 
                                                      "Samba4 torture account created by host %s: %s", 
-                                                     lp_netbios_name(), timestring(tj, time(NULL)));
+                                                     lpcfg_netbios_name(tctx->lp_ctx), timestring(tj, time(NULL)));
 
-       status = dcerpc_samr_SetUserInfo(tj->p, tj, &s);
+       status = dcerpc_samr_SetUserInfo_r(tj->p->binding_handle, tj, &s);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo (non-critical) failed - %s\n", nt_errstr(status));
+               torture_comment(tctx, "SetUserInfo (non-critical) failed - %s\n", nt_errstr(status));
+       }
+       if (!NT_STATUS_IS_OK(s.out.result)) {
+               torture_comment(tctx, "SetUserInfo (non-critical) failed - %s\n", nt_errstr(s.out.result));
        }
 
        *machine_credentials = cli_credentials_init(tj);
-       cli_credentials_set_conf(*machine_credentials);
+       cli_credentials_set_conf(*machine_credentials, tctx->lp_ctx);
        cli_credentials_set_workstation(*machine_credentials, machine_name, CRED_SPECIFIED);
        cli_credentials_set_domain(*machine_credentials, libnet_r->out.domain_name, CRED_SPECIFIED);
        if (libnet_r->out.realm) {
@@ -370,6 +629,7 @@ _PUBLIC_ struct test_join *torture_join_domain(const char *machine_name,
        }
        cli_credentials_set_username(*machine_credentials, libnet_r->in.account_name, CRED_SPECIFIED);
        cli_credentials_set_password(*machine_credentials, libnet_r->out.join_password, CRED_SPECIFIED);
+       cli_credentials_set_kvno(*machine_credentials, libnet_r->out.kvno);
        if (acct_flags & ACB_SVRTRUST) {
                cli_credentials_set_secure_channel_type(*machine_credentials,
                                                        SEC_CHAN_BDC);
@@ -395,7 +655,9 @@ 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)
+static NTSTATUS torture_leave_ads_domain(struct torture_context *torture,
+                                        TALLOC_CTX *mem_ctx,
+                                        struct libnet_JoinDomain *libnet_r)
 {
        int rtn;
        TALLOC_CTX *tmp_ctx;
@@ -416,7 +678,7 @@ NTSTATUS torture_leave_ads_domain(TALLOC_CTX *mem_ctx, struct libnet_JoinDomain
                return NT_STATUS_NO_MEMORY;
        }
 
-       ldb_ctx = ldb_init(tmp_ctx);
+       ldb_ctx = ldb_init(tmp_ctx, torture->ev);
        if (!ldb_ctx) {
                libnet_r->out.error_string = NULL;
                talloc_free(tmp_ctx);
@@ -431,24 +693,26 @@ NTSTATUS torture_leave_ads_domain(TALLOC_CTX *mem_ctx, struct libnet_JoinDomain
                return NT_STATUS_NO_MEMORY;
        }
 
-       remote_ldb_url = talloc_asprintf(tmp_ctx, "ldap://%s", libnet_r->out.samr_binding->host);
+       remote_ldb_url = talloc_asprintf(tmp_ctx, "ldap://%s",
+               dcerpc_binding_get_string_option(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;
        }
 
-       ldb_set_opaque(ldb_ctx, "credentials", cmdline_credentials);
+       ldb_set_opaque(ldb_ctx, "credentials", samba_cmdline_get_creds());
+       ldb_set_opaque(ldb_ctx, "loadparm", samba_cmdline_get_lp_ctx());
 
        rtn = ldb_connect(ldb_ctx, remote_ldb_url, 0, NULL);
-       if (rtn != 0) {
+       if (rtn != LDB_SUCCESS) {
                libnet_r->out.error_string = NULL;
                talloc_free(tmp_ctx);
                return NT_STATUS_UNSUCCESSFUL;
        }
 
        rtn = ldb_delete(ldb_ctx, server_dn);
-       if (rtn != 0) {
+       if (rtn != LDB_SUCCESS) {
                libnet_r->out.error_string = NULL;
                talloc_free(tmp_ctx);
                return NT_STATUS_UNSUCCESSFUL;
@@ -464,7 +728,7 @@ NTSTATUS torture_leave_ads_domain(TALLOC_CTX *mem_ctx, struct libnet_JoinDomain
   leave the domain, deleting the machine acct
 */
 
-_PUBLIC_ void torture_leave_domain(struct test_join *join)
+_PUBLIC_ void torture_leave_domain(struct torture_context *tctx, struct test_join *join)
 {
        struct samr_DeleteUser d;
        NTSTATUS status;
@@ -474,17 +738,21 @@ _PUBLIC_ void torture_leave_domain(struct test_join *join)
        }
        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);
+
+       /* Delete machine account */
+       status = dcerpc_samr_DeleteUser_r(join->p->binding_handle, join, &d);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("Delete of machine account failed\n");
+               torture_comment(tctx, "DeleteUser failed\n");
+       } else if (!NT_STATUS_IS_OK(d.out.result)) {
+               torture_comment(tctx, "Delete of machine account %s failed\n",
+                      join->netbios_name);
        } else {
-               printf("Delete of machine account was successful.\n");
+               torture_comment(tctx, "Delete of machine account %s was successful.\n",
+                      join->netbios_name);
        }
 
        if (join->libnet_r) {
-               status = torture_leave_ads_domain(join, join->libnet_r);
+               status = torture_leave_ads_domain(tctx, join, join->libnet_r);
        }
        
        talloc_free(join);
@@ -503,7 +771,27 @@ const struct dom_sid *torture_join_user_sid(struct test_join *join)
        return join->user_sid;
 }
 
+const char *torture_join_netbios_name(struct test_join *join)
+{
+       return join->netbios_name;
+}
 
+const struct GUID *torture_join_user_guid(struct test_join *join)
+{
+       return &join->user_guid;
+}
+
+const char *torture_join_dom_netbios_name(struct test_join *join)
+{
+       return join->dom_netbios_name;
+}
+
+const char *torture_join_dom_dns_name(struct test_join *join)
+{
+       return join->dom_dns_name;
+}
+
+#if 0 /* Left as the documentation of the join process, but see new implementation in libnet_become_dc.c */
 struct test_join_ads_dc {
        struct test_join *join;
 };
@@ -527,6 +815,7 @@ struct test_join_ads_dc *torture_join_domain_ads_dc(const char *machine_name,
                return NULL;
        }
 
+/* W2K: */
        /* W2K: modify userAccountControl from 4096 to 532480 */
        
        /* W2K: modify RDN to OU=Domain Controllers and skip the $ from server name */
@@ -582,21 +871,17 @@ struct test_join_ads_dc *torture_join_domain_ads_dc(const char *machine_name,
         */
 
        /* replicate CN=Schema,CN=Configuration,...
-        * using DRSUAPI_DS_BIND_GUID_W2K3 ("6afab99c-6e26-464a-975f-f58f105218bc")
+        * using DRSUAPI_DS_BIND_GUID_W2K ("6abec3d1-3054-41c8-a362-5a0c5b7d5d71")
         *
         */
 
        /* replicate CN=Configuration,...
-        * using DRSUAPI_DS_BIND_GUID_W2K3 ("6afab99c-6e26-464a-975f-f58f105218bc")
+        * using DRSUAPI_DS_BIND_GUID_W2K ("6abec3d1-3054-41c8-a362-5a0c5b7d5d71")
         *
         */
 
-       /* W2K3: modify userAccountControl from 4096 to 532480 */
-       
-       /* W2K3: modify RDN to OU=Domain Controllers and skip the $ from server name */
-
        /* replicate Domain Partition
-        * using DRSUAPI_DS_BIND_GUID_W2K3 ("6afab99c-6e26-464a-975f-f58f105218bc")
+        * using DRSUAPI_DS_BIND_GUID_W2K ("6abec3d1-3054-41c8-a362-5a0c5b7d5d71")
         *
         */
 
@@ -623,15 +908,8 @@ struct test_join_ads_dc *torture_join_domain_ads_dc(const char *machine_name,
         * CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
         */
 
+/* W2K3: see libnet/libnet_become_dc.c */
        return join;
 }
-               
-void torture_leave_domain_ads_dc(struct test_join_ads_dc *join)
-{
-
-       if (join->join) {
-               torture_leave_domain(join->join);
-       }
 
-       talloc_free(join);
-}
+#endif