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