5b92ce138261643b4a3547c15b556ce09ba7ab28
[metze/samba/wip.git] / source / torture / rpc / netlogon.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    test suite for netlogon rpc operations
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
8    Copyright (C) Tim Potter      2003
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 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 static bool test_GetPassword(struct torture_context *tctx,
442                              struct dcerpc_pipe *p,
443                              struct cli_credentials *machine_credentials)
444 {
445         struct netr_ServerPasswordGet r;
446         struct creds_CredentialState *creds;
447         struct netr_Authenticator credential;
448         NTSTATUS status;
449         struct netr_Authenticator return_authenticator;
450         struct samr_Password password;
451
452         if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
453                 return false;
454         }
455
456         creds_client_authenticator(creds, &credential);
457
458         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
459         r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
460         r.in.secure_channel_type = SEC_CHAN_BDC;
461         r.in.computer_name = TEST_MACHINE_NAME;
462         r.in.credential = &credential;
463         r.out.return_authenticator = &return_authenticator;
464         r.out.password = &password;
465
466         status = dcerpc_netr_ServerPasswordGet(p, tctx, &r);
467         torture_assert_ntstatus_ok(tctx, status, "ServerPasswordGet");
468
469         return true;
470 }
471
472 static bool test_GetTrustPasswords(struct torture_context *tctx,
473                                    struct dcerpc_pipe *p,
474                                    struct cli_credentials *machine_credentials)
475 {
476         struct netr_ServerTrustPasswordsGet r;
477         struct creds_CredentialState *creds;
478         struct netr_Authenticator credential;
479         NTSTATUS status;
480         struct netr_Authenticator return_authenticator;
481         struct samr_Password password, password2;
482
483         if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
484                 return false;
485         }
486
487         creds_client_authenticator(creds, &credential);
488
489         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
490         r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
491         r.in.secure_channel_type = SEC_CHAN_BDC;
492         r.in.computer_name = TEST_MACHINE_NAME;
493         r.in.credential = &credential;
494         r.out.return_authenticator = &return_authenticator;
495         r.out.password = &password;
496         r.out.password2 = &password2;
497
498         status = dcerpc_netr_ServerTrustPasswordsGet(p, tctx, &r);
499         torture_assert_ntstatus_ok(tctx, status, "ServerTrustPasswordsGet");
500
501         return true;
502 }
503
504 /*
505   try a netlogon SamLogon
506 */
507 bool test_netlogon_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
508                               struct cli_credentials *credentials, 
509                               struct creds_CredentialState *creds)
510 {
511         NTSTATUS status;
512         struct netr_LogonSamLogon r;
513         struct netr_Authenticator auth, auth2;
514         struct netr_NetworkInfo ninfo;
515         DATA_BLOB names_blob, chal, lm_resp, nt_resp;
516         int i;
517         int flags = CLI_CRED_NTLM_AUTH;
518         if (lp_client_lanman_auth(tctx->lp_ctx)) {
519                 flags |= CLI_CRED_LANMAN_AUTH;
520         }
521
522         if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
523                 flags |= CLI_CRED_NTLMv2_AUTH;
524         }
525
526         cli_credentials_get_ntlm_username_domain(cmdline_credentials, tctx, 
527                                                  &ninfo.identity_info.account_name.string,
528                                                  &ninfo.identity_info.domain_name.string);
529         
530         generate_random_buffer(ninfo.challenge, 
531                                sizeof(ninfo.challenge));
532         chal = data_blob_const(ninfo.challenge, 
533                                sizeof(ninfo.challenge));
534
535         names_blob = NTLMv2_generate_names_blob(tctx, lp_iconv_convenience(tctx->lp_ctx), cli_credentials_get_workstation(credentials), 
536                                                 cli_credentials_get_domain(credentials));
537
538         status = cli_credentials_get_ntlm_response(cmdline_credentials, tctx, 
539                                                    &flags, 
540                                                    chal,
541                                                    names_blob,
542                                                    &lm_resp, &nt_resp,
543                                                    NULL, NULL);
544         torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
545
546         ninfo.lm.data = lm_resp.data;
547         ninfo.lm.length = lm_resp.length;
548
549         ninfo.nt.data = nt_resp.data;
550         ninfo.nt.length = nt_resp.length;
551
552         ninfo.identity_info.parameter_control = 0;
553         ninfo.identity_info.logon_id_low = 0;
554         ninfo.identity_info.logon_id_high = 0;
555         ninfo.identity_info.workstation.string = cli_credentials_get_workstation(credentials);
556
557         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
558         r.in.computer_name = cli_credentials_get_workstation(credentials);
559         r.in.credential = &auth;
560         r.in.return_authenticator = &auth2;
561         r.in.logon_level = 2;
562         r.in.logon.network = &ninfo;
563
564         d_printf("Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
565         
566         for (i=2;i<3;i++) {
567                 ZERO_STRUCT(auth2);
568                 creds_client_authenticator(creds, &auth);
569                 
570                 r.in.validation_level = i;
571                 
572                 status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
573                 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
574                 
575                 torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), 
576                         "Credential chaining failed");
577         }
578
579         r.in.credential = NULL;
580
581         for (i=2;i<=3;i++) {
582
583                 r.in.validation_level = i;
584
585                 torture_comment(tctx, "Testing SamLogon with validation level %d and a NULL credential\n", i);
586
587                 status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
588                 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, 
589                         "LogonSamLogon expected INVALID_PARAMETER");
590
591         }
592
593         return true;
594 }
595
596 /*
597   try a netlogon SamLogon
598 */
599 static bool test_SamLogon(struct torture_context *tctx, 
600                           struct dcerpc_pipe *p,
601                           struct cli_credentials *credentials)
602 {
603         struct creds_CredentialState *creds;
604
605         if (!test_SetupCredentials(p, tctx, credentials, &creds)) {
606                 return false;
607         }
608
609         return test_netlogon_ops(p, tctx, credentials, creds);
610 }
611
612 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
613 static uint64_t sequence_nums[3];
614
615 /*
616   try a netlogon DatabaseSync
617 */
618 static bool test_DatabaseSync(struct torture_context *tctx, 
619                               struct dcerpc_pipe *p,
620                               struct cli_credentials *machine_credentials)
621 {
622         NTSTATUS status;
623         struct netr_DatabaseSync r;
624         struct creds_CredentialState *creds;
625         const uint32_t database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS}; 
626         int i;
627
628         if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
629                 return false;
630         }
631
632         r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
633         r.in.computername = TEST_MACHINE_NAME;
634         r.in.preferredmaximumlength = (uint32_t)-1;
635         ZERO_STRUCT(r.in.return_authenticator);
636
637         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
638                 r.in.sync_context = 0;
639                 r.in.database_id = database_ids[i];
640
641                 torture_comment(tctx, "Testing DatabaseSync of id %d\n", r.in.database_id);
642
643                 do {
644                         creds_client_authenticator(creds, &r.in.credential);
645
646                         status = dcerpc_netr_DatabaseSync(p, tctx, &r);
647                         if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
648                             break;
649
650                         /* Native mode servers don't do this */
651                         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
652                                 return true;
653                         }
654                         torture_assert_ntstatus_ok(tctx, status, "DatabaseSync");
655
656                         if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
657                                 torture_comment(tctx, "Credential chaining failed\n");
658                         }
659
660                         r.in.sync_context = r.out.sync_context;
661
662                         if (r.out.delta_enum_array &&
663                             r.out.delta_enum_array->num_deltas > 0 &&
664                             r.out.delta_enum_array->delta_enum[0].delta_type == NETR_DELTA_DOMAIN &&
665                             r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
666                                 sequence_nums[r.in.database_id] = 
667                                         r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
668                                 torture_comment(tctx, "\tsequence_nums[%d]=%llu\n",
669                                        r.in.database_id, 
670                                        (unsigned long long)sequence_nums[r.in.database_id]);
671                         }
672                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
673         }
674
675         return true;
676 }
677
678
679 /*
680   try a netlogon DatabaseDeltas
681 */
682 static bool test_DatabaseDeltas(struct torture_context *tctx, 
683                                 struct dcerpc_pipe *p,
684                                 struct cli_credentials *machine_credentials)
685 {
686         NTSTATUS status;
687         struct netr_DatabaseDeltas r;
688         struct creds_CredentialState *creds;
689         const uint32_t database_ids[] = {0, 1, 2}; 
690         int i;
691
692         if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
693                 return false;
694         }
695
696         r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
697         r.in.computername = TEST_MACHINE_NAME;
698         r.in.preferredmaximumlength = (uint32_t)-1;
699         ZERO_STRUCT(r.in.return_authenticator);
700
701         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
702                 r.in.database_id = database_ids[i];
703                 r.in.sequence_num = sequence_nums[r.in.database_id];
704
705                 if (r.in.sequence_num == 0) continue;
706
707                 r.in.sequence_num -= 1;
708
709                 torture_comment(tctx, "Testing DatabaseDeltas of id %d at %llu\n", 
710                        r.in.database_id, (unsigned long long)r.in.sequence_num);
711
712                 do {
713                         creds_client_authenticator(creds, &r.in.credential);
714
715                         status = dcerpc_netr_DatabaseDeltas(p, tctx, &r);
716                         if (NT_STATUS_EQUAL(status, 
717                                              NT_STATUS_SYNCHRONIZATION_REQUIRED)) {
718                                 torture_comment(tctx, "not considering %s to be an error\n",
719                                        nt_errstr(status));
720                                 return true;
721                         }
722                         if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) 
723                             break;
724
725                         torture_assert_ntstatus_ok(tctx, status, "DatabaseDeltas");
726
727                         if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
728                                 torture_comment(tctx, "Credential chaining failed\n");
729                         }
730
731                         r.in.sequence_num++;
732                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
733         }
734
735         return true;
736 }
737
738
739 /*
740   try a netlogon AccountDeltas
741 */
742 static bool test_AccountDeltas(struct torture_context *tctx, 
743                                struct dcerpc_pipe *p,
744                                struct cli_credentials *machine_credentials)
745 {
746         NTSTATUS status;
747         struct netr_AccountDeltas r;
748         struct creds_CredentialState *creds;
749
750         if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
751                 return false;
752         }
753
754         r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
755         r.in.computername = TEST_MACHINE_NAME;
756         ZERO_STRUCT(r.in.return_authenticator);
757         creds_client_authenticator(creds, &r.in.credential);
758         ZERO_STRUCT(r.in.uas);
759         r.in.count=10;
760         r.in.level=0;
761         r.in.buffersize=100;
762
763         /* w2k3 returns "NOT IMPLEMENTED" for this call */
764         status = dcerpc_netr_AccountDeltas(p, tctx, &r);
765         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "AccountDeltas");
766
767         return true;
768 }
769
770 /*
771   try a netlogon AccountSync
772 */
773 static bool test_AccountSync(struct torture_context *tctx, struct dcerpc_pipe *p, 
774                              struct cli_credentials *machine_credentials)
775 {
776         NTSTATUS status;
777         struct netr_AccountSync r;
778         struct creds_CredentialState *creds;
779
780         if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
781                 return false;
782         }
783
784         r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
785         r.in.computername = TEST_MACHINE_NAME;
786         ZERO_STRUCT(r.in.return_authenticator);
787         creds_client_authenticator(creds, &r.in.credential);
788         ZERO_STRUCT(r.in.recordid);
789         r.in.reference=0;
790         r.in.level=0;
791         r.in.buffersize=100;
792
793         /* w2k3 returns "NOT IMPLEMENTED" for this call */
794         status = dcerpc_netr_AccountSync(p, tctx, &r);
795         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "AccountSync");
796
797         return true;
798 }
799
800 /*
801   try a netlogon GetDcName
802 */
803 static bool test_GetDcName(struct torture_context *tctx, 
804                            struct dcerpc_pipe *p)
805 {
806         NTSTATUS status;
807         struct netr_GetDcName r;
808
809         r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
810         r.in.domainname = lp_workgroup(tctx->lp_ctx);
811
812         status = dcerpc_netr_GetDcName(p, tctx, &r);
813         torture_assert_ntstatus_ok(tctx, status, "GetDcName");
814         torture_assert_werr_ok(tctx, r.out.result, "GetDcName");
815
816         torture_comment(tctx, "\tDC is at '%s'\n", r.out.dcname);
817
818         return true;
819 }
820
821 /*
822   try a netlogon LogonControl 
823 */
824 static bool test_LogonControl(struct torture_context *tctx, 
825                               struct dcerpc_pipe *p)
826 {
827         NTSTATUS status;
828         struct netr_LogonControl r;
829         int i;
830
831         r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
832         r.in.function_code = 1;
833
834         for (i=1;i<4;i++) {
835                 r.in.level = i;
836
837                 torture_comment(tctx, "Testing LogonControl level %d\n", i);
838
839                 status = dcerpc_netr_LogonControl(p, tctx, &r);
840                 torture_assert_ntstatus_ok(tctx, status, "LogonControl");
841         }
842
843         return true;
844 }
845
846
847 /*
848   try a netlogon GetAnyDCName
849 */
850 static bool test_GetAnyDCName(struct torture_context *tctx, 
851                               struct dcerpc_pipe *p)
852 {
853         NTSTATUS status;
854         struct netr_GetAnyDCName r;
855
856         r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
857         r.in.domainname = lp_workgroup(tctx->lp_ctx);
858
859         status = dcerpc_netr_GetAnyDCName(p, tctx, &r);
860         torture_assert_ntstatus_ok(tctx, status, "GetAnyDCName");
861
862         if (r.out.dcname) {
863             torture_comment(tctx, "\tDC is at '%s'\n", r.out.dcname);
864         }
865
866         return true;
867 }
868
869
870 /*
871   try a netlogon LogonControl2
872 */
873 static bool test_LogonControl2(struct torture_context *tctx, 
874                                struct dcerpc_pipe *p)
875 {
876         NTSTATUS status;
877         struct netr_LogonControl2 r;
878         int i;
879
880         r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
881
882         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
883         r.in.data.domain = lp_workgroup(tctx->lp_ctx);
884
885         for (i=1;i<4;i++) {
886                 r.in.level = i;
887
888                 torture_comment(tctx, "Testing LogonControl2 level %d function %d\n", 
889                        i, r.in.function_code);
890
891                 status = dcerpc_netr_LogonControl2(p, tctx, &r);
892                 torture_assert_ntstatus_ok(tctx, status, "LogonControl");
893         }
894
895         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
896         r.in.data.domain = lp_workgroup(tctx->lp_ctx);
897
898         for (i=1;i<4;i++) {
899                 r.in.level = i;
900
901                 torture_comment(tctx, "Testing LogonControl2 level %d function %d\n", 
902                        i, r.in.function_code);
903
904                 status = dcerpc_netr_LogonControl2(p, tctx, &r);
905                 torture_assert_ntstatus_ok(tctx, status, "LogonControl");
906         }
907
908         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
909         r.in.data.domain = lp_workgroup(tctx->lp_ctx);
910
911         for (i=1;i<4;i++) {
912                 r.in.level = i;
913
914                 torture_comment(tctx, "Testing LogonControl2 level %d function %d\n", 
915                        i, r.in.function_code);
916
917                 status = dcerpc_netr_LogonControl2(p, tctx, &r);
918                 torture_assert_ntstatus_ok(tctx, status, "LogonControl");
919         }
920
921         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
922         r.in.data.debug_level = ~0;
923
924         for (i=1;i<4;i++) {
925                 r.in.level = i;
926
927                 torture_comment(tctx, "Testing LogonControl2 level %d function %d\n", 
928                        i, r.in.function_code);
929
930                 status = dcerpc_netr_LogonControl2(p, tctx, &r);
931                 torture_assert_ntstatus_ok(tctx, status, "LogonControl");
932         }
933
934         return true;
935 }
936
937 /*
938   try a netlogon DatabaseSync2
939 */
940 static bool test_DatabaseSync2(struct torture_context *tctx, 
941                                struct dcerpc_pipe *p,
942                                struct cli_credentials *machine_credentials)
943 {
944         NTSTATUS status;
945         struct netr_DatabaseSync2 r;
946         struct creds_CredentialState *creds;
947         const uint32_t database_ids[] = {0, 1, 2}; 
948         int i;
949
950         if (!test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_FLAGS, 
951                                     machine_credentials,
952                                     SEC_CHAN_BDC, &creds)) {
953                 return false;
954         }
955
956         r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
957         r.in.computername = TEST_MACHINE_NAME;
958         r.in.preferredmaximumlength = (uint32_t)-1;
959         ZERO_STRUCT(r.in.return_authenticator);
960
961         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
962                 r.in.sync_context = 0;
963                 r.in.database_id = database_ids[i];
964                 r.in.restart_state = 0;
965
966                 torture_comment(tctx, "Testing DatabaseSync2 of id %d\n", r.in.database_id);
967
968                 do {
969                         creds_client_authenticator(creds, &r.in.credential);
970
971                         status = dcerpc_netr_DatabaseSync2(p, tctx, &r);
972                         if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
973                             break;
974
975                         /* Native mode servers don't do this */
976                         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
977                                 return true;
978                         }
979
980                         torture_assert_ntstatus_ok(tctx, status, "DatabaseSync2");
981
982                         if (!creds_client_check(creds, &r.out.return_authenticator.cred)) {
983                                 torture_comment(tctx, "Credential chaining failed\n");
984                         }
985
986                         r.in.sync_context = r.out.sync_context;
987                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
988         }
989
990         return true;
991 }
992
993
994 /*
995   try a netlogon LogonControl2Ex
996 */
997 static bool test_LogonControl2Ex(struct torture_context *tctx, 
998                                  struct dcerpc_pipe *p)
999 {
1000         NTSTATUS status;
1001         struct netr_LogonControl2Ex r;
1002         int i;
1003
1004         r.in.logon_server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1005
1006         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1007         r.in.data.domain = lp_workgroup(tctx->lp_ctx);
1008
1009         for (i=1;i<4;i++) {
1010                 r.in.level = i;
1011
1012                 torture_comment(tctx, "Testing LogonControl2Ex level %d function %d\n", 
1013                        i, r.in.function_code);
1014
1015                 status = dcerpc_netr_LogonControl2Ex(p, tctx, &r);
1016                 torture_assert_ntstatus_ok(tctx, status, "LogonControl");
1017         }
1018
1019         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1020         r.in.data.domain = lp_workgroup(tctx->lp_ctx);
1021
1022         for (i=1;i<4;i++) {
1023                 r.in.level = i;
1024
1025                 torture_comment(tctx, "Testing LogonControl2Ex level %d function %d\n", 
1026                        i, r.in.function_code);
1027
1028                 status = dcerpc_netr_LogonControl2Ex(p, tctx, &r);
1029                 torture_assert_ntstatus_ok(tctx, status, "LogonControl");
1030         }
1031
1032         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1033         r.in.data.domain = lp_workgroup(tctx->lp_ctx);
1034
1035         for (i=1;i<4;i++) {
1036                 r.in.level = i;
1037
1038                 torture_comment(tctx, "Testing LogonControl2Ex level %d function %d\n", 
1039                        i, r.in.function_code);
1040
1041                 status = dcerpc_netr_LogonControl2Ex(p, tctx, &r);
1042                 torture_assert_ntstatus_ok(tctx, status, "LogonControl");
1043         }
1044
1045         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1046         r.in.data.debug_level = ~0;
1047
1048         for (i=1;i<4;i++) {
1049                 r.in.level = i;
1050
1051                 torture_comment(tctx, "Testing LogonControl2Ex level %d function %d\n", 
1052                        i, r.in.function_code);
1053
1054                 status = dcerpc_netr_LogonControl2Ex(p, tctx, &r);
1055                 torture_assert_ntstatus_ok(tctx, status, "LogonControl");
1056         }
1057
1058         return true;
1059 }
1060
1061 static bool test_netr_DsRGetForestTrustInformation(struct torture_context *tctx, 
1062                                                    struct dcerpc_pipe *p, const char *trusted_domain_name) 
1063 {
1064         NTSTATUS status;
1065         struct netr_DsRGetForestTrustInformation r;
1066         struct lsa_ForestTrustInformation info, *info_ptr;
1067
1068         info_ptr = &info;
1069
1070         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1071         r.in.trusted_domain_name = trusted_domain_name;
1072         r.in.flags = 0;
1073         r.out.forest_trust_info = &info_ptr;
1074
1075         torture_comment(tctx ,"Testing netr_DsRGetForestTrustInformation\n");
1076
1077         status = dcerpc_netr_DsRGetForestTrustInformation(p, tctx, &r);
1078         torture_assert_ntstatus_ok(tctx, status, "DsRGetForestTrustInformation");
1079         torture_assert_werr_ok(tctx, r.out.result, "DsRGetForestTrustInformation");
1080
1081         return true;
1082 }
1083
1084 /*
1085   try a netlogon netr_DsrEnumerateDomainTrusts
1086 */
1087 static bool test_DsrEnumerateDomainTrusts(struct torture_context *tctx, 
1088                                           struct dcerpc_pipe *p)
1089 {
1090         NTSTATUS status;
1091         struct netr_DsrEnumerateDomainTrusts r;
1092         int i;
1093
1094         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1095         r.in.trust_flags = 0x3f;
1096
1097         status = dcerpc_netr_DsrEnumerateDomainTrusts(p, tctx, &r);
1098         torture_assert_ntstatus_ok(tctx, status, "DsrEnumerateDomaintrusts");
1099         torture_assert_werr_ok(tctx, r.out.result, "DsrEnumerateDomaintrusts");
1100
1101         /* when trusted_domain_name is NULL, netr_DsRGetForestTrustInformation
1102          * will show non-forest trusts and all UPN suffixes of the own forest
1103          * as LSA_FOREST_TRUST_TOP_LEVEL_NAME types */
1104
1105         if (r.out.count) {
1106                 if (!test_netr_DsRGetForestTrustInformation(tctx, p, NULL)) {
1107                         return false;
1108                 }
1109         }
1110
1111         for (i=0; i<r.out.count; i++) {
1112
1113                 /* get info for transitive forest trusts */
1114
1115                 if (r.out.trusts[i].trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1116                         if (!test_netr_DsRGetForestTrustInformation(tctx, p, 
1117                                                                     r.out.trusts[i].dns_name)) {
1118                                 return false;
1119                         }
1120                 }
1121         }
1122
1123         return true;
1124 }
1125
1126 static bool test_netr_NetrEnumerateTrustedDomains(struct torture_context *tctx,
1127                                                   struct dcerpc_pipe *p)
1128 {
1129         NTSTATUS status;
1130         struct netr_NetrEnumerateTrustedDomains r;
1131         struct netr_Blob trusted_domains_blob;
1132
1133         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1134         r.out.trusted_domains_blob = &trusted_domains_blob;
1135
1136         status = dcerpc_netr_NetrEnumerateTrustedDomains(p, tctx, &r);
1137         torture_assert_ntstatus_ok(tctx, status, "netr_NetrEnumerateTrustedDomains");
1138         torture_assert_werr_ok(tctx, r.out.result, "NetrEnumerateTrustedDomains");
1139
1140         return true;
1141 }
1142
1143 static bool test_netr_NetrEnumerateTrustedDomainsEx(struct torture_context *tctx,
1144                                                     struct dcerpc_pipe *p)
1145 {
1146         NTSTATUS status;
1147         struct netr_NetrEnumerateTrustedDomainsEx r;
1148         struct netr_DomainTrustList dom_trust_list;
1149
1150         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1151         r.out.dom_trust_list = &dom_trust_list;
1152
1153         status = dcerpc_netr_NetrEnumerateTrustedDomainsEx(p, tctx, &r);
1154         torture_assert_ntstatus_ok(tctx, status, "netr_NetrEnumerateTrustedDomainsEx");
1155         torture_assert_werr_ok(tctx, r.out.result, "NetrEnumerateTrustedDomainsEx");
1156
1157         return true;
1158 }
1159
1160
1161 static bool test_netr_DsRGetSiteName(struct dcerpc_pipe *p, struct torture_context *tctx,
1162                                      const char *computer_name, 
1163                                      const char *expected_site) 
1164 {
1165         NTSTATUS status;
1166         struct netr_DsRGetSiteName r;
1167
1168         if (torture_setting_bool(tctx, "samba4", false))
1169                 torture_skip(tctx, "skipping DsRGetSiteName test against Samba4");
1170
1171         r.in.computer_name              = computer_name;
1172         torture_comment(tctx, "Testing netr_DsRGetSiteName\n");
1173
1174         status = dcerpc_netr_DsRGetSiteName(p, tctx, &r);
1175         torture_assert_ntstatus_ok(tctx, status, "DsRGetSiteName");
1176         torture_assert_werr_ok(tctx, r.out.result, "DsRGetSiteName");
1177         torture_assert_str_equal(tctx, expected_site, r.out.site, "netr_DsRGetSiteName");
1178
1179         r.in.computer_name              = talloc_asprintf(tctx, "\\\\%s", computer_name);
1180         torture_comment(tctx, 
1181                         "Testing netr_DsRGetSiteName with broken computer name: %s\n", r.in.computer_name);
1182
1183         status = dcerpc_netr_DsRGetSiteName(p, tctx, &r);
1184         torture_assert_ntstatus_ok(tctx, status, "DsRGetSiteName");
1185         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_COMPUTERNAME, "netr_DsRGetSiteName");
1186
1187         return true;
1188 }
1189
1190 /*
1191   try a netlogon netr_DsRGetDCName
1192 */
1193 static bool test_netr_DsRGetDCName(struct torture_context *tctx, 
1194                                    struct dcerpc_pipe *p)
1195 {
1196         NTSTATUS status;
1197         struct netr_DsRGetDCName r;
1198
1199         r.in.server_unc         = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1200         r.in.domain_name        = talloc_asprintf(tctx, "%s", lp_realm(tctx->lp_ctx));
1201         r.in.domain_guid        = NULL;
1202         r.in.site_guid          = NULL;
1203         r.in.flags              = DS_RETURN_DNS_NAME;
1204
1205         status = dcerpc_netr_DsRGetDCName(p, tctx, &r);
1206         torture_assert_ntstatus_ok(tctx, status, "DsRGetDCName");
1207         torture_assert_werr_ok(tctx, r.out.result, "DsRGetDCName");
1208         return test_netr_DsRGetSiteName(p, tctx, 
1209                                        r.out.info->dc_unc, 
1210                                        r.out.info->dc_site_name);
1211 }
1212
1213 /*
1214   try a netlogon netr_DsRGetDCNameEx
1215 */
1216 static bool test_netr_DsRGetDCNameEx(struct torture_context *tctx, 
1217                                      struct dcerpc_pipe *p)
1218 {
1219         NTSTATUS status;
1220         struct netr_DsRGetDCNameEx r;
1221
1222         r.in.server_unc         = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1223         r.in.domain_name        = talloc_asprintf(tctx, "%s", lp_realm(tctx->lp_ctx));
1224         r.in.domain_guid        = NULL;
1225         r.in.site_name          = NULL;
1226         r.in.flags              = DS_RETURN_DNS_NAME;
1227
1228         status = dcerpc_netr_DsRGetDCNameEx(p, tctx, &r);
1229         torture_assert_ntstatus_ok(tctx, status, "netr_DsRGetDCNameEx");
1230         torture_assert_werr_ok(tctx, r.out.result, "netr_DsRGetDCNameEx");
1231
1232         return test_netr_DsRGetSiteName(p, tctx, r.out.info->dc_unc, 
1233                                        r.out.info->dc_site_name);
1234 }
1235
1236 /*
1237   try a netlogon netr_DsRGetDCNameEx2
1238 */
1239 static bool test_netr_DsRGetDCNameEx2(struct torture_context *tctx, 
1240                                       struct dcerpc_pipe *p)
1241 {
1242         NTSTATUS status;
1243         struct netr_DsRGetDCNameEx2 r;
1244
1245         r.in.server_unc         = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1246         r.in.client_account     = NULL;
1247         r.in.mask               = 0x00000000;
1248         r.in.domain_name        = talloc_asprintf(tctx, "%s", lp_realm(tctx->lp_ctx));
1249         r.in.domain_guid        = NULL;
1250         r.in.site_name          = NULL;
1251         r.in.flags              = DS_RETURN_DNS_NAME;
1252
1253         torture_comment(tctx, "Testing netr_DsRGetDCNameEx2 without client account\n");
1254
1255         status = dcerpc_netr_DsRGetDCNameEx2(p, tctx, &r);
1256         torture_assert_ntstatus_ok(tctx, status, "netr_DsRGetDCNameEx2");
1257         torture_assert_werr_ok(tctx, r.out.result, "netr_DsRGetDCNameEx2");
1258
1259         torture_comment(tctx, "Testing netr_DsRGetDCNameEx2 with client acount\n");
1260         r.in.client_account     = TEST_MACHINE_NAME"$";
1261         r.in.mask               = ACB_SVRTRUST;
1262         r.in.flags              = DS_RETURN_FLAT_NAME;
1263
1264         status = dcerpc_netr_DsRGetDCNameEx2(p, tctx, &r);
1265         torture_assert_ntstatus_ok(tctx, status, "netr_DsRGetDCNameEx2");
1266         torture_assert_werr_ok(tctx, r.out.result, "netr_DsRGetDCNameEx2");
1267         return test_netr_DsRGetSiteName(p, tctx, r.out.info->dc_unc, 
1268                                         r.out.info->dc_site_name);
1269 }
1270
1271 static bool test_netr_DsrGetDcSiteCoverageW(struct torture_context *tctx, 
1272                                             struct dcerpc_pipe *p)
1273 {
1274         NTSTATUS status;
1275         struct netr_DsrGetDcSiteCoverageW r;
1276
1277         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1278
1279         status = dcerpc_netr_DsrGetDcSiteCoverageW(p, tctx, &r);
1280         torture_assert_ntstatus_ok(tctx, status, "failed");
1281         torture_assert_werr_ok(tctx, r.out.result, "failed");
1282
1283         return true;
1284 }
1285
1286 static bool test_netr_DsRAddressToSitenamesW(struct torture_context *tctx,
1287                                              struct dcerpc_pipe *p)
1288 {
1289         NTSTATUS status;
1290         struct netr_DsRAddressToSitenamesW r;
1291         struct netr_DsRAddress addr;
1292         struct netr_DsRAddressToSitenamesWCtr *ctr;
1293
1294         ctr = talloc(tctx, struct netr_DsRAddressToSitenamesWCtr);
1295
1296         addr.size = 16;
1297         addr.buffer = talloc_zero_array(tctx, uint8_t, addr.size);
1298
1299         addr.buffer[0] = 2; /* AF_INET */
1300         addr.buffer[4] = 127;
1301         addr.buffer[5] = 0;
1302         addr.buffer[6] = 0;
1303         addr.buffer[7] = 1;
1304
1305         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1306         r.in.count = 1;
1307         r.in.addresses = talloc_zero_array(tctx, struct netr_DsRAddress, r.in.count);
1308         r.in.addresses[0] = addr;
1309         r.out.ctr = &ctr;
1310
1311         status = dcerpc_netr_DsRAddressToSitenamesW(p, tctx, &r);
1312         torture_assert_ntstatus_ok(tctx, status, "failed");
1313         torture_assert_werr_ok(tctx, r.out.result, "failed");
1314
1315         return true;
1316 }
1317
1318 static bool test_netr_DsRAddressToSitenamesExW(struct torture_context *tctx,
1319                                                struct dcerpc_pipe *p)
1320 {
1321         NTSTATUS status;
1322         struct netr_DsRAddressToSitenamesExW r;
1323         struct netr_DsRAddress addr;
1324         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1325
1326         ctr = talloc(tctx, struct netr_DsRAddressToSitenamesExWCtr);
1327
1328         addr.size = 16;
1329         addr.buffer = talloc_zero_array(tctx, uint8_t, addr.size);
1330
1331         addr.buffer[0] = 2; /* AF_INET */
1332         addr.buffer[4] = 127;
1333         addr.buffer[5] = 0;
1334         addr.buffer[6] = 0;
1335         addr.buffer[7] = 1;
1336
1337         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1338         r.in.count = 1;
1339         r.in.addresses = talloc_zero_array(tctx, struct netr_DsRAddress, r.in.count);
1340         r.in.addresses[0] = addr;
1341         r.out.ctr = &ctr;
1342
1343         status = dcerpc_netr_DsRAddressToSitenamesExW(p, tctx, &r);
1344         torture_assert_ntstatus_ok(tctx, status, "failed");
1345         torture_assert_werr_ok(tctx, r.out.result, "failed");
1346
1347         return true;
1348 }
1349
1350 static bool test_GetDomainInfo(struct torture_context *tctx, 
1351                                struct dcerpc_pipe *p,
1352                                struct cli_credentials *machine_credentials)
1353 {
1354         NTSTATUS status;
1355         struct netr_LogonGetDomainInfo r;
1356         struct netr_DomainQuery1 q1;
1357         struct netr_Authenticator a;
1358         struct creds_CredentialState *creds;
1359
1360         if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
1361                                     machine_credentials, &creds)) {
1362                 return false;
1363         }
1364
1365         ZERO_STRUCT(r);
1366
1367         creds_client_authenticator(creds, &a);
1368
1369         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1370         r.in.computer_name = TEST_MACHINE_NAME;
1371         r.in.level = 1;
1372         r.in.credential = &a;
1373         r.in.return_authenticator = &a;
1374         r.out.return_authenticator = &a;
1375
1376         r.in.query.query1 = &q1;
1377         ZERO_STRUCT(q1);
1378         
1379         /* this should really be the fully qualified name */
1380         q1.workstation_domain = TEST_MACHINE_NAME;
1381         q1.workstation_site = "Default-First-Site-Name";
1382         q1.blob2.length = 0;
1383         q1.blob2.size = 0;
1384         q1.blob2.data = NULL;
1385         q1.product.string = "product string";
1386
1387         torture_comment(tctx, "Testing netr_uogonGetDomainInfo\n");
1388
1389         status = dcerpc_netr_LogonGetDomainInfo(p, tctx, &r);
1390         torture_assert_ntstatus_ok(tctx, status, "netr_LogonGetDomainInfo");
1391         torture_assert(tctx, creds_client_check(creds, &a.cred), "Credential chaining failed");
1392
1393         return true;
1394 }
1395
1396
1397 static void async_callback(struct rpc_request *req)
1398 {
1399         int *counter = (int *)req->async.private_data;
1400         if (NT_STATUS_IS_OK(req->status)) {
1401                 (*counter)++;
1402         }
1403 }
1404
1405 static bool test_GetDomainInfo_async(struct torture_context *tctx, 
1406                                      struct dcerpc_pipe *p,
1407                                      struct cli_credentials *machine_credentials)
1408 {
1409         NTSTATUS status;
1410         struct netr_LogonGetDomainInfo r;
1411         struct netr_DomainQuery1 q1;
1412         struct netr_Authenticator a;
1413 #define ASYNC_COUNT 100
1414         struct creds_CredentialState *creds;
1415         struct creds_CredentialState *creds_async[ASYNC_COUNT];
1416         struct rpc_request *req[ASYNC_COUNT];
1417         int i;
1418         int *async_counter = talloc(tctx, int);
1419
1420         if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, 
1421                                     machine_credentials, &creds)) {
1422                 return false;
1423         }
1424
1425         ZERO_STRUCT(r);
1426         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1427         r.in.computer_name = TEST_MACHINE_NAME;
1428         r.in.level = 1;
1429         r.in.credential = &a;
1430         r.in.return_authenticator = &a;
1431         r.out.return_authenticator = &a;
1432
1433         r.in.query.query1 = &q1;
1434         ZERO_STRUCT(q1);
1435         
1436         /* this should really be the fully qualified name */
1437         q1.workstation_domain = TEST_MACHINE_NAME;
1438         q1.workstation_site = "Default-First-Site-Name";
1439         q1.blob2.length = 0;
1440         q1.blob2.size = 0;
1441         q1.blob2.data = NULL;
1442         q1.product.string = "product string";
1443
1444         torture_comment(tctx, "Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT);
1445
1446         *async_counter = 0;
1447
1448         for (i=0;i<ASYNC_COUNT;i++) {
1449                 creds_client_authenticator(creds, &a);
1450
1451                 creds_async[i] = (struct creds_CredentialState *)talloc_memdup(creds, creds, sizeof(*creds));
1452                 req[i] = dcerpc_netr_LogonGetDomainInfo_send(p, tctx, &r);
1453
1454                 req[i]->async.callback = async_callback;
1455                 req[i]->async.private_data = async_counter;
1456
1457                 /* even with this flush per request a w2k3 server seems to 
1458                    clag with multiple outstanding requests. bleergh. */
1459                 torture_assert_int_equal(tctx, event_loop_once(dcerpc_event_context(p)), 0, 
1460                                          "event_loop_once failed");
1461         }
1462
1463         for (i=0;i<ASYNC_COUNT;i++) {
1464                 status = dcerpc_ndr_request_recv(req[i]);
1465
1466                 torture_assert_ntstatus_ok(tctx, status, "netr_LogonGetDomainInfo_async");
1467                 torture_assert_ntstatus_ok(tctx, r.out.result, "netr_LogonGetDomainInfo_async"); 
1468
1469                 torture_assert(tctx, creds_client_check(creds_async[i], &a.cred), 
1470                         "Credential chaining failed at async");
1471         }
1472
1473         torture_comment(tctx, 
1474                         "Testing netr_LogonGetDomainInfo - async count %d OK\n", *async_counter);
1475
1476         torture_assert_int_equal(tctx, (*async_counter), ASYNC_COUNT, "int");
1477
1478         return true;
1479 }
1480
1481 static bool test_ManyGetDCName(struct torture_context *tctx, 
1482                                struct dcerpc_pipe *p)
1483 {
1484         NTSTATUS status;
1485         struct dcerpc_pipe *p2;
1486         struct lsa_ObjectAttribute attr;
1487         struct lsa_QosInfo qos;
1488         struct lsa_OpenPolicy2 o;
1489         struct policy_handle lsa_handle;
1490         struct lsa_DomainList domains;
1491
1492         struct lsa_EnumTrustDom t;
1493         uint32_t resume_handle = 0;
1494         struct netr_GetAnyDCName d;
1495
1496         int i;
1497
1498         if (p->conn->transport.transport != NCACN_NP) {
1499                 return true;
1500         }
1501
1502         torture_comment(tctx, "Torturing GetDCName\n");
1503
1504         status = dcerpc_secondary_connection(p, &p2, p->binding);
1505         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
1506
1507         status = dcerpc_bind_auth_none(p2, &ndr_table_lsarpc);
1508         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
1509
1510         qos.len = 0;
1511         qos.impersonation_level = 2;
1512         qos.context_mode = 1;
1513         qos.effective_only = 0;
1514
1515         attr.len = 0;
1516         attr.root_dir = NULL;
1517         attr.object_name = NULL;
1518         attr.attributes = 0;
1519         attr.sec_desc = NULL;
1520         attr.sec_qos = &qos;
1521
1522         o.in.system_name = "\\";
1523         o.in.attr = &attr;
1524         o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1525         o.out.handle = &lsa_handle;
1526
1527         status = dcerpc_lsa_OpenPolicy2(p2, tctx, &o);
1528         torture_assert_ntstatus_ok(tctx, status, "OpenPolicy2 failed");
1529
1530         t.in.handle = &lsa_handle;
1531         t.in.resume_handle = &resume_handle;
1532         t.in.max_size = 1000;
1533         t.out.domains = &domains;
1534         t.out.resume_handle = &resume_handle;
1535
1536         status = dcerpc_lsa_EnumTrustDom(p2, tctx, &t);
1537
1538         if ((!NT_STATUS_IS_OK(status) &&
1539              (!NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES))))
1540                 torture_fail(tctx, "Could not list domains");
1541
1542         talloc_free(p2);
1543
1544         d.in.logon_server = talloc_asprintf(tctx, "\\\\%s",
1545                                             dcerpc_server_name(p));
1546
1547         for (i=0; i<domains.count * 4; i++) {
1548                 struct lsa_DomainInfo *info =
1549                         &domains.domains[rand()%domains.count];
1550
1551                 d.in.domainname = info->name.string;
1552
1553                 status = dcerpc_netr_GetAnyDCName(p, tctx, &d);
1554                 torture_assert_ntstatus_ok(tctx, status, "GetAnyDCName");
1555
1556                 torture_comment(tctx, "\tDC for domain %s is %s\n", info->name.string,
1557                        d.out.dcname ? d.out.dcname : "unknown");
1558         }
1559
1560         return true;
1561 }
1562
1563 struct torture_suite *torture_rpc_netlogon(TALLOC_CTX *mem_ctx)
1564 {
1565         struct torture_suite *suite = torture_suite_create(mem_ctx, "NETLOGON");
1566         struct torture_rpc_tcase *tcase;
1567         struct torture_test *test;
1568
1569         tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "netlogon", 
1570                                                   &ndr_table_netlogon, TEST_MACHINE_NAME);
1571         torture_rpc_tcase_add_test(tcase, "LogonUasLogon", test_LogonUasLogon);
1572         torture_rpc_tcase_add_test(tcase, "LogonUasLogoff", test_LogonUasLogoff);
1573         torture_rpc_tcase_add_test_creds(tcase, "SamLogon", test_SamLogon);
1574         torture_rpc_tcase_add_test_creds(tcase, "SetPassword", test_SetPassword);
1575         torture_rpc_tcase_add_test_creds(tcase, "SetPassword2", test_SetPassword2);
1576         torture_rpc_tcase_add_test_creds(tcase, "GetPassword", test_GetPassword);
1577         torture_rpc_tcase_add_test_creds(tcase, "GetTrustPasswords", test_GetTrustPasswords);
1578         torture_rpc_tcase_add_test_creds(tcase, "GetDomainInfo", test_GetDomainInfo);
1579         torture_rpc_tcase_add_test_creds(tcase, "DatabaseSync", test_DatabaseSync);
1580         torture_rpc_tcase_add_test_creds(tcase, "DatabaseDeltas", test_DatabaseDeltas);
1581         torture_rpc_tcase_add_test_creds(tcase, "AccountDeltas", test_AccountDeltas);
1582         torture_rpc_tcase_add_test_creds(tcase, "AccountSync", test_AccountSync);
1583         torture_rpc_tcase_add_test(tcase, "GetDcName", test_GetDcName);
1584         torture_rpc_tcase_add_test(tcase, "ManyGetDCName", test_ManyGetDCName);
1585         torture_rpc_tcase_add_test(tcase, "LogonControl", test_LogonControl);
1586         torture_rpc_tcase_add_test(tcase, "GetAnyDCName", test_GetAnyDCName);
1587         torture_rpc_tcase_add_test(tcase, "LogonControl2", test_LogonControl2);
1588         torture_rpc_tcase_add_test_creds(tcase, "DatabaseSync2", test_DatabaseSync2);
1589         torture_rpc_tcase_add_test(tcase, "LogonControl2Ex", test_LogonControl2Ex);
1590         torture_rpc_tcase_add_test(tcase, "DsrEnumerateDomainTrusts", test_DsrEnumerateDomainTrusts);
1591         torture_rpc_tcase_add_test(tcase, "NetrEnumerateTrustedDomains", test_netr_NetrEnumerateTrustedDomains);
1592         torture_rpc_tcase_add_test(tcase, "NetrEnumerateTrustedDomainsEx", test_netr_NetrEnumerateTrustedDomainsEx);
1593         test = torture_rpc_tcase_add_test_creds(tcase, "GetDomainInfo_async", test_GetDomainInfo_async);
1594         test->dangerous = true;
1595         torture_rpc_tcase_add_test(tcase, "DsRGetDCName", test_netr_DsRGetDCName);
1596         torture_rpc_tcase_add_test(tcase, "DsRGetDCNameEx", test_netr_DsRGetDCNameEx);
1597         torture_rpc_tcase_add_test(tcase, "DsRGetDCNameEx2", test_netr_DsRGetDCNameEx2);
1598         torture_rpc_tcase_add_test(tcase, "DsrGetDcSiteCoverageW", test_netr_DsrGetDcSiteCoverageW);
1599         torture_rpc_tcase_add_test(tcase, "DsRAddressToSitenamesW", test_netr_DsRAddressToSitenamesW);
1600         torture_rpc_tcase_add_test(tcase, "DsRAddressToSitenamesExW", test_netr_DsRAddressToSitenamesExW);
1601
1602         return suite;
1603 }