7bfd3a9a6c816feeac4985bb71f0cea9b278ab58
[samba.git] / source4 / 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    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
8    Copyright (C) Tim Potter      2003
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "librpc/gen_ndr/ndr_netlogon.h"
27 #include "auth/auth.h"
28
29 static const char *machine_password;
30
31 #define TEST_MACHINE_NAME "torturetest"
32
33 static BOOL test_LogonUasLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
34 {
35         NTSTATUS status;
36         struct netr_LogonUasLogon r;
37
38         r.in.server_name = NULL;
39         r.in.account_name = lp_parm_string(-1, "torture", "username");
40         r.in.workstation = TEST_MACHINE_NAME;
41
42         printf("Testing LogonUasLogon\n");
43
44         status = dcerpc_netr_LogonUasLogon(p, mem_ctx, &r);
45         if (!NT_STATUS_IS_OK(status)) {
46                 printf("LogonUasLogon - %s\n", nt_errstr(status));
47                 return False;
48         }
49
50         return True;
51         
52 }
53
54 static BOOL test_LogonUasLogoff(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
55 {
56         NTSTATUS status;
57         struct netr_LogonUasLogoff r;
58
59         r.in.server_name = NULL;
60         r.in.account_name = lp_parm_string(-1, "torture", "username");
61         r.in.workstation = TEST_MACHINE_NAME;
62
63         printf("Testing LogonUasLogoff\n");
64
65         status = dcerpc_netr_LogonUasLogoff(p, mem_ctx, &r);
66         if (!NT_STATUS_IS_OK(status)) {
67                 printf("LogonUasLogoff - %s\n", nt_errstr(status));
68                 return False;
69         }
70
71         return True;
72         
73 }
74
75 BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
76                            const char *machine_name,
77                            const char *plain_pass,
78                            struct creds_CredentialState *creds)
79 {
80         NTSTATUS status;
81         struct netr_ServerReqChallenge r;
82         struct netr_ServerAuthenticate a;
83         struct netr_Credential credentials1, credentials2, credentials3;
84         struct samr_Password mach_password;
85
86         printf("Testing ServerReqChallenge\n");
87
88         r.in.server_name = NULL;
89         r.in.computer_name = machine_name;
90         r.in.credentials = &credentials1;
91         r.out.credentials = &credentials2;
92
93         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
94
95         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
96         if (!NT_STATUS_IS_OK(status)) {
97                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
98                 return False;
99         }
100
101         E_md4hash(plain_pass, mach_password.hash);
102
103         a.in.server_name = NULL;
104         a.in.account_name = talloc_asprintf(mem_ctx, "%s$", machine_name);
105         a.in.secure_channel_type = SEC_CHAN_BDC;
106         a.in.computer_name = machine_name;
107         a.in.credentials = &credentials3;
108         a.out.credentials = &credentials3;
109
110         creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3, 
111                           0);
112
113         printf("Testing ServerAuthenticate\n");
114
115         status = dcerpc_netr_ServerAuthenticate(p, mem_ctx, &a);
116         if (!NT_STATUS_IS_OK(status)) {
117                 printf("ServerAuthenticate - %s\n", nt_errstr(status));
118                 return False;
119         }
120
121         if (!creds_client_check(creds, &credentials3)) {
122                 printf("Credential chaining failed\n");
123                 return False;
124         }
125
126         return True;
127 }
128
129 BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
130                             uint32_t negotiate_flags,
131                             const char *machine_name,
132                             const char *plain_pass,
133                             struct creds_CredentialState *creds)
134 {
135         NTSTATUS status;
136         struct netr_ServerReqChallenge r;
137         struct netr_ServerAuthenticate2 a;
138         struct netr_Credential credentials1, credentials2, credentials3;
139         struct samr_Password mach_password;
140
141         printf("Testing ServerReqChallenge\n");
142
143         r.in.server_name = NULL;
144         r.in.computer_name = machine_name;
145         r.in.credentials = &credentials1;
146         r.out.credentials = &credentials2;
147
148         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
149
150         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
151         if (!NT_STATUS_IS_OK(status)) {
152                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
153                 return False;
154         }
155
156         E_md4hash(plain_pass, mach_password.hash);
157
158         a.in.server_name = NULL;
159         a.in.account_name = talloc_asprintf(mem_ctx, "%s$", machine_name);
160         a.in.secure_channel_type = SEC_CHAN_BDC;
161         a.in.computer_name = machine_name;
162         a.in.negotiate_flags = &negotiate_flags;
163         a.out.negotiate_flags = &negotiate_flags;
164         a.in.credentials = &credentials3;
165         a.out.credentials = &credentials3;
166
167         creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3, 
168                           negotiate_flags);
169
170         printf("Testing ServerAuthenticate2\n");
171
172         status = dcerpc_netr_ServerAuthenticate2(p, mem_ctx, &a);
173         if (!NT_STATUS_IS_OK(status)) {
174                 printf("ServerAuthenticate2 - %s\n", nt_errstr(status));
175                 return False;
176         }
177
178         if (!creds_client_check(creds, &credentials3)) {
179                 printf("Credential chaining failed\n");
180                 return False;
181         }
182
183         printf("negotiate_flags=0x%08x\n", negotiate_flags);
184
185         return True;
186 }
187
188
189 BOOL test_SetupCredentials3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
190                             uint32_t negotiate_flags,
191                             const char *machine_name,
192                             const char *plain_pass,
193                             struct creds_CredentialState *creds)
194 {
195         NTSTATUS status;
196         struct netr_ServerReqChallenge r;
197         struct netr_ServerAuthenticate3 a;
198         struct netr_Credential credentials1, credentials2, credentials3;
199         struct samr_Password mach_password;
200         uint32 rid;
201
202         printf("Testing ServerReqChallenge\n");
203
204         r.in.server_name = NULL;
205         r.in.computer_name = machine_name;
206         r.in.credentials = &credentials1;
207         r.out.credentials = &credentials2;
208
209         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
210
211         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
212         if (!NT_STATUS_IS_OK(status)) {
213                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
214                 return False;
215         }
216
217         E_md4hash(plain_pass, mach_password.hash);
218
219         a.in.server_name = NULL;
220         a.in.account_name = talloc_asprintf(mem_ctx, "%s$", machine_name);
221         a.in.secure_channel_type = SEC_CHAN_BDC;
222         a.in.computer_name = machine_name;
223         a.in.negotiate_flags = &negotiate_flags;
224         a.in.credentials = &credentials3;
225         a.out.credentials = &credentials3;
226         a.out.negotiate_flags = &negotiate_flags;
227         a.out.rid = &rid;
228
229         creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3,
230                           negotiate_flags);
231
232         printf("Testing ServerAuthenticate3\n");
233
234         status = dcerpc_netr_ServerAuthenticate3(p, mem_ctx, &a);
235         if (!NT_STATUS_IS_OK(status)) {
236                 printf("ServerAuthenticate3 - %s\n", nt_errstr(status));
237                 return False;
238         }
239
240         if (!creds_client_check(creds, &credentials3)) {
241                 printf("Credential chaining failed\n");
242                 return False;
243         }
244
245         printf("negotiate_flags=0x%08x\n", negotiate_flags);
246
247         return True;
248 }
249
250 /*
251   try a change password for our machine account
252 */
253 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
254 {
255         NTSTATUS status;
256         struct netr_ServerPasswordSet r;
257         const char *password;
258         struct creds_CredentialState creds;
259
260         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, 
261                                    machine_password, &creds)) {
262                 return False;
263         }
264
265         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
266         r.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
267         r.in.secure_channel_type = SEC_CHAN_BDC;
268         r.in.computer_name = TEST_MACHINE_NAME;
269
270         password = generate_random_str(mem_ctx, 8);
271         E_md4hash(password, r.in.new_password.hash);
272
273         creds_des_encrypt(&creds, &r.in.new_password);
274
275         printf("Testing ServerPasswordSet on machine account\n");
276         printf("Changing machine account password to '%s'\n", password);
277
278         creds_client_authenticator(&creds, &r.in.credential);
279
280         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
281         if (!NT_STATUS_IS_OK(status)) {
282                 printf("ServerPasswordSet - %s\n", nt_errstr(status));
283                 return False;
284         }
285
286         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
287                 printf("Credential chaining failed\n");
288         }
289
290         /* by changing the machine password twice we test the
291            credentials chaining fully, and we verify that the server
292            allows the password to be set to the same value twice in a
293            row (match win2k3) */
294         printf("Testing a second ServerPasswordSet on machine account\n");
295         printf("Changing machine account password to '%s' (same as previous run)\n", password);
296
297         creds_client_authenticator(&creds, &r.in.credential);
298
299         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
300         if (!NT_STATUS_IS_OK(status)) {
301                 printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
302                 return False;
303         }
304
305         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
306                 printf("Credential chaining failed\n");
307         }
308
309         machine_password = password;
310
311         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
312                 printf("ServerPasswordSet failed to actually change the password\n");
313                 return False;
314         }
315
316         return True;
317 }
318
319 /*
320   try a netlogon SamLogon
321 */
322 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
323 {
324         NTSTATUS status;
325         struct netr_LogonSamLogon r;
326         struct netr_Authenticator auth, auth2;
327         struct netr_NetworkInfo ninfo;
328         const char *username = lp_parm_string(-1, "torture", "username");
329         const char *password = lp_parm_string(-1, "torture", "password");
330         struct creds_CredentialState creds;
331
332         int i;
333         BOOL ret = True;
334
335         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, 
336                                    machine_password, &creds)) {
337                 return False;
338         }
339
340         ninfo.identity_info.domain_name.string = lp_workgroup();
341         ninfo.identity_info.parameter_control = 0;
342         ninfo.identity_info.logon_id_low = 0;
343         ninfo.identity_info.logon_id_high = 0;
344         ninfo.identity_info.account_name.string = username;
345         ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
346         generate_random_buffer(ninfo.challenge, 
347                                sizeof(ninfo.challenge));
348         ninfo.nt.length = 24;
349         ninfo.nt.data = talloc_size(mem_ctx, 24);
350         SMBNTencrypt(password, ninfo.challenge, ninfo.nt.data);
351         ninfo.lm.length = 24;
352         ninfo.lm.data = talloc_size(mem_ctx, 24);
353         SMBencrypt(password, ninfo.challenge, ninfo.lm.data);
354
355         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
356         r.in.workstation = TEST_MACHINE_NAME;
357         r.in.credential = &auth;
358         r.in.return_authenticator = &auth2;
359         r.in.logon_level = 2;
360         r.in.logon.network = &ninfo;
361
362         for (i=2;i<=3;i++) {
363                 ZERO_STRUCT(auth2);
364                 creds_client_authenticator(&creds, &auth);
365
366                 r.in.validation_level = i;
367
368                 printf("Testing SamLogon with validation level %d\n", i);
369
370                 status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
371                 if (!NT_STATUS_IS_OK(status)) {
372                         printf("LogonSamLogon - %s\n", nt_errstr(status));
373                         ret = False;
374                 }
375
376                 if (!creds_client_check(&creds, &r.out.return_authenticator->cred)) {
377                         printf("Credential chaining failed\n");
378                 }
379         }
380
381         r.in.credential = NULL;
382
383         for (i=2;i<=3;i++) {
384
385                 r.in.validation_level = i;
386
387                 printf("Testing SamLogon with validation level %d\n", i);
388
389                 status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
390                 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
391                         printf("LogonSamLogon expected INVALID_PARAMETER, got: %s\n", nt_errstr(status));
392                         ret = False;
393                 }
394
395         }
396
397         return ret;
398 }
399
400
401
402 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
403 static uint64_t sequence_nums[3];
404
405 /*
406   try a netlogon DatabaseSync
407 */
408 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
409 {
410         NTSTATUS status;
411         struct netr_DatabaseSync r;
412         struct creds_CredentialState creds;
413         const uint32_t database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS}; 
414         int i;
415         BOOL ret = True;
416
417         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
418                 return False;
419         }
420
421         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
422         r.in.computername = TEST_MACHINE_NAME;
423         r.in.preferredmaximumlength = (uint32_t)-1;
424         ZERO_STRUCT(r.in.return_authenticator);
425
426         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
427                 r.in.sync_context = 0;
428                 r.in.database_id = database_ids[i];
429
430                 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
431
432                 do {
433                         creds_client_authenticator(&creds, &r.in.credential);
434
435                         status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
436                         if (!NT_STATUS_IS_OK(status) &&
437                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
438                                 printf("DatabaseSync - %s\n", nt_errstr(status));
439                                 ret = False;
440                                 break;
441                         }
442
443                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
444                                 printf("Credential chaining failed\n");
445                         }
446
447                         r.in.sync_context = r.out.sync_context;
448
449                         if (r.out.delta_enum_array &&
450                             r.out.delta_enum_array->num_deltas > 0 &&
451                             r.out.delta_enum_array->delta_enum[0].delta_type == NETR_DELTA_DOMAIN &&
452                             r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
453                                 sequence_nums[r.in.database_id] = 
454                                         r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
455                                 printf("\tsequence_nums[%d]=%llu\n",
456                                        r.in.database_id, 
457                                        sequence_nums[r.in.database_id]);
458                         }
459                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
460         }
461
462         return ret;
463 }
464
465
466 /*
467   try a netlogon DatabaseDeltas
468 */
469 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
470 {
471         NTSTATUS status;
472         struct netr_DatabaseDeltas r;
473         struct creds_CredentialState creds;
474         const uint32_t database_ids[] = {0, 1, 2}; 
475         int i;
476         BOOL ret = True;
477
478         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
479                 return False;
480         }
481
482         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
483         r.in.computername = TEST_MACHINE_NAME;
484         r.in.preferredmaximumlength = (uint32_t)-1;
485         ZERO_STRUCT(r.in.return_authenticator);
486
487         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
488                 r.in.database_id = database_ids[i];
489                 r.in.sequence_num = sequence_nums[r.in.database_id];
490
491                 if (r.in.sequence_num == 0) continue;
492
493                 r.in.sequence_num -= 1;
494
495
496                 printf("Testing DatabaseDeltas of id %d at %llu\n", 
497                        r.in.database_id, r.in.sequence_num);
498
499                 do {
500                         creds_client_authenticator(&creds, &r.in.credential);
501
502                         status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
503                         if (!NT_STATUS_IS_OK(status) &&
504                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
505                                 printf("DatabaseDeltas - %s\n", nt_errstr(status));
506                                 ret = False;
507                                 break;
508                         }
509
510                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
511                                 printf("Credential chaining failed\n");
512                         }
513
514                         r.in.sequence_num++;
515                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
516         }
517
518         return ret;
519 }
520
521
522 /*
523   try a netlogon AccountDeltas
524 */
525 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
526 {
527         NTSTATUS status;
528         struct netr_AccountDeltas r;
529         struct creds_CredentialState creds;
530         BOOL ret = True;
531
532         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
533                 return False;
534         }
535
536         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
537         r.in.computername = TEST_MACHINE_NAME;
538         ZERO_STRUCT(r.in.return_authenticator);
539         creds_client_authenticator(&creds, &r.in.credential);
540         ZERO_STRUCT(r.in.uas);
541         r.in.count=10;
542         r.in.level=0;
543         r.in.buffersize=100;
544
545         printf("Testing AccountDeltas\n");
546
547         /* w2k3 returns "NOT IMPLEMENTED" for this call */
548         status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
549         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
550                 printf("AccountDeltas - %s\n", nt_errstr(status));
551                 ret = False;
552         }
553
554         return ret;
555 }
556
557 /*
558   try a netlogon AccountSync
559 */
560 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
561 {
562         NTSTATUS status;
563         struct netr_AccountSync r;
564         struct creds_CredentialState creds;
565         BOOL ret = True;
566
567         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
568                 return False;
569         }
570
571         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
572         r.in.computername = TEST_MACHINE_NAME;
573         ZERO_STRUCT(r.in.return_authenticator);
574         creds_client_authenticator(&creds, &r.in.credential);
575         ZERO_STRUCT(r.in.recordid);
576         r.in.reference=0;
577         r.in.level=0;
578         r.in.buffersize=100;
579
580         printf("Testing AccountSync\n");
581
582         /* w2k3 returns "NOT IMPLEMENTED" for this call */
583         status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
584         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
585                 printf("AccountSync - %s\n", nt_errstr(status));
586                 ret = False;
587         }
588
589         return ret;
590 }
591
592 /*
593   try a netlogon GetDcName
594 */
595 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
596 {
597         NTSTATUS status;
598         struct netr_GetDcName r;
599
600         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
601         r.in.domainname = lp_workgroup();
602
603         printf("Testing GetDcName\n");
604
605         status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
606         if (!NT_STATUS_IS_OK(status)) {
607                 printf("GetDcName - %s\n", nt_errstr(status));
608                 return False;
609         }
610
611         printf("\tDC is at '%s'\n", r.out.dcname);
612
613         return True;
614 }
615
616 /*
617   try a netlogon LogonControl 
618 */
619 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
620 {
621         NTSTATUS status;
622         struct netr_LogonControl r;
623         BOOL ret = True;
624         int i;
625
626         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
627         r.in.function_code = 1;
628
629         for (i=1;i<4;i++) {
630                 r.in.level = i;
631
632                 printf("Testing LogonControl level %d\n", i);
633
634                 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
635                 if (!NT_STATUS_IS_OK(status)) {
636                         printf("LogonControl - %s\n", nt_errstr(status));
637                         ret = False;
638                 }
639         }
640
641         return ret;
642 }
643
644
645 /*
646   try a netlogon GetAnyDCName
647 */
648 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
649 {
650         NTSTATUS status;
651         struct netr_GetAnyDCName r;
652
653         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
654         r.in.domainname = lp_workgroup();
655
656         printf("Testing GetAnyDCName\n");
657
658         status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
659         if (!NT_STATUS_IS_OK(status)) {
660                 printf("GetAnyDCName - %s\n", nt_errstr(status));
661                 return False;
662         }
663
664         if (r.out.dcname) {
665                 printf("\tDC is at '%s'\n", r.out.dcname);
666         }
667
668         return True;
669 }
670
671
672 /*
673   try a netlogon LogonControl2
674 */
675 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
676 {
677         NTSTATUS status;
678         struct netr_LogonControl2 r;
679         BOOL ret = True;
680         int i;
681
682         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
683
684         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
685         r.in.data.domain = lp_workgroup();
686
687         for (i=1;i<4;i++) {
688                 r.in.level = i;
689
690                 printf("Testing LogonControl2 level %d function %d\n", 
691                        i, r.in.function_code);
692
693                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
694                 if (!NT_STATUS_IS_OK(status)) {
695                         printf("LogonControl - %s\n", nt_errstr(status));
696                         ret = False;
697                 }
698         }
699
700         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
701         r.in.data.domain = lp_workgroup();
702
703         for (i=1;i<4;i++) {
704                 r.in.level = i;
705
706                 printf("Testing LogonControl2 level %d function %d\n", 
707                        i, r.in.function_code);
708
709                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
710                 if (!NT_STATUS_IS_OK(status)) {
711                         printf("LogonControl - %s\n", nt_errstr(status));
712                         ret = False;
713                 }
714         }
715
716         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
717         r.in.data.domain = lp_workgroup();
718
719         for (i=1;i<4;i++) {
720                 r.in.level = i;
721
722                 printf("Testing LogonControl2 level %d function %d\n", 
723                        i, r.in.function_code);
724
725                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
726                 if (!NT_STATUS_IS_OK(status)) {
727                         printf("LogonControl - %s\n", nt_errstr(status));
728                         ret = False;
729                 }
730         }
731
732         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
733         r.in.data.debug_level = ~0;
734
735         for (i=1;i<4;i++) {
736                 r.in.level = i;
737
738                 printf("Testing LogonControl2 level %d function %d\n", 
739                        i, r.in.function_code);
740
741                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
742                 if (!NT_STATUS_IS_OK(status)) {
743                         printf("LogonControl - %s\n", nt_errstr(status));
744                         ret = False;
745                 }
746         }
747
748         return ret;
749 }
750
751 /*
752   try a netlogon DatabaseSync2
753 */
754 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
755 {
756         NTSTATUS status;
757         struct netr_DatabaseSync2 r;
758         struct creds_CredentialState creds;
759         const uint32_t database_ids[] = {0, 1, 2}; 
760         int i;
761         BOOL ret = True;
762
763         if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, 
764                                     TEST_MACHINE_NAME, machine_password, &creds)) {
765                 return False;
766         }
767
768         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
769         r.in.computername = TEST_MACHINE_NAME;
770         r.in.preferredmaximumlength = (uint32_t)-1;
771         ZERO_STRUCT(r.in.return_authenticator);
772
773         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
774                 r.in.sync_context = 0;
775                 r.in.database_id = database_ids[i];
776                 r.in.restart_state = 0;
777
778                 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
779
780                 do {
781                         creds_client_authenticator(&creds, &r.in.credential);
782
783                         status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
784                         if (!NT_STATUS_IS_OK(status) &&
785                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
786                                 printf("DatabaseSync2 - %s\n", nt_errstr(status));
787                                 ret = False;
788                                 break;
789                         }
790
791                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
792                                 printf("Credential chaining failed\n");
793                         }
794
795                         r.in.sync_context = r.out.sync_context;
796                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
797         }
798
799         return ret;
800 }
801
802
803 /*
804   try a netlogon LogonControl2Ex
805 */
806 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
807 {
808         NTSTATUS status;
809         struct netr_LogonControl2Ex r;
810         BOOL ret = True;
811         int i;
812
813         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
814
815         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
816         r.in.data.domain = lp_workgroup();
817
818         for (i=1;i<4;i++) {
819                 r.in.level = i;
820
821                 printf("Testing LogonControl2Ex level %d function %d\n", 
822                        i, r.in.function_code);
823
824                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
825                 if (!NT_STATUS_IS_OK(status)) {
826                         printf("LogonControl - %s\n", nt_errstr(status));
827                         ret = False;
828                 }
829         }
830
831         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
832         r.in.data.domain = lp_workgroup();
833
834         for (i=1;i<4;i++) {
835                 r.in.level = i;
836
837                 printf("Testing LogonControl2Ex level %d function %d\n", 
838                        i, r.in.function_code);
839
840                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
841                 if (!NT_STATUS_IS_OK(status)) {
842                         printf("LogonControl - %s\n", nt_errstr(status));
843                         ret = False;
844                 }
845         }
846
847         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
848         r.in.data.domain = lp_workgroup();
849
850         for (i=1;i<4;i++) {
851                 r.in.level = i;
852
853                 printf("Testing LogonControl2Ex level %d function %d\n", 
854                        i, r.in.function_code);
855
856                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
857                 if (!NT_STATUS_IS_OK(status)) {
858                         printf("LogonControl - %s\n", nt_errstr(status));
859                         ret = False;
860                 }
861         }
862
863         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
864         r.in.data.debug_level = ~0;
865
866         for (i=1;i<4;i++) {
867                 r.in.level = i;
868
869                 printf("Testing LogonControl2Ex level %d function %d\n", 
870                        i, r.in.function_code);
871
872                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
873                 if (!NT_STATUS_IS_OK(status)) {
874                         printf("LogonControl - %s\n", nt_errstr(status));
875                         ret = False;
876                 }
877         }
878
879         return ret;
880 }
881
882
883 /*
884   try a netlogon netr_DsrEnumerateDomainTrusts
885 */
886 static BOOL test_DsrEnumerateDomainTrusts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
887 {
888         NTSTATUS status;
889         struct netr_DsrEnumerateDomainTrusts r;
890
891         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
892         r.in.trust_flags = 0x3f;
893
894         printf("Testing netr_DsrEnumerateDomainTrusts\n");
895
896         status = dcerpc_netr_DsrEnumerateDomainTrusts(p, mem_ctx, &r);
897         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
898                 printf("netr_DsrEnumerateDomainTrusts - %s/%s\n", 
899                        nt_errstr(status), win_errstr(r.out.result));
900                 return False;
901         }
902
903         return True;
904 }
905
906 /*
907   try a netlogon netr_DrsGetDCNameEx2
908 */
909 static BOOL test_netr_DrsGetDCNameEx2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
910 {
911         NTSTATUS status;
912         struct netr_DrsGetDCNameEx2 r;
913         BOOL ret = True;
914
915         r.in.server_unc         = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
916         r.in.client_account     = NULL;
917         r.in.mask               = 0x00000000;
918         r.in.domain_name        = talloc_asprintf(mem_ctx, "%s", lp_realm());
919         r.in.domain_guid        = NULL;
920         r.in.site_name          = NULL;
921         r.in.flags              = 0x40000000;
922
923         printf("Testing netr_DrsGetDCNameEx2 without client account\n");
924
925         status = dcerpc_netr_DrsGetDCNameEx2(p, mem_ctx, &r);
926         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
927                 printf("netr_DrsGetDCNameEx2 - %s/%s\n", 
928                        nt_errstr(status), win_errstr(r.out.result));
929                 ret = False;
930         }
931
932         printf("Testing netr_DrsGetDCNameEx2 with client acount\n");
933         r.in.client_account     = TEST_MACHINE_NAME"$";
934         r.in.mask               = 0x00002000;
935         r.in.flags              = 0x80000000;
936
937         status = dcerpc_netr_DrsGetDCNameEx2(p, mem_ctx, &r);
938         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
939                 printf("netr_DrsGetDCNameEx2 - %s/%s\n", 
940                        nt_errstr(status), win_errstr(r.out.result));
941                 ret = False;
942         }
943
944         return ret;
945 }
946
947 static BOOL test_GetDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
948 {
949         NTSTATUS status;
950         struct netr_LogonGetDomainInfo r;
951         struct netr_DomainQuery1 q1;
952         struct netr_Authenticator a;
953         struct creds_CredentialState creds;
954
955         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
956                                     TEST_MACHINE_NAME, machine_password, &creds)) {
957                 return False;
958         }
959
960         ZERO_STRUCT(r);
961
962         creds_client_authenticator(&creds, &a);
963
964         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
965         r.in.computer_name = TEST_MACHINE_NAME;
966         r.in.unknown1 = 512;
967         r.in.level = 1;
968         r.in.credential = &a;
969         r.out.credential = &a;
970
971         r.in.i1[0] = 0;
972         r.in.i1[1] = 0;
973
974         r.in.query.query1 = &q1;
975         ZERO_STRUCT(q1);
976         
977         /* this should really be the fully qualified name */
978         q1.workstation_domain = TEST_MACHINE_NAME;
979         q1.workstation_site = "Default-First-Site-Name";
980         q1.blob2.length = 0;
981         q1.blob2.size = 0;
982         q1.blob2.data = NULL;
983         q1.product.string = "product string";
984
985         printf("Testing netr_LogonGetDomainInfo\n");
986
987         status = dcerpc_netr_LogonGetDomainInfo(p, mem_ctx, &r);
988         if (!NT_STATUS_IS_OK(status)) {
989                 printf("netr_LogonGetDomainInfo - %s\n", nt_errstr(status));
990                 return False;
991         }
992
993         if (!creds_client_check(&creds, &a.cred)) {
994                 printf("Credential chaining failed\n");
995                 return False;
996         }
997
998         return True;
999 }
1000
1001
1002 static void async_callback(struct rpc_request *req)
1003 {
1004         int *counter = req->async.private;
1005         if (NT_STATUS_IS_OK(req->status)) {
1006                 (*counter)++;
1007         }
1008 }
1009
1010 static BOOL test_GetDomainInfo_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1011 {
1012         NTSTATUS status;
1013         struct netr_LogonGetDomainInfo r;
1014         struct netr_DomainQuery1 q1;
1015         struct netr_Authenticator a;
1016 #define ASYNC_COUNT 100
1017         struct creds_CredentialState creds;
1018         struct creds_CredentialState creds_async[ASYNC_COUNT];
1019         struct rpc_request *req[ASYNC_COUNT];
1020         int i;
1021         int *async_counter = talloc_p(mem_ctx, int);
1022
1023         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
1024                 printf("test_GetDomainInfo_async disabled - enable dangerous tests to use\n");
1025                 return True;
1026         }
1027
1028         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
1029                                     TEST_MACHINE_NAME, machine_password, &creds)) {
1030                 return False;
1031         }
1032
1033         ZERO_STRUCT(r);
1034         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1035         r.in.computer_name = TEST_MACHINE_NAME;
1036         r.in.unknown1 = 512;
1037         r.in.level = 1;
1038         r.in.credential = &a;
1039         r.out.credential = &a;
1040
1041         r.in.i1[0] = 0;
1042         r.in.i1[1] = 0;
1043
1044         r.in.query.query1 = &q1;
1045         ZERO_STRUCT(q1);
1046         
1047         /* this should really be the fully qualified name */
1048         q1.workstation_domain = TEST_MACHINE_NAME;
1049         q1.workstation_site = "Default-First-Site-Name";
1050         q1.blob2.length = 0;
1051         q1.blob2.size = 0;
1052         q1.blob2.data = NULL;
1053         q1.product.string = "product string";
1054
1055         printf("Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT);
1056
1057         *async_counter = 0;
1058
1059         for (i=0;i<ASYNC_COUNT;i++) {
1060                 creds_client_authenticator(&creds, &a);
1061
1062                 creds_async[i] = creds;
1063                 req[i] = dcerpc_netr_LogonGetDomainInfo_send(p, mem_ctx, &r);
1064
1065                 req[i]->async.callback = async_callback;
1066                 req[i]->async.private = async_counter;
1067
1068                 /* even with this flush per request a w2k3 server seems to 
1069                    clag with multiple outstanding requests. bleergh. */
1070                 if (event_loop_once(dcerpc_event_context(p)) != 0) {
1071                         return False;
1072                 }
1073         }
1074
1075         for (i=0;i<ASYNC_COUNT;i++) {
1076                 status = dcerpc_ndr_request_recv(req[i]);
1077                 if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(r.out.result)) {
1078                         printf("netr_LogonGetDomainInfo_async(%d) - %s/%s\n", 
1079                                i, nt_errstr(status), nt_errstr(r.out.result));
1080                         break;
1081                 }
1082
1083                 if (!creds_client_check(&creds_async[i], &a.cred)) {
1084                         printf("Credential chaining failed at async %d\n", i);
1085                         break;
1086                 }
1087         }
1088
1089         printf("Testing netr_LogonGetDomainInfo - async count %d OK\n", *async_counter);
1090
1091         return (*async_counter) == ASYNC_COUNT;
1092 }
1093
1094
1095 BOOL torture_rpc_netlogon(void)
1096 {
1097         NTSTATUS status;
1098         struct dcerpc_pipe *p;
1099         TALLOC_CTX *mem_ctx;
1100         BOOL ret = True;
1101         struct test_join *join_ctx;
1102
1103         mem_ctx = talloc_init("torture_rpc_netlogon");
1104
1105         join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST, 
1106                                        &machine_password);
1107         if (!join_ctx) {
1108                 printf("Failed to join as BDC\n");
1109                 return False;
1110         }
1111
1112         status = torture_rpc_connection(&p, 
1113                                         DCERPC_NETLOGON_NAME,
1114                                         DCERPC_NETLOGON_UUID,
1115                                         DCERPC_NETLOGON_VERSION);
1116         if (!NT_STATUS_IS_OK(status)) {
1117                 return False;
1118         }
1119
1120         ret &= test_LogonUasLogon(p, mem_ctx);
1121         ret &= test_LogonUasLogoff(p, mem_ctx);
1122         ret &= test_SamLogon(p, mem_ctx);
1123         ret &= test_SetPassword(p, mem_ctx);
1124         ret &= test_GetDomainInfo(p, mem_ctx);
1125         ret &= test_DatabaseSync(p, mem_ctx);
1126         ret &= test_DatabaseDeltas(p, mem_ctx);
1127         ret &= test_AccountDeltas(p, mem_ctx);
1128         ret &= test_AccountSync(p, mem_ctx);
1129         ret &= test_GetDcName(p, mem_ctx);
1130         ret &= test_LogonControl(p, mem_ctx);
1131         ret &= test_GetAnyDCName(p, mem_ctx);
1132         ret &= test_LogonControl2(p, mem_ctx);
1133         ret &= test_DatabaseSync2(p, mem_ctx);
1134         ret &= test_LogonControl2Ex(p, mem_ctx);
1135         ret &= test_DsrEnumerateDomainTrusts(p, mem_ctx);
1136         ret &= test_GetDomainInfo_async(p, mem_ctx);
1137         ret &= test_netr_DrsGetDCNameEx2(p, mem_ctx);
1138
1139         talloc_destroy(mem_ctx);
1140
1141         torture_rpc_close(p);
1142
1143         torture_leave_domain(join_ctx);
1144
1145         return ret;
1146 }