r24735: Use torture API in more places.
[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 3 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, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "lib/events/events.h"
27 #include "auth/auth.h"
28 #include "lib/cmdline/popt_common.h"
29 #include "torture/rpc/rpc.h"
30 #include "libcli/auth/libcli_auth.h"
31 #include "librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "librpc/gen_ndr/ndr_lsa_c.h"
33
34 static const char *machine_password;
35
36 #define TEST_MACHINE_NAME "torturetest"
37
38 static BOOL test_LogonUasLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
39 {
40         NTSTATUS status;
41         struct netr_LogonUasLogon r;
42
43         if (lp_parm_bool(-1, "torture", "samba4", False)) {
44                 printf("skipping LogonUasLogon test against Samba4\n");
45                 return True;
46         }
47
48         r.in.server_name = NULL;
49         r.in.account_name = cli_credentials_get_username(cmdline_credentials);
50         r.in.workstation = TEST_MACHINE_NAME;
51
52         printf("Testing LogonUasLogon\n");
53
54         status = dcerpc_netr_LogonUasLogon(p, mem_ctx, &r);
55         if (!NT_STATUS_IS_OK(status)) {
56                 printf("LogonUasLogon - %s\n", nt_errstr(status));
57                 return False;
58         }
59
60         return True;
61         
62 }
63
64 static BOOL test_LogonUasLogoff(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
65 {
66         NTSTATUS status;
67         struct netr_LogonUasLogoff r;
68
69         if (lp_parm_bool(-1, "torture", "samba4", False)) {
70                 printf("skipping LogonUasLogoff test against Samba4\n");
71                 return True;
72         }
73
74         r.in.server_name = NULL;
75         r.in.account_name = cli_credentials_get_username(cmdline_credentials);
76         r.in.workstation = TEST_MACHINE_NAME;
77
78         printf("Testing LogonUasLogoff\n");
79
80         status = dcerpc_netr_LogonUasLogoff(p, mem_ctx, &r);
81         if (!NT_STATUS_IS_OK(status)) {
82                 printf("LogonUasLogoff - %s\n", nt_errstr(status));
83                 return False;
84         }
85
86         return True;
87         
88 }
89
90 static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
91                            const char *machine_name,
92                            const char *plain_pass,
93                            struct creds_CredentialState **creds_out)
94 {
95         NTSTATUS status;
96         struct netr_ServerReqChallenge r;
97         struct netr_ServerAuthenticate a;
98         struct netr_Credential credentials1, credentials2, credentials3;
99         struct creds_CredentialState *creds;
100         struct samr_Password mach_password;
101
102         printf("Testing ServerReqChallenge\n");
103
104         creds = talloc(mem_ctx, struct creds_CredentialState);
105         if (!creds) {
106                 return False;
107         }
108
109         r.in.server_name = NULL;
110         r.in.computer_name = machine_name;
111         r.in.credentials = &credentials1;
112         r.out.credentials = &credentials2;
113
114         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
115
116         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
117         if (!NT_STATUS_IS_OK(status)) {
118                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
119                 return False;
120         }
121
122         E_md4hash(plain_pass, mach_password.hash);
123
124         a.in.server_name = NULL;
125         a.in.account_name = talloc_asprintf(mem_ctx, "%s$", machine_name);
126         a.in.secure_channel_type = SEC_CHAN_BDC;
127         a.in.computer_name = machine_name;
128         a.in.credentials = &credentials3;
129         a.out.credentials = &credentials3;
130
131         creds_client_init(creds, &credentials1, &credentials2, 
132                           &mach_password, &credentials3, 
133                           0);
134
135         printf("Testing ServerAuthenticate\n");
136
137         status = dcerpc_netr_ServerAuthenticate(p, mem_ctx, &a);
138         if (!NT_STATUS_IS_OK(status)) {
139                 printf("ServerAuthenticate - %s\n", nt_errstr(status));
140                 return False;
141         }
142
143         if (!creds_client_check(creds, &credentials3)) {
144                 printf("Credential chaining failed\n");
145                 return False;
146         }
147
148         *creds_out = creds;
149         return True;
150 }
151
152 static BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
153                             uint32_t negotiate_flags,
154                             const char *machine_name,
155                             const char *plain_pass,
156                             int sec_chan_type,
157                             struct creds_CredentialState **creds_out)
158 {
159         NTSTATUS status;
160         struct netr_ServerReqChallenge r;
161         struct netr_ServerAuthenticate2 a;
162         struct netr_Credential credentials1, credentials2, credentials3;
163         struct creds_CredentialState *creds;
164         struct samr_Password mach_password;
165
166         printf("Testing ServerReqChallenge\n");
167
168         creds = talloc(mem_ctx, struct creds_CredentialState);
169         if (!creds) {
170                 return False;
171         }
172
173         r.in.server_name = NULL;
174         r.in.computer_name = machine_name;
175         r.in.credentials = &credentials1;
176         r.out.credentials = &credentials2;
177
178         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
179
180         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
181         if (!NT_STATUS_IS_OK(status)) {
182                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
183                 return False;
184         }
185
186         E_md4hash(plain_pass, mach_password.hash);
187
188         a.in.server_name = NULL;
189         a.in.account_name = talloc_asprintf(mem_ctx, "%s$", machine_name);
190         a.in.secure_channel_type = sec_chan_type;
191         a.in.computer_name = machine_name;
192         a.in.negotiate_flags = &negotiate_flags;
193         a.out.negotiate_flags = &negotiate_flags;
194         a.in.credentials = &credentials3;
195         a.out.credentials = &credentials3;
196
197         creds_client_init(creds, &credentials1, &credentials2, 
198                           &mach_password, &credentials3, 
199                           negotiate_flags);
200
201         printf("Testing ServerAuthenticate2\n");
202
203         status = dcerpc_netr_ServerAuthenticate2(p, mem_ctx, &a);
204         if (!NT_STATUS_IS_OK(status)) {
205                 printf("ServerAuthenticate2 - %s\n", nt_errstr(status));
206                 return False;
207         }
208
209         if (!creds_client_check(creds, &credentials3)) {
210                 printf("Credential chaining failed\n");
211                 return False;
212         }
213
214         printf("negotiate_flags=0x%08x\n", negotiate_flags);
215
216         *creds_out = creds;
217         return True;
218 }
219
220
221 static BOOL test_SetupCredentials3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
222                             uint32_t negotiate_flags,
223                             const char *machine_name,
224                             const char *plain_pass,
225                             struct creds_CredentialState **creds_out)
226 {
227         NTSTATUS status;
228         struct netr_ServerReqChallenge r;
229         struct netr_ServerAuthenticate3 a;
230         struct netr_Credential credentials1, credentials2, credentials3;
231         struct creds_CredentialState *creds;
232         struct samr_Password mach_password;
233         uint32_t rid;
234
235         printf("Testing ServerReqChallenge\n");
236
237         creds = talloc(mem_ctx, struct creds_CredentialState);
238         if (!creds) {
239                 return False;
240         }
241
242         r.in.server_name = NULL;
243         r.in.computer_name = machine_name;
244         r.in.credentials = &credentials1;
245         r.out.credentials = &credentials2;
246
247         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
248
249         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
250         if (!NT_STATUS_IS_OK(status)) {
251                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
252                 return False;
253         }
254
255         E_md4hash(plain_pass, mach_password.hash);
256
257         a.in.server_name = NULL;
258         a.in.account_name = talloc_asprintf(mem_ctx, "%s$", machine_name);
259         a.in.secure_channel_type = SEC_CHAN_BDC;
260         a.in.computer_name = machine_name;
261         a.in.negotiate_flags = &negotiate_flags;
262         a.in.credentials = &credentials3;
263         a.out.credentials = &credentials3;
264         a.out.negotiate_flags = &negotiate_flags;
265         a.out.rid = &rid;
266
267         creds_client_init(creds, &credentials1, &credentials2, 
268                           &mach_password, &credentials3,
269                           negotiate_flags);
270
271         printf("Testing ServerAuthenticate3\n");
272
273         status = dcerpc_netr_ServerAuthenticate3(p, mem_ctx, &a);
274         if (!NT_STATUS_IS_OK(status)) {
275                 printf("ServerAuthenticate3 - %s\n", nt_errstr(status));
276                 return False;
277         }
278
279         if (!creds_client_check(creds, &credentials3)) {
280                 printf("Credential chaining failed\n");
281                 return False;
282         }
283
284         printf("negotiate_flags=0x%08x\n", negotiate_flags);
285
286         *creds_out = creds;
287         return True;
288 }
289
290 /*
291   try a change password for our machine account
292 */
293 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
294 {
295         NTSTATUS status;
296         struct netr_ServerPasswordSet r;
297         const char *password;
298         struct creds_CredentialState *creds;
299
300         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, 
301                                    machine_password, &creds)) {
302                 return False;
303         }
304
305         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
306         r.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
307         r.in.secure_channel_type = SEC_CHAN_BDC;
308         r.in.computer_name = TEST_MACHINE_NAME;
309
310         password = generate_random_str(mem_ctx, 8);
311         E_md4hash(password, r.in.new_password.hash);
312
313         creds_des_encrypt(creds, &r.in.new_password);
314
315         printf("Testing ServerPasswordSet on machine account\n");
316         d_printf("Changing machine account password to '%s'\n", password);
317
318         creds_client_authenticator(creds, &r.in.credential);
319
320         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
321         if (!NT_STATUS_IS_OK(status)) {
322                 printf("ServerPasswordSet - %s\n", nt_errstr(status));
323                 return False;
324         }
325
326         if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
327                 printf("Credential chaining failed\n");
328         }
329
330         /* by changing the machine password twice we test the
331            credentials chaining fully, and we verify that the server
332            allows the password to be set to the same value twice in a
333            row (match win2k3) */
334         printf("Testing a second ServerPasswordSet on machine account\n");
335         d_printf("Changing machine account password to '%s' (same as previous run)\n", password);
336
337         creds_client_authenticator(creds, &r.in.credential);
338
339         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
340         if (!NT_STATUS_IS_OK(status)) {
341                 printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
342                 return False;
343         }
344
345         if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
346                 printf("Credential chaining failed\n");
347         }
348
349         machine_password = password;
350
351         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
352                 printf("ServerPasswordSet failed to actually change the password\n");
353                 return False;
354         }
355
356         return True;
357 }
358
359 /*
360   try a change password for our machine account
361 */
362 static BOOL test_SetPassword2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
363 {
364         NTSTATUS status;
365         struct netr_ServerPasswordSet2 r;
366         const char *password;
367         struct creds_CredentialState *creds;
368         struct samr_CryptPassword password_buf;
369
370         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME,
371                                    machine_password, &creds)) {
372                 return False;
373         }
374
375         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
376         r.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
377         r.in.secure_channel_type = SEC_CHAN_BDC;
378         r.in.computer_name = TEST_MACHINE_NAME;
379
380         password = generate_random_str(mem_ctx, 8);
381         encode_pw_buffer(password_buf.data, password, STR_UNICODE);
382         creds_arcfour_crypt(creds, password_buf.data, 516);
383
384         memcpy(r.in.new_password.data, password_buf.data, 512);
385         r.in.new_password.length = IVAL(password_buf.data, 512);
386
387         printf("Testing ServerPasswordSet2 on machine account\n");
388         d_printf("Changing machine account password to '%s'\n", password);
389
390         creds_client_authenticator(creds, &r.in.credential);
391
392         status = dcerpc_netr_ServerPasswordSet2(p, mem_ctx, &r);
393         if (!NT_STATUS_IS_OK(status)) {
394                 printf("ServerPasswordSet2 - %s\n", nt_errstr(status));
395                 return False;
396         }
397
398         if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
399                 printf("Credential chaining failed\n");
400         }
401
402         machine_password = password;
403
404         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
405                 printf("Not testing ability to set password to '', enable dangerous tests to perform this test\n");
406         } else {
407                 /* by changing the machine password to ""
408                  * we check if the server uses password restrictions
409                  * for ServerPasswordSet2
410                  * (win2k3 accepts "")
411                  */
412                 password = "";
413                 encode_pw_buffer(password_buf.data, password, STR_UNICODE);
414                 creds_arcfour_crypt(creds, password_buf.data, 516);
415                 
416                 memcpy(r.in.new_password.data, password_buf.data, 512);
417                 r.in.new_password.length = IVAL(password_buf.data, 512);
418                 
419                 printf("Testing ServerPasswordSet2 on machine account\n");
420                 d_printf("Changing machine account password to '%s'\n", password);
421                 
422                 creds_client_authenticator(creds, &r.in.credential);
423                 
424                 status = dcerpc_netr_ServerPasswordSet2(p, mem_ctx, &r);
425                 if (!NT_STATUS_IS_OK(status)) {
426                         printf("ServerPasswordSet2 - %s\n", nt_errstr(status));
427                         return False;
428                 }
429                 
430                 if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
431                         printf("Credential chaining failed\n");
432                 }
433                 
434                 machine_password = password;
435         }
436
437         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
438                 printf("ServerPasswordSet failed to actually change the password\n");
439                 return False;
440         }
441
442         /* now try a random password */
443         password = generate_random_str(mem_ctx, 8);
444         encode_pw_buffer(password_buf.data, password, STR_UNICODE);
445         creds_arcfour_crypt(creds, password_buf.data, 516);
446
447         memcpy(r.in.new_password.data, password_buf.data, 512);
448         r.in.new_password.length = IVAL(password_buf.data, 512);
449
450         printf("Testing second ServerPasswordSet2 on machine account\n");
451         d_printf("Changing machine account password to '%s'\n", password);
452
453         creds_client_authenticator(creds, &r.in.credential);
454
455         status = dcerpc_netr_ServerPasswordSet2(p, mem_ctx, &r);
456         if (!NT_STATUS_IS_OK(status)) {
457                 printf("ServerPasswordSet2 (2) - %s\n", nt_errstr(status));
458                 return False;
459         }
460
461         if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
462                 printf("Credential chaining failed\n");
463         }
464
465         /* by changing the machine password twice we test the
466            credentials chaining fully, and we verify that the server
467            allows the password to be set to the same value twice in a
468            row (match win2k3) */
469         printf("Testing a second ServerPasswordSet2 on machine account\n");
470         d_printf("Changing machine account password to '%s' (same as previous run)\n", password);
471
472         creds_client_authenticator(creds, &r.in.credential);
473
474         status = dcerpc_netr_ServerPasswordSet2(p, mem_ctx, &r);
475         if (!NT_STATUS_IS_OK(status)) {
476                 printf("ServerPasswordSet (3) - %s\n", nt_errstr(status));
477                 return False;
478         }
479
480         if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
481                 printf("Credential chaining failed\n");
482         }
483
484         machine_password = password;
485
486         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
487                 printf("ServerPasswordSet failed to actually change the password\n");
488                 return False;
489         }
490
491         return True;
492 }
493
494 /*
495   try a netlogon SamLogon
496 */
497 BOOL test_netlogon_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
498                               struct cli_credentials *credentials, 
499                               struct creds_CredentialState *creds)
500 {
501         NTSTATUS status;
502         struct netr_LogonSamLogon r;
503         struct netr_Authenticator auth, auth2;
504         struct netr_NetworkInfo ninfo;
505         DATA_BLOB names_blob, chal, lm_resp, nt_resp;
506         int i;
507         BOOL ret = True;
508         int flags = CLI_CRED_NTLM_AUTH;
509         if (lp_client_lanman_auth()) {
510                 flags |= CLI_CRED_LANMAN_AUTH;
511         }
512
513         if (lp_client_ntlmv2_auth()) {
514                 flags |= CLI_CRED_NTLMv2_AUTH;
515         }
516
517         cli_credentials_get_ntlm_username_domain(cmdline_credentials, mem_ctx, 
518                                                  &ninfo.identity_info.account_name.string,
519                                                  &ninfo.identity_info.domain_name.string);
520         
521         generate_random_buffer(ninfo.challenge, 
522                                sizeof(ninfo.challenge));
523         chal = data_blob_const(ninfo.challenge, 
524                                sizeof(ninfo.challenge));
525
526         names_blob = NTLMv2_generate_names_blob(mem_ctx, cli_credentials_get_workstation(credentials), 
527                                                 cli_credentials_get_domain(credentials));
528
529         status = cli_credentials_get_ntlm_response(cmdline_credentials, mem_ctx, 
530                                                    &flags, 
531                                                    chal,
532                                                    names_blob,
533                                                    &lm_resp, &nt_resp,
534                                                    NULL, NULL);
535         if (!NT_STATUS_IS_OK(status)) {
536                 printf("cli_credentials_get_ntlm_response failed: %s\n", 
537                        nt_errstr(status));
538                 return False;
539         }
540
541         ninfo.lm.data = lm_resp.data;
542         ninfo.lm.length = lm_resp.length;
543
544         ninfo.nt.data = nt_resp.data;
545         ninfo.nt.length = nt_resp.length;
546
547         ninfo.identity_info.parameter_control = 0;
548         ninfo.identity_info.logon_id_low = 0;
549         ninfo.identity_info.logon_id_high = 0;
550         ninfo.identity_info.workstation.string = cli_credentials_get_workstation(credentials);
551
552         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
553         r.in.computer_name = cli_credentials_get_workstation(credentials);
554         r.in.credential = &auth;
555         r.in.return_authenticator = &auth2;
556         r.in.logon_level = 2;
557         r.in.logon.network = &ninfo;
558
559         d_printf("Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
560         
561         for (i=2;i<3;i++) {
562                 ZERO_STRUCT(auth2);
563                 creds_client_authenticator(creds, &auth);
564                 
565                 r.in.validation_level = i;
566                 
567                 status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
568                 if (!NT_STATUS_IS_OK(status)) {
569                         printf("LogonSamLogon failed: %s\n", 
570                                nt_errstr(status));
571                         return False;
572                 }
573                 
574                 if (!creds_client_check(creds, &r.out.return_authenticator->cred)) {
575                         printf("Credential chaining failed\n");
576                         ret = False;
577                 }
578         }
579
580         r.in.credential = NULL;
581
582         for (i=2;i<=3;i++) {
583
584                 r.in.validation_level = i;
585
586                 printf("Testing SamLogon with validation level %d and a NULL credential\n", i);
587
588                 status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
589                 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
590                         printf("LogonSamLogon expected INVALID_PARAMETER, got: %s\n", nt_errstr(status));
591                         ret = False;
592                 }
593
594         }
595
596         return ret;
597 }
598
599 /*
600   try a netlogon SamLogon
601 */
602 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
603                           struct cli_credentials *credentials)
604 {
605         struct creds_CredentialState *creds;
606
607         if (!test_SetupCredentials(p, mem_ctx, cli_credentials_get_workstation(credentials), 
608                                    cli_credentials_get_password(credentials), &creds)) {
609                 return False;
610         }
611
612         return test_netlogon_ops(p, mem_ctx, credentials, creds);
613 }
614
615 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
616 static uint64_t sequence_nums[3];
617
618 /*
619   try a netlogon DatabaseSync
620 */
621 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
622 {
623         NTSTATUS status;
624         struct netr_DatabaseSync r;
625         struct creds_CredentialState *creds;
626         const uint32_t database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS}; 
627         int i;
628         BOOL ret = True;
629
630         if (lp_parm_bool(-1, "torture", "samba4", False)) {
631                 printf("skipping DatabaseSync test against Samba4\n");
632                 return True;
633         }
634
635         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
636                 return False;
637         }
638
639         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
640         r.in.computername = TEST_MACHINE_NAME;
641         r.in.preferredmaximumlength = (uint32_t)-1;
642         ZERO_STRUCT(r.in.return_authenticator);
643
644         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
645                 r.in.sync_context = 0;
646                 r.in.database_id = database_ids[i];
647
648                 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
649
650                 do {
651                         creds_client_authenticator(creds, &r.in.credential);
652
653                         status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
654                         if (!NT_STATUS_IS_OK(status) &&
655                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
656                                 printf("DatabaseSync - %s\n", nt_errstr(status));
657                                 ret = False;
658                                 break;
659                         }
660
661                         if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
662                                 printf("Credential chaining failed\n");
663                         }
664
665                         r.in.sync_context = r.out.sync_context;
666
667                         if (r.out.delta_enum_array &&
668                             r.out.delta_enum_array->num_deltas > 0 &&
669                             r.out.delta_enum_array->delta_enum[0].delta_type == NETR_DELTA_DOMAIN &&
670                             r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
671                                 sequence_nums[r.in.database_id] = 
672                                         r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
673                                 printf("\tsequence_nums[%d]=%llu\n",
674                                        r.in.database_id, 
675                                        (unsigned long long)sequence_nums[r.in.database_id]);
676                         }
677                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
678         }
679
680         return ret;
681 }
682
683
684 /*
685   try a netlogon DatabaseDeltas
686 */
687 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
688 {
689         NTSTATUS status;
690         struct netr_DatabaseDeltas r;
691         struct creds_CredentialState *creds;
692         const uint32_t database_ids[] = {0, 1, 2}; 
693         int i;
694         BOOL ret = True;
695
696         if (lp_parm_bool(-1, "torture", "samba4", False)) {
697                 printf("skipping DatabaseDeltas test against Samba4\n");
698                 return True;
699         }
700
701         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
702                 return False;
703         }
704
705         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
706         r.in.computername = TEST_MACHINE_NAME;
707         r.in.preferredmaximumlength = (uint32_t)-1;
708         ZERO_STRUCT(r.in.return_authenticator);
709
710         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
711                 r.in.database_id = database_ids[i];
712                 r.in.sequence_num = sequence_nums[r.in.database_id];
713
714                 if (r.in.sequence_num == 0) continue;
715
716                 r.in.sequence_num -= 1;
717
718
719                 printf("Testing DatabaseDeltas of id %d at %llu\n", 
720                        r.in.database_id, (unsigned long long)r.in.sequence_num);
721
722                 do {
723                         creds_client_authenticator(creds, &r.in.credential);
724
725                         status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
726                         if (NT_STATUS_EQUAL(status, 
727                                              NT_STATUS_SYNCHRONIZATION_REQUIRED)) {
728                                 printf("no considering %s to be an error\n",
729                                        nt_errstr(status));
730                                 return True;
731                         }
732                         if (!NT_STATUS_IS_OK(status) &&
733                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
734                                 printf("DatabaseDeltas - %s\n", nt_errstr(status));
735                                 ret = False;
736                                 break;
737                         }
738
739                         if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
740                                 printf("Credential chaining failed\n");
741                         }
742
743                         r.in.sequence_num++;
744                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
745         }
746
747         return ret;
748 }
749
750
751 /*
752   try a netlogon AccountDeltas
753 */
754 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
755 {
756         NTSTATUS status;
757         struct netr_AccountDeltas r;
758         struct creds_CredentialState *creds;
759         BOOL ret = True;
760
761         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
762                 return False;
763         }
764
765         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
766         r.in.computername = TEST_MACHINE_NAME;
767         ZERO_STRUCT(r.in.return_authenticator);
768         creds_client_authenticator(creds, &r.in.credential);
769         ZERO_STRUCT(r.in.uas);
770         r.in.count=10;
771         r.in.level=0;
772         r.in.buffersize=100;
773
774         printf("Testing AccountDeltas\n");
775
776         /* w2k3 returns "NOT IMPLEMENTED" for this call */
777         status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
778         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
779                 printf("AccountDeltas - %s\n", nt_errstr(status));
780                 ret = False;
781         }
782
783         return ret;
784 }
785
786 /*
787   try a netlogon AccountSync
788 */
789 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
790 {
791         NTSTATUS status;
792         struct netr_AccountSync r;
793         struct creds_CredentialState *creds;
794         BOOL ret = True;
795
796         if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, machine_password, &creds)) {
797                 return False;
798         }
799
800         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
801         r.in.computername = TEST_MACHINE_NAME;
802         ZERO_STRUCT(r.in.return_authenticator);
803         creds_client_authenticator(creds, &r.in.credential);
804         ZERO_STRUCT(r.in.recordid);
805         r.in.reference=0;
806         r.in.level=0;
807         r.in.buffersize=100;
808
809         printf("Testing AccountSync\n");
810
811         /* w2k3 returns "NOT IMPLEMENTED" for this call */
812         status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
813         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
814                 printf("AccountSync - %s\n", nt_errstr(status));
815                 ret = False;
816         }
817
818         return ret;
819 }
820
821 /*
822   try a netlogon GetDcName
823 */
824 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
825 {
826         NTSTATUS status;
827         struct netr_GetDcName r;
828
829
830         if (lp_parm_bool(-1, "torture", "samba4", False)) {
831                 printf("skipping GetDCName test against Samba4\n");
832                 return True;
833         }       
834
835         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
836         r.in.domainname = lp_workgroup();
837
838         printf("Testing GetDcName\n");
839
840         status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
841         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
842                 printf("GetDcName - %s/%s\n", nt_errstr(status), win_errstr(r.out.result));
843                 return False;
844         }
845
846         d_printf("\tDC is at '%s'\n", r.out.dcname);
847
848         return True;
849 }
850
851 /*
852   try a netlogon LogonControl 
853 */
854 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
855 {
856         NTSTATUS status;
857         struct netr_LogonControl r;
858         BOOL ret = True;
859         int i;
860
861         if (lp_parm_bool(-1, "torture", "samba4", False)) {
862                 printf("skipping LogonControl test against Samba4\n");
863                 return True;
864         }
865
866         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
867         r.in.function_code = 1;
868
869         for (i=1;i<4;i++) {
870                 r.in.level = i;
871
872                 printf("Testing LogonControl level %d\n", i);
873
874                 status = dcerpc_netr_LogonControl(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 GetAnyDCName
887 */
888 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
889 {
890         NTSTATUS status;
891         struct netr_GetAnyDCName r;
892
893         if (lp_parm_bool(-1, "torture", "samba4", False)) {
894                 printf("skipping GetAnyDCName test against Samba4\n");
895                 return True;
896         }
897
898         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
899         r.in.domainname = lp_workgroup();
900
901         printf("Testing GetAnyDCName\n");
902
903         status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
904         if (!NT_STATUS_IS_OK(status)) {
905                 printf("GetAnyDCName - %s\n", nt_errstr(status));
906                 return False;
907         }
908
909         if (r.out.dcname) {
910                 printf("\tDC is at '%s'\n", r.out.dcname);
911         }
912
913         return True;
914 }
915
916
917 /*
918   try a netlogon LogonControl2
919 */
920 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
921 {
922         NTSTATUS status;
923         struct netr_LogonControl2 r;
924         BOOL ret = True;
925         int i;
926
927         if (lp_parm_bool(-1, "torture", "samba4", False)) {
928                 printf("skipping LogonControl2 test against Samba4\n");
929                 return True;
930         }
931
932         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
933
934         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
935         r.in.data.domain = lp_workgroup();
936
937         for (i=1;i<4;i++) {
938                 r.in.level = i;
939
940                 printf("Testing LogonControl2 level %d function %d\n", 
941                        i, r.in.function_code);
942
943                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
944                 if (!NT_STATUS_IS_OK(status)) {
945                         printf("LogonControl - %s\n", nt_errstr(status));
946                         ret = False;
947                 }
948         }
949
950         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
951         r.in.data.domain = lp_workgroup();
952
953         for (i=1;i<4;i++) {
954                 r.in.level = i;
955
956                 printf("Testing LogonControl2 level %d function %d\n", 
957                        i, r.in.function_code);
958
959                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
960                 if (!NT_STATUS_IS_OK(status)) {
961                         printf("LogonControl - %s\n", nt_errstr(status));
962                         ret = False;
963                 }
964         }
965
966         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
967         r.in.data.domain = lp_workgroup();
968
969         for (i=1;i<4;i++) {
970                 r.in.level = i;
971
972                 printf("Testing LogonControl2 level %d function %d\n", 
973                        i, r.in.function_code);
974
975                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
976                 if (!NT_STATUS_IS_OK(status)) {
977                         printf("LogonControl - %s\n", nt_errstr(status));
978                         ret = False;
979                 }
980         }
981
982         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
983         r.in.data.debug_level = ~0;
984
985         for (i=1;i<4;i++) {
986                 r.in.level = i;
987
988                 printf("Testing LogonControl2 level %d function %d\n", 
989                        i, r.in.function_code);
990
991                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
992                 if (!NT_STATUS_IS_OK(status)) {
993                         printf("LogonControl - %s\n", nt_errstr(status));
994                         ret = False;
995                 }
996         }
997
998         return ret;
999 }
1000
1001 /*
1002   try a netlogon DatabaseSync2
1003 */
1004 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1005 {
1006         NTSTATUS status;
1007         struct netr_DatabaseSync2 r;
1008         struct creds_CredentialState *creds;
1009         const uint32_t database_ids[] = {0, 1, 2}; 
1010         int i;
1011         BOOL ret = True;
1012
1013         if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, 
1014                                     TEST_MACHINE_NAME, machine_password, 
1015                                     SEC_CHAN_BDC, &creds)) {
1016                 return False;
1017         }
1018
1019         if (lp_parm_bool(-1, "torture", "samba4", False)) {
1020                 printf("skipping DatabaseSync2 test against Samba4\n");
1021                 return True;
1022         }
1023
1024         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1025         r.in.computername = TEST_MACHINE_NAME;
1026         r.in.preferredmaximumlength = (uint32_t)-1;
1027         ZERO_STRUCT(r.in.return_authenticator);
1028
1029         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1030                 r.in.sync_context = 0;
1031                 r.in.database_id = database_ids[i];
1032                 r.in.restart_state = 0;
1033
1034                 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
1035
1036                 do {
1037                         creds_client_authenticator(creds, &r.in.credential);
1038
1039                         status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
1040                         if (!NT_STATUS_IS_OK(status) &&
1041                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1042                                 printf("DatabaseSync2 - %s\n", nt_errstr(status));
1043                                 ret = False;
1044                                 break;
1045                         }
1046
1047                         if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
1048                                 printf("Credential chaining failed\n");
1049                         }
1050
1051                         r.in.sync_context = r.out.sync_context;
1052                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1053         }
1054
1055         return ret;
1056 }
1057
1058
1059 /*
1060   try a netlogon LogonControl2Ex
1061 */
1062 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1063 {
1064         NTSTATUS status;
1065         struct netr_LogonControl2Ex r;
1066         BOOL ret = True;
1067         int i;
1068
1069         if (lp_parm_bool(-1, "torture", "samba4", False)) {
1070                 printf("skipping DatabaseSync2 test against Samba4\n");
1071                 return True;
1072         }
1073
1074         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1075
1076         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1077         r.in.data.domain = lp_workgroup();
1078
1079         for (i=1;i<4;i++) {
1080                 r.in.level = i;
1081
1082                 printf("Testing LogonControl2Ex level %d function %d\n", 
1083                        i, r.in.function_code);
1084
1085                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1086                 if (!NT_STATUS_IS_OK(status)) {
1087                         printf("LogonControl - %s\n", nt_errstr(status));
1088                         ret = False;
1089                 }
1090         }
1091
1092         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1093         r.in.data.domain = lp_workgroup();
1094
1095         for (i=1;i<4;i++) {
1096                 r.in.level = i;
1097
1098                 printf("Testing LogonControl2Ex level %d function %d\n", 
1099                        i, r.in.function_code);
1100
1101                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1102                 if (!NT_STATUS_IS_OK(status)) {
1103                         printf("LogonControl - %s\n", nt_errstr(status));
1104                         ret = False;
1105                 }
1106         }
1107
1108         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1109         r.in.data.domain = lp_workgroup();
1110
1111         for (i=1;i<4;i++) {
1112                 r.in.level = i;
1113
1114                 printf("Testing LogonControl2Ex level %d function %d\n", 
1115                        i, r.in.function_code);
1116
1117                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1118                 if (!NT_STATUS_IS_OK(status)) {
1119                         printf("LogonControl - %s\n", nt_errstr(status));
1120                         ret = False;
1121                 }
1122         }
1123
1124         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1125         r.in.data.debug_level = ~0;
1126
1127         for (i=1;i<4;i++) {
1128                 r.in.level = i;
1129
1130                 printf("Testing LogonControl2Ex level %d function %d\n", 
1131                        i, r.in.function_code);
1132
1133                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1134                 if (!NT_STATUS_IS_OK(status)) {
1135                         printf("LogonControl - %s\n", nt_errstr(status));
1136                         ret = False;
1137                 }
1138         }
1139
1140         return ret;
1141 }
1142
1143 static BOOL test_netr_DsRGetForestTrustInformation(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *trusted_domain_name) 
1144 {
1145         NTSTATUS status;
1146         struct netr_DsRGetForestTrustInformation r;
1147         BOOL ret = True;
1148         struct lsa_ForestTrustInformation info, *info_ptr;
1149
1150         if (lp_parm_bool(-1, "torture", "samba4", False)) {
1151                 printf("skipping DsRGetForestTrustInformation test against Samba4\n");
1152                 return True;
1153         }
1154
1155         info_ptr = &info;
1156
1157         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1158         r.in.trusted_domain_name = trusted_domain_name;
1159         r.in.flags = 0;
1160         r.out.forest_trust_info = &info_ptr;
1161
1162         printf("Testing netr_DsRGetForestTrustInformation\n");
1163
1164         status = dcerpc_netr_DsRGetForestTrustInformation(p, mem_ctx, &r);
1165         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1166                 printf("netr_DsRGetForestTrustInformation - %s/%s\n", 
1167                        nt_errstr(status), win_errstr(r.out.result));
1168                 ret = False;
1169         }
1170         return ret;
1171 }
1172
1173 /*
1174   try a netlogon netr_DsrEnumerateDomainTrusts
1175 */
1176 static BOOL test_DsrEnumerateDomainTrusts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1177 {
1178         NTSTATUS status;
1179         struct netr_DsrEnumerateDomainTrusts r;
1180         int i;
1181
1182         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1183         r.in.trust_flags = 0x3f;
1184
1185         printf("Testing netr_DsrEnumerateDomainTrusts\n");
1186
1187         status = dcerpc_netr_DsrEnumerateDomainTrusts(p, mem_ctx, &r);
1188         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1189                 printf("netr_DsrEnumerateDomainTrusts - %s/%s\n", 
1190                        nt_errstr(status), win_errstr(r.out.result));
1191                 return False;
1192         }
1193
1194         /* when trusted_domain_name is NULL, netr_DsRGetForestTrustInformation
1195          * will show non-forest trusts and all UPN suffixes of the own forest
1196          * as LSA_FOREST_TRUST_TOP_LEVEL_NAME types */
1197
1198         if (r.out.count) {
1199                 if (!test_netr_DsRGetForestTrustInformation(p, mem_ctx, NULL)) {
1200                         return False;
1201                 }
1202         }
1203
1204         for (i=0; i<r.out.count; i++) {
1205
1206                 /* get info for transitive forest trusts */
1207
1208                 if (r.out.trusts[i].trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1209                         if (!test_netr_DsRGetForestTrustInformation(p, mem_ctx, 
1210                                                                     r.out.trusts[i].dns_name)) {
1211                                 return False;
1212                         }
1213                 }
1214         }
1215
1216         return True;
1217 }
1218
1219 static BOOL test_netr_DsRGetSiteName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1220                                      const char *computer_name, 
1221                                      const char *expected_site) 
1222 {
1223         NTSTATUS status;
1224         struct netr_DsRGetSiteName r;
1225         BOOL ret = True;
1226
1227         if (lp_parm_bool(-1, "torture", "samba4", False)) {
1228                 printf("skipping DsRGetSiteName test against Samba4\n");
1229                 return True;
1230         }
1231
1232         r.in.computer_name              = computer_name;
1233         printf("Testing netr_DsRGetSiteName\n");
1234
1235         status = dcerpc_netr_DsRGetSiteName(p, mem_ctx, &r);
1236         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1237                 printf("netr_DsRGetSiteName - %s/%s\n", 
1238                        nt_errstr(status), win_errstr(r.out.result));
1239                 ret = False;
1240         } else {
1241                 if (strcmp(expected_site, r.out.site) != 0) {
1242                         d_printf("netr_DsRGetSiteName - unexpected result: %s, expected %s\n", 
1243                                r.out.site, expected_site);
1244                                         
1245                         ret = False;
1246                 }
1247         }
1248         r.in.computer_name              = talloc_asprintf(mem_ctx, "\\\\%s", computer_name);
1249         d_printf("Testing netr_DsRGetSiteName with broken computer name: %s\n", r.in.computer_name);
1250
1251         status = dcerpc_netr_DsRGetSiteName(p, mem_ctx, &r);
1252         if (!NT_STATUS_IS_OK(status)) {
1253                 printf("netr_DsRGetSiteName - %s\n", 
1254                        nt_errstr(status));
1255                 ret = False;
1256         } else if (!W_ERROR_EQUAL(r.out.result, WERR_INVALID_COMPUTERNAME)) {
1257                 printf("netr_DsRGetSiteName - incorrect error return %s, expected %s\n", 
1258                        win_errstr(r.out.result), win_errstr(WERR_INVALID_COMPUTERNAME));
1259                 ret = False;
1260         }
1261         return ret;
1262 }
1263
1264 /*
1265   try a netlogon netr_DsRGetDCName
1266 */
1267 static BOOL test_netr_DsRGetDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1268 {
1269         NTSTATUS status;
1270         struct netr_DsRGetDCName r;
1271         BOOL ret = True;
1272
1273         r.in.server_unc         = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1274         r.in.domain_name        = talloc_asprintf(mem_ctx, "%s", lp_realm());
1275         r.in.domain_guid        = NULL;
1276         r.in.site_guid          = NULL;
1277         r.in.flags              = DS_RETURN_DNS_NAME;
1278
1279         printf("Testing netr_DsRGetDCName\n");
1280
1281         status = dcerpc_netr_DsRGetDCName(p, mem_ctx, &r);
1282         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1283                 printf("netr_DsRGetDCName - %s/%s\n", 
1284                        nt_errstr(status), win_errstr(r.out.result));
1285                 ret = False;
1286         } else {
1287                 ret = test_netr_DsRGetSiteName(p, mem_ctx, 
1288                                                r.out.info->dc_unc, 
1289                                                r.out.info->dc_site_name);
1290         }
1291
1292         return ret;
1293 }
1294
1295 /*
1296   try a netlogon netr_DsRGetDCNameEx
1297 */
1298 static BOOL test_netr_DsRGetDCNameEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1299 {
1300         NTSTATUS status;
1301         struct netr_DsRGetDCNameEx r;
1302         BOOL ret = True;
1303
1304         r.in.server_unc         = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1305         r.in.domain_name        = talloc_asprintf(mem_ctx, "%s", lp_realm());
1306         r.in.domain_guid        = NULL;
1307         r.in.site_name          = NULL;
1308         r.in.flags              = DS_RETURN_DNS_NAME;
1309
1310         printf("Testing netr_DsRGetDCNameEx\n");
1311
1312         status = dcerpc_netr_DsRGetDCNameEx(p, mem_ctx, &r);
1313         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1314                 printf("netr_DsRGetDCNameEx - %s/%s\n", 
1315                        nt_errstr(status), win_errstr(r.out.result));
1316                 ret = False;
1317         } else {
1318                 ret = test_netr_DsRGetSiteName(p, mem_ctx, 
1319                                                r.out.info->dc_unc, 
1320                                                r.out.info->dc_site_name);
1321         }
1322
1323         return ret;
1324 }
1325
1326 /*
1327   try a netlogon netr_DsRGetDCNameEx2
1328 */
1329 static BOOL test_netr_DsRGetDCNameEx2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1330 {
1331         NTSTATUS status;
1332         struct netr_DsRGetDCNameEx2 r;
1333         BOOL ret = True;
1334
1335         r.in.server_unc         = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1336         r.in.client_account     = NULL;
1337         r.in.mask               = 0x00000000;
1338         r.in.domain_name        = talloc_asprintf(mem_ctx, "%s", lp_realm());
1339         r.in.domain_guid        = NULL;
1340         r.in.site_name          = NULL;
1341         r.in.flags              = DS_RETURN_DNS_NAME;
1342
1343         printf("Testing netr_DsRGetDCNameEx2 without client account\n");
1344
1345         status = dcerpc_netr_DsRGetDCNameEx2(p, mem_ctx, &r);
1346         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1347                 printf("netr_DsRGetDCNameEx2 - %s/%s\n", 
1348                        nt_errstr(status), win_errstr(r.out.result));
1349                 ret = False;
1350         }
1351
1352         printf("Testing netr_DsRGetDCNameEx2 with client acount\n");
1353         r.in.client_account     = TEST_MACHINE_NAME"$";
1354         r.in.mask               = ACB_SVRTRUST;
1355         r.in.flags              = DS_RETURN_FLAT_NAME;
1356
1357         status = dcerpc_netr_DsRGetDCNameEx2(p, mem_ctx, &r);
1358         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1359                 printf("netr_DsRGetDCNameEx2 - %s/%s\n", 
1360                        nt_errstr(status), win_errstr(r.out.result));
1361                 ret = False;
1362         } else {
1363                 ret = test_netr_DsRGetSiteName(p, mem_ctx, 
1364                                                r.out.info->dc_unc, 
1365                                                r.out.info->dc_site_name);
1366         }
1367
1368         return ret;
1369 }
1370
1371 static BOOL test_netr_DsrGetDcSiteCoverageW(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) 
1372 {
1373         NTSTATUS status;
1374         struct netr_DsrGetDcSiteCoverageW r;
1375         BOOL ret = True;
1376
1377         if (lp_parm_bool(-1, "torture", "samba4", False)) {
1378                 printf("skipping DsrGetDcSiteCoverageW test against Samba4\n");
1379                 return True;
1380         }
1381
1382         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1383
1384         printf("Testing netr_DsrGetDcSiteCoverageW\n");
1385
1386         status = dcerpc_netr_DsrGetDcSiteCoverageW(p, mem_ctx, &r);
1387         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1388                 printf("netr_DsrGetDcSiteCoverageW - %s/%s\n", 
1389                        nt_errstr(status), win_errstr(r.out.result));
1390                 ret = False;
1391         }
1392         return ret;
1393 }
1394
1395
1396 static BOOL test_GetDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1397 {
1398         NTSTATUS status;
1399         struct netr_LogonGetDomainInfo r;
1400         struct netr_DomainQuery1 q1;
1401         struct netr_Authenticator a;
1402         struct creds_CredentialState *creds;
1403
1404         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
1405                                     TEST_MACHINE_NAME, machine_password, &creds)) {
1406                 return False;
1407         }
1408
1409         ZERO_STRUCT(r);
1410
1411         creds_client_authenticator(creds, &a);
1412
1413         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1414         r.in.computer_name = TEST_MACHINE_NAME;
1415         r.in.level = 1;
1416         r.in.credential = &a;
1417         r.in.return_authenticator = &a;
1418         r.out.return_authenticator = &a;
1419
1420         r.in.query.query1 = &q1;
1421         ZERO_STRUCT(q1);
1422         
1423         /* this should really be the fully qualified name */
1424         q1.workstation_domain = TEST_MACHINE_NAME;
1425         q1.workstation_site = "Default-First-Site-Name";
1426         q1.blob2.length = 0;
1427         q1.blob2.size = 0;
1428         q1.blob2.data = NULL;
1429         q1.product.string = "product string";
1430
1431         printf("Testing netr_LogonGetDomainInfo\n");
1432
1433         status = dcerpc_netr_LogonGetDomainInfo(p, mem_ctx, &r);
1434         if (!NT_STATUS_IS_OK(status)) {
1435                 printf("netr_LogonGetDomainInfo - %s\n", nt_errstr(status));
1436                 return False;
1437         }
1438
1439         if (!creds_client_check(creds, &a.cred)) {
1440                 printf("Credential chaining failed\n");
1441                 return False;
1442         }
1443
1444         return True;
1445 }
1446
1447
1448 static void async_callback(struct rpc_request *req)
1449 {
1450         int *counter = req->async.private_data;
1451         if (NT_STATUS_IS_OK(req->status)) {
1452                 (*counter)++;
1453         }
1454 }
1455
1456 static BOOL test_GetDomainInfo_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1457 {
1458         NTSTATUS status;
1459         struct netr_LogonGetDomainInfo r;
1460         struct netr_DomainQuery1 q1;
1461         struct netr_Authenticator a;
1462 #define ASYNC_COUNT 100
1463         struct creds_CredentialState *creds;
1464         struct creds_CredentialState *creds_async[ASYNC_COUNT];
1465         struct rpc_request *req[ASYNC_COUNT];
1466         int i;
1467         int *async_counter = talloc(mem_ctx, int);
1468
1469         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
1470                 printf("test_GetDomainInfo_async disabled - enable dangerous tests to use\n");
1471                 return True;
1472         }
1473
1474         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
1475                                     TEST_MACHINE_NAME, machine_password, &creds)) {
1476                 return False;
1477         }
1478
1479         ZERO_STRUCT(r);
1480         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1481         r.in.computer_name = TEST_MACHINE_NAME;
1482         r.in.level = 1;
1483         r.in.credential = &a;
1484         r.in.return_authenticator = &a;
1485         r.out.return_authenticator = &a;
1486
1487         r.in.query.query1 = &q1;
1488         ZERO_STRUCT(q1);
1489         
1490         /* this should really be the fully qualified name */
1491         q1.workstation_domain = TEST_MACHINE_NAME;
1492         q1.workstation_site = "Default-First-Site-Name";
1493         q1.blob2.length = 0;
1494         q1.blob2.size = 0;
1495         q1.blob2.data = NULL;
1496         q1.product.string = "product string";
1497
1498         printf("Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT);
1499
1500         *async_counter = 0;
1501
1502         for (i=0;i<ASYNC_COUNT;i++) {
1503                 creds_client_authenticator(creds, &a);
1504
1505                 creds_async[i] = talloc_memdup(creds, creds, sizeof(*creds));
1506                 req[i] = dcerpc_netr_LogonGetDomainInfo_send(p, mem_ctx, &r);
1507
1508                 req[i]->async.callback = async_callback;
1509                 req[i]->async.private_data = async_counter;
1510
1511                 /* even with this flush per request a w2k3 server seems to 
1512                    clag with multiple outstanding requests. bleergh. */
1513                 if (event_loop_once(dcerpc_event_context(p)) != 0) {
1514                         return False;
1515                 }
1516         }
1517
1518         for (i=0;i<ASYNC_COUNT;i++) {
1519                 status = dcerpc_ndr_request_recv(req[i]);
1520                 if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(r.out.result)) {
1521                         printf("netr_LogonGetDomainInfo_async(%d) - %s/%s\n", 
1522                                i, nt_errstr(status), nt_errstr(r.out.result));
1523                         break;
1524                 }
1525
1526                 if (!creds_client_check(creds_async[i], &a.cred)) {
1527                         printf("Credential chaining failed at async %d\n", i);
1528                         break;
1529                 }
1530         }
1531
1532         printf("Testing netr_LogonGetDomainInfo - async count %d OK\n", *async_counter);
1533
1534         return (*async_counter) == ASYNC_COUNT;
1535 }
1536
1537 static BOOL test_ManyGetDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1538 {
1539         NTSTATUS status;
1540         struct dcerpc_pipe *p2;
1541         struct lsa_ObjectAttribute attr;
1542         struct lsa_QosInfo qos;
1543         struct lsa_OpenPolicy2 o;
1544         struct policy_handle lsa_handle;
1545         struct lsa_DomainList domains;
1546
1547         struct lsa_EnumTrustDom t;
1548         uint32_t resume_handle = 0;
1549         struct netr_GetAnyDCName d;
1550
1551         int i;
1552         BOOL ret = True;
1553
1554         if (p->conn->transport.transport != NCACN_NP) {
1555                 return True;
1556         }
1557
1558         printf("Torturing GetDCName\n");
1559
1560         status = dcerpc_secondary_connection(p, &p2, p->binding);
1561         if (!NT_STATUS_IS_OK(status)) {
1562                 printf("Failed to create secondary connection\n");
1563                 return False;
1564         }
1565
1566         status = dcerpc_bind_auth_none(p2, &ndr_table_lsarpc);
1567         if (!NT_STATUS_IS_OK(status)) {
1568                 printf("Failed to create bind on secondary connection\n");
1569                 return False;
1570         }
1571
1572         qos.len = 0;
1573         qos.impersonation_level = 2;
1574         qos.context_mode = 1;
1575         qos.effective_only = 0;
1576
1577         attr.len = 0;
1578         attr.root_dir = NULL;
1579         attr.object_name = NULL;
1580         attr.attributes = 0;
1581         attr.sec_desc = NULL;
1582         attr.sec_qos = &qos;
1583
1584         o.in.system_name = "\\";
1585         o.in.attr = &attr;
1586         o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1587         o.out.handle = &lsa_handle;
1588
1589         status = dcerpc_lsa_OpenPolicy2(p2, mem_ctx, &o);
1590         if (!NT_STATUS_IS_OK(status)) {
1591                 printf("OpenPolicy2 failed - %s\n", nt_errstr(status));
1592                 return False;
1593         }
1594
1595         t.in.handle = &lsa_handle;
1596         t.in.resume_handle = &resume_handle;
1597         t.in.max_size = 1000;
1598         t.out.domains = &domains;
1599         t.out.resume_handle = &resume_handle;
1600
1601         status = dcerpc_lsa_EnumTrustDom(p2, mem_ctx, &t);
1602
1603         if ((!NT_STATUS_IS_OK(status) &&
1604              (!NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)))) {
1605                 printf("Could not list domains\n");
1606                 return False;
1607         }
1608
1609         talloc_free(p2);
1610
1611         d.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s",
1612                                             dcerpc_server_name(p));
1613
1614         for (i=0; i<domains.count * 4; i++) {
1615                 struct lsa_DomainInfo *info =
1616                         &domains.domains[rand()%domains.count];
1617
1618                 d.in.domainname = info->name.string;
1619
1620                 status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &d);
1621                 if (!NT_STATUS_IS_OK(status)) {
1622                         printf("GetAnyDCName - %s\n", nt_errstr(status));
1623                         continue;
1624                 }
1625
1626                 printf("\tDC for domain %s is %s\n", info->name.string,
1627                        d.out.dcname ? d.out.dcname : "unknown");
1628         }
1629
1630         return ret;
1631 }
1632
1633
1634 BOOL torture_rpc_netlogon(struct torture_context *torture)
1635 {
1636         NTSTATUS status;
1637         struct dcerpc_pipe *p;
1638         TALLOC_CTX *mem_ctx;
1639         BOOL ret = True;
1640         struct test_join *join_ctx;
1641         struct cli_credentials *machine_credentials;
1642
1643         mem_ctx = talloc_init("torture_rpc_netlogon");
1644
1645         join_ctx = torture_join_domain(TEST_MACHINE_NAME, ACB_SVRTRUST, 
1646                                        &machine_credentials);
1647         if (!join_ctx) {
1648                 talloc_free(mem_ctx);
1649                 printf("Failed to join as BDC\n");
1650                 return False;
1651         }
1652
1653         machine_password = cli_credentials_get_password(machine_credentials);
1654
1655         status = torture_rpc_connection(torture, &p, &ndr_table_netlogon);
1656         if (!NT_STATUS_IS_OK(status)) {
1657                 talloc_free(mem_ctx);
1658                 return False;
1659         }
1660
1661         ret &= test_LogonUasLogon(p, mem_ctx);
1662         ret &= test_LogonUasLogoff(p, mem_ctx);
1663         ret &= test_SamLogon(p, mem_ctx, machine_credentials);
1664         ret &= test_SetPassword(p, mem_ctx);
1665         ret &= test_SetPassword2(p, mem_ctx);
1666         ret &= test_GetDomainInfo(p, mem_ctx);
1667         ret &= test_DatabaseSync(p, mem_ctx);
1668         ret &= test_DatabaseDeltas(p, mem_ctx);
1669         ret &= test_AccountDeltas(p, mem_ctx);
1670         ret &= test_AccountSync(p, mem_ctx);
1671         ret &= test_GetDcName(p, mem_ctx);
1672         ret &= test_ManyGetDCName(p, mem_ctx);
1673         ret &= test_LogonControl(p, mem_ctx);
1674         ret &= test_GetAnyDCName(p, mem_ctx);
1675         ret &= test_LogonControl2(p, mem_ctx);
1676         ret &= test_DatabaseSync2(p, mem_ctx);
1677         ret &= test_LogonControl2Ex(p, mem_ctx);
1678         ret &= test_DsrEnumerateDomainTrusts(p, mem_ctx);
1679         ret &= test_GetDomainInfo_async(p, mem_ctx);
1680         ret &= test_netr_DsRGetDCName(p, mem_ctx);
1681         ret &= test_netr_DsRGetDCNameEx(p, mem_ctx);
1682         ret &= test_netr_DsRGetDCNameEx2(p, mem_ctx);
1683         ret &= test_netr_DsrGetDcSiteCoverageW(p, mem_ctx);
1684
1685         talloc_free(mem_ctx);
1686
1687         torture_leave_domain(join_ctx);
1688
1689         return ret;
1690 }