r4616: the first phase in the addition of proper support for
[ira/wip.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                             int sec_chan_type,
134                             struct creds_CredentialState *creds)
135 {
136         NTSTATUS status;
137         struct netr_ServerReqChallenge r;
138         struct netr_ServerAuthenticate2 a;
139         struct netr_Credential credentials1, credentials2, credentials3;
140         struct samr_Password mach_password;
141
142         printf("Testing ServerReqChallenge\n");
143
144         r.in.server_name = NULL;
145         r.in.computer_name = machine_name;
146         r.in.credentials = &credentials1;
147         r.out.credentials = &credentials2;
148
149         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
150
151         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
152         if (!NT_STATUS_IS_OK(status)) {
153                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
154                 return False;
155         }
156
157         E_md4hash(plain_pass, mach_password.hash);
158
159         a.in.server_name = NULL;
160         a.in.account_name = talloc_asprintf(mem_ctx, "%s$", machine_name);
161         a.in.secure_channel_type = sec_chan_type;
162         a.in.computer_name = machine_name;
163         a.in.negotiate_flags = &negotiate_flags;
164         a.out.negotiate_flags = &negotiate_flags;
165         a.in.credentials = &credentials3;
166         a.out.credentials = &credentials3;
167
168         creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3, 
169                           negotiate_flags);
170
171         printf("Testing ServerAuthenticate2\n");
172
173         status = dcerpc_netr_ServerAuthenticate2(p, mem_ctx, &a);
174         if (!NT_STATUS_IS_OK(status)) {
175                 printf("ServerAuthenticate2 - %s\n", nt_errstr(status));
176                 return False;
177         }
178
179         if (!creds_client_check(creds, &credentials3)) {
180                 printf("Credential chaining failed\n");
181                 return False;
182         }
183
184         printf("negotiate_flags=0x%08x\n", negotiate_flags);
185
186         return True;
187 }
188
189
190 BOOL test_SetupCredentials3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
191                             uint32_t negotiate_flags,
192                             const char *machine_name,
193                             const char *plain_pass,
194                             struct creds_CredentialState *creds)
195 {
196         NTSTATUS status;
197         struct netr_ServerReqChallenge r;
198         struct netr_ServerAuthenticate3 a;
199         struct netr_Credential credentials1, credentials2, credentials3;
200         struct samr_Password mach_password;
201         uint32 rid;
202
203         printf("Testing ServerReqChallenge\n");
204
205         r.in.server_name = NULL;
206         r.in.computer_name = machine_name;
207         r.in.credentials = &credentials1;
208         r.out.credentials = &credentials2;
209
210         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
211
212         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
213         if (!NT_STATUS_IS_OK(status)) {
214                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
215                 return False;
216         }
217
218         E_md4hash(plain_pass, mach_password.hash);
219
220         a.in.server_name = NULL;
221         a.in.account_name = talloc_asprintf(mem_ctx, "%s$", machine_name);
222         a.in.secure_channel_type = SEC_CHAN_BDC;
223         a.in.computer_name = machine_name;
224         a.in.negotiate_flags = &negotiate_flags;
225         a.in.credentials = &credentials3;
226         a.out.credentials = &credentials3;
227         a.out.negotiate_flags = &negotiate_flags;
228         a.out.rid = &rid;
229
230         creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3,
231                           negotiate_flags);
232
233         printf("Testing ServerAuthenticate3\n");
234
235         status = dcerpc_netr_ServerAuthenticate3(p, mem_ctx, &a);
236         if (!NT_STATUS_IS_OK(status)) {
237                 printf("ServerAuthenticate3 - %s\n", nt_errstr(status));
238                 return False;
239         }
240
241         if (!creds_client_check(creds, &credentials3)) {
242                 printf("Credential chaining failed\n");
243                 return False;
244         }
245
246         printf("negotiate_flags=0x%08x\n", negotiate_flags);
247
248         return True;
249 }
250
251 /*
252   try a change password for our machine account
253 */
254 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
255 {
256         NTSTATUS status;
257         struct netr_ServerPasswordSet r;
258         const char *password;
259         struct creds_CredentialState creds;
260
261         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, 
262                                    machine_password, &creds)) {
263                 return False;
264         }
265
266         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
267         r.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
268         r.in.secure_channel_type = SEC_CHAN_BDC;
269         r.in.computer_name = TEST_MACHINE_NAME;
270
271         password = generate_random_str(mem_ctx, 8);
272         E_md4hash(password, r.in.new_password.hash);
273
274         creds_des_encrypt(&creds, &r.in.new_password);
275
276         printf("Testing ServerPasswordSet on machine account\n");
277         printf("Changing machine account password to '%s'\n", password);
278
279         creds_client_authenticator(&creds, &r.in.credential);
280
281         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
282         if (!NT_STATUS_IS_OK(status)) {
283                 printf("ServerPasswordSet - %s\n", nt_errstr(status));
284                 return False;
285         }
286
287         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
288                 printf("Credential chaining failed\n");
289         }
290
291         /* by changing the machine password twice we test the
292            credentials chaining fully, and we verify that the server
293            allows the password to be set to the same value twice in a
294            row (match win2k3) */
295         printf("Testing a second ServerPasswordSet on machine account\n");
296         printf("Changing machine account password to '%s' (same as previous run)\n", password);
297
298         creds_client_authenticator(&creds, &r.in.credential);
299
300         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
301         if (!NT_STATUS_IS_OK(status)) {
302                 printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
303                 return False;
304         }
305
306         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
307                 printf("Credential chaining failed\n");
308         }
309
310         machine_password = password;
311
312         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
313                 printf("ServerPasswordSet failed to actually change the password\n");
314                 return False;
315         }
316
317         return True;
318 }
319
320 /*
321   try a netlogon SamLogon
322 */
323 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
324 {
325         NTSTATUS status;
326         struct netr_LogonSamLogon r;
327         struct netr_Authenticator auth, auth2;
328         struct netr_NetworkInfo ninfo;
329         const char *username = lp_parm_string(-1, "torture", "username");
330         const char *password = lp_parm_string(-1, "torture", "password");
331         struct creds_CredentialState creds;
332
333         int i;
334         BOOL ret = True;
335
336         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, 
337                                    machine_password, &creds)) {
338                 return False;
339         }
340
341         ninfo.identity_info.domain_name.string = lp_workgroup();
342         ninfo.identity_info.parameter_control = 0;
343         ninfo.identity_info.logon_id_low = 0;
344         ninfo.identity_info.logon_id_high = 0;
345         ninfo.identity_info.account_name.string = username;
346         ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
347         generate_random_buffer(ninfo.challenge, 
348                                sizeof(ninfo.challenge));
349         ninfo.nt.length = 24;
350         ninfo.nt.data = talloc_size(mem_ctx, 24);
351         SMBNTencrypt(password, ninfo.challenge, ninfo.nt.data);
352         ninfo.lm.length = 24;
353         ninfo.lm.data = talloc_size(mem_ctx, 24);
354         SMBencrypt(password, ninfo.challenge, ninfo.lm.data);
355
356         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
357         r.in.workstation = TEST_MACHINE_NAME;
358         r.in.credential = &auth;
359         r.in.return_authenticator = &auth2;
360         r.in.logon_level = 2;
361         r.in.logon.network = &ninfo;
362
363         for (i=2;i<=3;i++) {
364                 ZERO_STRUCT(auth2);
365                 creds_client_authenticator(&creds, &auth);
366
367                 r.in.validation_level = i;
368
369                 printf("Testing SamLogon with validation level %d\n", i);
370
371                 status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
372                 if (!NT_STATUS_IS_OK(status)) {
373                         printf("LogonSamLogon - %s\n", nt_errstr(status));
374                         ret = False;
375                 }
376
377                 if (!creds_client_check(&creds, &r.out.return_authenticator->cred)) {
378                         printf("Credential chaining failed\n");
379                 }
380         }
381
382         r.in.credential = NULL;
383
384         for (i=2;i<=3;i++) {
385
386                 r.in.validation_level = i;
387
388                 printf("Testing SamLogon with validation level %d\n", i);
389
390                 status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
391                 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
392                         printf("LogonSamLogon expected INVALID_PARAMETER, got: %s\n", nt_errstr(status));
393                         ret = False;
394                 }
395
396         }
397
398         return ret;
399 }
400
401
402
403 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
404 static uint64_t sequence_nums[3];
405
406 /*
407   try a netlogon DatabaseSync
408 */
409 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
410 {
411         NTSTATUS status;
412         struct netr_DatabaseSync r;
413         struct creds_CredentialState creds;
414         const uint32_t database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS}; 
415         int i;
416         BOOL ret = True;
417
418         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
419                 return False;
420         }
421
422         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
423         r.in.computername = TEST_MACHINE_NAME;
424         r.in.preferredmaximumlength = (uint32_t)-1;
425         ZERO_STRUCT(r.in.return_authenticator);
426
427         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
428                 r.in.sync_context = 0;
429                 r.in.database_id = database_ids[i];
430
431                 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
432
433                 do {
434                         creds_client_authenticator(&creds, &r.in.credential);
435
436                         status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
437                         if (!NT_STATUS_IS_OK(status) &&
438                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
439                                 printf("DatabaseSync - %s\n", nt_errstr(status));
440                                 ret = False;
441                                 break;
442                         }
443
444                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
445                                 printf("Credential chaining failed\n");
446                         }
447
448                         r.in.sync_context = r.out.sync_context;
449
450                         if (r.out.delta_enum_array &&
451                             r.out.delta_enum_array->num_deltas > 0 &&
452                             r.out.delta_enum_array->delta_enum[0].delta_type == NETR_DELTA_DOMAIN &&
453                             r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
454                                 sequence_nums[r.in.database_id] = 
455                                         r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
456                                 printf("\tsequence_nums[%d]=%llu\n",
457                                        r.in.database_id, 
458                                        sequence_nums[r.in.database_id]);
459                         }
460                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
461         }
462
463         return ret;
464 }
465
466
467 /*
468   try a netlogon DatabaseDeltas
469 */
470 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
471 {
472         NTSTATUS status;
473         struct netr_DatabaseDeltas r;
474         struct creds_CredentialState creds;
475         const uint32_t database_ids[] = {0, 1, 2}; 
476         int i;
477         BOOL ret = True;
478
479         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
480                 return False;
481         }
482
483         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
484         r.in.computername = TEST_MACHINE_NAME;
485         r.in.preferredmaximumlength = (uint32_t)-1;
486         ZERO_STRUCT(r.in.return_authenticator);
487
488         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
489                 r.in.database_id = database_ids[i];
490                 r.in.sequence_num = sequence_nums[r.in.database_id];
491
492                 if (r.in.sequence_num == 0) continue;
493
494                 r.in.sequence_num -= 1;
495
496
497                 printf("Testing DatabaseDeltas of id %d at %llu\n", 
498                        r.in.database_id, r.in.sequence_num);
499
500                 do {
501                         creds_client_authenticator(&creds, &r.in.credential);
502
503                         status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
504                         if (!NT_STATUS_IS_OK(status) &&
505                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
506                                 printf("DatabaseDeltas - %s\n", nt_errstr(status));
507                                 ret = False;
508                                 break;
509                         }
510
511                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
512                                 printf("Credential chaining failed\n");
513                         }
514
515                         r.in.sequence_num++;
516                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
517         }
518
519         return ret;
520 }
521
522
523 /*
524   try a netlogon AccountDeltas
525 */
526 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
527 {
528         NTSTATUS status;
529         struct netr_AccountDeltas r;
530         struct creds_CredentialState creds;
531         BOOL ret = True;
532
533         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
534                 return False;
535         }
536
537         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
538         r.in.computername = TEST_MACHINE_NAME;
539         ZERO_STRUCT(r.in.return_authenticator);
540         creds_client_authenticator(&creds, &r.in.credential);
541         ZERO_STRUCT(r.in.uas);
542         r.in.count=10;
543         r.in.level=0;
544         r.in.buffersize=100;
545
546         printf("Testing AccountDeltas\n");
547
548         /* w2k3 returns "NOT IMPLEMENTED" for this call */
549         status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
550         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
551                 printf("AccountDeltas - %s\n", nt_errstr(status));
552                 ret = False;
553         }
554
555         return ret;
556 }
557
558 /*
559   try a netlogon AccountSync
560 */
561 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
562 {
563         NTSTATUS status;
564         struct netr_AccountSync r;
565         struct creds_CredentialState creds;
566         BOOL ret = True;
567
568         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
569                 return False;
570         }
571
572         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
573         r.in.computername = TEST_MACHINE_NAME;
574         ZERO_STRUCT(r.in.return_authenticator);
575         creds_client_authenticator(&creds, &r.in.credential);
576         ZERO_STRUCT(r.in.recordid);
577         r.in.reference=0;
578         r.in.level=0;
579         r.in.buffersize=100;
580
581         printf("Testing AccountSync\n");
582
583         /* w2k3 returns "NOT IMPLEMENTED" for this call */
584         status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
585         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
586                 printf("AccountSync - %s\n", nt_errstr(status));
587                 ret = False;
588         }
589
590         return ret;
591 }
592
593 /*
594   try a netlogon GetDcName
595 */
596 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
597 {
598         NTSTATUS status;
599         struct netr_GetDcName r;
600
601         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
602         r.in.domainname = lp_workgroup();
603
604         printf("Testing GetDcName\n");
605
606         status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
607         if (!NT_STATUS_IS_OK(status)) {
608                 printf("GetDcName - %s\n", nt_errstr(status));
609                 return False;
610         }
611
612         printf("\tDC is at '%s'\n", r.out.dcname);
613
614         return True;
615 }
616
617 /*
618   try a netlogon LogonControl 
619 */
620 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
621 {
622         NTSTATUS status;
623         struct netr_LogonControl r;
624         BOOL ret = True;
625         int i;
626
627         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
628         r.in.function_code = 1;
629
630         for (i=1;i<4;i++) {
631                 r.in.level = i;
632
633                 printf("Testing LogonControl level %d\n", i);
634
635                 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
636                 if (!NT_STATUS_IS_OK(status)) {
637                         printf("LogonControl - %s\n", nt_errstr(status));
638                         ret = False;
639                 }
640         }
641
642         return ret;
643 }
644
645
646 /*
647   try a netlogon GetAnyDCName
648 */
649 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
650 {
651         NTSTATUS status;
652         struct netr_GetAnyDCName r;
653
654         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
655         r.in.domainname = lp_workgroup();
656
657         printf("Testing GetAnyDCName\n");
658
659         status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
660         if (!NT_STATUS_IS_OK(status)) {
661                 printf("GetAnyDCName - %s\n", nt_errstr(status));
662                 return False;
663         }
664
665         if (r.out.dcname) {
666                 printf("\tDC is at '%s'\n", r.out.dcname);
667         }
668
669         return True;
670 }
671
672
673 /*
674   try a netlogon LogonControl2
675 */
676 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
677 {
678         NTSTATUS status;
679         struct netr_LogonControl2 r;
680         BOOL ret = True;
681         int i;
682
683         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
684
685         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
686         r.in.data.domain = lp_workgroup();
687
688         for (i=1;i<4;i++) {
689                 r.in.level = i;
690
691                 printf("Testing LogonControl2 level %d function %d\n", 
692                        i, r.in.function_code);
693
694                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
695                 if (!NT_STATUS_IS_OK(status)) {
696                         printf("LogonControl - %s\n", nt_errstr(status));
697                         ret = False;
698                 }
699         }
700
701         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
702         r.in.data.domain = lp_workgroup();
703
704         for (i=1;i<4;i++) {
705                 r.in.level = i;
706
707                 printf("Testing LogonControl2 level %d function %d\n", 
708                        i, r.in.function_code);
709
710                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
711                 if (!NT_STATUS_IS_OK(status)) {
712                         printf("LogonControl - %s\n", nt_errstr(status));
713                         ret = False;
714                 }
715         }
716
717         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
718         r.in.data.domain = lp_workgroup();
719
720         for (i=1;i<4;i++) {
721                 r.in.level = i;
722
723                 printf("Testing LogonControl2 level %d function %d\n", 
724                        i, r.in.function_code);
725
726                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
727                 if (!NT_STATUS_IS_OK(status)) {
728                         printf("LogonControl - %s\n", nt_errstr(status));
729                         ret = False;
730                 }
731         }
732
733         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
734         r.in.data.debug_level = ~0;
735
736         for (i=1;i<4;i++) {
737                 r.in.level = i;
738
739                 printf("Testing LogonControl2 level %d function %d\n", 
740                        i, r.in.function_code);
741
742                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
743                 if (!NT_STATUS_IS_OK(status)) {
744                         printf("LogonControl - %s\n", nt_errstr(status));
745                         ret = False;
746                 }
747         }
748
749         return ret;
750 }
751
752 /*
753   try a netlogon DatabaseSync2
754 */
755 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
756 {
757         NTSTATUS status;
758         struct netr_DatabaseSync2 r;
759         struct creds_CredentialState creds;
760         const uint32_t database_ids[] = {0, 1, 2}; 
761         int i;
762         BOOL ret = True;
763
764         if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, 
765                                     TEST_MACHINE_NAME, machine_password, 
766                                     SEC_CHAN_BDC, &creds)) {
767                 return False;
768         }
769
770         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
771         r.in.computername = TEST_MACHINE_NAME;
772         r.in.preferredmaximumlength = (uint32_t)-1;
773         ZERO_STRUCT(r.in.return_authenticator);
774
775         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
776                 r.in.sync_context = 0;
777                 r.in.database_id = database_ids[i];
778                 r.in.restart_state = 0;
779
780                 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
781
782                 do {
783                         creds_client_authenticator(&creds, &r.in.credential);
784
785                         status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
786                         if (!NT_STATUS_IS_OK(status) &&
787                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
788                                 printf("DatabaseSync2 - %s\n", nt_errstr(status));
789                                 ret = False;
790                                 break;
791                         }
792
793                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
794                                 printf("Credential chaining failed\n");
795                         }
796
797                         r.in.sync_context = r.out.sync_context;
798                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
799         }
800
801         return ret;
802 }
803
804
805 /*
806   try a netlogon LogonControl2Ex
807 */
808 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
809 {
810         NTSTATUS status;
811         struct netr_LogonControl2Ex r;
812         BOOL ret = True;
813         int i;
814
815         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
816
817         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
818         r.in.data.domain = lp_workgroup();
819
820         for (i=1;i<4;i++) {
821                 r.in.level = i;
822
823                 printf("Testing LogonControl2Ex level %d function %d\n", 
824                        i, r.in.function_code);
825
826                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
827                 if (!NT_STATUS_IS_OK(status)) {
828                         printf("LogonControl - %s\n", nt_errstr(status));
829                         ret = False;
830                 }
831         }
832
833         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
834         r.in.data.domain = lp_workgroup();
835
836         for (i=1;i<4;i++) {
837                 r.in.level = i;
838
839                 printf("Testing LogonControl2Ex level %d function %d\n", 
840                        i, r.in.function_code);
841
842                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
843                 if (!NT_STATUS_IS_OK(status)) {
844                         printf("LogonControl - %s\n", nt_errstr(status));
845                         ret = False;
846                 }
847         }
848
849         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
850         r.in.data.domain = lp_workgroup();
851
852         for (i=1;i<4;i++) {
853                 r.in.level = i;
854
855                 printf("Testing LogonControl2Ex level %d function %d\n", 
856                        i, r.in.function_code);
857
858                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
859                 if (!NT_STATUS_IS_OK(status)) {
860                         printf("LogonControl - %s\n", nt_errstr(status));
861                         ret = False;
862                 }
863         }
864
865         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
866         r.in.data.debug_level = ~0;
867
868         for (i=1;i<4;i++) {
869                 r.in.level = i;
870
871                 printf("Testing LogonControl2Ex level %d function %d\n", 
872                        i, r.in.function_code);
873
874                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
875                 if (!NT_STATUS_IS_OK(status)) {
876                         printf("LogonControl - %s\n", nt_errstr(status));
877                         ret = False;
878                 }
879         }
880
881         return ret;
882 }
883
884
885 /*
886   try a netlogon netr_DsrEnumerateDomainTrusts
887 */
888 static BOOL test_DsrEnumerateDomainTrusts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
889 {
890         NTSTATUS status;
891         struct netr_DsrEnumerateDomainTrusts r;
892
893         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
894         r.in.trust_flags = 0x3f;
895
896         printf("Testing netr_DsrEnumerateDomainTrusts\n");
897
898         status = dcerpc_netr_DsrEnumerateDomainTrusts(p, mem_ctx, &r);
899         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
900                 printf("netr_DsrEnumerateDomainTrusts - %s/%s\n", 
901                        nt_errstr(status), win_errstr(r.out.result));
902                 return False;
903         }
904
905         return True;
906 }
907
908 /*
909   try a netlogon netr_DrsGetDCNameEx2
910 */
911 static BOOL test_netr_DrsGetDCNameEx2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
912 {
913         NTSTATUS status;
914         struct netr_DrsGetDCNameEx2 r;
915         BOOL ret = True;
916
917         r.in.server_unc         = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
918         r.in.client_account     = NULL;
919         r.in.mask               = 0x00000000;
920         r.in.domain_name        = talloc_asprintf(mem_ctx, "%s", lp_realm());
921         r.in.domain_guid        = NULL;
922         r.in.site_name          = NULL;
923         r.in.flags              = 0x40000000;
924
925         printf("Testing netr_DrsGetDCNameEx2 without client account\n");
926
927         status = dcerpc_netr_DrsGetDCNameEx2(p, mem_ctx, &r);
928         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
929                 printf("netr_DrsGetDCNameEx2 - %s/%s\n", 
930                        nt_errstr(status), win_errstr(r.out.result));
931                 ret = False;
932         }
933
934         printf("Testing netr_DrsGetDCNameEx2 with client acount\n");
935         r.in.client_account     = TEST_MACHINE_NAME"$";
936         r.in.mask               = 0x00002000;
937         r.in.flags              = 0x80000000;
938
939         status = dcerpc_netr_DrsGetDCNameEx2(p, mem_ctx, &r);
940         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
941                 printf("netr_DrsGetDCNameEx2 - %s/%s\n", 
942                        nt_errstr(status), win_errstr(r.out.result));
943                 ret = False;
944         }
945
946         return ret;
947 }
948
949 static BOOL test_GetDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
950 {
951         NTSTATUS status;
952         struct netr_LogonGetDomainInfo r;
953         struct netr_DomainQuery1 q1;
954         struct netr_Authenticator a;
955         struct creds_CredentialState creds;
956
957         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
958                                     TEST_MACHINE_NAME, machine_password, &creds)) {
959                 return False;
960         }
961
962         ZERO_STRUCT(r);
963
964         creds_client_authenticator(&creds, &a);
965
966         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
967         r.in.computer_name = TEST_MACHINE_NAME;
968         r.in.unknown1 = 512;
969         r.in.level = 1;
970         r.in.credential = &a;
971         r.out.credential = &a;
972
973         r.in.i1[0] = 0;
974         r.in.i1[1] = 0;
975
976         r.in.query.query1 = &q1;
977         ZERO_STRUCT(q1);
978         
979         /* this should really be the fully qualified name */
980         q1.workstation_domain = TEST_MACHINE_NAME;
981         q1.workstation_site = "Default-First-Site-Name";
982         q1.blob2.length = 0;
983         q1.blob2.size = 0;
984         q1.blob2.data = NULL;
985         q1.product.string = "product string";
986
987         printf("Testing netr_LogonGetDomainInfo\n");
988
989         status = dcerpc_netr_LogonGetDomainInfo(p, mem_ctx, &r);
990         if (!NT_STATUS_IS_OK(status)) {
991                 printf("netr_LogonGetDomainInfo - %s\n", nt_errstr(status));
992                 return False;
993         }
994
995         if (!creds_client_check(&creds, &a.cred)) {
996                 printf("Credential chaining failed\n");
997                 return False;
998         }
999
1000         return True;
1001 }
1002
1003
1004 static void async_callback(struct rpc_request *req)
1005 {
1006         int *counter = req->async.private;
1007         if (NT_STATUS_IS_OK(req->status)) {
1008                 (*counter)++;
1009         }
1010 }
1011
1012 static BOOL test_GetDomainInfo_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1013 {
1014         NTSTATUS status;
1015         struct netr_LogonGetDomainInfo r;
1016         struct netr_DomainQuery1 q1;
1017         struct netr_Authenticator a;
1018 #define ASYNC_COUNT 100
1019         struct creds_CredentialState creds;
1020         struct creds_CredentialState creds_async[ASYNC_COUNT];
1021         struct rpc_request *req[ASYNC_COUNT];
1022         int i;
1023         int *async_counter = talloc_p(mem_ctx, int);
1024
1025         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
1026                 printf("test_GetDomainInfo_async disabled - enable dangerous tests to use\n");
1027                 return True;
1028         }
1029
1030         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
1031                                     TEST_MACHINE_NAME, machine_password, &creds)) {
1032                 return False;
1033         }
1034
1035         ZERO_STRUCT(r);
1036         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1037         r.in.computer_name = TEST_MACHINE_NAME;
1038         r.in.unknown1 = 512;
1039         r.in.level = 1;
1040         r.in.credential = &a;
1041         r.out.credential = &a;
1042
1043         r.in.i1[0] = 0;
1044         r.in.i1[1] = 0;
1045
1046         r.in.query.query1 = &q1;
1047         ZERO_STRUCT(q1);
1048         
1049         /* this should really be the fully qualified name */
1050         q1.workstation_domain = TEST_MACHINE_NAME;
1051         q1.workstation_site = "Default-First-Site-Name";
1052         q1.blob2.length = 0;
1053         q1.blob2.size = 0;
1054         q1.blob2.data = NULL;
1055         q1.product.string = "product string";
1056
1057         printf("Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT);
1058
1059         *async_counter = 0;
1060
1061         for (i=0;i<ASYNC_COUNT;i++) {
1062                 creds_client_authenticator(&creds, &a);
1063
1064                 creds_async[i] = creds;
1065                 req[i] = dcerpc_netr_LogonGetDomainInfo_send(p, mem_ctx, &r);
1066
1067                 req[i]->async.callback = async_callback;
1068                 req[i]->async.private = async_counter;
1069
1070                 /* even with this flush per request a w2k3 server seems to 
1071                    clag with multiple outstanding requests. bleergh. */
1072                 if (event_loop_once(dcerpc_event_context(p)) != 0) {
1073                         return False;
1074                 }
1075         }
1076
1077         for (i=0;i<ASYNC_COUNT;i++) {
1078                 status = dcerpc_ndr_request_recv(req[i]);
1079                 if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(r.out.result)) {
1080                         printf("netr_LogonGetDomainInfo_async(%d) - %s/%s\n", 
1081                                i, nt_errstr(status), nt_errstr(r.out.result));
1082                         break;
1083                 }
1084
1085                 if (!creds_client_check(&creds_async[i], &a.cred)) {
1086                         printf("Credential chaining failed at async %d\n", i);
1087                         break;
1088                 }
1089         }
1090
1091         printf("Testing netr_LogonGetDomainInfo - async count %d OK\n", *async_counter);
1092
1093         return (*async_counter) == ASYNC_COUNT;
1094 }
1095
1096 static BOOL test_ManyGetDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1097 {
1098         NTSTATUS status;
1099         struct dcerpc_pipe *p2;
1100         struct lsa_ObjectAttribute attr;
1101         struct lsa_QosInfo qos;
1102         struct lsa_OpenPolicy2 o;
1103         struct policy_handle lsa_handle;
1104         struct lsa_DomainList domains;
1105
1106         struct lsa_EnumTrustDom t;
1107         uint32_t resume_handle = 0;
1108         struct netr_GetAnyDCName d;
1109
1110         int i;
1111         BOOL ret = True;
1112
1113         if (p->conn->transport.transport != NCACN_NP) {
1114                 return True;
1115         }
1116
1117         printf("Torturing GetDCName\n");
1118
1119         status = dcerpc_secondary_connection(p, &p2, 
1120                                              DCERPC_LSARPC_NAME, 
1121                                              DCERPC_LSARPC_UUID, 
1122                                              DCERPC_LSARPC_VERSION);
1123         if (!NT_STATUS_IS_OK(status)) {
1124                 printf("Failed to create secondary connection\n");
1125                 return False;
1126         }
1127
1128         qos.len = 0;
1129         qos.impersonation_level = 2;
1130         qos.context_mode = 1;
1131         qos.effective_only = 0;
1132
1133         attr.len = 0;
1134         attr.root_dir = NULL;
1135         attr.object_name = NULL;
1136         attr.attributes = 0;
1137         attr.sec_desc = NULL;
1138         attr.sec_qos = &qos;
1139
1140         o.in.system_name = "\\";
1141         o.in.attr = &attr;
1142         o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1143         o.out.handle = &lsa_handle;
1144
1145         status = dcerpc_lsa_OpenPolicy2(p2, mem_ctx, &o);
1146         if (!NT_STATUS_IS_OK(status)) {
1147                 printf("OpenPolicy2 failed - %s\n", nt_errstr(status));
1148                 return False;
1149         }
1150
1151         t.in.handle = &lsa_handle;
1152         t.in.resume_handle = &resume_handle;
1153         t.in.num_entries = 1000;
1154         t.out.domains = &domains;
1155         t.out.resume_handle = &resume_handle;
1156
1157         status = dcerpc_lsa_EnumTrustDom(p2, mem_ctx, &t);
1158
1159         if ((!NT_STATUS_IS_OK(status) &&
1160              (!NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)))) {
1161                 printf("Could not list domains\n");
1162                 return False;
1163         }
1164
1165         dcerpc_pipe_close(p2);
1166
1167         d.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s",
1168                                             dcerpc_server_name(p));
1169
1170         for (i=0; i<domains.count * 4; i++) {
1171                 struct lsa_DomainInformation *info =
1172                         &domains.domains[rand()%domains.count];
1173
1174                 d.in.domainname = info->name.string;
1175
1176                 status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &d);
1177                 if (!NT_STATUS_IS_OK(status)) {
1178                         printf("GetAnyDCName - %s\n", nt_errstr(status));
1179                         continue;
1180                 }
1181
1182                 printf("\tDC for domain %s is %s\n", info->name.string,
1183                        d.out.dcname ? d.out.dcname : "unknown");
1184         }
1185
1186         return ret;
1187 }
1188
1189
1190 BOOL torture_rpc_netlogon(void)
1191 {
1192         NTSTATUS status;
1193         struct dcerpc_pipe *p;
1194         TALLOC_CTX *mem_ctx;
1195         BOOL ret = True;
1196         struct test_join *join_ctx;
1197
1198         mem_ctx = talloc_init("torture_rpc_netlogon");
1199
1200         join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST, 
1201                                        &machine_password);
1202         if (!join_ctx) {
1203                 printf("Failed to join as BDC\n");
1204                 return False;
1205         }
1206
1207         status = torture_rpc_connection(&p, 
1208                                         DCERPC_NETLOGON_NAME,
1209                                         DCERPC_NETLOGON_UUID,
1210                                         DCERPC_NETLOGON_VERSION);
1211         if (!NT_STATUS_IS_OK(status)) {
1212                 return False;
1213         }
1214
1215         ret &= test_LogonUasLogon(p, mem_ctx);
1216         ret &= test_LogonUasLogoff(p, mem_ctx);
1217         ret &= test_SamLogon(p, mem_ctx);
1218         ret &= test_SetPassword(p, mem_ctx);
1219         ret &= test_GetDomainInfo(p, mem_ctx);
1220         ret &= test_DatabaseSync(p, mem_ctx);
1221         ret &= test_DatabaseDeltas(p, mem_ctx);
1222         ret &= test_AccountDeltas(p, mem_ctx);
1223         ret &= test_AccountSync(p, mem_ctx);
1224         ret &= test_GetDcName(p, mem_ctx);
1225         ret &= test_ManyGetDCName(p, mem_ctx);
1226         ret &= test_LogonControl(p, mem_ctx);
1227         ret &= test_GetAnyDCName(p, mem_ctx);
1228         ret &= test_LogonControl2(p, mem_ctx);
1229         ret &= test_DatabaseSync2(p, mem_ctx);
1230         ret &= test_LogonControl2Ex(p, mem_ctx);
1231         ret &= test_DsrEnumerateDomainTrusts(p, mem_ctx);
1232         ret &= test_GetDomainInfo_async(p, mem_ctx);
1233         ret &= test_netr_DrsGetDCNameEx2(p, mem_ctx);
1234
1235         talloc_destroy(mem_ctx);
1236
1237         torture_rpc_close(p);
1238
1239         torture_leave_domain(join_ctx);
1240
1241         return ret;
1242 }