s3-libsmb: Remove unused spnego_parse_auth_and_mic
[ira/wip.git] / source4 / torture / rpc / testjoin.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    utility code to join/leave a domain
5
6    Copyright (C) Andrew Tridgell 2004
7    
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.
12    
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.
17    
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/>.
20 */
21
22 /*
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
25 */
26
27 #include "includes.h"
28 #include "system/time.h"
29 #include "../lib/crypto/crypto.h"
30 #include "libnet/libnet.h"
31 #include "lib/cmdline/popt_common.h"
32 #include "librpc/gen_ndr/ndr_samr_c.h"
33
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
39 struct test_join {
40         struct dcerpc_pipe *p;
41         struct policy_handle user_handle;
42         struct policy_handle domain_handle;
43         struct libnet_JoinDomain *libnet_r;
44         struct dom_sid *dom_sid;
45         const char *dom_netbios_name;
46         const char *dom_dns_name;
47         struct dom_sid *user_sid;
48         struct GUID user_guid;
49         const char *netbios_name;
50 };
51
52
53 static NTSTATUS DeleteUser_byname(struct dcerpc_binding_handle *b,
54                                   TALLOC_CTX *mem_ctx,
55                                   struct policy_handle *handle, const char *name)
56 {
57         NTSTATUS status;
58         struct samr_DeleteUser d;
59         struct policy_handle user_handle;
60         uint32_t rid;
61         struct samr_LookupNames n;
62         struct samr_Ids rids, types;
63         struct lsa_String sname;
64         struct samr_OpenUser r;
65
66         sname.string = name;
67
68         n.in.domain_handle = handle;
69         n.in.num_names = 1;
70         n.in.names = &sname;
71         n.out.rids = &rids;
72         n.out.types = &types;
73
74         status = dcerpc_samr_LookupNames_r(b, mem_ctx, &n);
75         if (!NT_STATUS_IS_OK(status)) {
76                 return status;
77         }
78         if (NT_STATUS_IS_OK(n.out.result)) {
79                 rid = n.out.rids->ids[0];
80         } else {
81                 return n.out.result;
82         }
83
84         r.in.domain_handle = handle;
85         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
86         r.in.rid = rid;
87         r.out.user_handle = &user_handle;
88
89         status = dcerpc_samr_OpenUser_r(b, mem_ctx, &r);
90         if (!NT_STATUS_IS_OK(status)) {
91                 printf("OpenUser(%s) failed - %s\n", name, nt_errstr(status));
92                 return status;
93         }
94         if (!NT_STATUS_IS_OK(r.out.result)) {
95                 printf("OpenUser(%s) failed - %s\n", name, nt_errstr(r.out.result));
96                 return r.out.result;
97         }
98
99         d.in.user_handle = &user_handle;
100         d.out.user_handle = &user_handle;
101         status = dcerpc_samr_DeleteUser_r(b, mem_ctx, &d);
102         if (!NT_STATUS_IS_OK(status)) {
103                 return status;
104         }
105         if (!NT_STATUS_IS_OK(d.out.result)) {
106                 return d.out.result;
107         }
108
109         return NT_STATUS_OK;
110 }
111
112 /*
113   create a test user in the domain
114   an opaque pointer is returned. Pass it to torture_leave_domain() 
115   when finished
116 */
117
118 struct test_join *torture_create_testuser_max_pwlen(struct torture_context *torture,
119                                                     const char *username,
120                                                     const char *domain,
121                                                     uint16_t acct_type,
122                                                     const char **random_password,
123                                                     int max_pw_len)
124 {
125         NTSTATUS status;
126         struct samr_Connect c;
127         struct samr_CreateUser2 r;
128         struct samr_OpenDomain o;
129         struct samr_LookupDomain l;
130         struct dom_sid2 *sid = NULL;
131         struct samr_GetUserPwInfo pwp;
132         struct samr_PwInfo info;
133         struct samr_SetUserInfo s;
134         union samr_UserInfo u;
135         struct policy_handle handle;
136         uint32_t access_granted;
137         uint32_t rid;
138         DATA_BLOB session_key;
139         struct lsa_String name;
140         
141         int policy_min_pw_len = 0;
142         struct test_join *join;
143         char *random_pw;
144         const char *dc_binding = torture_setting_string(torture, "dc_binding", NULL);
145         struct dcerpc_binding_handle *b = NULL;
146
147         join = talloc(NULL, struct test_join);
148         if (join == NULL) {
149                 return NULL;
150         }
151
152         ZERO_STRUCTP(join);
153
154         printf("Connecting to SAMR\n");
155         
156         if (dc_binding) {
157                 status = dcerpc_pipe_connect(join,
158                                              &join->p,
159                                              dc_binding,
160                                              &ndr_table_samr,
161                                              cmdline_credentials, NULL, torture->lp_ctx);
162                                              
163         } else {
164                 status = torture_rpc_connection(torture, 
165                                                 &join->p, 
166                                                 &ndr_table_samr);
167         }
168         if (!NT_STATUS_IS_OK(status)) {
169                 return NULL;
170         }
171         b = join->p->binding_handle;
172
173         c.in.system_name = NULL;
174         c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
175         c.out.connect_handle = &handle;
176
177         status = dcerpc_samr_Connect_r(b, join, &c);
178         if (!NT_STATUS_IS_OK(status)) {
179                 const char *errstr = nt_errstr(status);
180                 printf("samr_Connect failed - %s\n", errstr);
181                 return NULL;
182         }
183         if (!NT_STATUS_IS_OK(c.out.result)) {
184                 const char *errstr = nt_errstr(c.out.result);
185                 printf("samr_Connect failed - %s\n", errstr);
186                 return NULL;
187         }
188
189         if (domain) {
190                 printf("Opening domain %s\n", domain);
191
192                 name.string = domain;
193                 l.in.connect_handle = &handle;
194                 l.in.domain_name = &name;
195                 l.out.sid = &sid;
196
197                 status = dcerpc_samr_LookupDomain_r(b, join, &l);
198                 if (!NT_STATUS_IS_OK(status)) {
199                         printf("LookupDomain failed - %s\n", nt_errstr(status));
200                         goto failed;
201                 }
202                 if (!NT_STATUS_IS_OK(l.out.result)) {
203                         printf("LookupDomain failed - %s\n", nt_errstr(l.out.result));
204                         goto failed;
205                 }
206         } else {
207                 struct samr_EnumDomains e;
208                 uint32_t resume_handle = 0, num_entries;
209                 struct samr_SamArray *sam;
210                 int i;
211
212                 e.in.connect_handle = &handle;
213                 e.in.buf_size = (uint32_t)-1;
214                 e.in.resume_handle = &resume_handle;
215                 e.out.sam = &sam;
216                 e.out.num_entries = &num_entries;
217                 e.out.resume_handle = &resume_handle;
218
219                 status = dcerpc_samr_EnumDomains_r(b, join, &e);
220                 if (!NT_STATUS_IS_OK(status)) {
221                         printf("EnumDomains failed - %s\n", nt_errstr(status));
222                         goto failed;
223                 }
224                 if (!NT_STATUS_IS_OK(e.out.result)) {
225                         printf("EnumDomains failed - %s\n", nt_errstr(e.out.result));
226                         goto failed;
227                 }
228                 if ((num_entries != 2) || (sam && sam->count != 2)) {
229                         printf("unexpected number of domains\n");
230                         goto failed;
231                 }
232                 for (i=0; i < 2; i++) {
233                         if (!strequal(sam->entries[i].name.string, "builtin")) {
234                                 domain = sam->entries[i].name.string;
235                                 break;
236                         }
237                 }
238                 if (domain) {
239                         printf("Opening domain %s\n", domain);
240
241                         name.string = domain;
242                         l.in.connect_handle = &handle;
243                         l.in.domain_name = &name;
244                         l.out.sid = &sid;
245
246                         status = dcerpc_samr_LookupDomain_r(b, join, &l);
247                         if (!NT_STATUS_IS_OK(status)) {
248                                 printf("LookupDomain failed - %s\n", nt_errstr(status));
249                                 goto failed;
250                         }
251                         if (!NT_STATUS_IS_OK(l.out.result)) {
252                                 printf("LookupDomain failed - %s\n", nt_errstr(l.out.result));
253                                 goto failed;
254                         }
255                 } else {
256                         printf("cannot proceed without domain name\n");
257                         goto failed;
258                 }
259         }
260
261         talloc_steal(join, *l.out.sid);
262         join->dom_sid = *l.out.sid;
263         join->dom_netbios_name = talloc_strdup(join, domain);
264         if (!join->dom_netbios_name) goto failed;
265
266         o.in.connect_handle = &handle;
267         o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
268         o.in.sid = *l.out.sid;
269         o.out.domain_handle = &join->domain_handle;
270
271         status = dcerpc_samr_OpenDomain_r(b, join, &o);
272         if (!NT_STATUS_IS_OK(status)) {
273                 printf("OpenDomain failed - %s\n", nt_errstr(status));
274                 goto failed;
275         }
276         if (!NT_STATUS_IS_OK(o.out.result)) {
277                 printf("OpenDomain failed - %s\n", nt_errstr(o.out.result));
278                 goto failed;
279         }
280
281         printf("Creating account %s\n", username);
282
283 again:
284         name.string = username;
285         r.in.domain_handle = &join->domain_handle;
286         r.in.account_name = &name;
287         r.in.acct_flags = acct_type;
288         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
289         r.out.user_handle = &join->user_handle;
290         r.out.access_granted = &access_granted;
291         r.out.rid = &rid;
292
293         status = dcerpc_samr_CreateUser2_r(b, join, &r);
294         if (!NT_STATUS_IS_OK(status)) {
295                 printf("CreateUser2 failed - %s\n", nt_errstr(status));
296                 goto failed;
297         }
298
299         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
300                 status = DeleteUser_byname(b, join, &join->domain_handle, name.string);
301                 if (NT_STATUS_IS_OK(status)) {
302                         goto again;
303                 }
304         }
305
306         if (!NT_STATUS_IS_OK(r.out.result)) {
307                 printf("CreateUser2 failed - %s\n", nt_errstr(r.out.result));
308                 goto failed;
309         }
310
311         join->user_sid = dom_sid_add_rid(join, join->dom_sid, rid);
312
313         pwp.in.user_handle = &join->user_handle;
314         pwp.out.info = &info;
315
316         status = dcerpc_samr_GetUserPwInfo_r(b, join, &pwp);
317         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(pwp.out.result)) {
318                 policy_min_pw_len = pwp.out.info->min_password_length;
319         }
320
321         random_pw = generate_random_password(join, MAX(8, policy_min_pw_len), max_pw_len);
322
323         printf("Setting account password '%s'\n", random_pw);
324
325         ZERO_STRUCT(u);
326         s.in.user_handle = &join->user_handle;
327         s.in.info = &u;
328         s.in.level = 24;
329
330         encode_pw_buffer(u.info24.password.data, random_pw, STR_UNICODE);
331         u.info24.password_expired = 0;
332
333         status = dcerpc_fetch_session_key(join->p, &session_key);
334         if (!NT_STATUS_IS_OK(status)) {
335                 printf("SetUserInfo level %u - no session key - %s\n",
336                        s.in.level, nt_errstr(status));
337                 torture_leave_domain(torture, join);
338                 goto failed;
339         }
340
341         arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
342
343         status = dcerpc_samr_SetUserInfo_r(b, join, &s);
344         if (!NT_STATUS_IS_OK(status)) {
345                 printf("SetUserInfo failed - %s\n", nt_errstr(status));
346                 goto failed;
347         }
348         if (!NT_STATUS_IS_OK(s.out.result)) {
349                 printf("SetUserInfo failed - %s\n", nt_errstr(s.out.result));
350                 goto failed;
351         }
352
353         ZERO_STRUCT(u);
354         s.in.user_handle = &join->user_handle;
355         s.in.info = &u;
356         s.in.level = 21;
357
358         u.info21.acct_flags = acct_type | ACB_PWNOEXP;
359         u.info21.fields_present = SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME;
360
361         u.info21.comment.string = talloc_asprintf(join, 
362                                                   "Tortured by Samba4: %s", 
363                                                   timestring(join, time(NULL)));
364         
365         u.info21.full_name.string = talloc_asprintf(join, 
366                                                     "Torture account for Samba4: %s", 
367                                                     timestring(join, time(NULL)));
368         
369         u.info21.description.string = talloc_asprintf(join, 
370                                          "Samba4 torture account created by host %s: %s", 
371                                          lpcfg_netbios_name(torture->lp_ctx),
372                                          timestring(join, time(NULL)));
373
374         printf("Resetting ACB flags, force pw change time\n");
375
376         status = dcerpc_samr_SetUserInfo_r(b, join, &s);
377         if (!NT_STATUS_IS_OK(status)) {
378                 printf("SetUserInfo failed - %s\n", nt_errstr(status));
379                 goto failed;
380         }
381         if (!NT_STATUS_IS_OK(s.out.result)) {
382                 printf("SetUserInfo failed - %s\n", nt_errstr(s.out.result));
383                 goto failed;
384         }
385
386         if (random_password) {
387                 *random_password = random_pw;
388         }
389
390         return join;
391
392 failed:
393         torture_leave_domain(torture, join);
394         return NULL;
395 }
396
397
398 struct test_join *torture_create_testuser(struct torture_context *torture,
399                                           const char *username,
400                                           const char *domain,
401                                           uint16_t acct_type,
402                                           const char **random_password)
403 {
404         return torture_create_testuser_max_pwlen(torture, username, domain, acct_type, random_password, 255);
405 }
406
407 NTSTATUS torture_delete_testuser(struct torture_context *torture,
408                                  struct test_join *join,
409                                  const char *username)
410 {
411         NTSTATUS status;
412
413         status = DeleteUser_byname(join->p->binding_handle,
414                                    torture,
415                                    &join->domain_handle,
416                                    username);
417
418         return status;
419 }
420
421 _PUBLIC_ struct test_join *torture_join_domain(struct torture_context *tctx,
422                                                const char *machine_name, 
423                                       uint32_t acct_flags,
424                                       struct cli_credentials **machine_credentials)
425 {
426         NTSTATUS status;
427         struct libnet_context *libnet_ctx;
428         struct libnet_JoinDomain *libnet_r;
429         struct test_join *tj;
430         struct samr_SetUserInfo s;
431         union samr_UserInfo u;
432         
433         tj = talloc_zero(tctx, struct test_join);
434         if (!tj) return NULL;
435
436         libnet_r = talloc_zero(tj, struct libnet_JoinDomain);
437         if (!libnet_r) {
438                 talloc_free(tj);
439                 return NULL;
440         }
441         
442         libnet_ctx = libnet_context_init(tctx->ev, tctx->lp_ctx);
443         if (!libnet_ctx) {
444                 talloc_free(tj);
445                 return NULL;
446         }
447         
448         tj->libnet_r = libnet_r;
449                 
450         libnet_ctx->cred = cmdline_credentials;
451         libnet_r->in.binding = torture_setting_string(tctx, "binding", NULL);
452         if (!libnet_r->in.binding) {
453                 libnet_r->in.binding = talloc_asprintf(libnet_r, "ncacn_np:%s", torture_setting_string(tctx, "host", NULL));
454         }
455         libnet_r->in.level = LIBNET_JOINDOMAIN_SPECIFIED;
456         libnet_r->in.netbios_name = machine_name;
457         libnet_r->in.account_name = talloc_asprintf(libnet_r, "%s$", machine_name);
458         if (!libnet_r->in.account_name) {
459                 talloc_free(tj);
460                 return NULL;
461         }
462         
463         libnet_r->in.acct_type = acct_flags;
464         libnet_r->in.recreate_account = true;
465
466         status = libnet_JoinDomain(libnet_ctx, libnet_r, libnet_r);
467         if (!NT_STATUS_IS_OK(status)) {
468                 if (libnet_r->out.error_string) {
469                         DEBUG(0, ("Domain join failed - %s\n", libnet_r->out.error_string));
470                 } else {
471                         DEBUG(0, ("Domain join failed - %s\n", nt_errstr(status)));
472                 }
473                 talloc_free(tj);
474                 return NULL;
475         }
476         tj->p = libnet_r->out.samr_pipe;
477         tj->user_handle = *libnet_r->out.user_handle;
478         tj->dom_sid = libnet_r->out.domain_sid;
479         talloc_steal(tj, libnet_r->out.domain_sid);
480         tj->dom_netbios_name    = libnet_r->out.domain_name;
481         talloc_steal(tj, libnet_r->out.domain_name);
482         tj->dom_dns_name        = libnet_r->out.realm;
483         talloc_steal(tj, libnet_r->out.realm);
484         tj->user_guid = libnet_r->out.account_guid;
485         tj->netbios_name = talloc_strdup(tj, machine_name);
486         if (!tj->netbios_name) {
487                 talloc_free(tj);
488                 return NULL;
489         }
490
491         ZERO_STRUCT(u);
492         s.in.user_handle = &tj->user_handle;
493         s.in.info = &u;
494         s.in.level = 21;
495
496         u.info21.fields_present = SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME;
497         u.info21.comment.string = talloc_asprintf(tj, 
498                                                   "Tortured by Samba4: %s", 
499                                                   timestring(tj, time(NULL)));
500         u.info21.full_name.string = talloc_asprintf(tj, 
501                                                     "Torture account for Samba4: %s", 
502                                                     timestring(tj, time(NULL)));
503         
504         u.info21.description.string = talloc_asprintf(tj, 
505                                                       "Samba4 torture account created by host %s: %s", 
506                                                       lpcfg_netbios_name(tctx->lp_ctx), timestring(tj, time(NULL)));
507
508         status = dcerpc_samr_SetUserInfo_r(tj->p->binding_handle, tj, &s);
509         if (!NT_STATUS_IS_OK(status)) {
510                 printf("SetUserInfo (non-critical) failed - %s\n", nt_errstr(status));
511         }
512         if (!NT_STATUS_IS_OK(s.out.result)) {
513                 printf("SetUserInfo (non-critical) failed - %s\n", nt_errstr(s.out.result));
514         }
515
516         *machine_credentials = cli_credentials_init(tj);
517         cli_credentials_set_conf(*machine_credentials, tctx->lp_ctx);
518         cli_credentials_set_workstation(*machine_credentials, machine_name, CRED_SPECIFIED);
519         cli_credentials_set_domain(*machine_credentials, libnet_r->out.domain_name, CRED_SPECIFIED);
520         if (libnet_r->out.realm) {
521                 cli_credentials_set_realm(*machine_credentials, libnet_r->out.realm, CRED_SPECIFIED);
522         }
523         cli_credentials_set_username(*machine_credentials, libnet_r->in.account_name, CRED_SPECIFIED);
524         cli_credentials_set_password(*machine_credentials, libnet_r->out.join_password, CRED_SPECIFIED);
525         cli_credentials_set_kvno(*machine_credentials, libnet_r->out.kvno);
526         if (acct_flags & ACB_SVRTRUST) {
527                 cli_credentials_set_secure_channel_type(*machine_credentials,
528                                                         SEC_CHAN_BDC);
529         } else if (acct_flags & ACB_WSTRUST) {
530                 cli_credentials_set_secure_channel_type(*machine_credentials,
531                                                         SEC_CHAN_WKSTA);
532         } else {
533                 DEBUG(0, ("Invalid account type specificed to torture_join_domain\n"));
534                 talloc_free(*machine_credentials);
535                 return NULL;
536         }
537
538         return tj;
539 }
540
541 struct dcerpc_pipe *torture_join_samr_pipe(struct test_join *join) 
542 {
543         return join->p;
544 }
545
546 struct policy_handle *torture_join_samr_user_policy(struct test_join *join) 
547 {
548         return &join->user_handle;
549 }
550
551 static NTSTATUS torture_leave_ads_domain(struct torture_context *torture,
552                                          TALLOC_CTX *mem_ctx,
553                                          struct libnet_JoinDomain *libnet_r)
554 {
555         int rtn;
556         TALLOC_CTX *tmp_ctx;
557
558         struct ldb_dn *server_dn;
559         struct ldb_context *ldb_ctx;
560
561         char *remote_ldb_url; 
562          
563         /* Check if we are a domain controller. If not, exit. */
564         if (!libnet_r->out.server_dn_str) {
565                 return NT_STATUS_OK;
566         }
567
568         tmp_ctx = talloc_named(mem_ctx, 0, "torture_leave temporary context");
569         if (!tmp_ctx) {
570                 libnet_r->out.error_string = NULL;
571                 return NT_STATUS_NO_MEMORY;
572         }
573
574         ldb_ctx = ldb_init(tmp_ctx, torture->ev);
575         if (!ldb_ctx) {
576                 libnet_r->out.error_string = NULL;
577                 talloc_free(tmp_ctx);
578                 return NT_STATUS_NO_MEMORY;
579         }
580
581         /* Remove CN=Servers,... entry from the AD. */ 
582         server_dn = ldb_dn_new(tmp_ctx, ldb_ctx, libnet_r->out.server_dn_str);
583         if (! ldb_dn_validate(server_dn)) {
584                 libnet_r->out.error_string = NULL;
585                 talloc_free(tmp_ctx);
586                 return NT_STATUS_NO_MEMORY;
587         }
588
589         remote_ldb_url = talloc_asprintf(tmp_ctx, "ldap://%s", libnet_r->out.samr_binding->host);
590         if (!remote_ldb_url) {
591                 libnet_r->out.error_string = NULL;
592                 talloc_free(tmp_ctx);
593                 return NT_STATUS_NO_MEMORY;
594         }
595
596         ldb_set_opaque(ldb_ctx, "credentials", cmdline_credentials);
597         ldb_set_opaque(ldb_ctx, "loadparm", cmdline_lp_ctx);
598
599         rtn = ldb_connect(ldb_ctx, remote_ldb_url, 0, NULL);
600         if (rtn != LDB_SUCCESS) {
601                 libnet_r->out.error_string = NULL;
602                 talloc_free(tmp_ctx);
603                 return NT_STATUS_UNSUCCESSFUL;
604         }
605
606         rtn = ldb_delete(ldb_ctx, server_dn);
607         if (rtn != LDB_SUCCESS) {
608                 libnet_r->out.error_string = NULL;
609                 talloc_free(tmp_ctx);
610                 return NT_STATUS_UNSUCCESSFUL;
611         }
612
613         DEBUG(0, ("%s removed successfully.\n", libnet_r->out.server_dn_str));
614
615         talloc_free(tmp_ctx); 
616         return NT_STATUS_OK;
617 }
618
619 /*
620   leave the domain, deleting the machine acct
621 */
622
623 _PUBLIC_ void torture_leave_domain(struct torture_context *torture, struct test_join *join)
624 {
625         struct samr_DeleteUser d;
626         NTSTATUS status;
627
628         if (!join) {
629                 return;
630         }
631         d.in.user_handle = &join->user_handle;
632         d.out.user_handle = &join->user_handle;
633
634         /* Delete machine account */
635         status = dcerpc_samr_DeleteUser_r(join->p->binding_handle, join, &d);
636         if (!NT_STATUS_IS_OK(status)) {
637                 printf("DeleteUser failed\n");
638         }
639         if (!NT_STATUS_IS_OK(d.out.result)) {
640                 printf("Delete of machine account %s failed\n",
641                        join->netbios_name);
642         } else {
643                 printf("Delete of machine account %s was successful.\n",
644                        join->netbios_name);
645         }
646
647         if (join->libnet_r) {
648                 status = torture_leave_ads_domain(torture, join, join->libnet_r);
649         }
650         
651         talloc_free(join);
652 }
653
654 /*
655   return the dom sid for a test join
656 */
657 _PUBLIC_ const struct dom_sid *torture_join_sid(struct test_join *join)
658 {
659         return join->dom_sid;
660 }
661
662 const struct dom_sid *torture_join_user_sid(struct test_join *join)
663 {
664         return join->user_sid;
665 }
666
667 const char *torture_join_netbios_name(struct test_join *join)
668 {
669         return join->netbios_name;
670 }
671
672 const struct GUID *torture_join_user_guid(struct test_join *join)
673 {
674         return &join->user_guid;
675 }
676
677 const char *torture_join_dom_netbios_name(struct test_join *join)
678 {
679         return join->dom_netbios_name;
680 }
681
682 const char *torture_join_dom_dns_name(struct test_join *join)
683 {
684         return join->dom_dns_name;
685 }
686
687 const char *torture_join_server_dn_str(struct test_join *join)
688 {
689         if (join->libnet_r) {
690                 return join->libnet_r->out.server_dn_str;
691         }
692         return NULL;
693 }
694
695
696 #if 0 /* Left as the documentation of the join process, but see new implementation in libnet_become_dc.c */
697 struct test_join_ads_dc {
698         struct test_join *join;
699 };
700
701 struct test_join_ads_dc *torture_join_domain_ads_dc(const char *machine_name, 
702                                                     const char *domain,
703                                                     struct cli_credentials **machine_credentials)
704 {
705         struct test_join_ads_dc *join;
706
707         join = talloc(NULL, struct test_join_ads_dc);
708         if (join == NULL) {
709                 return NULL;
710         }
711
712         join->join = torture_join_domain(machine_name, 
713                                         ACB_SVRTRUST,
714                                         machine_credentials);
715
716         if (!join->join) {
717                 return NULL;
718         }
719
720 /* W2K: */
721         /* W2K: modify userAccountControl from 4096 to 532480 */
722         
723         /* W2K: modify RDN to OU=Domain Controllers and skip the $ from server name */
724
725         /* ask objectVersion of Schema Partition */
726
727         /* ask rIDManagerReferenz of the Domain Partition */
728
729         /* ask fsMORoleOwner of the RID-Manager$ object
730          * returns CN=NTDS Settings,CN=<DC>,CN=Servers,CN=Default-First-Site-Name, ...
731          */
732
733         /* ask for dnsHostName of CN=<DC>,CN=Servers,CN=Default-First-Site-Name, ... */
734
735         /* ask for objectGUID of CN=NTDS Settings,CN=<DC>,CN=Servers,CN=Default-First-Site-Name, ... */
736
737         /* ask for * of CN=Default-First-Site-Name, ... */
738
739         /* search (&(|(objectClass=user)(objectClass=computer))(sAMAccountName=<machine_name>$)) in Domain Partition 
740          * attributes : distinguishedName, userAccountControl
741          */
742
743         /* ask * for CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name,... 
744          * should fail with noSuchObject
745          */
746
747         /* add CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name,... 
748          *
749          * objectClass = server
750          * systemFlags = 50000000
751          * serverReferenz = CN=<machine_name>,OU=Domain Controllers,...
752          */
753
754         /* ask for * of CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
755          * should fail with noSuchObject
756          */
757
758         /* search for (ncname=<domain_nc>) in CN=Partitions,CN=Configuration,... 
759          * attributes: ncName, dnsRoot
760          */
761
762         /* modify add CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name,...
763          * serverReferenz = CN=<machine_name>,OU=Domain Controllers,...
764          * should fail with attributeOrValueExists
765          */
766
767         /* modify replace CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name,...
768          * serverReferenz = CN=<machine_name>,OU=Domain Controllers,...
769          */
770
771         /* DsAddEntry to create the CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
772          *
773          */
774
775         /* replicate CN=Schema,CN=Configuration,...
776          * using DRSUAPI_DS_BIND_GUID_W2K ("6abec3d1-3054-41c8-a362-5a0c5b7d5d71")
777          *
778          */
779
780         /* replicate CN=Configuration,...
781          * using DRSUAPI_DS_BIND_GUID_W2K ("6abec3d1-3054-41c8-a362-5a0c5b7d5d71")
782          *
783          */
784
785         /* replicate Domain Partition
786          * using DRSUAPI_DS_BIND_GUID_W2K ("6abec3d1-3054-41c8-a362-5a0c5b7d5d71")
787          *
788          */
789
790         /* call DsReplicaUpdateRefs() for all partitions like this:
791          *     req1: struct drsuapi_DsReplicaUpdateRefsRequest1
792          *           naming_context           : *
793          *                 naming_context: struct drsuapi_DsReplicaObjectIdentifier
794          *                     __ndr_size               : 0x000000ae (174)
795          *                     __ndr_size_sid           : 0x00000000 (0)
796          *                     guid                     : 00000000-0000-0000-0000-000000000000
797          *                     sid                      : S-0-0
798          *                     dn                       : 'CN=Schema,CN=Configuration,DC=w2k3,DC=vmnet1,DC=vm,DC=base'
799          *           dest_dsa_dns_name        : *
800          *                 dest_dsa_dns_name        : '4a0df188-a0b8-47ea-bbe5-e614723f16dd._msdcs.w2k3.vmnet1.vm.base'
801          *           dest_dsa_guid            : 4a0df188-a0b8-47ea-bbe5-e614723f16dd
802          *           options                  : 0x0000001c (28)
803          *                 0: DRSUAPI_DS_REPLICA_UPDATE_ASYNCHRONOUS_OPERATION
804          *                 0: DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE
805          *                 1: DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE
806          *                 1: DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE
807          *                 1: DRSUAPI_DS_REPLICA_UPDATE_0x00000010      
808          *
809          * 4a0df188-a0b8-47ea-bbe5-e614723f16dd is the objectGUID the DsAddEntry() returned for the
810          * CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
811          */
812
813 /* W2K3: see libnet/libnet_become_dc.c */
814         return join;
815 }
816
817 #endif