_PUBLIC_ void torture_leave_domain(struct torture_context *torture, struct test_join *join) { struct samr_DeleteUser d; NTSTATUS status; if (!join) { return; } 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 %s failed\n", join->netbios_name); } else { printf("Delete of machine account %s was successful.\n", join->netbios_name); } if (join->libnet_r) { status = torture_leave_ads_domain(torture, join, join->libnet_r); } talloc_free(join); }
bool test_user_cleanup(struct torture_context *tctx, struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *domain_handle, const char *name) { NTSTATUS status; struct samr_LookupNames r1; struct samr_OpenUser r2; struct samr_DeleteUser r3; struct lsa_String names[2]; uint32_t rid; struct policy_handle user_handle; struct samr_Ids rids, types; names[0].string = name; r1.in.domain_handle = domain_handle; r1.in.num_names = 1; r1.in.names = names; r1.out.rids = &rids; r1.out.types = &types; torture_comment(tctx, "user account lookup '%s'\n", name); status = dcerpc_samr_LookupNames(p, mem_ctx, &r1); torture_assert_ntstatus_ok(tctx, status, "LookupNames failed"); rid = r1.out.rids->ids[0]; r2.in.domain_handle = domain_handle; r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r2.in.rid = rid; r2.out.user_handle = &user_handle; torture_comment(tctx, "opening user account\n"); status = dcerpc_samr_OpenUser(p, mem_ctx, &r2); torture_assert_ntstatus_ok(tctx, status, "OpenUser failed"); r3.in.user_handle = &user_handle; r3.out.user_handle = &user_handle; torture_comment(tctx, "deleting user account\n"); status = dcerpc_samr_DeleteUser(p, mem_ctx, &r3); torture_assert_ntstatus_ok(tctx, status, "DeleteUser failed"); return true; }
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 user_handle; uint32_t rid; struct samr_LookupNames n; struct samr_Ids rids, types; struct lsa_String sname; struct samr_OpenUser r; sname.string = name; 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 { return status; } 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); if (!NT_STATUS_IS_OK(status)) { printf("OpenUser(%s) failed - %s\n", name, nt_errstr(status)); return status; } d.in.user_handle = &user_handle; d.out.user_handle = &user_handle; status = dcerpc_samr_DeleteUser(p, mem_ctx, &d); if (!NT_STATUS_IS_OK(status)) { return status; } return NT_STATUS_OK; }
/* * do a domain join using DCERPC/SAMR calls * - connect to the LSA pipe, to try and find out information about the domain * - create a secondary connection to SAMR pipe * - do a samr_Connect to get a policy handle * - do a samr_LookupDomain to get the domain sid * - do a samr_OpenDomain to get a domain handle * - do a samr_CreateAccount to try and get a new account * * If that fails, do: * - do a samr_LookupNames to get the users rid * - do a samr_OpenUser to get a user handle * - potentially delete and recreate the user * - assert the account is of the right type with samrQueryUserInfo * * - call libnet_SetPassword_samr_handle to set the password, * and pass a samr_UserInfo21 struct to set full_name and the account flags * * - do some ADS specific things when we join as Domain Controller, * look at libnet_joinADSDomain() for the details */ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_JoinDomain *r) { TALLOC_CTX *tmp_ctx; NTSTATUS status, cu_status; struct libnet_RpcConnect *connect_with_info; struct dcerpc_pipe *samr_pipe; struct samr_Connect sc; struct policy_handle p_handle; struct samr_OpenDomain od; struct policy_handle d_handle; struct samr_LookupNames ln; struct samr_Ids rids, types; struct samr_OpenUser ou; struct samr_CreateUser2 cu; struct policy_handle *u_handle = NULL; struct samr_QueryUserInfo qui; union samr_UserInfo *uinfo; struct samr_UserInfo21 u_info21; union libnet_SetPassword r2; struct samr_GetUserPwInfo pwp; struct samr_PwInfo info; struct lsa_String samr_account_name; uint32_t acct_flags, old_acct_flags; uint32_t rid, access_granted; int policy_min_pw_len = 0; struct dom_sid *account_sid = NULL; const char *password_str = NULL; r->out.error_string = NULL; r2.samr_handle.out.error_string = NULL; tmp_ctx = talloc_named(mem_ctx, 0, "libnet_Join temp context"); if (!tmp_ctx) { r->out.error_string = NULL; return NT_STATUS_NO_MEMORY; } u_handle = talloc(tmp_ctx, struct policy_handle); if (!u_handle) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } connect_with_info = talloc(tmp_ctx, struct libnet_RpcConnect); if (!connect_with_info) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } /* prepare connect to the SAMR pipe of PDC */ if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) { connect_with_info->in.binding = NULL; connect_with_info->in.name = r->in.domain_name; } else { connect_with_info->in.binding = r->in.binding; connect_with_info->in.name = NULL; } /* This level makes a connection to the LSA pipe on the way, * to get some useful bits of information about the domain */ connect_with_info->level = LIBNET_RPC_CONNECT_DC_INFO; connect_with_info->in.dcerpc_iface = &ndr_table_samr; /* establish the SAMR connection */ status = libnet_RpcConnect(ctx, tmp_ctx, connect_with_info); if (!NT_STATUS_IS_OK(status)) { if (r->in.binding) { r->out.error_string = talloc_asprintf(mem_ctx, "Connection to SAMR pipe of DC %s failed: %s", r->in.binding, connect_with_info->out.error_string); } else { r->out.error_string = talloc_asprintf(mem_ctx, "Connection to SAMR pipe of PDC for %s failed: %s", r->in.domain_name, connect_with_info->out.error_string); } talloc_free(tmp_ctx); return status; } samr_pipe = connect_with_info->out.dcerpc_pipe; status = dcerpc_pipe_auth(tmp_ctx, &samr_pipe, connect_with_info->out.dcerpc_pipe->binding, &ndr_table_samr, ctx->cred, ctx->lp_ctx); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "SAMR bind failed: %s", nt_errstr(status)); talloc_free(tmp_ctx); return status; } /* prepare samr_Connect */ ZERO_STRUCT(p_handle); sc.in.system_name = NULL; sc.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; sc.out.connect_handle = &p_handle; /* 2. do a samr_Connect to get a policy handle */ status = dcerpc_samr_Connect(samr_pipe, tmp_ctx, &sc); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_Connect failed: %s", nt_errstr(status)); talloc_free(tmp_ctx); return status; } /* If this is a connection on ncacn_ip_tcp to Win2k3 SP1, we don't get back this useful info */ if (!connect_with_info->out.domain_name) { if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) { connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, r->in.domain_name); } else { /* Bugger, we just lost our way to automaticly find the domain name */ connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, lp_workgroup(ctx->lp_ctx)); connect_with_info->out.realm = talloc_strdup(tmp_ctx, lp_realm(ctx->lp_ctx)); } } /* Perhaps we didn't get a SID above, because we are against ncacn_ip_tcp */ if (!connect_with_info->out.domain_sid) { struct lsa_String name; struct samr_LookupDomain l; struct dom_sid2 *sid = NULL; name.string = connect_with_info->out.domain_name; l.in.connect_handle = &p_handle; l.in.domain_name = &name; l.out.sid = &sid; status = dcerpc_samr_LookupDomain(samr_pipe, tmp_ctx, &l); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "SAMR LookupDomain failed: %s", nt_errstr(status)); talloc_free(tmp_ctx); return status; } connect_with_info->out.domain_sid = *l.out.sid; } /* prepare samr_OpenDomain */ ZERO_STRUCT(d_handle); od.in.connect_handle = &p_handle; od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; od.in.sid = connect_with_info->out.domain_sid; od.out.domain_handle = &d_handle; /* do a samr_OpenDomain to get a domain handle */ status = dcerpc_samr_OpenDomain(samr_pipe, tmp_ctx, &od); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_OpenDomain for [%s] failed: %s", dom_sid_string(tmp_ctx, connect_with_info->out.domain_sid), nt_errstr(status)); talloc_free(tmp_ctx); return status; } /* prepare samr_CreateUser2 */ ZERO_STRUCTP(u_handle); cu.in.domain_handle = &d_handle; cu.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; samr_account_name.string = r->in.account_name; cu.in.account_name = &samr_account_name; cu.in.acct_flags = r->in.acct_type; cu.out.user_handle = u_handle; cu.out.rid = &rid; cu.out.access_granted = &access_granted; /* do a samr_CreateUser2 to get an account handle, or an error */ cu_status = dcerpc_samr_CreateUser2(samr_pipe, tmp_ctx, &cu); status = cu_status; if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { /* prepare samr_LookupNames */ ln.in.domain_handle = &d_handle; ln.in.num_names = 1; ln.in.names = talloc_array(tmp_ctx, struct lsa_String, 1); ln.out.rids = &rids; ln.out.types = &types; if (!ln.in.names) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } ln.in.names[0].string = r->in.account_name; /* 5. do a samr_LookupNames to get the users rid */ status = dcerpc_samr_LookupNames(samr_pipe, tmp_ctx, &ln); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_LookupNames for [%s] failed: %s", r->in.account_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; } /* check if we got one RID for the user */ if (ln.out.rids->count != 1) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_LookupNames for [%s] returns %d RIDs", r->in.account_name, ln.out.rids->count); talloc_free(tmp_ctx); return NT_STATUS_INVALID_PARAMETER; } /* prepare samr_OpenUser */ ZERO_STRUCTP(u_handle); ou.in.domain_handle = &d_handle; ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; ou.in.rid = ln.out.rids->ids[0]; rid = ou.in.rid; ou.out.user_handle = u_handle; /* 6. do a samr_OpenUser to get a user handle */ status = dcerpc_samr_OpenUser(samr_pipe, tmp_ctx, &ou); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_OpenUser for [%s] failed: %s", r->in.account_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; } if (r->in.recreate_account) { struct samr_DeleteUser d; d.in.user_handle = u_handle; d.out.user_handle = u_handle; status = dcerpc_samr_DeleteUser(samr_pipe, mem_ctx, &d); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_DeleteUser (for recreate) of [%s] failed: %s", r->in.account_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; } /* We want to recreate, so delete and another samr_CreateUser2 */ /* &cu filled in above */ status = dcerpc_samr_CreateUser2(samr_pipe, tmp_ctx, &cu); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_CreateUser2 (recreate) for [%s] failed: %s", r->in.account_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; } } } else if (!NT_STATUS_IS_OK(status)) {