r12510: Change the DCE/RPC interfaces to take a pointer to a
[jelmer/samba4-debian.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 "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         r.in.computer_name              = talloc_asprintf(mem_ctx, "\\\\%s", computer_name);
1140         printf("Testing netr_DsRGetSiteName with broken computer name: %s\n", r.in.computer_name);
1141
1142         status = dcerpc_netr_DsRGetSiteName(p, mem_ctx, &r);
1143         if (!NT_STATUS_IS_OK(status)) {
1144                 printf("netr_DsRGetSiteName - %s\n", 
1145                        nt_errstr(status));
1146                 ret = False;
1147         } else if (!W_ERROR_EQUAL(r.out.result, WERR_INVALID_COMPUTERNAME)) {
1148                 printf("netr_DsRGetSiteName - incorrect error return %s, expected %s\n", 
1149                        win_errstr(r.out.result), win_errstr(WERR_INVALID_COMPUTERNAME));
1150                 ret = False;
1151         }
1152         return ret;
1153 }
1154
1155 /*
1156   try a netlogon netr_DsRGetDCName
1157 */
1158 static BOOL test_netr_DsRGetDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1159 {
1160         NTSTATUS status;
1161         struct netr_DsRGetDCName r;
1162         BOOL ret = True;
1163
1164         r.in.server_unc         = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1165         r.in.domain_name        = talloc_asprintf(mem_ctx, "%s", lp_realm());
1166         r.in.domain_guid        = NULL;
1167         r.in.site_guid          = NULL;
1168         r.in.flags              = 0x40000000;
1169
1170         printf("Testing netr_DsRGetDCName\n");
1171
1172         status = dcerpc_netr_DsRGetDCName(p, mem_ctx, &r);
1173         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1174                 printf("netr_DsRGetDCName - %s/%s\n", 
1175                        nt_errstr(status), win_errstr(r.out.result));
1176                 ret = False;
1177         } else {
1178                 ret = test_netr_DsRGetSiteName(p, mem_ctx, 
1179                                                r.out.info->dc_unc, 
1180                                                r.out.info->dc_site_name);
1181         }
1182
1183         return ret;
1184 }
1185
1186 /*
1187   try a netlogon netr_DsRGetDCNameEx
1188 */
1189 static BOOL test_netr_DsRGetDCNameEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1190 {
1191         NTSTATUS status;
1192         struct netr_DsRGetDCNameEx r;
1193         BOOL ret = True;
1194
1195         r.in.server_unc         = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1196         r.in.domain_name        = talloc_asprintf(mem_ctx, "%s", lp_realm());
1197         r.in.domain_guid        = NULL;
1198         r.in.site_name          = NULL;
1199         r.in.flags              = 0x40000000;
1200
1201         printf("Testing netr_DsRGetDCNameEx\n");
1202
1203         status = dcerpc_netr_DsRGetDCNameEx(p, mem_ctx, &r);
1204         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1205                 printf("netr_DsRGetDCNameEx - %s/%s\n", 
1206                        nt_errstr(status), win_errstr(r.out.result));
1207                 ret = False;
1208         } else {
1209                 ret = test_netr_DsRGetSiteName(p, mem_ctx, 
1210                                                r.out.info->dc_unc, 
1211                                                r.out.info->dc_site_name);
1212         }
1213
1214         return ret;
1215 }
1216
1217 /*
1218   try a netlogon netr_DsRGetDCNameEx2
1219 */
1220 static BOOL test_netr_DsRGetDCNameEx2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1221 {
1222         NTSTATUS status;
1223         struct netr_DsRGetDCNameEx2 r;
1224         BOOL ret = True;
1225
1226         r.in.server_unc         = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1227         r.in.client_account     = NULL;
1228         r.in.mask               = 0x00000000;
1229         r.in.domain_name        = talloc_asprintf(mem_ctx, "%s", lp_realm());
1230         r.in.domain_guid        = NULL;
1231         r.in.site_name          = NULL;
1232         r.in.flags              = 0x40000000;
1233
1234         printf("Testing netr_DsRGetDCNameEx2 without client account\n");
1235
1236         status = dcerpc_netr_DsRGetDCNameEx2(p, mem_ctx, &r);
1237         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1238                 printf("netr_DsRGetDCNameEx2 - %s/%s\n", 
1239                        nt_errstr(status), win_errstr(r.out.result));
1240                 ret = False;
1241         }
1242
1243         printf("Testing netr_DsRGetDCNameEx2 with client acount\n");
1244         r.in.client_account     = TEST_MACHINE_NAME"$";
1245         r.in.mask               = 0x00002000;
1246         r.in.flags              = 0x80000000;
1247
1248         status = dcerpc_netr_DsRGetDCNameEx2(p, mem_ctx, &r);
1249         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1250                 printf("netr_DsRGetDCNameEx2 - %s/%s\n", 
1251                        nt_errstr(status), win_errstr(r.out.result));
1252                 ret = False;
1253         } else {
1254                 ret = test_netr_DsRGetSiteName(p, mem_ctx, 
1255                                                r.out.info->dc_unc, 
1256                                                r.out.info->dc_site_name);
1257         }
1258
1259         return ret;
1260 }
1261
1262 static BOOL test_GetDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1263 {
1264         NTSTATUS status;
1265         struct netr_LogonGetDomainInfo r;
1266         struct netr_DomainQuery1 q1;
1267         struct netr_Authenticator a;
1268         struct creds_CredentialState *creds;
1269
1270         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
1271                                     TEST_MACHINE_NAME, machine_password, &creds)) {
1272                 return False;
1273         }
1274
1275         ZERO_STRUCT(r);
1276
1277         creds_client_authenticator(creds, &a);
1278
1279         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1280         r.in.computer_name = TEST_MACHINE_NAME;
1281         r.in.level = 1;
1282         r.in.credential = &a;
1283         r.in.return_authenticator = &a;
1284         r.out.return_authenticator = &a;
1285
1286         r.in.query.query1 = &q1;
1287         ZERO_STRUCT(q1);
1288         
1289         /* this should really be the fully qualified name */
1290         q1.workstation_domain = TEST_MACHINE_NAME;
1291         q1.workstation_site = "Default-First-Site-Name";
1292         q1.blob2.length = 0;
1293         q1.blob2.size = 0;
1294         q1.blob2.data = NULL;
1295         q1.product.string = "product string";
1296
1297         printf("Testing netr_LogonGetDomainInfo\n");
1298
1299         status = dcerpc_netr_LogonGetDomainInfo(p, mem_ctx, &r);
1300         if (!NT_STATUS_IS_OK(status)) {
1301                 printf("netr_LogonGetDomainInfo - %s\n", nt_errstr(status));
1302                 return False;
1303         }
1304
1305         if (!creds_client_check(creds, &a.cred)) {
1306                 printf("Credential chaining failed\n");
1307                 return False;
1308         }
1309
1310         return True;
1311 }
1312
1313
1314 static void async_callback(struct rpc_request *req)
1315 {
1316         int *counter = req->async.private;
1317         if (NT_STATUS_IS_OK(req->status)) {
1318                 (*counter)++;
1319         }
1320 }
1321
1322 static BOOL test_GetDomainInfo_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1323 {
1324         NTSTATUS status;
1325         struct netr_LogonGetDomainInfo r;
1326         struct netr_DomainQuery1 q1;
1327         struct netr_Authenticator a;
1328 #define ASYNC_COUNT 100
1329         struct creds_CredentialState *creds;
1330         struct creds_CredentialState *creds_async[ASYNC_COUNT];
1331         struct rpc_request *req[ASYNC_COUNT];
1332         int i;
1333         int *async_counter = talloc(mem_ctx, int);
1334
1335         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
1336                 printf("test_GetDomainInfo_async disabled - enable dangerous tests to use\n");
1337                 return True;
1338         }
1339
1340         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
1341                                     TEST_MACHINE_NAME, machine_password, &creds)) {
1342                 return False;
1343         }
1344
1345         ZERO_STRUCT(r);
1346         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1347         r.in.computer_name = TEST_MACHINE_NAME;
1348         r.in.level = 1;
1349         r.in.credential = &a;
1350         r.in.return_authenticator = &a;
1351         r.out.return_authenticator = &a;
1352
1353         r.in.query.query1 = &q1;
1354         ZERO_STRUCT(q1);
1355         
1356         /* this should really be the fully qualified name */
1357         q1.workstation_domain = TEST_MACHINE_NAME;
1358         q1.workstation_site = "Default-First-Site-Name";
1359         q1.blob2.length = 0;
1360         q1.blob2.size = 0;
1361         q1.blob2.data = NULL;
1362         q1.product.string = "product string";
1363
1364         printf("Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT);
1365
1366         *async_counter = 0;
1367
1368         for (i=0;i<ASYNC_COUNT;i++) {
1369                 creds_client_authenticator(creds, &a);
1370
1371                 creds_async[i] = talloc_memdup(creds, creds, sizeof(*creds));
1372                 req[i] = dcerpc_netr_LogonGetDomainInfo_send(p, mem_ctx, &r);
1373
1374                 req[i]->async.callback = async_callback;
1375                 req[i]->async.private = async_counter;
1376
1377                 /* even with this flush per request a w2k3 server seems to 
1378                    clag with multiple outstanding requests. bleergh. */
1379                 if (event_loop_once(dcerpc_event_context(p)) != 0) {
1380                         return False;
1381                 }
1382         }
1383
1384         for (i=0;i<ASYNC_COUNT;i++) {
1385                 status = dcerpc_ndr_request_recv(req[i]);
1386                 if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(r.out.result)) {
1387                         printf("netr_LogonGetDomainInfo_async(%d) - %s/%s\n", 
1388                                i, nt_errstr(status), nt_errstr(r.out.result));
1389                         break;
1390                 }
1391
1392                 if (!creds_client_check(creds_async[i], &a.cred)) {
1393                         printf("Credential chaining failed at async %d\n", i);
1394                         break;
1395                 }
1396         }
1397
1398         printf("Testing netr_LogonGetDomainInfo - async count %d OK\n", *async_counter);
1399
1400         return (*async_counter) == ASYNC_COUNT;
1401 }
1402
1403 static BOOL test_ManyGetDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1404 {
1405         NTSTATUS status;
1406         struct dcerpc_binding *b;
1407         struct dcerpc_pipe *p2;
1408         struct lsa_ObjectAttribute attr;
1409         struct lsa_QosInfo qos;
1410         struct lsa_OpenPolicy2 o;
1411         struct policy_handle lsa_handle;
1412         struct lsa_DomainList domains;
1413
1414         struct lsa_EnumTrustDom t;
1415         uint32_t resume_handle = 0;
1416         struct netr_GetAnyDCName d;
1417
1418         int i;
1419         BOOL ret = True;
1420
1421         if (p->conn->transport.transport != NCACN_NP) {
1422                 return True;
1423         }
1424
1425         printf("Torturing GetDCName\n");
1426
1427         status = dcerpc_parse_binding(mem_ctx, p->conn->binding_string, &b);
1428         if (!NT_STATUS_IS_OK(status)) {
1429                 printf("Failed to parse dcerpc binding '%s'\n", p->conn->binding_string);
1430                 return False;
1431         }
1432
1433         status = dcerpc_secondary_connection(p, &p2, b);
1434         if (!NT_STATUS_IS_OK(status)) {
1435                 printf("Failed to create secondary connection\n");
1436                 return False;
1437         }
1438
1439         status = dcerpc_bind_auth_none(p2, &dcerpc_table_lsarpc);
1440         if (!NT_STATUS_IS_OK(status)) {
1441                 printf("Failed to create bind on secondary connection\n");
1442                 return False;
1443         }
1444
1445         qos.len = 0;
1446         qos.impersonation_level = 2;
1447         qos.context_mode = 1;
1448         qos.effective_only = 0;
1449
1450         attr.len = 0;
1451         attr.root_dir = NULL;
1452         attr.object_name = NULL;
1453         attr.attributes = 0;
1454         attr.sec_desc = NULL;
1455         attr.sec_qos = &qos;
1456
1457         o.in.system_name = "\\";
1458         o.in.attr = &attr;
1459         o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1460         o.out.handle = &lsa_handle;
1461
1462         status = dcerpc_lsa_OpenPolicy2(p2, mem_ctx, &o);
1463         if (!NT_STATUS_IS_OK(status)) {
1464                 printf("OpenPolicy2 failed - %s\n", nt_errstr(status));
1465                 return False;
1466         }
1467
1468         t.in.handle = &lsa_handle;
1469         t.in.resume_handle = &resume_handle;
1470         t.in.max_size = 1000;
1471         t.out.domains = &domains;
1472         t.out.resume_handle = &resume_handle;
1473
1474         status = dcerpc_lsa_EnumTrustDom(p2, mem_ctx, &t);
1475
1476         if ((!NT_STATUS_IS_OK(status) &&
1477              (!NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)))) {
1478                 printf("Could not list domains\n");
1479                 return False;
1480         }
1481
1482         talloc_free(p2);
1483
1484         d.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s",
1485                                             dcerpc_server_name(p));
1486
1487         for (i=0; i<domains.count * 4; i++) {
1488                 struct lsa_DomainInformation *info =
1489                         &domains.domains[rand()%domains.count];
1490
1491                 d.in.domainname = info->name.string;
1492
1493                 status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &d);
1494                 if (!NT_STATUS_IS_OK(status)) {
1495                         printf("GetAnyDCName - %s\n", nt_errstr(status));
1496                         continue;
1497                 }
1498
1499                 printf("\tDC for domain %s is %s\n", info->name.string,
1500                        d.out.dcname ? d.out.dcname : "unknown");
1501         }
1502
1503         return ret;
1504 }
1505
1506
1507 BOOL torture_rpc_netlogon(void)
1508 {
1509         NTSTATUS status;
1510         struct dcerpc_pipe *p;
1511         TALLOC_CTX *mem_ctx;
1512         BOOL ret = True;
1513         struct test_join *join_ctx;
1514         struct cli_credentials *machine_credentials;
1515
1516         mem_ctx = talloc_init("torture_rpc_netlogon");
1517
1518         join_ctx = torture_join_domain(TEST_MACHINE_NAME, ACB_SVRTRUST, 
1519                                        &machine_credentials);
1520         if (!join_ctx) {
1521                 talloc_free(mem_ctx);
1522                 printf("Failed to join as BDC\n");
1523                 return False;
1524         }
1525
1526         machine_password = cli_credentials_get_password(machine_credentials);
1527
1528         status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_netlogon);
1529         if (!NT_STATUS_IS_OK(status)) {
1530                 talloc_free(mem_ctx);
1531                 return False;
1532         }
1533
1534         ret &= test_LogonUasLogon(p, mem_ctx);
1535         ret &= test_LogonUasLogoff(p, mem_ctx);
1536         ret &= test_SamLogon(p, mem_ctx, machine_credentials);
1537         ret &= test_SetPassword(p, mem_ctx);
1538         ret &= test_SetPassword2(p, mem_ctx);
1539         ret &= test_GetDomainInfo(p, mem_ctx);
1540         ret &= test_DatabaseSync(p, mem_ctx);
1541         ret &= test_DatabaseDeltas(p, mem_ctx);
1542         ret &= test_AccountDeltas(p, mem_ctx);
1543         ret &= test_AccountSync(p, mem_ctx);
1544         ret &= test_GetDcName(p, mem_ctx);
1545         ret &= test_ManyGetDCName(p, mem_ctx);
1546         ret &= test_LogonControl(p, mem_ctx);
1547         ret &= test_GetAnyDCName(p, mem_ctx);
1548         ret &= test_LogonControl2(p, mem_ctx);
1549         ret &= test_DatabaseSync2(p, mem_ctx);
1550         ret &= test_LogonControl2Ex(p, mem_ctx);
1551         ret &= test_DsrEnumerateDomainTrusts(p, mem_ctx);
1552         ret &= test_GetDomainInfo_async(p, mem_ctx);
1553         ret &= test_netr_DsRGetDCName(p, mem_ctx);
1554         ret &= test_netr_DsRGetDCNameEx(p, mem_ctx);
1555         ret &= test_netr_DsRGetDCNameEx2(p, mem_ctx);
1556
1557         talloc_free(mem_ctx);
1558
1559         torture_leave_domain(join_ctx);
1560
1561         return ret;
1562 }