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