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