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 "lib/cmdline/cmdline.h"
31 #include "librpc/gen_ndr/ndr_lsa_c.h"
32 #include "librpc/gen_ndr/ndr_samr_c.h"
34 #include "libcli/auth/libcli_auth.h"
35 #include "torture/rpc/torture_rpc.h"
36 #include "libcli/security/security.h"
37 #include "param/param.h"
38 #include "source3/rpc_client/init_samr.h"
41 struct dcerpc_pipe *p;
42 struct policy_handle user_handle;
43 struct policy_handle domain_handle;
44 struct libnet_JoinDomain *libnet_r;
45 struct dom_sid *dom_sid;
46 const char *dom_netbios_name;
47 const char *dom_dns_name;
48 struct dom_sid *user_sid;
49 struct GUID user_guid;
50 const char *netbios_name;
54 static NTSTATUS DeleteUser_byname(struct torture_context *tctx,
55 struct dcerpc_binding_handle *b,
57 struct policy_handle *handle, const char *name)
60 struct samr_DeleteUser d;
61 struct policy_handle user_handle;
63 struct samr_LookupNames n;
64 struct samr_Ids rids, types;
65 struct lsa_String sname;
66 struct samr_OpenUser r;
70 n.in.domain_handle = handle;
76 status = dcerpc_samr_LookupNames_r(b, mem_ctx, &n);
77 if (!NT_STATUS_IS_OK(status)) {
80 if (NT_STATUS_IS_OK(n.out.result)) {
81 rid = n.out.rids->ids[0];
86 r.in.domain_handle = handle;
87 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
89 r.out.user_handle = &user_handle;
91 status = dcerpc_samr_OpenUser_r(b, mem_ctx, &r);
92 if (!NT_STATUS_IS_OK(status)) {
93 torture_comment(tctx, "OpenUser(%s) failed - %s\n", name, nt_errstr(status));
96 if (!NT_STATUS_IS_OK(r.out.result)) {
97 torture_comment(tctx, "OpenUser(%s) failed - %s\n", name, nt_errstr(r.out.result));
101 d.in.user_handle = &user_handle;
102 d.out.user_handle = &user_handle;
103 status = dcerpc_samr_DeleteUser_r(b, mem_ctx, &d);
104 if (!NT_STATUS_IS_OK(status)) {
107 if (!NT_STATUS_IS_OK(d.out.result)) {
115 create a test user in the domain
116 an opaque pointer is returned. Pass it to torture_leave_domain()
120 struct test_join *torture_create_testuser_max_pwlen(struct torture_context *tctx,
121 const char *username,
124 const char **random_password,
128 struct samr_Connect c;
129 struct samr_CreateUser2 r;
130 struct samr_OpenDomain o;
131 struct samr_LookupDomain l;
132 struct dom_sid2 *sid = NULL;
133 struct samr_GetUserPwInfo pwp;
134 struct samr_PwInfo info;
135 struct samr_SetUserInfo s;
136 union samr_UserInfo u;
137 struct policy_handle handle;
138 uint32_t access_granted;
140 DATA_BLOB session_key;
141 struct lsa_String name;
143 int policy_min_pw_len = 0;
144 struct test_join *join;
146 const char *dc_binding = torture_setting_string(tctx, "dc_binding", NULL);
147 struct dcerpc_binding_handle *b = NULL;
148 join = talloc(NULL, struct test_join);
155 torture_comment(tctx, "Connecting to SAMR\n");
158 status = dcerpc_pipe_connect(join,
162 samba_cmdline_get_creds(),
166 status = torture_rpc_connection(tctx,
170 if (!NT_STATUS_IS_OK(status)) {
173 b = join->p->binding_handle;
175 c.in.system_name = NULL;
176 c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
177 c.out.connect_handle = &handle;
179 status = dcerpc_samr_Connect_r(b, join, &c);
180 if (!NT_STATUS_IS_OK(status)) {
181 const char *errstr = nt_errstr(status);
182 torture_comment(tctx, "samr_Connect failed - %s\n", errstr);
185 if (!NT_STATUS_IS_OK(c.out.result)) {
186 const char *errstr = nt_errstr(c.out.result);
187 torture_comment(tctx, "samr_Connect failed - %s\n", errstr);
192 torture_comment(tctx, "Opening domain %s\n", domain);
194 name.string = domain;
195 l.in.connect_handle = &handle;
196 l.in.domain_name = &name;
199 status = dcerpc_samr_LookupDomain_r(b, join, &l);
200 if (!NT_STATUS_IS_OK(status)) {
201 torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(status));
204 if (!NT_STATUS_IS_OK(l.out.result)) {
205 torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(l.out.result));
209 struct samr_EnumDomains e;
210 uint32_t resume_handle = 0, num_entries;
211 struct samr_SamArray *sam;
214 e.in.connect_handle = &handle;
215 e.in.buf_size = (uint32_t)-1;
216 e.in.resume_handle = &resume_handle;
218 e.out.num_entries = &num_entries;
219 e.out.resume_handle = &resume_handle;
221 status = dcerpc_samr_EnumDomains_r(b, join, &e);
222 if (!NT_STATUS_IS_OK(status)) {
223 torture_comment(tctx, "EnumDomains failed - %s\n", nt_errstr(status));
226 if (!NT_STATUS_IS_OK(e.out.result)) {
227 torture_comment(tctx, "EnumDomains failed - %s\n", nt_errstr(e.out.result));
230 if ((num_entries != 2) || (sam && sam->count != 2)) {
231 torture_comment(tctx, "unexpected number of domains\n");
234 for (i=0; i < 2; i++) {
235 if (!strequal(sam->entries[i].name.string, "builtin")) {
236 domain = sam->entries[i].name.string;
241 torture_comment(tctx, "Opening domain %s\n", domain);
243 name.string = domain;
244 l.in.connect_handle = &handle;
245 l.in.domain_name = &name;
248 status = dcerpc_samr_LookupDomain_r(b, join, &l);
249 if (!NT_STATUS_IS_OK(status)) {
250 torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(status));
253 if (!NT_STATUS_IS_OK(l.out.result)) {
254 torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(l.out.result));
258 torture_comment(tctx, "cannot proceed without domain name\n");
263 talloc_steal(join, *l.out.sid);
264 join->dom_sid = *l.out.sid;
265 join->dom_netbios_name = talloc_strdup(join, domain);
266 if (!join->dom_netbios_name) goto failed;
268 o.in.connect_handle = &handle;
269 o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
270 o.in.sid = *l.out.sid;
271 o.out.domain_handle = &join->domain_handle;
273 status = dcerpc_samr_OpenDomain_r(b, join, &o);
274 if (!NT_STATUS_IS_OK(status)) {
275 torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(status));
278 if (!NT_STATUS_IS_OK(o.out.result)) {
279 torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(o.out.result));
283 torture_comment(tctx, "Creating account %s\n", username);
286 name.string = username;
287 r.in.domain_handle = &join->domain_handle;
288 r.in.account_name = &name;
289 r.in.acct_flags = acct_type;
290 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
291 r.out.user_handle = &join->user_handle;
292 r.out.access_granted = &access_granted;
295 status = dcerpc_samr_CreateUser2_r(b, join, &r);
296 if (!NT_STATUS_IS_OK(status)) {
297 torture_comment(tctx, "CreateUser2 failed - %s\n", nt_errstr(status));
301 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
302 status = DeleteUser_byname(tctx, b, join, &join->domain_handle, name.string);
303 if (NT_STATUS_IS_OK(status)) {
308 if (!NT_STATUS_IS_OK(r.out.result)) {
309 torture_comment(tctx, "CreateUser2 failed - %s\n", nt_errstr(r.out.result));
313 join->user_sid = dom_sid_add_rid(join, join->dom_sid, rid);
315 pwp.in.user_handle = &join->user_handle;
316 pwp.out.info = &info;
318 status = dcerpc_samr_GetUserPwInfo_r(b, join, &pwp);
319 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(pwp.out.result)) {
320 policy_min_pw_len = pwp.out.info->min_password_length;
323 random_pw = generate_random_password(join, MAX(8, policy_min_pw_len), max_pw_len);
325 torture_comment(tctx, "Setting account password '%s'\n", random_pw);
328 s.in.user_handle = &join->user_handle;
332 u.info24.password_expired = 0;
334 status = dcerpc_fetch_session_key(join->p, &session_key);
335 if (!NT_STATUS_IS_OK(status)) {
336 torture_comment(tctx, "SetUserInfo level %u - no session key - %s\n",
337 s.in.level, nt_errstr(status));
338 torture_leave_domain(tctx, join);
342 status = init_samr_CryptPassword(random_pw,
345 torture_assert_ntstatus_ok(tctx,
347 "init_samr_CryptPassword failed");
349 status = dcerpc_samr_SetUserInfo_r(b, join, &s);
350 if (!NT_STATUS_IS_OK(status)) {
351 torture_comment(tctx, "SetUserInfo failed - %s\n", nt_errstr(status));
354 if (!NT_STATUS_IS_OK(s.out.result)) {
355 torture_comment(tctx, "SetUserInfo failed - %s\n", nt_errstr(s.out.result));
360 s.in.user_handle = &join->user_handle;
364 u.info21.acct_flags = acct_type | ACB_PWNOEXP;
365 u.info21.fields_present = SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME;
367 u.info21.comment.string = talloc_asprintf(join,
368 "Tortured by Samba4: %s",
369 timestring(join, time(NULL)));
371 u.info21.full_name.string = talloc_asprintf(join,
372 "Torture account for Samba4: %s",
373 timestring(join, time(NULL)));
375 u.info21.description.string = talloc_asprintf(join,
376 "Samba4 torture account created by host %s: %s",
377 lpcfg_netbios_name(tctx->lp_ctx),
378 timestring(join, time(NULL)));
380 torture_comment(tctx, "Resetting ACB flags, force pw change time\n");
382 status = dcerpc_samr_SetUserInfo_r(b, join, &s);
383 if (!NT_STATUS_IS_OK(status)) {
384 torture_comment(tctx, "SetUserInfo failed - %s\n", nt_errstr(status));
387 if (!NT_STATUS_IS_OK(s.out.result)) {
388 torture_comment(tctx, "SetUserInfo failed - %s\n", nt_errstr(s.out.result));
392 if (random_password) {
393 *random_password = random_pw;
399 torture_leave_domain(tctx, join);
404 * Set privileges on an account.
407 static void init_lsa_StringLarge(struct lsa_StringLarge *name, const char *s)
411 static void init_lsa_String(struct lsa_String *name, const char *s)
416 bool torture_setup_privs(struct torture_context *tctx,
417 struct dcerpc_pipe *p,
420 const struct dom_sid *user_sid)
422 struct dcerpc_binding_handle *b = p->binding_handle;
423 struct policy_handle *handle;
427 test_lsa_OpenPolicy2(b, tctx, &handle),
428 "failed to open policy");
430 for (i=0; i < num_privs; i++) {
431 struct lsa_LookupPrivValue r;
432 struct lsa_LUID luid;
433 struct lsa_String name;
435 init_lsa_String(&name, privs[i]);
437 r.in.handle = handle;
441 torture_assert_ntstatus_ok(tctx,
442 dcerpc_lsa_LookupPrivValue_r(b, tctx, &r),
443 "lsa_LookupPrivValue failed");
444 if (!NT_STATUS_IS_OK(r.out.result)) {
445 torture_comment(tctx, "lsa_LookupPrivValue failed for '%s' with %s\n",
446 privs[i], nt_errstr(r.out.result));
452 struct lsa_AddAccountRights r;
453 struct lsa_RightSet rights;
455 rights.count = num_privs;
456 rights.names = talloc_zero_array(tctx, struct lsa_StringLarge, rights.count);
457 for (i=0; i < rights.count; i++) {
458 init_lsa_StringLarge(&rights.names[i], privs[i]);
461 r.in.handle = handle;
462 r.in.sid = discard_const_p(struct dom_sid, user_sid);
463 r.in.rights = &rights;
465 torture_assert_ntstatus_ok(tctx,
466 dcerpc_lsa_AddAccountRights_r(b, tctx, &r),
467 "lsa_AddAccountRights failed");
468 torture_assert_ntstatus_ok(tctx, r.out.result,
469 "lsa_AddAccountRights failed");
472 test_lsa_Close(b, tctx, handle);
477 struct test_join *torture_create_testuser(struct torture_context *torture,
478 const char *username,
481 const char **random_password)
483 return torture_create_testuser_max_pwlen(torture, username, domain, acct_type, random_password, 255);
486 NTSTATUS torture_delete_testuser(struct torture_context *torture,
487 struct test_join *join,
488 const char *username)
492 status = DeleteUser_byname(torture,
493 join->p->binding_handle,
495 &join->domain_handle,
501 _PUBLIC_ struct test_join *torture_join_domain(struct torture_context *tctx,
502 const char *machine_name,
504 struct cli_credentials **machine_credentials)
507 struct libnet_context *libnet_ctx;
508 struct libnet_JoinDomain *libnet_r;
509 struct test_join *tj;
510 struct samr_SetUserInfo s;
511 union samr_UserInfo u;
512 const char *binding_str = NULL;
513 struct dcerpc_binding *binding = NULL;
514 enum dcerpc_transport_t transport;
516 tj = talloc_zero(tctx, struct test_join);
517 if (!tj) return NULL;
519 binding_str = torture_setting_string(tctx, "binding", NULL);
520 if (binding_str == NULL) {
521 const char *host = torture_setting_string(tctx, "host", NULL);
522 binding_str = talloc_asprintf(tj, "ncacn_np:%s", host);
524 status = dcerpc_parse_binding(tj, binding_str, &binding);
525 if (!NT_STATUS_IS_OK(status)) {
526 DEBUG(0, ("dcerpc_parse_binding(%s) failed - %s\n",
527 binding_str, nt_errstr(status)));
531 transport = dcerpc_binding_get_transport(binding);
534 case NCACN_UNIX_STREAM:
537 dcerpc_binding_set_transport(binding, NCACN_NP);
538 dcerpc_binding_set_flags(binding, 0, DCERPC_AUTH_OPTIONS);
542 libnet_r = talloc_zero(tj, struct libnet_JoinDomain);
548 libnet_ctx = libnet_context_init(tctx->ev, tctx->lp_ctx);
554 tj->libnet_r = libnet_r;
556 libnet_ctx->cred = samba_cmdline_get_creds();
557 libnet_r->in.binding = dcerpc_binding_string(libnet_r, binding);
558 if (libnet_r->in.binding == NULL) {
562 libnet_r->in.level = LIBNET_JOINDOMAIN_SPECIFIED;
563 libnet_r->in.netbios_name = machine_name;
564 libnet_r->in.account_name = talloc_asprintf(libnet_r, "%s$", machine_name);
565 if (!libnet_r->in.account_name) {
570 libnet_r->in.acct_type = acct_flags;
571 libnet_r->in.recreate_account = true;
573 status = libnet_JoinDomain(libnet_ctx, libnet_r, libnet_r);
574 if (!NT_STATUS_IS_OK(status)) {
575 if (libnet_r->out.error_string) {
576 DEBUG(0, ("Domain join failed - %s\n", libnet_r->out.error_string));
578 DEBUG(0, ("Domain join failed - %s\n", nt_errstr(status)));
583 tj->p = libnet_r->out.samr_pipe;
584 tj->user_handle = *libnet_r->out.user_handle;
585 tj->dom_sid = libnet_r->out.domain_sid;
586 talloc_steal(tj, libnet_r->out.domain_sid);
587 tj->dom_netbios_name = libnet_r->out.domain_name;
588 talloc_steal(tj, libnet_r->out.domain_name);
589 tj->dom_dns_name = libnet_r->out.realm;
590 talloc_steal(tj, libnet_r->out.realm);
591 tj->user_guid = libnet_r->out.account_guid;
592 tj->netbios_name = talloc_strdup(tj, machine_name);
593 if (!tj->netbios_name) {
599 s.in.user_handle = &tj->user_handle;
603 u.info21.fields_present = SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME;
604 u.info21.comment.string = talloc_asprintf(tj,
605 "Tortured by Samba4: %s",
606 timestring(tj, time(NULL)));
607 u.info21.full_name.string = talloc_asprintf(tj,
608 "Torture account for Samba4: %s",
609 timestring(tj, time(NULL)));
611 u.info21.description.string = talloc_asprintf(tj,
612 "Samba4 torture account created by host %s: %s",
613 lpcfg_netbios_name(tctx->lp_ctx), timestring(tj, time(NULL)));
615 status = dcerpc_samr_SetUserInfo_r(tj->p->binding_handle, tj, &s);
616 if (!NT_STATUS_IS_OK(status)) {
617 torture_comment(tctx, "SetUserInfo (non-critical) failed - %s\n", nt_errstr(status));
619 if (!NT_STATUS_IS_OK(s.out.result)) {
620 torture_comment(tctx, "SetUserInfo (non-critical) failed - %s\n", nt_errstr(s.out.result));
623 *machine_credentials = cli_credentials_init(tj);
624 cli_credentials_set_conf(*machine_credentials, tctx->lp_ctx);
625 cli_credentials_set_workstation(*machine_credentials, machine_name, CRED_SPECIFIED);
626 cli_credentials_set_domain(*machine_credentials, libnet_r->out.domain_name, CRED_SPECIFIED);
627 if (libnet_r->out.realm) {
628 cli_credentials_set_realm(*machine_credentials, libnet_r->out.realm, CRED_SPECIFIED);
630 cli_credentials_set_username(*machine_credentials, libnet_r->in.account_name, CRED_SPECIFIED);
631 cli_credentials_set_password(*machine_credentials, libnet_r->out.join_password, CRED_SPECIFIED);
632 cli_credentials_set_kvno(*machine_credentials, libnet_r->out.kvno);
633 if (acct_flags & ACB_SVRTRUST) {
634 cli_credentials_set_secure_channel_type(*machine_credentials,
636 } else if (acct_flags & ACB_WSTRUST) {
637 cli_credentials_set_secure_channel_type(*machine_credentials,
640 DEBUG(0, ("Invalid account type specified to torture_join_domain\n"));
641 talloc_free(*machine_credentials);
648 struct dcerpc_pipe *torture_join_samr_pipe(struct test_join *join)
653 struct policy_handle *torture_join_samr_user_policy(struct test_join *join)
655 return &join->user_handle;
658 static NTSTATUS torture_leave_ads_domain(struct torture_context *torture,
660 struct libnet_JoinDomain *libnet_r)
665 struct ldb_dn *server_dn;
666 struct ldb_context *ldb_ctx;
668 char *remote_ldb_url;
670 /* Check if we are a domain controller. If not, exit. */
671 if (!libnet_r->out.server_dn_str) {
675 tmp_ctx = talloc_named(mem_ctx, 0, "torture_leave temporary context");
677 libnet_r->out.error_string = NULL;
678 return NT_STATUS_NO_MEMORY;
681 ldb_ctx = ldb_init(tmp_ctx, torture->ev);
683 libnet_r->out.error_string = NULL;
684 talloc_free(tmp_ctx);
685 return NT_STATUS_NO_MEMORY;
688 /* Remove CN=Servers,... entry from the AD. */
689 server_dn = ldb_dn_new(tmp_ctx, ldb_ctx, libnet_r->out.server_dn_str);
690 if (! ldb_dn_validate(server_dn)) {
691 libnet_r->out.error_string = NULL;
692 talloc_free(tmp_ctx);
693 return NT_STATUS_NO_MEMORY;
696 remote_ldb_url = talloc_asprintf(tmp_ctx, "ldap://%s",
697 dcerpc_binding_get_string_option(libnet_r->out.samr_binding, "host"));
698 if (!remote_ldb_url) {
699 libnet_r->out.error_string = NULL;
700 talloc_free(tmp_ctx);
701 return NT_STATUS_NO_MEMORY;
704 ldb_set_opaque(ldb_ctx, "credentials", samba_cmdline_get_creds());
705 ldb_set_opaque(ldb_ctx, "loadparm", samba_cmdline_get_lp_ctx());
707 rtn = ldb_connect(ldb_ctx, remote_ldb_url, 0, NULL);
708 if (rtn != LDB_SUCCESS) {
709 libnet_r->out.error_string = NULL;
710 talloc_free(tmp_ctx);
711 return NT_STATUS_UNSUCCESSFUL;
714 rtn = ldb_delete(ldb_ctx, server_dn);
715 if (rtn != LDB_SUCCESS) {
716 libnet_r->out.error_string = NULL;
717 talloc_free(tmp_ctx);
718 return NT_STATUS_UNSUCCESSFUL;
721 DEBUG(0, ("%s removed successfully.\n", libnet_r->out.server_dn_str));
723 talloc_free(tmp_ctx);
728 leave the domain, deleting the machine acct
731 _PUBLIC_ void torture_leave_domain(struct torture_context *tctx, struct test_join *join)
733 struct samr_DeleteUser d;
739 d.in.user_handle = &join->user_handle;
740 d.out.user_handle = &join->user_handle;
742 /* Delete machine account */
743 status = dcerpc_samr_DeleteUser_r(join->p->binding_handle, join, &d);
744 if (!NT_STATUS_IS_OK(status)) {
745 torture_comment(tctx, "DeleteUser failed\n");
746 } else if (!NT_STATUS_IS_OK(d.out.result)) {
747 torture_comment(tctx, "Delete of machine account %s failed\n",
750 torture_comment(tctx, "Delete of machine account %s was successful.\n",
754 if (join->libnet_r) {
755 status = torture_leave_ads_domain(tctx, join, join->libnet_r);
762 return the dom sid for a test join
764 _PUBLIC_ const struct dom_sid *torture_join_sid(struct test_join *join)
766 return join->dom_sid;
769 const struct dom_sid *torture_join_user_sid(struct test_join *join)
771 return join->user_sid;
774 const char *torture_join_netbios_name(struct test_join *join)
776 return join->netbios_name;
779 const struct GUID *torture_join_user_guid(struct test_join *join)
781 return &join->user_guid;
784 const char *torture_join_dom_netbios_name(struct test_join *join)
786 return join->dom_netbios_name;
789 const char *torture_join_dom_dns_name(struct test_join *join)
791 return join->dom_dns_name;
794 #if 0 /* Left as the documentation of the join process, but see new implementation in libnet_become_dc.c */
795 struct test_join_ads_dc {
796 struct test_join *join;
799 struct test_join_ads_dc *torture_join_domain_ads_dc(const char *machine_name,
801 struct cli_credentials **machine_credentials)
803 struct test_join_ads_dc *join;
805 join = talloc(NULL, struct test_join_ads_dc);
810 join->join = torture_join_domain(machine_name,
812 machine_credentials);
819 /* W2K: modify userAccountControl from 4096 to 532480 */
821 /* W2K: modify RDN to OU=Domain Controllers and skip the $ from server name */
823 /* ask objectVersion of Schema Partition */
825 /* ask rIDManagerReferenz of the Domain Partition */
827 /* ask fsMORoleOwner of the RID-Manager$ object
828 * returns CN=NTDS Settings,CN=<DC>,CN=Servers,CN=Default-First-Site-Name, ...
831 /* ask for dnsHostName of CN=<DC>,CN=Servers,CN=Default-First-Site-Name, ... */
833 /* ask for objectGUID of CN=NTDS Settings,CN=<DC>,CN=Servers,CN=Default-First-Site-Name, ... */
835 /* ask for * of CN=Default-First-Site-Name, ... */
837 /* search (&(|(objectClass=user)(objectClass=computer))(sAMAccountName=<machine_name>$)) in Domain Partition
838 * attributes : distinguishedName, userAccountControl
841 /* ask * for CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name,...
842 * should fail with noSuchObject
845 /* add CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name,...
847 * objectClass = server
848 * systemFlags = 50000000
849 * serverReferenz = CN=<machine_name>,OU=Domain Controllers,...
852 /* ask for * of CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
853 * should fail with noSuchObject
856 /* search for (ncname=<domain_nc>) in CN=Partitions,CN=Configuration,...
857 * attributes: ncName, dnsRoot
860 /* modify add CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name,...
861 * serverReferenz = CN=<machine_name>,OU=Domain Controllers,...
862 * should fail with attributeOrValueExists
865 /* modify replace CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name,...
866 * serverReferenz = CN=<machine_name>,OU=Domain Controllers,...
869 /* DsAddEntry to create the CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
873 /* replicate CN=Schema,CN=Configuration,...
874 * using DRSUAPI_DS_BIND_GUID_W2K ("6abec3d1-3054-41c8-a362-5a0c5b7d5d71")
878 /* replicate CN=Configuration,...
879 * using DRSUAPI_DS_BIND_GUID_W2K ("6abec3d1-3054-41c8-a362-5a0c5b7d5d71")
883 /* replicate Domain Partition
884 * using DRSUAPI_DS_BIND_GUID_W2K ("6abec3d1-3054-41c8-a362-5a0c5b7d5d71")
888 /* call DsReplicaUpdateRefs() for all partitions like this:
889 * req1: struct drsuapi_DsReplicaUpdateRefsRequest1
891 * naming_context: struct drsuapi_DsReplicaObjectIdentifier
892 * __ndr_size : 0x000000ae (174)
893 * __ndr_size_sid : 0x00000000 (0)
894 * guid : 00000000-0000-0000-0000-000000000000
896 * dn : 'CN=Schema,CN=Configuration,DC=w2k3,DC=vmnet1,DC=vm,DC=base'
897 * dest_dsa_dns_name : *
898 * dest_dsa_dns_name : '4a0df188-a0b8-47ea-bbe5-e614723f16dd._msdcs.w2k3.vmnet1.vm.base'
899 * dest_dsa_guid : 4a0df188-a0b8-47ea-bbe5-e614723f16dd
900 * options : 0x0000001c (28)
901 * 0: DRSUAPI_DS_REPLICA_UPDATE_ASYNCHRONOUS_OPERATION
902 * 0: DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE
903 * 1: DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE
904 * 1: DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE
905 * 1: DRSUAPI_DS_REPLICA_UPDATE_0x00000010
907 * 4a0df188-a0b8-47ea-bbe5-e614723f16dd is the objectGUID the DsAddEntry() returned for the
908 * CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
911 /* W2K3: see libnet/libnet_become_dc.c */