2 Unix SMB/CIFS implementation.
4 utility code to join/leave a domain
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 this code is used by other torture modules to join/leave a domain
24 as either a member, bdc or thru a trust relationship
28 #include "system/time.h"
29 #include "libnet/libnet.h"
30 #include "libnet/libnet_join_proto.h"
31 #include "lib/cmdline/cmdline.h"
32 #include "librpc/gen_ndr/ndr_lsa_c.h"
33 #include "librpc/gen_ndr/ndr_samr_c.h"
35 #include "libcli/auth/libcli_auth.h"
36 #include "torture/rpc/torture_rpc.h"
37 #include "libcli/security/security.h"
38 #include "param/param.h"
39 #include "source3/rpc_client/init_samr.h"
42 struct dcerpc_pipe
*p
;
43 struct policy_handle user_handle
;
44 struct policy_handle domain_handle
;
45 struct libnet_JoinDomain
*libnet_r
;
46 struct dom_sid
*dom_sid
;
47 const char *dom_netbios_name
;
48 const char *dom_dns_name
;
49 struct dom_sid
*user_sid
;
50 struct GUID user_guid
;
51 const char *netbios_name
;
55 static NTSTATUS
DeleteUser_byname(struct torture_context
*tctx
,
56 struct dcerpc_binding_handle
*b
,
58 struct policy_handle
*handle
, const char *name
)
61 struct samr_DeleteUser d
;
62 struct policy_handle user_handle
;
64 struct samr_LookupNames n
;
65 struct samr_Ids rids
, types
;
66 struct lsa_String sname
;
67 struct samr_OpenUser r
;
71 n
.in
.domain_handle
= handle
;
77 status
= dcerpc_samr_LookupNames_r(b
, mem_ctx
, &n
);
78 if (!NT_STATUS_IS_OK(status
)) {
81 if (NT_STATUS_IS_OK(n
.out
.result
)) {
82 rid
= n
.out
.rids
->ids
[0];
87 r
.in
.domain_handle
= handle
;
88 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
90 r
.out
.user_handle
= &user_handle
;
92 status
= dcerpc_samr_OpenUser_r(b
, mem_ctx
, &r
);
93 if (!NT_STATUS_IS_OK(status
)) {
94 torture_comment(tctx
, "OpenUser(%s) failed - %s\n", name
, nt_errstr(status
));
97 if (!NT_STATUS_IS_OK(r
.out
.result
)) {
98 torture_comment(tctx
, "OpenUser(%s) failed - %s\n", name
, nt_errstr(r
.out
.result
));
102 d
.in
.user_handle
= &user_handle
;
103 d
.out
.user_handle
= &user_handle
;
104 status
= dcerpc_samr_DeleteUser_r(b
, mem_ctx
, &d
);
105 if (!NT_STATUS_IS_OK(status
)) {
108 if (!NT_STATUS_IS_OK(d
.out
.result
)) {
116 create a test user in the domain
117 an opaque pointer is returned. Pass it to torture_leave_domain()
121 struct test_join
*torture_create_testuser_max_pwlen(struct torture_context
*tctx
,
122 const char *username
,
125 const char **random_password
,
129 struct samr_Connect c
;
130 struct samr_CreateUser2 r
;
131 struct samr_OpenDomain o
;
132 struct samr_LookupDomain l
;
133 struct dom_sid2
*sid
= NULL
;
134 struct samr_GetUserPwInfo pwp
;
135 struct samr_PwInfo info
;
136 struct samr_SetUserInfo s
;
137 union samr_UserInfo u
;
138 struct policy_handle handle
;
139 uint32_t access_granted
;
141 DATA_BLOB session_key
;
142 struct lsa_String name
;
144 int policy_min_pw_len
= 0;
145 struct test_join
*join
;
147 const char *dc_binding
= torture_setting_string(tctx
, "dc_binding", NULL
);
148 struct dcerpc_binding_handle
*b
= NULL
;
149 join
= talloc(NULL
, struct test_join
);
156 torture_comment(tctx
, "Connecting to SAMR\n");
159 status
= dcerpc_pipe_connect(join
,
163 samba_cmdline_get_creds(),
167 status
= torture_rpc_connection(tctx
,
171 if (!NT_STATUS_IS_OK(status
)) {
174 b
= join
->p
->binding_handle
;
176 c
.in
.system_name
= NULL
;
177 c
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
178 c
.out
.connect_handle
= &handle
;
180 status
= dcerpc_samr_Connect_r(b
, join
, &c
);
181 if (!NT_STATUS_IS_OK(status
)) {
182 const char *errstr
= nt_errstr(status
);
183 torture_comment(tctx
, "samr_Connect failed - %s\n", errstr
);
186 if (!NT_STATUS_IS_OK(c
.out
.result
)) {
187 const char *errstr
= nt_errstr(c
.out
.result
);
188 torture_comment(tctx
, "samr_Connect failed - %s\n", errstr
);
193 torture_comment(tctx
, "Opening domain %s\n", domain
);
195 name
.string
= domain
;
196 l
.in
.connect_handle
= &handle
;
197 l
.in
.domain_name
= &name
;
200 status
= dcerpc_samr_LookupDomain_r(b
, join
, &l
);
201 if (!NT_STATUS_IS_OK(status
)) {
202 torture_comment(tctx
, "LookupDomain failed - %s\n", nt_errstr(status
));
205 if (!NT_STATUS_IS_OK(l
.out
.result
)) {
206 torture_comment(tctx
, "LookupDomain failed - %s\n", nt_errstr(l
.out
.result
));
210 struct samr_EnumDomains e
;
211 uint32_t resume_handle
= 0, num_entries
;
212 struct samr_SamArray
*sam
;
215 e
.in
.connect_handle
= &handle
;
216 e
.in
.buf_size
= (uint32_t)-1;
217 e
.in
.resume_handle
= &resume_handle
;
219 e
.out
.num_entries
= &num_entries
;
220 e
.out
.resume_handle
= &resume_handle
;
222 status
= dcerpc_samr_EnumDomains_r(b
, join
, &e
);
223 if (!NT_STATUS_IS_OK(status
)) {
224 torture_comment(tctx
, "EnumDomains failed - %s\n", nt_errstr(status
));
227 if (!NT_STATUS_IS_OK(e
.out
.result
)) {
228 torture_comment(tctx
, "EnumDomains failed - %s\n", nt_errstr(e
.out
.result
));
231 if ((num_entries
!= 2) || (sam
&& sam
->count
!= 2)) {
232 torture_comment(tctx
, "unexpected number of domains\n");
235 for (i
=0; i
< 2; i
++) {
236 if (!strequal(sam
->entries
[i
].name
.string
, "builtin")) {
237 domain
= sam
->entries
[i
].name
.string
;
242 torture_comment(tctx
, "Opening domain %s\n", domain
);
244 name
.string
= domain
;
245 l
.in
.connect_handle
= &handle
;
246 l
.in
.domain_name
= &name
;
249 status
= dcerpc_samr_LookupDomain_r(b
, join
, &l
);
250 if (!NT_STATUS_IS_OK(status
)) {
251 torture_comment(tctx
, "LookupDomain failed - %s\n", nt_errstr(status
));
254 if (!NT_STATUS_IS_OK(l
.out
.result
)) {
255 torture_comment(tctx
, "LookupDomain failed - %s\n", nt_errstr(l
.out
.result
));
259 torture_comment(tctx
, "cannot proceed without domain name\n");
264 talloc_steal(join
, *l
.out
.sid
);
265 join
->dom_sid
= *l
.out
.sid
;
266 join
->dom_netbios_name
= talloc_strdup(join
, domain
);
267 if (!join
->dom_netbios_name
) goto failed
;
269 o
.in
.connect_handle
= &handle
;
270 o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
271 o
.in
.sid
= *l
.out
.sid
;
272 o
.out
.domain_handle
= &join
->domain_handle
;
274 status
= dcerpc_samr_OpenDomain_r(b
, join
, &o
);
275 if (!NT_STATUS_IS_OK(status
)) {
276 torture_comment(tctx
, "OpenDomain failed - %s\n", nt_errstr(status
));
279 if (!NT_STATUS_IS_OK(o
.out
.result
)) {
280 torture_comment(tctx
, "OpenDomain failed - %s\n", nt_errstr(o
.out
.result
));
284 torture_comment(tctx
, "Creating account %s\n", username
);
287 name
.string
= username
;
288 r
.in
.domain_handle
= &join
->domain_handle
;
289 r
.in
.account_name
= &name
;
290 r
.in
.acct_flags
= acct_type
;
291 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
292 r
.out
.user_handle
= &join
->user_handle
;
293 r
.out
.access_granted
= &access_granted
;
296 status
= dcerpc_samr_CreateUser2_r(b
, join
, &r
);
297 if (!NT_STATUS_IS_OK(status
)) {
298 torture_comment(tctx
, "CreateUser2 failed - %s\n", nt_errstr(status
));
302 if (NT_STATUS_EQUAL(r
.out
.result
, NT_STATUS_USER_EXISTS
)) {
303 status
= DeleteUser_byname(tctx
, b
, join
, &join
->domain_handle
, name
.string
);
304 if (NT_STATUS_IS_OK(status
)) {
309 if (!NT_STATUS_IS_OK(r
.out
.result
)) {
310 torture_comment(tctx
, "CreateUser2 failed - %s\n", nt_errstr(r
.out
.result
));
314 join
->user_sid
= dom_sid_add_rid(join
, join
->dom_sid
, rid
);
316 pwp
.in
.user_handle
= &join
->user_handle
;
317 pwp
.out
.info
= &info
;
319 status
= dcerpc_samr_GetUserPwInfo_r(b
, join
, &pwp
);
320 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(pwp
.out
.result
)) {
321 policy_min_pw_len
= pwp
.out
.info
->min_password_length
;
324 random_pw
= generate_random_password(join
, MAX(8, policy_min_pw_len
), max_pw_len
);
326 torture_comment(tctx
, "Setting account password '%s'\n", random_pw
);
329 s
.in
.user_handle
= &join
->user_handle
;
333 u
.info24
.password_expired
= 0;
335 status
= dcerpc_binding_handle_transport_session_key(b
, tctx
, &session_key
);
336 if (!NT_STATUS_IS_OK(status
)) {
337 torture_comment(tctx
, "SetUserInfo level %u - no session key - %s\n",
338 s
.in
.level
, nt_errstr(status
));
339 torture_leave_domain(tctx
, join
);
343 status
= init_samr_CryptPassword(random_pw
,
346 torture_assert_ntstatus_ok(tctx
,
348 "init_samr_CryptPassword failed");
350 status
= dcerpc_samr_SetUserInfo_r(b
, join
, &s
);
351 if (!NT_STATUS_IS_OK(status
)) {
352 torture_comment(tctx
, "SetUserInfo failed - %s\n", nt_errstr(status
));
355 if (!NT_STATUS_IS_OK(s
.out
.result
)) {
356 torture_comment(tctx
, "SetUserInfo failed - %s\n", nt_errstr(s
.out
.result
));
361 s
.in
.user_handle
= &join
->user_handle
;
365 u
.info21
.acct_flags
= acct_type
| ACB_PWNOEXP
;
366 u
.info21
.fields_present
= SAMR_FIELD_ACCT_FLAGS
| SAMR_FIELD_DESCRIPTION
| SAMR_FIELD_COMMENT
| SAMR_FIELD_FULL_NAME
;
368 u
.info21
.comment
.string
= talloc_asprintf(join
,
369 "Tortured by Samba4: %s",
370 timestring(join
, time(NULL
)));
372 u
.info21
.full_name
.string
= talloc_asprintf(join
,
373 "Torture account for Samba4: %s",
374 timestring(join
, time(NULL
)));
376 u
.info21
.description
.string
= talloc_asprintf(join
,
377 "Samba4 torture account created by host %s: %s",
378 lpcfg_netbios_name(tctx
->lp_ctx
),
379 timestring(join
, time(NULL
)));
381 torture_comment(tctx
, "Resetting ACB flags, force pw change time\n");
383 status
= dcerpc_samr_SetUserInfo_r(b
, join
, &s
);
384 if (!NT_STATUS_IS_OK(status
)) {
385 torture_comment(tctx
, "SetUserInfo failed - %s\n", nt_errstr(status
));
388 if (!NT_STATUS_IS_OK(s
.out
.result
)) {
389 torture_comment(tctx
, "SetUserInfo failed - %s\n", nt_errstr(s
.out
.result
));
393 if (random_password
) {
394 *random_password
= random_pw
;
400 torture_leave_domain(tctx
, join
);
405 * Set privileges on an account.
408 static void init_lsa_StringLarge(struct lsa_StringLarge
*name
, const char *s
)
412 static void init_lsa_String(struct lsa_String
*name
, const char *s
)
417 bool torture_setup_privs(struct torture_context
*tctx
,
418 struct dcerpc_pipe
*p
,
421 const struct dom_sid
*user_sid
)
423 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
424 struct policy_handle
*handle
;
428 test_lsa_OpenPolicy2(b
, tctx
, &handle
),
429 "failed to open policy");
431 for (i
=0; i
< num_privs
; i
++) {
432 struct lsa_LookupPrivValue r
;
433 struct lsa_LUID luid
;
434 struct lsa_String name
;
436 init_lsa_String(&name
, privs
[i
]);
438 r
.in
.handle
= handle
;
442 torture_assert_ntstatus_ok(tctx
,
443 dcerpc_lsa_LookupPrivValue_r(b
, tctx
, &r
),
444 "lsa_LookupPrivValue failed");
445 if (!NT_STATUS_IS_OK(r
.out
.result
)) {
446 torture_comment(tctx
, "lsa_LookupPrivValue failed for '%s' with %s\n",
447 privs
[i
], nt_errstr(r
.out
.result
));
453 struct lsa_AddAccountRights r
;
454 struct lsa_RightSet rights
;
456 rights
.count
= num_privs
;
457 rights
.names
= talloc_zero_array(tctx
, struct lsa_StringLarge
, rights
.count
);
458 for (i
=0; i
< rights
.count
; i
++) {
459 init_lsa_StringLarge(&rights
.names
[i
], privs
[i
]);
462 r
.in
.handle
= handle
;
463 r
.in
.sid
= discard_const_p(struct dom_sid
, user_sid
);
464 r
.in
.rights
= &rights
;
466 torture_assert_ntstatus_ok(tctx
,
467 dcerpc_lsa_AddAccountRights_r(b
, tctx
, &r
),
468 "lsa_AddAccountRights failed");
469 torture_assert_ntstatus_ok(tctx
, r
.out
.result
,
470 "lsa_AddAccountRights failed");
473 test_lsa_Close(b
, tctx
, handle
);
478 struct test_join
*torture_create_testuser(struct torture_context
*torture
,
479 const char *username
,
482 const char **random_password
)
484 return torture_create_testuser_max_pwlen(torture
, username
, domain
, acct_type
, random_password
, 255);
487 NTSTATUS
torture_delete_testuser(struct torture_context
*torture
,
488 struct test_join
*join
,
489 const char *username
)
493 status
= DeleteUser_byname(torture
,
494 join
->p
->binding_handle
,
496 &join
->domain_handle
,
502 _PUBLIC_
struct test_join
*torture_join_domain(struct torture_context
*tctx
,
503 const char *machine_name
,
505 struct cli_credentials
**machine_credentials
)
508 struct libnet_context
*libnet_ctx
;
509 struct libnet_JoinDomain
*libnet_r
;
510 struct test_join
*tj
;
511 struct samr_SetUserInfo s
;
512 union samr_UserInfo u
;
513 const char *binding_str
= NULL
;
514 struct dcerpc_binding
*binding
= NULL
;
515 enum dcerpc_transport_t transport
;
517 tj
= talloc_zero(tctx
, struct test_join
);
518 if (!tj
) return NULL
;
520 binding_str
= torture_setting_string(tctx
, "binding", NULL
);
521 if (binding_str
== NULL
) {
522 const char *host
= torture_setting_string(tctx
, "host", NULL
);
523 binding_str
= talloc_asprintf(tj
, "ncacn_np:%s", host
);
525 status
= dcerpc_parse_binding(tj
, binding_str
, &binding
);
526 if (!NT_STATUS_IS_OK(status
)) {
527 DEBUG(0, ("dcerpc_parse_binding(%s) failed - %s\n",
528 binding_str
, nt_errstr(status
)));
532 transport
= dcerpc_binding_get_transport(binding
);
535 case NCACN_UNIX_STREAM
:
538 dcerpc_binding_set_transport(binding
, NCACN_NP
);
539 dcerpc_binding_set_flags(binding
, 0, DCERPC_AUTH_OPTIONS
);
543 libnet_r
= talloc_zero(tj
, struct libnet_JoinDomain
);
549 libnet_ctx
= libnet_context_init(tctx
->ev
, tctx
->lp_ctx
);
555 tj
->libnet_r
= libnet_r
;
557 libnet_ctx
->cred
= samba_cmdline_get_creds();
558 libnet_r
->in
.binding
= dcerpc_binding_string(libnet_r
, binding
);
559 if (libnet_r
->in
.binding
== NULL
) {
563 libnet_r
->in
.level
= LIBNET_JOINDOMAIN_SPECIFIED
;
564 libnet_r
->in
.netbios_name
= machine_name
;
565 libnet_r
->in
.account_name
= talloc_asprintf(libnet_r
, "%s$", machine_name
);
566 if (!libnet_r
->in
.account_name
) {
571 libnet_r
->in
.acct_type
= acct_flags
;
572 libnet_r
->in
.recreate_account
= true;
574 status
= libnet_JoinDomain(libnet_ctx
, libnet_r
, libnet_r
);
575 if (!NT_STATUS_IS_OK(status
)) {
576 if (libnet_r
->out
.error_string
) {
577 DEBUG(0, ("Domain join failed - %s\n", libnet_r
->out
.error_string
));
579 DEBUG(0, ("Domain join failed - %s\n", nt_errstr(status
)));
584 tj
->p
= libnet_r
->out
.samr_pipe
;
585 tj
->user_handle
= *libnet_r
->out
.user_handle
;
586 tj
->dom_sid
= libnet_r
->out
.domain_sid
;
587 talloc_steal(tj
, libnet_r
->out
.domain_sid
);
588 tj
->dom_netbios_name
= libnet_r
->out
.domain_name
;
589 talloc_steal(tj
, libnet_r
->out
.domain_name
);
590 tj
->dom_dns_name
= libnet_r
->out
.realm
;
591 talloc_steal(tj
, libnet_r
->out
.realm
);
592 tj
->user_guid
= libnet_r
->out
.account_guid
;
593 tj
->netbios_name
= talloc_strdup(tj
, machine_name
);
594 if (!tj
->netbios_name
) {
600 s
.in
.user_handle
= &tj
->user_handle
;
604 u
.info21
.fields_present
= SAMR_FIELD_DESCRIPTION
| SAMR_FIELD_COMMENT
| SAMR_FIELD_FULL_NAME
;
605 u
.info21
.comment
.string
= talloc_asprintf(tj
,
606 "Tortured by Samba4: %s",
607 timestring(tj
, time(NULL
)));
608 u
.info21
.full_name
.string
= talloc_asprintf(tj
,
609 "Torture account for Samba4: %s",
610 timestring(tj
, time(NULL
)));
612 u
.info21
.description
.string
= talloc_asprintf(tj
,
613 "Samba4 torture account created by host %s: %s",
614 lpcfg_netbios_name(tctx
->lp_ctx
), timestring(tj
, time(NULL
)));
616 status
= dcerpc_samr_SetUserInfo_r(tj
->p
->binding_handle
, tj
, &s
);
617 if (!NT_STATUS_IS_OK(status
)) {
618 torture_comment(tctx
, "SetUserInfo (non-critical) failed - %s\n", nt_errstr(status
));
620 if (!NT_STATUS_IS_OK(s
.out
.result
)) {
621 torture_comment(tctx
, "SetUserInfo (non-critical) failed - %s\n", nt_errstr(s
.out
.result
));
624 *machine_credentials
= cli_credentials_init(tj
);
625 cli_credentials_set_conf(*machine_credentials
, tctx
->lp_ctx
);
626 cli_credentials_set_workstation(*machine_credentials
, machine_name
, CRED_SPECIFIED
);
627 cli_credentials_set_domain(*machine_credentials
, libnet_r
->out
.domain_name
, CRED_SPECIFIED
);
628 if (libnet_r
->out
.realm
) {
629 cli_credentials_set_realm(*machine_credentials
, libnet_r
->out
.realm
, CRED_SPECIFIED
);
631 cli_credentials_set_username(*machine_credentials
, libnet_r
->in
.account_name
, CRED_SPECIFIED
);
632 cli_credentials_set_password(*machine_credentials
, libnet_r
->out
.join_password
, CRED_SPECIFIED
);
633 cli_credentials_set_kvno(*machine_credentials
, libnet_r
->out
.kvno
);
634 if (acct_flags
& ACB_SVRTRUST
) {
635 cli_credentials_set_secure_channel_type(*machine_credentials
,
637 } else if (acct_flags
& ACB_WSTRUST
) {
638 cli_credentials_set_secure_channel_type(*machine_credentials
,
641 DEBUG(0, ("Invalid account type specified to torture_join_domain\n"));
642 talloc_free(*machine_credentials
);
649 struct dcerpc_pipe
*torture_join_samr_pipe(struct test_join
*join
)
654 struct policy_handle
*torture_join_samr_user_policy(struct test_join
*join
)
656 return &join
->user_handle
;
659 static NTSTATUS
torture_leave_ads_domain(struct torture_context
*torture
,
661 struct libnet_JoinDomain
*libnet_r
)
666 struct ldb_dn
*server_dn
;
667 struct ldb_context
*ldb_ctx
;
669 char *remote_ldb_url
;
671 /* Check if we are a domain controller. If not, exit. */
672 if (!libnet_r
->out
.server_dn_str
) {
676 tmp_ctx
= talloc_named(mem_ctx
, 0, "torture_leave temporary context");
678 libnet_r
->out
.error_string
= NULL
;
679 return NT_STATUS_NO_MEMORY
;
682 ldb_ctx
= ldb_init(tmp_ctx
, torture
->ev
);
684 libnet_r
->out
.error_string
= NULL
;
685 talloc_free(tmp_ctx
);
686 return NT_STATUS_NO_MEMORY
;
689 /* Remove CN=Servers,... entry from the AD. */
690 server_dn
= ldb_dn_new(tmp_ctx
, ldb_ctx
, libnet_r
->out
.server_dn_str
);
691 if (! ldb_dn_validate(server_dn
)) {
692 libnet_r
->out
.error_string
= NULL
;
693 talloc_free(tmp_ctx
);
694 return NT_STATUS_NO_MEMORY
;
697 remote_ldb_url
= talloc_asprintf(tmp_ctx
, "ldap://%s",
698 dcerpc_binding_get_string_option(libnet_r
->out
.samr_binding
, "host"));
699 if (!remote_ldb_url
) {
700 libnet_r
->out
.error_string
= NULL
;
701 talloc_free(tmp_ctx
);
702 return NT_STATUS_NO_MEMORY
;
705 ldb_set_opaque(ldb_ctx
, "credentials", samba_cmdline_get_creds());
706 ldb_set_opaque(ldb_ctx
, "loadparm", samba_cmdline_get_lp_ctx());
708 rtn
= ldb_connect(ldb_ctx
, remote_ldb_url
, 0, NULL
);
709 if (rtn
!= LDB_SUCCESS
) {
710 libnet_r
->out
.error_string
= NULL
;
711 talloc_free(tmp_ctx
);
712 return NT_STATUS_UNSUCCESSFUL
;
715 rtn
= ldb_delete(ldb_ctx
, server_dn
);
716 if (rtn
!= LDB_SUCCESS
) {
717 libnet_r
->out
.error_string
= NULL
;
718 talloc_free(tmp_ctx
);
719 return NT_STATUS_UNSUCCESSFUL
;
722 DEBUG(0, ("%s removed successfully.\n", libnet_r
->out
.server_dn_str
));
724 talloc_free(tmp_ctx
);
729 leave the domain, deleting the machine acct
732 _PUBLIC_
void torture_leave_domain(struct torture_context
*tctx
, struct test_join
*join
)
734 struct samr_DeleteUser d
;
740 d
.in
.user_handle
= &join
->user_handle
;
741 d
.out
.user_handle
= &join
->user_handle
;
743 /* Delete machine account */
744 status
= dcerpc_samr_DeleteUser_r(join
->p
->binding_handle
, join
, &d
);
745 if (!NT_STATUS_IS_OK(status
)) {
746 torture_comment(tctx
, "DeleteUser failed\n");
747 } else if (!NT_STATUS_IS_OK(d
.out
.result
)) {
748 torture_comment(tctx
, "Delete of machine account %s failed\n",
751 torture_comment(tctx
, "Delete of machine account %s was successful.\n",
755 if (join
->libnet_r
) {
756 status
= torture_leave_ads_domain(tctx
, join
, join
->libnet_r
);
763 return the dom sid for a test join
765 _PUBLIC_
const struct dom_sid
*torture_join_sid(struct test_join
*join
)
767 return join
->dom_sid
;
770 const struct dom_sid
*torture_join_user_sid(struct test_join
*join
)
772 return join
->user_sid
;
775 const char *torture_join_netbios_name(struct test_join
*join
)
777 return join
->netbios_name
;
780 const struct GUID
*torture_join_user_guid(struct test_join
*join
)
782 return &join
->user_guid
;
785 const char *torture_join_dom_netbios_name(struct test_join
*join
)
787 return join
->dom_netbios_name
;
790 const char *torture_join_dom_dns_name(struct test_join
*join
)
792 return join
->dom_dns_name
;
795 #if 0 /* Left as the documentation of the join process, but see new implementation in libnet_become_dc.c */
796 struct test_join_ads_dc
{
797 struct test_join
*join
;
800 struct test_join_ads_dc
*torture_join_domain_ads_dc(const char *machine_name
,
802 struct cli_credentials
**machine_credentials
)
804 struct test_join_ads_dc
*join
;
806 join
= talloc(NULL
, struct test_join_ads_dc
);
811 join
->join
= torture_join_domain(machine_name
,
813 machine_credentials
);
820 /* W2K: modify userAccountControl from 4096 to 532480 */
822 /* W2K: modify RDN to OU=Domain Controllers and skip the $ from server name */
824 /* ask objectVersion of Schema Partition */
826 /* ask rIDManagerReferenz of the Domain Partition */
828 /* ask fsMORoleOwner of the RID-Manager$ object
829 * returns CN=NTDS Settings,CN=<DC>,CN=Servers,CN=Default-First-Site-Name, ...
832 /* ask for dnsHostName of CN=<DC>,CN=Servers,CN=Default-First-Site-Name, ... */
834 /* ask for objectGUID of CN=NTDS Settings,CN=<DC>,CN=Servers,CN=Default-First-Site-Name, ... */
836 /* ask for * of CN=Default-First-Site-Name, ... */
838 /* search (&(|(objectClass=user)(objectClass=computer))(sAMAccountName=<machine_name>$)) in Domain Partition
839 * attributes : distinguishedName, userAccountControl
842 /* ask * for CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name,...
843 * should fail with noSuchObject
846 /* add CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name,...
848 * objectClass = server
849 * systemFlags = 50000000
850 * serverReferenz = CN=<machine_name>,OU=Domain Controllers,...
853 /* ask for * of CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
854 * should fail with noSuchObject
857 /* search for (ncname=<domain_nc>) in CN=Partitions,CN=Configuration,...
858 * attributes: ncName, dnsRoot
861 /* modify add CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name,...
862 * serverReferenz = CN=<machine_name>,OU=Domain Controllers,...
863 * should fail with attributeOrValueExists
866 /* modify replace CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name,...
867 * serverReferenz = CN=<machine_name>,OU=Domain Controllers,...
870 /* DsAddEntry to create the CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
874 /* replicate CN=Schema,CN=Configuration,...
875 * using DRSUAPI_DS_BIND_GUID_W2K ("6abec3d1-3054-41c8-a362-5a0c5b7d5d71")
879 /* replicate CN=Configuration,...
880 * using DRSUAPI_DS_BIND_GUID_W2K ("6abec3d1-3054-41c8-a362-5a0c5b7d5d71")
884 /* replicate Domain Partition
885 * using DRSUAPI_DS_BIND_GUID_W2K ("6abec3d1-3054-41c8-a362-5a0c5b7d5d71")
889 /* call DsReplicaUpdateRefs() for all partitions like this:
890 * req1: struct drsuapi_DsReplicaUpdateRefsRequest1
892 * naming_context: struct drsuapi_DsReplicaObjectIdentifier
893 * __ndr_size : 0x000000ae (174)
894 * __ndr_size_sid : 0x00000000 (0)
895 * guid : 00000000-0000-0000-0000-000000000000
897 * dn : 'CN=Schema,CN=Configuration,DC=w2k3,DC=vmnet1,DC=vm,DC=base'
898 * dest_dsa_dns_name : *
899 * dest_dsa_dns_name : '4a0df188-a0b8-47ea-bbe5-e614723f16dd._msdcs.w2k3.vmnet1.vm.base'
900 * dest_dsa_guid : 4a0df188-a0b8-47ea-bbe5-e614723f16dd
901 * options : 0x0000001c (28)
902 * 0: DRSUAPI_DS_REPLICA_UPDATE_ASYNCHRONOUS_OPERATION
903 * 0: DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE
904 * 1: DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE
905 * 1: DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE
906 * 1: DRSUAPI_DS_REPLICA_UPDATE_0x00000010
908 * 4a0df188-a0b8-47ea-bbe5-e614723f16dd is the objectGUID the DsAddEntry() returned for the
909 * CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
912 /* W2K3: see libnet/libnet_become_dc.c */