static bool test_opendomain_samr(struct torture_context *tctx, struct dcerpc_binding_handle *b, TALLOC_CTX *mem_ctx, struct policy_handle *handle, struct lsa_String *domname, uint32_t *access_mask, struct dom_sid **sid_p) { struct policy_handle h, domain_handle; struct samr_Connect r1; struct samr_LookupDomain r2; struct dom_sid2 *sid = NULL; struct samr_OpenDomain r3; torture_comment(tctx, "connecting\n"); *access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r1.in.system_name = 0; r1.in.access_mask = *access_mask; r1.out.connect_handle = &h; torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, mem_ctx, &r1), "Connect failed"); torture_assert_ntstatus_ok(tctx, r1.out.result, "Connect failed"); r2.in.connect_handle = &h; r2.in.domain_name = domname; r2.out.sid = &sid; torture_comment(tctx, "domain lookup on %s\n", domname->string); torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, mem_ctx, &r2), "LookupDomain failed"); torture_assert_ntstatus_ok(tctx, r2.out.result, "LookupDomain failed"); r3.in.connect_handle = &h; r3.in.access_mask = *access_mask; r3.in.sid = *sid_p = *r2.out.sid; r3.out.domain_handle = &domain_handle; torture_comment(tctx, "opening domain\n"); torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, mem_ctx, &r3), "OpenDomain failed"); torture_assert_ntstatus_ok(tctx, r3.out.result, "OpenDomain failed"); *handle = domain_handle; return true; }
static bool spoolss_access_setup_membership(struct torture_context *tctx, struct dcerpc_pipe *p, uint32_t num_members, uint32_t *members, struct dom_sid *user_sid) { struct dcerpc_binding_handle *b = p->binding_handle; struct policy_handle connect_handle, domain_handle; int i; torture_comment(tctx, "Setting up BUILTIN membership for %s\n", dom_sid_string(tctx, user_sid)); for (i=0; i < num_members; i++) { torture_comment(tctx, "adding user to S-1-5-32-%d\n", members[i]); } { struct samr_Connect2 r; r.in.system_name = ""; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.connect_handle = &connect_handle; torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r), "samr_Connect2 failed"); torture_assert_ntstatus_ok(tctx, r.out.result, "samr_Connect2 failed"); } { struct samr_OpenDomain r; r.in.connect_handle = &connect_handle; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32"); r.out.domain_handle = &domain_handle; torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r), "samr_OpenDomain failed"); torture_assert_ntstatus_ok(tctx, r.out.result, "samr_OpenDomain failed"); } for (i=0; i < num_members; i++) { struct policy_handle alias_handle; { struct samr_OpenAlias r; r.in.domain_handle = &domain_handle; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.in.rid = members[i]; r.out.alias_handle = &alias_handle; torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r), "samr_OpenAlias failed"); torture_assert_ntstatus_ok(tctx, r.out.result, "samr_OpenAlias failed"); } { struct samr_AddAliasMember r; r.in.alias_handle = &alias_handle; r.in.sid = user_sid; torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r), "samr_AddAliasMember failed"); torture_assert_ntstatus_ok(tctx, r.out.result, "samr_AddAliasMember failed"); } test_samr_handle_Close(b, tctx, &alias_handle); } test_samr_handle_Close(b, tctx, &domain_handle); test_samr_handle_Close(b, tctx, &connect_handle); return true; }
/* do some samr ops using the schannel connection */ static bool test_samr_ops(struct torture_context *tctx, struct dcerpc_binding_handle *b) { struct samr_GetDomPwInfo r; struct samr_PwInfo info; struct samr_Connect connect_r; struct samr_OpenDomain opendom; int i; struct lsa_String name; struct policy_handle handle; struct policy_handle domain_handle; name.string = lpcfg_workgroup(tctx->lp_ctx); r.in.domain_name = &name; r.out.info = &info; connect_r.in.system_name = 0; connect_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; connect_r.out.connect_handle = &handle; torture_comment(tctx, "Testing Connect and OpenDomain on BUILTIN\n"); torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &connect_r), "Connect failed"); if (!NT_STATUS_IS_OK(connect_r.out.result)) { if (NT_STATUS_EQUAL(connect_r.out.result, NT_STATUS_ACCESS_DENIED)) { torture_comment(tctx, "Connect failed (expected, schannel mapped to anonymous): %s\n", nt_errstr(connect_r.out.result)); } else { torture_comment(tctx, "Connect failed - %s\n", nt_errstr(connect_r.out.result)); return false; } } else { opendom.in.connect_handle = &handle; opendom.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; opendom.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32"); opendom.out.domain_handle = &domain_handle; torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &opendom), "OpenDomain failed"); if (!NT_STATUS_IS_OK(opendom.out.result)) { torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(opendom.out.result)); return false; } } torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string); /* do several ops to test credential chaining */ for (i=0;i<5;i++) { torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r), "GetDomPwInfo failed"); if (!NT_STATUS_IS_OK(r.out.result)) { if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) { torture_comment(tctx, "GetDomPwInfo op %d failed - %s\n", i, nt_errstr(r.out.result)); return false; } } } return true; }
struct test_join *torture_create_testuser_max_pwlen(struct torture_context *torture, 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; uint32_t access_granted; uint32_t rid; DATA_BLOB session_key; struct lsa_String name; int policy_min_pw_len = 0; struct test_join *join; char *random_pw; const char *dc_binding = torture_setting_string(torture, "dc_binding", NULL); struct dcerpc_binding_handle *b = NULL; join = talloc(NULL, struct test_join); if (join == NULL) { return NULL; } ZERO_STRUCTP(join); printf("Connecting to SAMR\n"); if (dc_binding) { status = dcerpc_pipe_connect(join, &join->p, dc_binding, &ndr_table_samr, cmdline_credentials, NULL, torture->lp_ctx); } else { status = torture_rpc_connection(torture, &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_r(b, join, &c); if (!NT_STATUS_IS_OK(status)) { const char *errstr = nt_errstr(status); printf("samr_Connect failed - %s\n", errstr); return NULL; } if (!NT_STATUS_IS_OK(c.out.result)) { const char *errstr = nt_errstr(c.out.result); printf("samr_Connect failed - %s\n", errstr); return NULL; } if (domain) { printf("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)) { printf("LookupDomain failed - %s\n", nt_errstr(status)); goto failed; } if (!NT_STATUS_IS_OK(l.out.result)) { printf("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)) { printf("EnumDomains failed - %s\n", nt_errstr(status)); goto failed; } if (!NT_STATUS_IS_OK(e.out.result)) { printf("EnumDomains failed - %s\n", nt_errstr(e.out.result)); goto failed; } if ((num_entries != 2) || (sam && sam->count != 2)) { printf("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) { printf("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)) { printf("LookupDomain failed - %s\n", nt_errstr(status)); goto failed; } if (!NT_STATUS_IS_OK(l.out.result)) { printf("LookupDomain failed - %s\n", nt_errstr(l.out.result)); goto failed; } } else { printf("cannot proceed without domain name\n"); goto failed; } } 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 = &join->domain_handle; status = dcerpc_samr_OpenDomain_r(b, join, &o); if (!NT_STATUS_IS_OK(status)) { printf("OpenDomain failed - %s\n", nt_errstr(status)); goto failed; } if (!NT_STATUS_IS_OK(o.out.result)) { printf("OpenDomain failed - %s\n", nt_errstr(o.out.result)); goto failed; } printf("Creating account %s\n", username); again: name.string = username; 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; r.out.user_handle = &join->user_handle; r.out.access_granted = &access_granted; r.out.rid = &rid; status = dcerpc_samr_CreateUser2_r(b, join, &r); if (!NT_STATUS_IS_OK(status)) { printf("CreateUser2 failed - %s\n", nt_errstr(status)); goto failed; } if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) { status = DeleteUser_byname(b, join, &join->domain_handle, name.string); if (NT_STATUS_IS_OK(status)) { goto again; } } if (!NT_STATUS_IS_OK(r.out.result)) { printf("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_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_password(join, MAX(8, policy_min_pw_len), max_pw_len); printf("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.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", s.in.level, nt_errstr(status)); torture_leave_domain(torture, join); goto failed; } arcfour_crypt_blob(u.info24.password.data, 516, &session_key); status = dcerpc_samr_SetUserInfo_r(b, join, &s); if (!NT_STATUS_IS_OK(status)) { printf("SetUserInfo failed - %s\n", nt_errstr(status)); goto failed; } if (!NT_STATUS_IS_OK(s.out.result)) { printf("SetUserInfo failed - %s\n", nt_errstr(s.out.result)); goto failed; } ZERO_STRUCT(u); s.in.user_handle = &join->user_handle; s.in.info = &u; s.in.level = 21; 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, "Tortured by Samba4: %s", timestring(join, time(NULL))); u.info21.full_name.string = talloc_asprintf(join, "Torture account for Samba4: %s", timestring(join, time(NULL))); u.info21.description.string = talloc_asprintf(join, "Samba4 torture account created by host %s: %s", lpcfg_netbios_name(torture->lp_ctx), timestring(join, time(NULL))); printf("Resetting ACB flags, force pw change time\n"); status = dcerpc_samr_SetUserInfo_r(b, join, &s); if (!NT_STATUS_IS_OK(status)) { printf("SetUserInfo failed - %s\n", nt_errstr(status)); goto failed; } if (!NT_STATUS_IS_OK(s.out.result)) { printf("SetUserInfo failed - %s\n", nt_errstr(s.out.result)); goto failed; } if (random_password) { *random_password = random_pw; } return join; failed: torture_leave_domain(torture, join); return NULL; }
/* * 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_zero(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_r(samr_pipe->binding_handle, tmp_ctx, &sc); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sc.out.result)) { status = sc.out.result; } 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 automatically find the domain name */ connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, lpcfg_workgroup(ctx->lp_ctx)); connect_with_info->out.realm = talloc_strdup(tmp_ctx, lpcfg_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_r(samr_pipe->binding_handle, tmp_ctx, &l); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(l.out.result)) { status = l.out.result; } 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_r(samr_pipe->binding_handle, tmp_ctx, &od); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(od.out.result)) { status = od.out.result; } 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_r(samr_pipe->binding_handle, tmp_ctx, &cu); if (NT_STATUS_IS_OK(cu_status) && !NT_STATUS_IS_OK(cu.out.result)) { cu_status = cu.out.result; } 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_r(samr_pipe->binding_handle, tmp_ctx, &ln); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ln.out.result)) { status = ln.out.result; } 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_r(samr_pipe->binding_handle, tmp_ctx, &ou); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ou.out.result)) { status = ou.out.result; } 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_r(samr_pipe->binding_handle, mem_ctx, &d); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(d.out.result)) { status = d.out.result; } 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_r(samr_pipe->binding_handle, tmp_ctx, &cu); if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(cu.out.result)) { status = cu.out.result; } 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)) {
/** * open connection so SAMR + Join Domain * common code needed when adding or removing users */ static enum MAPISTATUS mapiadmin_samr_connect(struct mapiadmin_ctx *mapiadmin_ctx, TALLOC_CTX *mem_ctx) { NTSTATUS status; struct tevent_context *ev; struct mapi_context *mapi_ctx; struct mapi_profile *profile; struct samr_Connect c; struct samr_OpenDomain o; struct samr_LookupDomain l; struct policy_handle handle; struct policy_handle domain_handle; struct lsa_String name; MAPI_RETVAL_IF(!mapiadmin_ctx, MAPI_E_NOT_INITIALIZED, NULL); MAPI_RETVAL_IF(!mapiadmin_ctx->session, MAPI_E_NOT_INITIALIZED, NULL); MAPI_RETVAL_IF(!mapiadmin_ctx->session->profile, MAPI_E_NOT_INITIALIZED, NULL); MAPI_RETVAL_IF(!mapiadmin_ctx->session->profile->credentials, MAPI_E_NOT_INITIALIZED, NULL); MAPI_RETVAL_IF(!mapiadmin_ctx->username, MAPI_E_NOT_INITIALIZED, NULL); mapi_ctx = mapiadmin_ctx->session->mapi_ctx; MAPI_RETVAL_IF(!mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL); profile = mapiadmin_ctx->session->profile; mapiadmin_ctx->user_ctx = talloc_zero(mem_ctx, struct test_join); MAPI_RETVAL_IF(!mapiadmin_ctx->user_ctx, MAPI_E_NOT_ENOUGH_RESOURCES ,NULL); OC_DEBUG(3, "Connecting to SAMR"); ev = tevent_context_init(mem_ctx); status = dcerpc_pipe_connect(mapiadmin_ctx->user_ctx, &mapiadmin_ctx->user_ctx->p, mapiadmin_ctx->dc_binding ? mapiadmin_ctx->dc_binding : mapiadmin_ctx->binding, &ndr_table_samr, profile->credentials, ev, mapi_ctx->lp_ctx); MAPI_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, NULL); profile = mapiadmin_ctx->session->profile; c.in.system_name = NULL; c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; c.out.connect_handle = &handle; status = dcerpc_samr_Connect_r(mapiadmin_ctx->user_ctx->p->binding_handle, mapiadmin_ctx->user_ctx, &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(mapiadmin_ctx->user_ctx, mapiadmin_ctx->user_ctx->p->last_fault_code); } OC_DEBUG(3, "samr_Connect failed - %s", errstr); return MAPI_E_CALL_FAILED; } OC_DEBUG(3, "Opening domain %s", profile->domain); name.string = profile->domain; l.in.connect_handle = &handle; l.in.domain_name = &name; l.out.sid = talloc(mem_ctx, struct dom_sid2 *); talloc_steal(mapiadmin_ctx->user_ctx, l.out.sid); status = dcerpc_samr_LookupDomain_r(mapiadmin_ctx->user_ctx->p->binding_handle, mapiadmin_ctx->user_ctx, &l); if (!NT_STATUS_IS_OK(status)) { OC_DEBUG(3, "LookupDomain failed - %s", nt_errstr(status)); return MAPI_E_CALL_FAILED; } mapiadmin_ctx->user_ctx->dom_sid = *l.out.sid; mapiadmin_ctx->user_ctx->dom_netbios_name = talloc_strdup(mapiadmin_ctx->user_ctx, profile->domain); if (!mapiadmin_ctx->user_ctx->dom_netbios_name) return MAPI_E_CALL_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; status = dcerpc_samr_OpenDomain_r(mapiadmin_ctx->user_ctx->p->binding_handle, mapiadmin_ctx->user_ctx, &o); if (!NT_STATUS_IS_OK(status)) { OC_DEBUG(3, "OpenDomain failed - %s", nt_errstr(status)); return MAPI_E_CALL_FAILED; } mapiadmin_ctx->handle = talloc_memdup(mem_ctx, &domain_handle, sizeof (struct policy_handle)); errno = 0; return MAPI_E_SUCCESS; }
/** * Opens handle on Domain using SAMR * * @param _domain_handle [out] Ptr to storage to store Domain handle * @param _dom_sid [out] If NULL, Domain SID won't be returned */ bool test_domain_open(struct torture_context *tctx, struct dcerpc_binding_handle *b, struct lsa_String *domname, TALLOC_CTX *mem_ctx, struct policy_handle *_domain_handle, struct dom_sid2 *_dom_sid) { struct policy_handle connect_handle; struct policy_handle domain_handle; struct samr_Connect r1; struct samr_LookupDomain r2; struct dom_sid2 *sid = NULL; struct samr_OpenDomain r3; torture_comment(tctx, "connecting\n"); r1.in.system_name = 0; r1.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r1.out.connect_handle = &connect_handle; torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, mem_ctx, &r1), "Connect failed"); torture_assert_ntstatus_ok(tctx, r1.out.result, "Connect failed"); r2.in.connect_handle = &connect_handle; r2.in.domain_name = domname; r2.out.sid = &sid; torture_comment(tctx, "domain lookup on %s\n", domname->string); torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, mem_ctx, &r2), "LookupDomain failed"); torture_assert_ntstatus_ok(tctx, r2.out.result, "LookupDomain failed"); r3.in.connect_handle = &connect_handle; r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r3.in.sid = *r2.out.sid; r3.out.domain_handle = &domain_handle; torture_comment(tctx, "opening domain %s\n", domname->string); torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, mem_ctx, &r3), "OpenDomain failed"); torture_assert_ntstatus_ok(tctx, r3.out.result, "OpenDomain failed"); *_domain_handle = domain_handle; if (_dom_sid) { *_dom_sid = **r2.out.sid; } /* Close connect_handle, we don't need it anymore */ test_samr_close_handle(tctx, b, mem_ctx, &connect_handle); return true; }