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