r582: added the LMSessKey in SamInfo and SamInfo2, thanks to work by abartlet
[jelmer/samba4-debian.git] / source / torture / rpc / netlogon.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    test suite for netlogon rpc operations
5
6    Copyright (C) Andrew Tridgell 2003
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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25
26 #define TEST_MACHINE_NAME "torturetest"
27
28 static struct {
29         struct dcerpc_pipe *p;
30         const char *machine_password;
31         struct policy_handle acct_handle;
32 } join;
33
34 /*
35   join the domain as a BDC
36 */
37 static BOOL join_domain_bdc(TALLOC_CTX *mem_ctx)
38 {
39         NTSTATUS status;
40         struct samr_Connect c;
41         struct samr_CreateUser2 r;
42         struct samr_OpenDomain o;
43         struct samr_LookupDomain l;
44         struct samr_SetUserInfo s;
45         union samr_UserInfo u;
46         struct policy_handle handle;
47         struct policy_handle domain_handle;
48         uint32 access_granted;
49         uint32 rid;
50         BOOL ret = True;
51         uint8 session_key[16];
52         struct samr_Name name;
53
54         printf("Connecting to SAMR\n");
55
56         status = torture_rpc_connection(&join.p, 
57                                         DCERPC_SAMR_NAME,
58                                         DCERPC_SAMR_UUID,
59                                         DCERPC_SAMR_VERSION);
60         if (!NT_STATUS_IS_OK(status)) {
61                 return False;
62         }
63
64         c.in.system_name = NULL;
65         c.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
66         c.out.handle = &handle;
67
68         status = dcerpc_samr_Connect(join.p, mem_ctx, &c);
69         if (!NT_STATUS_IS_OK(status)) {
70                 printf("samr_Connect failed - %s\n", nt_errstr(status));
71                 return False;
72         }
73
74         printf("Opening domain %s\n", lp_workgroup());
75
76         name.name = lp_workgroup();
77         l.in.handle = &handle;
78         l.in.domain = &name;
79
80         status = dcerpc_samr_LookupDomain(join.p, mem_ctx, &l);
81         if (!NT_STATUS_IS_OK(status)) {
82                 printf("LookupDomain failed - %s\n", nt_errstr(status));
83                 return False;
84         }
85
86         o.in.handle = &handle;
87         o.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
88         o.in.sid = l.out.sid;
89         o.out.domain_handle = &domain_handle;
90
91         status = dcerpc_samr_OpenDomain(join.p, mem_ctx, &o);
92         if (!NT_STATUS_IS_OK(status)) {
93                 printf("OpenDomain failed - %s\n", nt_errstr(status));
94                 return False;
95         }
96
97         printf("Creating machine account %s\n", TEST_MACHINE_NAME);
98
99 again:
100         name.name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
101         r.in.handle = &domain_handle;
102         r.in.username = &name;
103         r.in.acct_flags = ACB_SVRTRUST;
104         r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
105         r.out.acct_handle = &join.acct_handle;
106         r.out.access_granted = &access_granted;
107         r.out.rid = &rid;
108
109         status = dcerpc_samr_CreateUser2(join.p, mem_ctx, &r);
110
111         if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS) &&
112             test_DeleteUser_byname(join.p, mem_ctx, &domain_handle, name.name)) {
113                 goto again;
114         }
115
116         if (!NT_STATUS_IS_OK(status)) {
117                 printf("CreateUser2 failed - %s\n", nt_errstr(status));
118                 return False;
119         }
120
121         join.machine_password = generate_random_str(8);
122
123         printf("Setting machine account password '%s'\n", join.machine_password);
124
125         s.in.handle = &join.acct_handle;
126         s.in.info = &u;
127         s.in.level = 24;
128
129         encode_pw_buffer(u.info24.password.data, join.machine_password, STR_UNICODE);
130         u.info24.pw_len = strlen(join.machine_password);
131
132         status = dcerpc_fetch_session_key(join.p, session_key);
133         if (!NT_STATUS_IS_OK(status)) {
134                 printf("SetUserInfo level %u - no session key - %s\n",
135                        s.in.level, nt_errstr(status));
136                 return False;
137         }
138
139         SamOEMhash(u.info24.password.data, session_key, 516);
140
141         status = dcerpc_samr_SetUserInfo(join.p, mem_ctx, &s);
142         if (!NT_STATUS_IS_OK(status)) {
143                 printf("SetUserInfo failed - %s\n", nt_errstr(status));
144                 return False;
145         }
146
147         s.in.handle = &join.acct_handle;
148         s.in.info = &u;
149         s.in.level = 16;
150
151         u.info16.acct_flags = ACB_SVRTRUST;
152
153         printf("Resetting ACB flags\n");
154
155         status = dcerpc_samr_SetUserInfo(join.p, mem_ctx, &s);
156         if (!NT_STATUS_IS_OK(status)) {
157                 printf("SetUserInfo failed - %s\n", nt_errstr(status));
158                 return False;
159         }
160
161         return ret;
162 }
163
164 /*
165   leave the domain as a BDC
166 */
167 static BOOL leave_domain_bdc(TALLOC_CTX *mem_ctx)
168 {
169         struct samr_DeleteUser d;
170         NTSTATUS status;
171
172         d.in.handle = &join.acct_handle;
173         d.out.handle = &join.acct_handle;
174
175         status = dcerpc_samr_DeleteUser(join.p, mem_ctx, &d);
176         if (!NT_STATUS_IS_OK(status)) {
177                 printf("Delete of machine account failed\n");
178                 return False;
179         }
180
181         return True;
182 }
183
184 static BOOL test_LogonUasLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
185 {
186         NTSTATUS status;
187         struct netr_LogonUasLogon r;
188
189         r.in.server_name = NULL;
190         r.in.username = lp_parm_string(-1, "torture", "username");
191         r.in.workstation = TEST_MACHINE_NAME;
192
193         printf("Testing LogonUasLogon\n");
194
195         status = dcerpc_netr_LogonUasLogon(p, mem_ctx, &r);
196         if (!NT_STATUS_IS_OK(status)) {
197                 printf("LogonUasLogon - %s\n", nt_errstr(status));
198                 return False;
199         }
200
201         return True;
202         
203 }
204
205 static BOOL test_LogonUasLogoff(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
206 {
207         NTSTATUS status;
208         struct netr_LogonUasLogoff r;
209
210         r.in.server_name = NULL;
211         r.in.username = lp_parm_string(-1, "torture", "username");
212         r.in.workstation = TEST_MACHINE_NAME;
213
214         printf("Testing LogonUasLogoff\n");
215
216         status = dcerpc_netr_LogonUasLogoff(p, mem_ctx, &r);
217         if (!NT_STATUS_IS_OK(status)) {
218                 printf("LogonUasLogoff - %s\n", nt_errstr(status));
219                 return False;
220         }
221
222         return True;
223         
224 }
225
226 static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
227                                   struct netr_CredentialState *creds)
228 {
229         NTSTATUS status;
230         struct netr_ServerReqChallenge r;
231         struct netr_ServerAuthenticate a;
232         const char *plain_pass;
233         uint8 mach_pwd[16];
234
235         printf("Testing ServerReqChallenge\n");
236
237         r.in.server_name = NULL;
238         r.in.computer_name = TEST_MACHINE_NAME;
239         generate_random_buffer(r.in.credentials.data, sizeof(r.in.credentials.data), False);
240
241         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
242         if (!NT_STATUS_IS_OK(status)) {
243                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
244                 return False;
245         }
246
247         plain_pass = join.machine_password;
248         if (!plain_pass) {
249                 printf("Unable to fetch machine password!\n");
250                 return False;
251         }
252
253         E_md4hash(plain_pass, mach_pwd);
254
255         creds_client_init(creds, &r.in.credentials, &r.out.credentials, mach_pwd,
256                           &a.in.credentials);
257
258         a.in.server_name = NULL;
259         a.in.username = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
260         a.in.secure_channel_type = SEC_CHAN_BDC;
261         a.in.computer_name = TEST_MACHINE_NAME;
262
263         printf("Testing ServerAuthenticate\n");
264
265         status = dcerpc_netr_ServerAuthenticate(p, mem_ctx, &a);
266         if (!NT_STATUS_IS_OK(status)) {
267                 printf("ServerAuthenticate - %s\n", nt_errstr(status));
268                 return False;
269         }
270
271         if (!creds_client_check(creds, &a.out.credentials)) {
272                 printf("Credential chaining failed\n");
273                 return False;
274         }
275
276         return True;
277 }
278
279 static BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
280                                    struct netr_CredentialState *creds)
281 {
282         NTSTATUS status;
283         struct netr_ServerReqChallenge r;
284         struct netr_ServerAuthenticate2 a;
285         const char *plain_pass;
286         uint8 mach_pwd[16];
287         uint32 negotiate_flags = 0;
288
289         printf("Testing ServerReqChallenge\n");
290
291         r.in.server_name = NULL;
292         r.in.computer_name = TEST_MACHINE_NAME;
293         generate_random_buffer(r.in.credentials.data, sizeof(r.in.credentials.data), False);
294
295         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
296         if (!NT_STATUS_IS_OK(status)) {
297                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
298                 return False;
299         }
300
301         plain_pass = join.machine_password;
302         if (!plain_pass) {
303                 printf("Unable to fetch machine password!\n");
304                 return False;
305         }
306
307         E_md4hash(plain_pass, mach_pwd);
308
309         creds_client_init(creds, &r.in.credentials, &r.out.credentials, mach_pwd,
310                           &a.in.credentials);
311
312         a.in.server_name = NULL;
313         a.in.username = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
314         a.in.secure_channel_type = SEC_CHAN_BDC;
315         a.in.computer_name = TEST_MACHINE_NAME;
316         a.in.negotiate_flags = &negotiate_flags;
317         a.out.negotiate_flags = &negotiate_flags;
318
319         printf("Testing ServerAuthenticate2\n");
320
321         status = dcerpc_netr_ServerAuthenticate2(p, mem_ctx, &a);
322         if (!NT_STATUS_IS_OK(status)) {
323                 printf("ServerAuthenticate2 - %s\n", nt_errstr(status));
324                 return False;
325         }
326
327         if (!creds_client_check(creds, &a.out.credentials)) {
328                 printf("Credential chaining failed\n");
329                 return False;
330         }
331
332         printf("negotiate_flags=0x%08x\n", negotiate_flags);
333
334         return True;
335 }
336
337 /*
338   try a netlogon SamLogon
339 */
340 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
341 {
342         NTSTATUS status;
343         struct netr_LogonSamLogon r;
344         struct netr_Authenticator auth, auth2;
345         struct netr_NetworkInfo ninfo;
346         const char *username = lp_parm_string(-1, "torture", "username");
347         const char *password = lp_parm_string(-1, "torture", "password");
348         struct netr_CredentialState creds;
349         int i;
350         BOOL ret = True;
351
352         if (!test_SetupCredentials2(p, mem_ctx, &creds)) {
353                 return False;
354         }
355
356         ninfo.logon_info.domain_name.string = lp_workgroup();
357         ninfo.logon_info.parameter_control = 0;
358         ninfo.logon_info.logon_id_low = 0;
359         ninfo.logon_info.logon_id_high = 0;
360         ninfo.logon_info.username.string = username;
361         ninfo.logon_info.workstation.string = TEST_MACHINE_NAME;
362         generate_random_buffer(ninfo.challenge, 
363                                sizeof(ninfo.challenge), False);
364         ninfo.nt.length = 24;
365         ninfo.nt.data = talloc(mem_ctx, 24);
366         SMBNTencrypt(password, ninfo.challenge, ninfo.nt.data);
367         ninfo.lm.length = 24;
368         ninfo.lm.data = talloc(mem_ctx, 24);
369         SMBencrypt(password, ninfo.challenge, ninfo.lm.data);
370
371         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
372         r.in.workstation = TEST_MACHINE_NAME;
373         r.in.credential = &auth;
374         r.in.authenticator = &auth2;
375         r.in.logon_level = 2;
376         r.in.logon.network = &ninfo;
377
378         for (i=2;i<=3;i++) {
379                 ZERO_STRUCT(auth2);
380                 creds_client_authenticator(&creds, &auth);
381
382                 r.in.validation_level = i;
383
384                 printf("Testing SamLogon with validation level %d\n", i);
385
386                 status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
387                 if (!NT_STATUS_IS_OK(status)) {
388                         printf("LogonSamLogon - %s\n", nt_errstr(status));
389                         ret = False;
390                 }
391
392                 if (!creds_client_check(&creds, &r.out.authenticator->cred)) {
393                         printf("Credential chaining failed\n");
394                 }
395         }
396
397         return ret;
398 }
399
400
401 /*
402   try a change password for our machine account
403 */
404 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
405 {
406         NTSTATUS status;
407         struct netr_ServerPasswordSet r;
408         const char *password;
409         struct netr_CredentialState creds;
410
411         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
412                 return False;
413         }
414
415         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
416         r.in.username = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
417         r.in.secure_channel_type = SEC_CHAN_BDC;
418         r.in.computer_name = TEST_MACHINE_NAME;
419
420         password = generate_random_str(8);
421         E_md4hash(password, r.in.new_password.data);
422
423         creds_client_encrypt(&creds, &r.in.new_password);
424
425         printf("Testing ServerPasswordSet on machine account\n");
426
427         creds_client_authenticator(&creds, &r.in.credential);
428
429         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
430         if (!NT_STATUS_IS_OK(status)) {
431                 printf("ServerPasswordSet - %s\n", nt_errstr(status));
432                 return False;
433         }
434
435         join.machine_password = password;
436
437         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
438                 printf("Credential chaining failed\n");
439         }
440
441         /* by changing the machine password twice we test the credentials
442            chaining fully */
443         printf("Testing a second ServerPasswordSet on machine account\n");
444
445         creds_client_authenticator(&creds, &r.in.credential);
446
447         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
448         if (!NT_STATUS_IS_OK(status)) {
449                 printf("ServerPasswordSet - %s\n", nt_errstr(status));
450                 return False;
451         }
452
453         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
454                 printf("Credential chaining failed\n");
455         }
456
457         return True;
458 }
459
460
461 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
462 static struct ULONG8 sequence_nums[3];
463
464 /*
465   try a netlogon DatabaseSync
466 */
467 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
468 {
469         NTSTATUS status;
470         struct netr_DatabaseSync r;
471         struct netr_CredentialState creds;
472         const uint32 database_ids[] = {0, 1, 2}; 
473         int i;
474         BOOL ret = True;
475
476         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
477                 return False;
478         }
479
480         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
481         r.in.computername = TEST_MACHINE_NAME;
482         r.in.preferredmaximumlength = (uint32)-1;
483         ZERO_STRUCT(r.in.return_authenticator);
484
485         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
486                 r.in.sync_context = 0;
487                 r.in.database_id = database_ids[i];
488
489                 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
490
491                 do {
492                         creds_client_authenticator(&creds, &r.in.credential);
493
494                         status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
495                         if (!NT_STATUS_IS_OK(status) &&
496                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
497                                 printf("DatabaseSync - %s\n", nt_errstr(status));
498                                 ret = False;
499                                 break;
500                         }
501
502                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
503                                 printf("Credential chaining failed\n");
504                         }
505
506                         r.in.sync_context = r.out.sync_context;
507
508                         if (r.out.delta_enum_array &&
509                             r.out.delta_enum_array->num_deltas > 0 &&
510                             r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
511                             r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
512                                 sequence_nums[r.in.database_id] = 
513                                         r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
514                                 printf("\tsequence_nums[%d]=0x%08x%08x\n",
515                                        r.in.database_id, 
516                                        sequence_nums[r.in.database_id].high,
517                                        sequence_nums[r.in.database_id].low);
518                         }
519                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
520         }
521
522         return ret;
523 }
524
525
526 /*
527   try a netlogon DatabaseDeltas
528 */
529 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
530 {
531         NTSTATUS status;
532         struct netr_DatabaseDeltas r;
533         struct netr_CredentialState creds;
534         const uint32 database_ids[] = {0, 1, 2}; 
535         int i;
536         BOOL ret = True;
537
538         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
539                 return False;
540         }
541
542         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
543         r.in.computername = TEST_MACHINE_NAME;
544         r.in.preferredmaximumlength = (uint32)-1;
545         ZERO_STRUCT(r.in.return_authenticator);
546
547         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
548                 r.in.database_id = database_ids[i];
549                 r.in.sequence_num = sequence_nums[r.in.database_id];
550
551                 if (r.in.sequence_num.low == 0) continue;
552
553                 r.in.sequence_num.low -= 1;
554
555
556                 printf("Testing DatabaseDeltas of id %d at %d\n", 
557                        r.in.database_id, r.in.sequence_num.low);
558
559                 do {
560                         creds_client_authenticator(&creds, &r.in.credential);
561
562                         status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
563                         if (!NT_STATUS_IS_OK(status) &&
564                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
565                                 printf("DatabaseDeltas - %s\n", nt_errstr(status));
566                                 ret = False;
567                                 break;
568                         }
569
570                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
571                                 printf("Credential chaining failed\n");
572                         }
573
574                         r.in.sequence_num.low++;
575                         r.in.sequence_num.high = 0;
576                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
577         }
578
579         return ret;
580 }
581
582
583 /*
584   try a netlogon AccountDeltas
585 */
586 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
587 {
588         NTSTATUS status;
589         struct netr_AccountDeltas r;
590         struct netr_CredentialState creds;
591         BOOL ret = True;
592
593         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
594                 return False;
595         }
596
597         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
598         r.in.computername = TEST_MACHINE_NAME;
599         ZERO_STRUCT(r.in.return_authenticator);
600         creds_client_authenticator(&creds, &r.in.credential);
601         ZERO_STRUCT(r.in.uas);
602         r.in.count=10;
603         r.in.level=0;
604         r.in.buffersize=100;
605
606         printf("Testing AccountDeltas\n");
607
608         /* w2k3 returns "NOT IMPLEMENTED" for this call */
609         status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
610         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
611                 printf("AccountDeltas - %s\n", nt_errstr(status));
612                 ret = False;
613         }
614
615         return ret;
616 }
617
618 /*
619   try a netlogon AccountSync
620 */
621 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
622 {
623         NTSTATUS status;
624         struct netr_AccountSync r;
625         struct netr_CredentialState creds;
626         BOOL ret = True;
627
628         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
629                 return False;
630         }
631
632         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
633         r.in.computername = TEST_MACHINE_NAME;
634         ZERO_STRUCT(r.in.return_authenticator);
635         creds_client_authenticator(&creds, &r.in.credential);
636         ZERO_STRUCT(r.in.recordid);
637         r.in.reference=0;
638         r.in.level=0;
639         r.in.buffersize=100;
640
641         printf("Testing AccountSync\n");
642
643         /* w2k3 returns "NOT IMPLEMENTED" for this call */
644         status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
645         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
646                 printf("AccountSync - %s\n", nt_errstr(status));
647                 ret = False;
648         }
649
650         return ret;
651 }
652
653 /*
654   try a netlogon GetDcName
655 */
656 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
657 {
658         NTSTATUS status;
659         struct netr_GetDcName r;
660
661         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
662         r.in.domainname = lp_workgroup();
663
664         printf("Testing GetDcName\n");
665
666         status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
667         if (!NT_STATUS_IS_OK(status)) {
668                 printf("GetDcName - %s\n", nt_errstr(status));
669                 return False;
670         }
671
672         printf("\tDC is at '%s'\n", r.out.dcname);
673
674         return True;
675 }
676
677 /*
678   try a netlogon LogonControl 
679 */
680 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
681 {
682         NTSTATUS status;
683         struct netr_LogonControl r;
684         BOOL ret = True;
685         int i;
686
687         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
688         r.in.function_code = 1;
689
690         for (i=1;i<4;i++) {
691                 r.in.level = i;
692
693                 printf("Testing LogonControl level %d\n", i);
694
695                 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
696                 if (!NT_STATUS_IS_OK(status)) {
697                         printf("LogonControl - %s\n", nt_errstr(status));
698                         ret = False;
699                 }
700         }
701
702         return ret;
703 }
704
705
706 /*
707   try a netlogon GetAnyDCName
708 */
709 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
710 {
711         NTSTATUS status;
712         struct netr_GetAnyDCName r;
713
714         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
715         r.in.domainname = lp_workgroup();
716
717         printf("Testing GetAnyDCName\n");
718
719         status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
720         if (!NT_STATUS_IS_OK(status)) {
721                 printf("GetAnyDCName - %s\n", nt_errstr(status));
722                 return False;
723         }
724
725         if (r.out.dcname) {
726                 printf("\tDC is at '%s'\n", r.out.dcname);
727         }
728
729         return True;
730 }
731
732
733 /*
734   try a netlogon LogonControl2
735 */
736 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
737 {
738         NTSTATUS status;
739         struct netr_LogonControl2 r;
740         BOOL ret = True;
741         int i;
742
743         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
744
745         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
746         r.in.data.domain = lp_workgroup();
747
748         for (i=1;i<4;i++) {
749                 r.in.level = i;
750
751                 printf("Testing LogonControl2 level %d function %d\n", 
752                        i, r.in.function_code);
753
754                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
755                 if (!NT_STATUS_IS_OK(status)) {
756                         printf("LogonControl - %s\n", nt_errstr(status));
757                         ret = False;
758                 }
759         }
760
761         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
762         r.in.data.domain = lp_workgroup();
763
764         for (i=1;i<4;i++) {
765                 r.in.level = i;
766
767                 printf("Testing LogonControl2 level %d function %d\n", 
768                        i, r.in.function_code);
769
770                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
771                 if (!NT_STATUS_IS_OK(status)) {
772                         printf("LogonControl - %s\n", nt_errstr(status));
773                         ret = False;
774                 }
775         }
776
777         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
778         r.in.data.domain = lp_workgroup();
779
780         for (i=1;i<4;i++) {
781                 r.in.level = i;
782
783                 printf("Testing LogonControl2 level %d function %d\n", 
784                        i, r.in.function_code);
785
786                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
787                 if (!NT_STATUS_IS_OK(status)) {
788                         printf("LogonControl - %s\n", nt_errstr(status));
789                         ret = False;
790                 }
791         }
792
793         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
794         r.in.data.debug_level = ~0;
795
796         for (i=1;i<4;i++) {
797                 r.in.level = i;
798
799                 printf("Testing LogonControl2 level %d function %d\n", 
800                        i, r.in.function_code);
801
802                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
803                 if (!NT_STATUS_IS_OK(status)) {
804                         printf("LogonControl - %s\n", nt_errstr(status));
805                         ret = False;
806                 }
807         }
808
809         return ret;
810 }
811
812 /*
813   try a netlogon DatabaseSync2
814 */
815 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
816 {
817         NTSTATUS status;
818         struct netr_DatabaseSync2 r;
819         struct netr_CredentialState creds;
820         const uint32 database_ids[] = {0, 1, 2}; 
821         int i;
822         BOOL ret = True;
823
824         if (!test_SetupCredentials2(p, mem_ctx, &creds)) {
825                 return False;
826         }
827
828         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
829         r.in.computername = TEST_MACHINE_NAME;
830         r.in.preferredmaximumlength = (uint32)-1;
831         ZERO_STRUCT(r.in.return_authenticator);
832
833         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
834                 r.in.sync_context = 0;
835                 r.in.database_id = database_ids[i];
836                 r.in.restart_state = 0;
837
838                 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
839
840                 do {
841                         creds_client_authenticator(&creds, &r.in.credential);
842
843                         status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
844                         if (!NT_STATUS_IS_OK(status) &&
845                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
846                                 printf("DatabaseSync2 - %s\n", nt_errstr(status));
847                                 ret = False;
848                                 break;
849                         }
850
851                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
852                                 printf("Credential chaining failed\n");
853                         }
854
855                         r.in.sync_context = r.out.sync_context;
856                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
857         }
858
859         return ret;
860 }
861
862
863 /*
864   try a netlogon LogonControl2Ex
865 */
866 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
867 {
868         NTSTATUS status;
869         struct netr_LogonControl2Ex r;
870         BOOL ret = True;
871         int i;
872
873         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
874
875         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
876         r.in.data.domain = lp_workgroup();
877
878         for (i=1;i<4;i++) {
879                 r.in.level = i;
880
881                 printf("Testing LogonControl2Ex level %d function %d\n", 
882                        i, r.in.function_code);
883
884                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
885                 if (!NT_STATUS_IS_OK(status)) {
886                         printf("LogonControl - %s\n", nt_errstr(status));
887                         ret = False;
888                 }
889         }
890
891         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
892         r.in.data.domain = lp_workgroup();
893
894         for (i=1;i<4;i++) {
895                 r.in.level = i;
896
897                 printf("Testing LogonControl2Ex level %d function %d\n", 
898                        i, r.in.function_code);
899
900                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
901                 if (!NT_STATUS_IS_OK(status)) {
902                         printf("LogonControl - %s\n", nt_errstr(status));
903                         ret = False;
904                 }
905         }
906
907         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
908         r.in.data.domain = lp_workgroup();
909
910         for (i=1;i<4;i++) {
911                 r.in.level = i;
912
913                 printf("Testing LogonControl2Ex level %d function %d\n", 
914                        i, r.in.function_code);
915
916                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
917                 if (!NT_STATUS_IS_OK(status)) {
918                         printf("LogonControl - %s\n", nt_errstr(status));
919                         ret = False;
920                 }
921         }
922
923         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
924         r.in.data.debug_level = ~0;
925
926         for (i=1;i<4;i++) {
927                 r.in.level = i;
928
929                 printf("Testing LogonControl2Ex level %d function %d\n", 
930                        i, r.in.function_code);
931
932                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
933                 if (!NT_STATUS_IS_OK(status)) {
934                         printf("LogonControl - %s\n", nt_errstr(status));
935                         ret = False;
936                 }
937         }
938
939         return ret;
940 }
941
942
943
944 BOOL torture_rpc_netlogon(int dummy)
945 {
946         NTSTATUS status;
947         struct dcerpc_pipe *p;
948         TALLOC_CTX *mem_ctx;
949         BOOL ret = True;
950
951         mem_ctx = talloc_init("torture_rpc_netlogon");
952
953         if (!join_domain_bdc(mem_ctx)) {
954                 printf("Failed to join as BDC\n");
955                 return False;
956         }
957
958         status = torture_rpc_connection(&p, 
959                                         DCERPC_NETLOGON_NAME,
960                                         DCERPC_NETLOGON_UUID,
961                                         DCERPC_NETLOGON_VERSION);
962         if (!NT_STATUS_IS_OK(status)) {
963                 return False;
964         }
965
966         if (!test_LogonUasLogon(p, mem_ctx)) {
967                 ret = False;
968         }
969
970         if (!test_LogonUasLogoff(p, mem_ctx)) {
971                 ret = False;
972         }
973
974         if (!test_SetPassword(p, mem_ctx)) {
975                 ret = False;
976         }
977
978         if (!test_SamLogon(p, mem_ctx)) {
979                 ret = False;
980         }
981
982         if (!test_DatabaseSync(p, mem_ctx)) {
983                 ret = False;
984         }
985
986         if (!test_DatabaseDeltas(p, mem_ctx)) {
987                 ret = False;
988         }
989
990         if (!test_AccountDeltas(p, mem_ctx)) {
991                 ret = False;
992         }
993
994         if (!test_AccountSync(p, mem_ctx)) {
995                 ret = False;
996         }
997
998         if (!test_GetDcName(p, mem_ctx)) {
999                 ret = False;
1000         }
1001
1002         if (!test_LogonControl(p, mem_ctx)) {
1003                 ret = False;
1004         }
1005
1006         if (!test_GetAnyDCName(p, mem_ctx)) {
1007                 ret = False;
1008         }
1009
1010         if (!test_LogonControl2(p, mem_ctx)) {
1011                 ret = False;
1012         }
1013
1014         if (!test_DatabaseSync2(p, mem_ctx)) {
1015                 ret = False;
1016         }
1017
1018         if (!test_LogonControl2Ex(p, mem_ctx)) {
1019                 ret = False;
1020         }
1021
1022         torture_rpc_close(p);
1023
1024         if (!leave_domain_bdc(mem_ctx)) {
1025                 printf("Failed to delete BDC machine account\n");
1026                 return False;
1027         }
1028
1029         return ret;
1030 }