r3324: made the smbtorture code completely warning free
[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 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26
27
28 static const char *machine_password;
29
30 #define TEST_MACHINE_NAME "torturetest"
31
32 static BOOL test_LogonUasLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
33 {
34         NTSTATUS status;
35         struct netr_LogonUasLogon r;
36
37         r.in.server_name = NULL;
38         r.in.account_name = lp_parm_string(-1, "torture", "username");
39         r.in.workstation = TEST_MACHINE_NAME;
40
41         printf("Testing LogonUasLogon\n");
42
43         status = dcerpc_netr_LogonUasLogon(p, mem_ctx, &r);
44         if (!NT_STATUS_IS_OK(status)) {
45                 printf("LogonUasLogon - %s\n", nt_errstr(status));
46                 return False;
47         }
48
49         return True;
50         
51 }
52
53 static BOOL test_LogonUasLogoff(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
54 {
55         NTSTATUS status;
56         struct netr_LogonUasLogoff r;
57
58         r.in.server_name = NULL;
59         r.in.account_name = lp_parm_string(-1, "torture", "username");
60         r.in.workstation = TEST_MACHINE_NAME;
61
62         printf("Testing LogonUasLogoff\n");
63
64         status = dcerpc_netr_LogonUasLogoff(p, mem_ctx, &r);
65         if (!NT_STATUS_IS_OK(status)) {
66                 printf("LogonUasLogoff - %s\n", nt_errstr(status));
67                 return False;
68         }
69
70         return True;
71         
72 }
73
74 static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
75                                   struct creds_CredentialState *creds)
76 {
77         NTSTATUS status;
78         struct netr_ServerReqChallenge r;
79         struct netr_ServerAuthenticate a;
80         struct netr_Credential credentials1, credentials2, credentials3;
81         const char *plain_pass;
82         struct samr_Password mach_password;
83
84         printf("Testing ServerReqChallenge\n");
85
86         r.in.server_name = NULL;
87         r.in.computer_name = TEST_MACHINE_NAME;
88         r.in.credentials = &credentials1;
89         r.out.credentials = &credentials2;
90
91         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
92
93         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
94         if (!NT_STATUS_IS_OK(status)) {
95                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
96                 return False;
97         }
98
99         plain_pass = machine_password;
100         if (!plain_pass) {
101                 printf("Unable to fetch machine password!\n");
102                 return False;
103         }
104
105         E_md4hash(plain_pass, mach_password.hash);
106
107         a.in.server_name = NULL;
108         a.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
109         a.in.secure_channel_type = SEC_CHAN_BDC;
110         a.in.computer_name = TEST_MACHINE_NAME;
111         a.in.credentials = &credentials3;
112         a.out.credentials = &credentials3;
113
114         creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3, 
115                           NETLOGON_NEG_AUTH2_FLAGS);
116
117         printf("Testing ServerAuthenticate\n");
118
119         status = dcerpc_netr_ServerAuthenticate(p, mem_ctx, &a);
120         if (!NT_STATUS_IS_OK(status)) {
121                 printf("ServerAuthenticate - %s\n", nt_errstr(status));
122                 return False;
123         }
124
125         if (!creds_client_check(creds, &credentials3)) {
126                 printf("Credential chaining failed\n");
127                 return False;
128         }
129
130         return True;
131 }
132
133 static BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
134                                    uint32_t negotiate_flags,
135                                    struct creds_CredentialState *creds)
136 {
137         NTSTATUS status;
138         struct netr_ServerReqChallenge r;
139         struct netr_ServerAuthenticate2 a;
140         struct netr_Credential credentials1, credentials2, credentials3;
141         const char *plain_pass;
142         struct samr_Password mach_password;
143
144         printf("Testing ServerReqChallenge\n");
145
146         r.in.server_name = NULL;
147         r.in.computer_name = TEST_MACHINE_NAME;
148         r.in.credentials = &credentials1;
149         r.out.credentials = &credentials2;
150
151         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
152
153         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
154         if (!NT_STATUS_IS_OK(status)) {
155                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
156                 return False;
157         }
158
159         plain_pass = machine_password;
160         if (!plain_pass) {
161                 printf("Unable to fetch machine password!\n");
162                 return False;
163         }
164
165         E_md4hash(plain_pass, mach_password.hash);
166
167         a.in.server_name = NULL;
168         a.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
169         a.in.secure_channel_type = SEC_CHAN_BDC;
170         a.in.computer_name = TEST_MACHINE_NAME;
171         a.in.negotiate_flags = &negotiate_flags;
172         a.out.negotiate_flags = &negotiate_flags;
173         a.in.credentials = &credentials3;
174         a.out.credentials = &credentials3;
175
176         creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3, 
177                           negotiate_flags);
178
179         printf("Testing ServerAuthenticate2\n");
180
181         status = dcerpc_netr_ServerAuthenticate2(p, mem_ctx, &a);
182         if (!NT_STATUS_IS_OK(status)) {
183                 printf("ServerAuthenticate2 - %s\n", nt_errstr(status));
184                 return False;
185         }
186
187         if (!creds_client_check(creds, &credentials3)) {
188                 printf("Credential chaining failed\n");
189                 return False;
190         }
191
192         printf("negotiate_flags=0x%08x\n", negotiate_flags);
193
194         return True;
195 }
196
197
198 static BOOL test_SetupCredentials3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
199                                    uint32_t negotiate_flags,
200                                    struct creds_CredentialState *creds)
201 {
202         NTSTATUS status;
203         struct netr_ServerReqChallenge r;
204         struct netr_ServerAuthenticate3 a;
205         struct netr_Credential credentials1, credentials2, credentials3;
206         const char *plain_pass;
207         struct samr_Password mach_password;
208         uint32 rid;
209
210         printf("Testing ServerReqChallenge\n");
211
212         r.in.server_name = NULL;
213         r.in.computer_name = TEST_MACHINE_NAME;
214         r.in.credentials = &credentials1;
215         r.out.credentials = &credentials2;
216
217         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
218
219         status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
220         if (!NT_STATUS_IS_OK(status)) {
221                 printf("ServerReqChallenge - %s\n", nt_errstr(status));
222                 return False;
223         }
224
225         plain_pass = machine_password;
226         if (!plain_pass) {
227                 printf("Unable to fetch machine password!\n");
228                 return False;
229         }
230
231         E_md4hash(plain_pass, mach_password.hash);
232
233         a.in.server_name = NULL;
234         a.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
235         a.in.secure_channel_type = SEC_CHAN_BDC;
236         a.in.computer_name = TEST_MACHINE_NAME;
237         a.in.negotiate_flags = &negotiate_flags;
238         a.in.credentials = &credentials3;
239         a.out.credentials = &credentials3;
240         a.out.negotiate_flags = &negotiate_flags;
241         a.out.rid = &rid;
242
243         creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3,
244                           negotiate_flags);
245
246         printf("Testing ServerAuthenticate3\n");
247
248         status = dcerpc_netr_ServerAuthenticate3(p, mem_ctx, &a);
249         if (!NT_STATUS_IS_OK(status)) {
250                 printf("ServerAuthenticate3 - %s\n", nt_errstr(status));
251                 return False;
252         }
253
254         if (!creds_client_check(creds, &credentials3)) {
255                 printf("Credential chaining failed\n");
256                 return False;
257         }
258
259         printf("negotiate_flags=0x%08x\n", negotiate_flags);
260
261         return True;
262 }
263
264 enum ntlm_break {
265         BREAK_NONE,
266         BREAK_LM,
267         BREAK_NT,
268         NO_LM,
269         NO_NT
270 };
271
272 struct samlogon_state {
273         TALLOC_CTX *mem_ctx;
274         const char *account_name;
275         const char *account_domain;
276         const char *password;
277         struct dcerpc_pipe *p;
278         struct netr_LogonSamLogon r;
279         struct netr_Authenticator auth, auth2;
280         struct creds_CredentialState creds;
281         DATA_BLOB chall;
282 };
283
284 /* 
285    Authenticate a user with a challenge/response, checking session key
286    and valid authentication types
287 */
288 static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, 
289                                enum ntlm_break break_which,
290                                DATA_BLOB *chall, 
291                                DATA_BLOB *lm_response, 
292                                DATA_BLOB *nt_response, 
293                                uint8_t lm_key[8], 
294                                uint8_t user_session_key[16], 
295                                char **error_string)
296 {
297         NTSTATUS status;
298         struct netr_LogonSamLogon *r = &samlogon_state->r;
299         struct netr_NetworkInfo ninfo;
300
301         struct netr_SamBaseInfo *base;
302         
303         printf("testing netr_LogonSamLogon\n");
304         
305         samlogon_state->r.in.logon.network = &ninfo;
306         
307         ninfo.identity_info.domain_name.string = samlogon_state->account_domain;
308         ninfo.identity_info.parameter_control = 0;
309         ninfo.identity_info.logon_id_low = 0;
310         ninfo.identity_info.logon_id_high = 0;
311         ninfo.identity_info.account_name.string = samlogon_state->account_name;
312         ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
313                 
314         memcpy(ninfo.challenge, chall->data, 8);
315                 
316         switch (break_which) {
317         case BREAK_NONE:
318                 break;
319         case BREAK_LM:
320                 if (lm_response && lm_response->data) {
321                         lm_response->data[0]++;
322                 }
323                 break;
324         case BREAK_NT:
325                 if (nt_response && nt_response->data) {
326                         nt_response->data[0]++;
327                 }
328                 break;
329         case NO_LM:
330                 data_blob_free(lm_response);
331                 break;
332         case NO_NT:
333                 data_blob_free(nt_response);
334                 break;
335         }
336                 
337         if (nt_response) {
338                 ninfo.nt.data = nt_response->data;
339                 ninfo.nt.length = nt_response->length;
340         } else {
341                 ninfo.nt.data = NULL;
342                 ninfo.nt.length = 0;
343         }
344                 
345         if (lm_response) {
346                 ninfo.lm.data = lm_response->data;
347                 ninfo.lm.length = lm_response->length;
348         } else {
349                 ninfo.lm.data = NULL;
350                 ninfo.lm.length = 0;
351         }
352                 
353         ZERO_STRUCT(samlogon_state->auth2);
354         creds_client_authenticator(&samlogon_state->creds, &samlogon_state->auth);
355                 
356         r->out.return_authenticator = NULL;
357         status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
358         if (!NT_STATUS_IS_OK(status)) {
359                 if (error_string) {
360                         *error_string = strdup(nt_errstr(status));
361                 }
362         }
363                 
364         if (!r->out.return_authenticator || 
365             !creds_client_check(&samlogon_state->creds, &r->out.return_authenticator->cred)) {
366                 printf("Credential chaining failed\n");
367         }
368
369         if (!NT_STATUS_IS_OK(status)) {
370                 /* we cannot check the session key, if the logon failed... */
371                 return status;
372         }
373                 
374         /* find and decyrpt the session keys, return in parameters above */
375         if (r->in.validation_level == 2) {
376                 base = &r->out.validation.sam2->base;
377         } else if (r->in.validation_level == 3) {
378                 base = &r->out.validation.sam3->base;
379         } else if (r->in.validation_level == 6) {
380                 base = &r->out.validation.sam6->base;
381         } else {
382                 base = NULL;
383         }
384
385         if (r->in.validation_level != 6) {
386                 static const char zeros[16];
387                         
388                 if (memcmp(base->key.key, zeros,  
389                            sizeof(base->key.key)) != 0) {
390                         creds_arcfour_crypt(&samlogon_state->creds, 
391                                             base->key.key, 
392                                             sizeof(base->key.key));
393                 }
394                         
395                 if (user_session_key) {
396                         memcpy(user_session_key, base->key.key, 16);
397                 }
398                         
399                 if (memcmp(base->LMSessKey.key, zeros,  
400                            sizeof(base->LMSessKey.key)) != 0) {
401                         creds_arcfour_crypt(&samlogon_state->creds, 
402                                             base->LMSessKey.key, 
403                                             sizeof(base->LMSessKey.key));
404                 }
405                         
406                 if (lm_key) {
407                         memcpy(lm_key, base->LMSessKey.key, 8);
408                 }
409         } else {
410                 /* they aren't encrypted! */
411                 if (user_session_key) {
412                         memcpy(user_session_key, base->key.key, 16);
413                 }
414                 if (lm_key) {
415                         memcpy(lm_key, base->LMSessKey.key, 8);
416                 }
417         }
418         
419         return status;
420
421
422
423 /* 
424  * Test the normal 'LM and NTLM' combination
425  */
426
427 static BOOL test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) 
428 {
429         BOOL pass = True;
430         BOOL lm_good;
431         NTSTATUS nt_status;
432         DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
433         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
434         DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
435
436         uint8_t lm_key[8];
437         uint8_t user_session_key[16];
438         uint8_t lm_hash[16];
439         uint8_t nt_hash[16];
440         
441         ZERO_STRUCT(lm_key);
442         ZERO_STRUCT(user_session_key);
443
444         lm_good = SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
445         if (!lm_good) {
446                 ZERO_STRUCT(lm_hash);
447         } else {
448                 E_deshash(samlogon_state->password, lm_hash); 
449         }
450                 
451         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
452
453         E_md4hash(samlogon_state->password, nt_hash);
454         SMBsesskeygen_ntv1(nt_hash, session_key.data);
455
456         nt_status = check_samlogon(samlogon_state,
457                                    break_which,
458                                    &samlogon_state->chall,
459                                    &lm_response,
460                                    &nt_response,
461                                    lm_key, 
462                                    user_session_key,
463                                    error_string);
464         
465         data_blob_free(&lm_response);
466
467         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
468                 /* for 'long' passwords, the LM password is invalid */
469                 if (break_which == NO_NT && !lm_good) {
470                         return True;
471                 }
472                 return break_which == BREAK_NT;
473         }
474
475         if (!NT_STATUS_IS_OK(nt_status)) {
476                 return False;
477         }
478
479         if (break_which == NO_NT && !lm_good) {
480                 printf("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
481                 return False;
482         }
483
484         if (memcmp(lm_hash, lm_key, 
485                    sizeof(lm_key)) != 0) {
486                 printf("LM Key does not match expectations!\n");
487                 printf("lm_key:\n");
488                 dump_data(1, (const char *)lm_key, 8);
489                 printf("expected:\n");
490                 dump_data(1, (const char *)lm_hash, 8);
491                 pass = False;
492         }
493
494         if (break_which == NO_NT) {
495                 char lm_key_expected[16];
496                 memcpy(lm_key_expected, lm_hash, 8);
497                 memset(lm_key_expected+8, '\0', 8);
498                 if (memcmp(lm_key_expected, user_session_key, 
499                            16) != 0) {
500                         printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
501                         printf("user_session_key:\n");
502                         dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
503                         printf("expected:\n");
504                         dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
505                         pass = False;
506                 }
507         } else {                
508                 if (memcmp(session_key.data, user_session_key, 
509                            sizeof(user_session_key)) != 0) {
510                         printf("NT Session Key does not match expectations!\n");
511                         printf("user_session_key:\n");
512                         dump_data(1, (const char *)user_session_key, 16);
513                         printf("expected:\n");
514                         dump_data(1, (const char *)session_key.data, session_key.length);
515                         pass = False;
516                 }
517         }
518         return pass;
519 }
520
521 /* 
522  * Test LM authentication, no NT response supplied
523  */
524
525 static BOOL test_lm(struct samlogon_state *samlogon_state, char **error_string) 
526 {
527
528         return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
529 }
530
531 /* 
532  * Test the NTLM response only, no LM.
533  */
534
535 static BOOL test_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
536 {
537         return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
538 }
539
540 /* 
541  * Test the NTLM response only, but in the LM field.
542  */
543
544 static BOOL test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string) 
545 {
546         BOOL pass = True;
547         NTSTATUS nt_status;
548         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
549
550         uint8_t lm_key[8];
551         uint8_t lm_hash[16];
552         uint8_t user_session_key[16];
553         
554         ZERO_STRUCT(user_session_key);
555
556         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
557
558         E_deshash(samlogon_state->password, lm_hash); 
559
560         nt_status = check_samlogon(samlogon_state,
561                                    BREAK_NONE,
562                                    &samlogon_state->chall,
563                                    &nt_response,
564                                    NULL,
565                                    lm_key, 
566                                    user_session_key,
567                                    error_string);
568         
569         if (!NT_STATUS_IS_OK(nt_status)) {
570                 return False;
571         }
572
573         if (memcmp(lm_hash, lm_key, 
574                    sizeof(lm_key)) != 0) {
575                 printf("LM Key does not match expectations!\n");
576                 printf("lm_key:\n");
577                 dump_data(1, (const char *)lm_key, 8);
578                 printf("expected:\n");
579                 dump_data(1, (const char *)lm_hash, 8);
580                 pass = False;
581         }
582         if (memcmp(lm_hash, user_session_key, 8) != 0) {
583                 char lm_key_expected[16];
584                 memcpy(lm_key_expected, lm_hash, 8);
585                 memset(lm_key_expected+8, '\0', 8);
586                 if (memcmp(lm_key_expected, user_session_key, 
587                            16) != 0) {
588                         printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
589                         printf("user_session_key:\n");
590                         dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
591                         printf("expected:\n");
592                         dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
593                         pass = False;
594                 }
595         }
596         return pass;
597 }
598
599 /* 
600  * Test the NTLM response only, but in the both the NT and LM fields.
601  */
602
603 static BOOL test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string) 
604 {
605         BOOL pass = True;
606         BOOL lm_good;
607         NTSTATUS nt_status;
608         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
609         DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
610
611         char lm_key[8];
612         char lm_hash[16];
613         char user_session_key[16];
614         char nt_hash[16];
615         
616         ZERO_STRUCT(lm_key);
617         ZERO_STRUCT(user_session_key);
618
619         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 
620                      nt_response.data);
621         E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
622         SMBsesskeygen_ntv1((const uint8_t *)nt_hash, 
623                            session_key.data);
624
625         lm_good = E_deshash(samlogon_state->password, (uint8_t *)lm_hash); 
626         if (!lm_good) {
627                 ZERO_STRUCT(lm_hash);
628         }
629
630         nt_status = check_samlogon(samlogon_state,
631                                    BREAK_NONE,
632                                    &samlogon_state->chall,
633                                    NULL, 
634                                    &nt_response,
635                                    lm_key, 
636                                    user_session_key,
637                                    error_string);
638         
639         if (!NT_STATUS_IS_OK(nt_status)) {
640                 return False;
641         }
642
643         if (memcmp(lm_hash, lm_key, 
644                    sizeof(lm_key)) != 0) {
645                 printf("LM Key does not match expectations!\n");
646                 printf("lm_key:\n");
647                 dump_data(1, lm_key, 8);
648                 printf("expected:\n");
649                 dump_data(1, lm_hash, 8);
650                 pass = False;
651         }
652         if (memcmp(session_key.data, user_session_key, 
653                    sizeof(user_session_key)) != 0) {
654                 printf("NT Session Key does not match expectations!\n");
655                 printf("user_session_key:\n");
656                 dump_data(1, user_session_key, 16);
657                 printf("expected:\n");
658                 dump_data(1, (const char *)session_key.data, session_key.length);
659                 pass = False;
660         }
661
662
663         return pass;
664 }
665
666 /* 
667  * Test the NTLMv2 and LMv2 responses
668  */
669
670 static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) 
671 {
672         BOOL pass = True;
673         NTSTATUS nt_status;
674         DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
675         DATA_BLOB lmv2_response = data_blob(NULL, 0);
676         DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
677         DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, lp_netbios_name(), lp_workgroup());
678
679         uint8_t user_session_key[16];
680
681         ZERO_STRUCT(user_session_key);
682         
683         /* TODO - test with various domain cases, and without domain */
684         if (!SMBNTLMv2encrypt(samlogon_state->account_name, samlogon_state->account_domain, 
685                               samlogon_state->password, &samlogon_state->chall,
686                               &names_blob,
687                               &lmv2_response, &ntlmv2_response, 
688                               &ntlmv2_session_key)) {
689                 data_blob_free(&names_blob);
690                 return False;
691         }
692         data_blob_free(&names_blob);
693
694         nt_status = check_samlogon(samlogon_state,
695                                    break_which,
696                                    &samlogon_state->chall,
697                                    &lmv2_response,
698                                    &ntlmv2_response,
699                                    NULL, 
700                                    user_session_key,
701                                    error_string);
702         
703         data_blob_free(&lmv2_response);
704         data_blob_free(&ntlmv2_response);
705
706         if (!NT_STATUS_IS_OK(nt_status)) {
707                 return break_which == BREAK_NT;
708         }
709
710         if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key, 
711                    sizeof(user_session_key)) != 0) {
712                 printf("USER (NTLMv2) Session Key does not match expectations!\n");
713                 printf("user_session_key:\n");
714                 dump_data(1, (const char *)user_session_key, 16);
715                 printf("expected:\n");
716                 dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length);
717                 pass = False;
718         }
719         return pass;
720 }
721
722 /* 
723  * Test the NTLMv2 and LMv2 responses
724  */
725
726 static BOOL test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 
727 {
728         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, error_string);
729 }
730
731 /* 
732  * Test the LMv2 response only
733  */
734
735 static BOOL test_lmv2(struct samlogon_state *samlogon_state, char **error_string) 
736 {
737         return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, error_string);
738 }
739
740 /* 
741  * Test the NTLMv2 response only
742  */
743
744 static BOOL test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 
745 {
746         return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, error_string);
747 }
748
749 static BOOL test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
750 {
751         return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
752 }
753
754 static BOOL test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string) 
755 {
756         return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
757 }
758
759 static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string) 
760 {
761         return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
762 }
763
764 static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 
765 {
766         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, error_string);
767 }
768
769 static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 
770 {
771         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, error_string);
772 }
773
774 static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
775 {
776         NTSTATUS nt_status;
777         DATA_BLOB nt_response = data_blob(NULL, 0);
778         DATA_BLOB lm_response = data_blob(NULL, 0);
779         char *password;
780         char *dospw;
781         void *unicodepw;
782
783         uint8_t user_session_key[16];
784         uint8_t lm_key[16];
785         static const uint8_t zeros[8];
786         DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
787
788         ZERO_STRUCT(user_session_key);
789         
790         if ((push_ucs2_talloc(samlogon_state->mem_ctx, &unicodepw, 
791                               samlogon_state->password)) == -1) {
792                 DEBUG(0, ("push_ucs2_allocate failed!\n"));
793                 exit(1);
794         }
795
796         nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, utf16_len(unicodepw));
797
798         password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password);
799
800         if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX, 
801                                    CH_DOS, password,
802                                    strlen(password)+1, 
803                                    (void**)&dospw)) == -1) {
804                 DEBUG(0, ("convert_string_talloc failed!\n"));
805                 exit(1);
806         }
807
808         lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
809
810         nt_status = check_samlogon(samlogon_state,
811                                    break_which,
812                                    &chall,
813                                    &lm_response,
814                                    &nt_response,
815                                    lm_key, 
816                                    user_session_key,
817                                    error_string);
818         
819         if (!NT_STATUS_IS_OK(nt_status)) {
820                 return break_which == BREAK_NT;
821         }
822
823         return True;
824 }
825
826 static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state, 
827                                        char **error_string) {
828         return test_plaintext(samlogon_state, BREAK_NONE, error_string);
829 }
830
831 static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state, 
832                                      char **error_string) {
833         return test_plaintext(samlogon_state, BREAK_LM, error_string);
834 }
835
836 static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state, 
837                                      char **error_string) {
838         return test_plaintext(samlogon_state, BREAK_NT, error_string);
839 }
840
841 static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state, 
842                                    char **error_string) {
843         return test_plaintext(samlogon_state, NO_LM, error_string);
844 }
845
846 static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state, 
847                                    char **error_string) {
848         return test_plaintext(samlogon_state, NO_NT, error_string);
849 }
850
851 /* 
852    Tests:
853    
854    - LM only
855    - NT and LM             
856    - NT
857    - NT in LM field
858    - NT in both fields
859    - NTLMv2
860    - NTLMv2 and LMv2
861    - LMv2
862    - plaintext tests (in challenge-response fields)
863   
864    check we get the correct session key in each case
865    check what values we get for the LM session key
866    
867 */
868
869 static const struct ntlm_tests {
870         BOOL (*fn)(struct samlogon_state *, char **);
871         const char *name;
872         BOOL expect_fail;
873 } test_table[] = {
874         {test_lm, "LM", False},
875         {test_lm_ntlm, "LM and NTLM", False},
876         {test_ntlm, "NTLM", False},
877         {test_ntlm_in_lm, "NTLM in LM", False},
878         {test_ntlm_in_both, "NTLM in both", False},
879         {test_ntlmv2, "NTLMv2", False},
880         {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
881         {test_lmv2, "LMv2", False},
882         {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
883         {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
884         {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
885         {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
886         {test_plaintext_none_broken, "Plaintext", True},
887         {test_plaintext_lm_broken, "Plaintext LM broken", True},
888         {test_plaintext_nt_broken, "Plaintext NT broken", True},
889         {test_plaintext_nt_only, "Plaintext NT only", True},
890         {test_plaintext_lm_only, "Plaintext LM only", True},
891         {NULL, NULL}
892 };
893
894 /*
895   try a netlogon SamLogon
896 */
897 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
898 {
899         int i, v, l;
900         BOOL ret = True;
901         int validation_levels[] = {2,3,6};
902         int logon_levels[] = { 2, 6 };
903         struct samlogon_state samlogon_state;
904         
905         samlogon_state.mem_ctx = mem_ctx;
906         samlogon_state.account_name = lp_parm_string(-1, "torture", "username");
907         samlogon_state.account_domain = lp_parm_string(-1, "torture", "userdomain");
908         samlogon_state.password = lp_parm_string(-1, "torture", "password");
909         samlogon_state.p = p;
910
911         samlogon_state.chall = data_blob_talloc(mem_ctx, NULL, 8);
912
913         generate_random_buffer(samlogon_state.chall.data, 8);
914
915         if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
916                 return False;
917         }
918
919         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
920                 return False;
921         }
922
923         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &samlogon_state.creds)) {
924                 return False;
925         }
926
927         samlogon_state.r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
928         samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
929         samlogon_state.r.in.credential = &samlogon_state.auth;
930         samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
931
932         for (i=0; test_table[i].fn; i++) {
933                 for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
934                         for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
935                                 char *error_string = NULL;
936                                 samlogon_state.r.in.validation_level = validation_levels[v];
937                                 samlogon_state.r.in.logon_level = logon_levels[l];
938                                 printf("Testing SamLogon with '%s' at validation level %d, logon level %d\n", 
939                                        test_table[i].name, validation_levels[v], logon_levels[l]);
940         
941                                 if (!test_table[i].fn(&samlogon_state, &error_string)) {
942                                         if (test_table[i].expect_fail) {
943                                                 printf("Test %s failed (expected, test incomplete): %s\n", test_table[i].name, error_string);
944                                         } else {
945                                                 printf("Test %s failed: %s\n", test_table[i].name, error_string);
946                                                 ret = False;
947                                         }
948                                         SAFE_FREE(error_string);
949                                 }
950                         }
951                 }
952         }
953
954         return ret;
955 }
956
957
958 /*
959   try a change password for our machine account
960 */
961 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
962 {
963         NTSTATUS status;
964         struct netr_ServerPasswordSet r;
965         const char *password;
966         struct creds_CredentialState creds;
967
968         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
969                 return False;
970         }
971
972         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
973         r.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
974         r.in.secure_channel_type = SEC_CHAN_BDC;
975         r.in.computer_name = TEST_MACHINE_NAME;
976
977         password = generate_random_str(mem_ctx, 8);
978         E_md4hash(password, r.in.new_password.hash);
979
980         creds_des_encrypt(&creds, &r.in.new_password);
981
982         printf("Testing ServerPasswordSet on machine account\n");
983         printf("Changing machine account password to '%s'\n", password);
984
985         creds_client_authenticator(&creds, &r.in.credential);
986
987         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
988         if (!NT_STATUS_IS_OK(status)) {
989                 printf("ServerPasswordSet - %s\n", nt_errstr(status));
990                 return False;
991         }
992
993         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
994                 printf("Credential chaining failed\n");
995         }
996
997         /* by changing the machine password twice we test the
998            credentials chaining fully, and we verify that the server
999            allows the password to be set to the same value twice in a
1000            row (match win2k3) */
1001         printf("Testing a second ServerPasswordSet on machine account\n");
1002         printf("Changing machine account password to '%s' (same as previous run)\n", password);
1003
1004         creds_client_authenticator(&creds, &r.in.credential);
1005
1006         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
1007         if (!NT_STATUS_IS_OK(status)) {
1008                 printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
1009                 return False;
1010         }
1011
1012         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1013                 printf("Credential chaining failed\n");
1014         }
1015
1016         machine_password = password;
1017
1018         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1019                 printf("ServerPasswordSet failed to actually change the password\n");
1020                 return False;
1021         }
1022
1023         return True;
1024 }
1025
1026
1027 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
1028 static uint64_t sequence_nums[3];
1029
1030 /*
1031   try a netlogon DatabaseSync
1032 */
1033 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1034 {
1035         NTSTATUS status;
1036         struct netr_DatabaseSync r;
1037         struct creds_CredentialState creds;
1038         const uint32_t database_ids[] = {0, 1, 2}; 
1039         int i;
1040         BOOL ret = True;
1041
1042         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1043                 return False;
1044         }
1045
1046         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1047         r.in.computername = TEST_MACHINE_NAME;
1048         r.in.preferredmaximumlength = (uint32_t)-1;
1049         ZERO_STRUCT(r.in.return_authenticator);
1050
1051         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1052                 r.in.sync_context = 0;
1053                 r.in.database_id = database_ids[i];
1054
1055                 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
1056
1057                 do {
1058                         creds_client_authenticator(&creds, &r.in.credential);
1059
1060                         status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
1061                         if (!NT_STATUS_IS_OK(status) &&
1062                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1063                                 printf("DatabaseSync - %s\n", nt_errstr(status));
1064                                 ret = False;
1065                                 break;
1066                         }
1067
1068                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1069                                 printf("Credential chaining failed\n");
1070                         }
1071
1072                         r.in.sync_context = r.out.sync_context;
1073
1074                         if (r.out.delta_enum_array &&
1075                             r.out.delta_enum_array->num_deltas > 0 &&
1076                             r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
1077                             r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
1078                                 sequence_nums[r.in.database_id] = 
1079                                         r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
1080                                 printf("\tsequence_nums[%d]=%llu\n",
1081                                        r.in.database_id, 
1082                                        sequence_nums[r.in.database_id]);
1083                         }
1084                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1085         }
1086
1087         return ret;
1088 }
1089
1090
1091 /*
1092   try a netlogon DatabaseDeltas
1093 */
1094 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1095 {
1096         NTSTATUS status;
1097         struct netr_DatabaseDeltas r;
1098         struct creds_CredentialState creds;
1099         const uint32_t database_ids[] = {0, 1, 2}; 
1100         int i;
1101         BOOL ret = True;
1102
1103         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1104                 return False;
1105         }
1106
1107         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1108         r.in.computername = TEST_MACHINE_NAME;
1109         r.in.preferredmaximumlength = (uint32_t)-1;
1110         ZERO_STRUCT(r.in.return_authenticator);
1111
1112         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1113                 r.in.database_id = database_ids[i];
1114                 r.in.sequence_num = sequence_nums[r.in.database_id];
1115
1116                 if (r.in.sequence_num == 0) continue;
1117
1118                 r.in.sequence_num -= 1;
1119
1120
1121                 printf("Testing DatabaseDeltas of id %d at %llu\n", 
1122                        r.in.database_id, r.in.sequence_num);
1123
1124                 do {
1125                         creds_client_authenticator(&creds, &r.in.credential);
1126
1127                         status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
1128                         if (!NT_STATUS_IS_OK(status) &&
1129                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1130                                 printf("DatabaseDeltas - %s\n", nt_errstr(status));
1131                                 ret = False;
1132                                 break;
1133                         }
1134
1135                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1136                                 printf("Credential chaining failed\n");
1137                         }
1138
1139                         r.in.sequence_num++;
1140                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1141         }
1142
1143         return ret;
1144 }
1145
1146
1147 /*
1148   try a netlogon AccountDeltas
1149 */
1150 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1151 {
1152         NTSTATUS status;
1153         struct netr_AccountDeltas r;
1154         struct creds_CredentialState creds;
1155         BOOL ret = True;
1156
1157         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1158                 return False;
1159         }
1160
1161         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1162         r.in.computername = TEST_MACHINE_NAME;
1163         ZERO_STRUCT(r.in.return_authenticator);
1164         creds_client_authenticator(&creds, &r.in.credential);
1165         ZERO_STRUCT(r.in.uas);
1166         r.in.count=10;
1167         r.in.level=0;
1168         r.in.buffersize=100;
1169
1170         printf("Testing AccountDeltas\n");
1171
1172         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1173         status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
1174         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1175                 printf("AccountDeltas - %s\n", nt_errstr(status));
1176                 ret = False;
1177         }
1178
1179         return ret;
1180 }
1181
1182 /*
1183   try a netlogon AccountSync
1184 */
1185 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1186 {
1187         NTSTATUS status;
1188         struct netr_AccountSync r;
1189         struct creds_CredentialState creds;
1190         BOOL ret = True;
1191
1192         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1193                 return False;
1194         }
1195
1196         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1197         r.in.computername = TEST_MACHINE_NAME;
1198         ZERO_STRUCT(r.in.return_authenticator);
1199         creds_client_authenticator(&creds, &r.in.credential);
1200         ZERO_STRUCT(r.in.recordid);
1201         r.in.reference=0;
1202         r.in.level=0;
1203         r.in.buffersize=100;
1204
1205         printf("Testing AccountSync\n");
1206
1207         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1208         status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
1209         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1210                 printf("AccountSync - %s\n", nt_errstr(status));
1211                 ret = False;
1212         }
1213
1214         return ret;
1215 }
1216
1217 /*
1218   try a netlogon GetDcName
1219 */
1220 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1221 {
1222         NTSTATUS status;
1223         struct netr_GetDcName r;
1224
1225         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1226         r.in.domainname = lp_workgroup();
1227
1228         printf("Testing GetDcName\n");
1229
1230         status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
1231         if (!NT_STATUS_IS_OK(status)) {
1232                 printf("GetDcName - %s\n", nt_errstr(status));
1233                 return False;
1234         }
1235
1236         printf("\tDC is at '%s'\n", r.out.dcname);
1237
1238         return True;
1239 }
1240
1241 /*
1242   try a netlogon LogonControl 
1243 */
1244 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1245 {
1246         NTSTATUS status;
1247         struct netr_LogonControl r;
1248         BOOL ret = True;
1249         int i;
1250
1251         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1252         r.in.function_code = 1;
1253
1254         for (i=1;i<4;i++) {
1255                 r.in.level = i;
1256
1257                 printf("Testing LogonControl level %d\n", i);
1258
1259                 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
1260                 if (!NT_STATUS_IS_OK(status)) {
1261                         printf("LogonControl - %s\n", nt_errstr(status));
1262                         ret = False;
1263                 }
1264         }
1265
1266         return ret;
1267 }
1268
1269
1270 /*
1271   try a netlogon GetAnyDCName
1272 */
1273 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1274 {
1275         NTSTATUS status;
1276         struct netr_GetAnyDCName r;
1277
1278         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1279         r.in.domainname = lp_workgroup();
1280
1281         printf("Testing GetAnyDCName\n");
1282
1283         status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
1284         if (!NT_STATUS_IS_OK(status)) {
1285                 printf("GetAnyDCName - %s\n", nt_errstr(status));
1286                 return False;
1287         }
1288
1289         if (r.out.dcname) {
1290                 printf("\tDC is at '%s'\n", r.out.dcname);
1291         }
1292
1293         return True;
1294 }
1295
1296
1297 /*
1298   try a netlogon LogonControl2
1299 */
1300 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1301 {
1302         NTSTATUS status;
1303         struct netr_LogonControl2 r;
1304         BOOL ret = True;
1305         int i;
1306
1307         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1308
1309         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1310         r.in.data.domain = lp_workgroup();
1311
1312         for (i=1;i<4;i++) {
1313                 r.in.level = i;
1314
1315                 printf("Testing LogonControl2 level %d function %d\n", 
1316                        i, r.in.function_code);
1317
1318                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1319                 if (!NT_STATUS_IS_OK(status)) {
1320                         printf("LogonControl - %s\n", nt_errstr(status));
1321                         ret = False;
1322                 }
1323         }
1324
1325         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1326         r.in.data.domain = lp_workgroup();
1327
1328         for (i=1;i<4;i++) {
1329                 r.in.level = i;
1330
1331                 printf("Testing LogonControl2 level %d function %d\n", 
1332                        i, r.in.function_code);
1333
1334                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1335                 if (!NT_STATUS_IS_OK(status)) {
1336                         printf("LogonControl - %s\n", nt_errstr(status));
1337                         ret = False;
1338                 }
1339         }
1340
1341         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1342         r.in.data.domain = lp_workgroup();
1343
1344         for (i=1;i<4;i++) {
1345                 r.in.level = i;
1346
1347                 printf("Testing LogonControl2 level %d function %d\n", 
1348                        i, r.in.function_code);
1349
1350                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1351                 if (!NT_STATUS_IS_OK(status)) {
1352                         printf("LogonControl - %s\n", nt_errstr(status));
1353                         ret = False;
1354                 }
1355         }
1356
1357         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1358         r.in.data.debug_level = ~0;
1359
1360         for (i=1;i<4;i++) {
1361                 r.in.level = i;
1362
1363                 printf("Testing LogonControl2 level %d function %d\n", 
1364                        i, r.in.function_code);
1365
1366                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1367                 if (!NT_STATUS_IS_OK(status)) {
1368                         printf("LogonControl - %s\n", nt_errstr(status));
1369                         ret = False;
1370                 }
1371         }
1372
1373         return ret;
1374 }
1375
1376 /*
1377   try a netlogon DatabaseSync2
1378 */
1379 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1380 {
1381         NTSTATUS status;
1382         struct netr_DatabaseSync2 r;
1383         struct creds_CredentialState creds;
1384         const uint32_t database_ids[] = {0, 1, 2}; 
1385         int i;
1386         BOOL ret = True;
1387
1388         if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &creds)) {
1389                 return False;
1390         }
1391
1392         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1393         r.in.computername = TEST_MACHINE_NAME;
1394         r.in.preferredmaximumlength = (uint32_t)-1;
1395         ZERO_STRUCT(r.in.return_authenticator);
1396
1397         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1398                 r.in.sync_context = 0;
1399                 r.in.database_id = database_ids[i];
1400                 r.in.restart_state = 0;
1401
1402                 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
1403
1404                 do {
1405                         creds_client_authenticator(&creds, &r.in.credential);
1406
1407                         status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
1408                         if (!NT_STATUS_IS_OK(status) &&
1409                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1410                                 printf("DatabaseSync2 - %s\n", nt_errstr(status));
1411                                 ret = False;
1412                                 break;
1413                         }
1414
1415                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1416                                 printf("Credential chaining failed\n");
1417                         }
1418
1419                         r.in.sync_context = r.out.sync_context;
1420                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1421         }
1422
1423         return ret;
1424 }
1425
1426
1427 /*
1428   try a netlogon LogonControl2Ex
1429 */
1430 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1431 {
1432         NTSTATUS status;
1433         struct netr_LogonControl2Ex r;
1434         BOOL ret = True;
1435         int i;
1436
1437         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1438
1439         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1440         r.in.data.domain = lp_workgroup();
1441
1442         for (i=1;i<4;i++) {
1443                 r.in.level = i;
1444
1445                 printf("Testing LogonControl2Ex level %d function %d\n", 
1446                        i, r.in.function_code);
1447
1448                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1449                 if (!NT_STATUS_IS_OK(status)) {
1450                         printf("LogonControl - %s\n", nt_errstr(status));
1451                         ret = False;
1452                 }
1453         }
1454
1455         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1456         r.in.data.domain = lp_workgroup();
1457
1458         for (i=1;i<4;i++) {
1459                 r.in.level = i;
1460
1461                 printf("Testing LogonControl2Ex level %d function %d\n", 
1462                        i, r.in.function_code);
1463
1464                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1465                 if (!NT_STATUS_IS_OK(status)) {
1466                         printf("LogonControl - %s\n", nt_errstr(status));
1467                         ret = False;
1468                 }
1469         }
1470
1471         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1472         r.in.data.domain = lp_workgroup();
1473
1474         for (i=1;i<4;i++) {
1475                 r.in.level = i;
1476
1477                 printf("Testing LogonControl2Ex level %d function %d\n", 
1478                        i, r.in.function_code);
1479
1480                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1481                 if (!NT_STATUS_IS_OK(status)) {
1482                         printf("LogonControl - %s\n", nt_errstr(status));
1483                         ret = False;
1484                 }
1485         }
1486
1487         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1488         r.in.data.debug_level = ~0;
1489
1490         for (i=1;i<4;i++) {
1491                 r.in.level = i;
1492
1493                 printf("Testing LogonControl2Ex level %d function %d\n", 
1494                        i, r.in.function_code);
1495
1496                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1497                 if (!NT_STATUS_IS_OK(status)) {
1498                         printf("LogonControl - %s\n", nt_errstr(status));
1499                         ret = False;
1500                 }
1501         }
1502
1503         return ret;
1504 }
1505
1506
1507 /*
1508   try a netlogon netr_DsrEnumerateDomainTrusts
1509 */
1510 static BOOL test_DsrEnumerateDomainTrusts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1511 {
1512         NTSTATUS status;
1513         struct netr_DsrEnumerateDomainTrusts r;
1514
1515         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1516         r.in.trust_flags = 0x3f;
1517
1518         printf("Testing netr_DsrEnumerateDomainTrusts\n");
1519
1520         status = dcerpc_netr_DsrEnumerateDomainTrusts(p, mem_ctx, &r);
1521         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1522                 printf("netr_DsrEnumerateDomainTrusts - %s/%s\n", 
1523                        nt_errstr(status), win_errstr(r.out.result));
1524                 return False;
1525         }
1526
1527         return True;
1528 }
1529
1530
1531 /*
1532   test an ADS style interactive domain login
1533 */
1534 static BOOL test_InteractiveLogin(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1535                                   struct creds_CredentialState *creds)
1536 {
1537         NTSTATUS status;
1538         struct netr_LogonSamLogonWithFlags r;
1539         struct netr_Authenticator a, ra;
1540         struct netr_PasswordInfo pinfo;
1541         const char *plain_pass;
1542
1543         ZERO_STRUCT(r);
1544         ZERO_STRUCT(ra);
1545
1546         creds_client_authenticator(creds, &a);
1547
1548         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1549         r.in.workstation = TEST_MACHINE_NAME;
1550         r.in.credential = &a;
1551         r.in.return_authenticator = &ra;
1552         r.in.logon_level = 5;
1553         r.in.logon.password = &pinfo;
1554         r.in.validation_level = 6;
1555         r.in.flags = 0;
1556
1557         pinfo.identity_info.domain_name.string = lp_parm_string(-1, "torture", "userdomain");
1558         pinfo.identity_info.parameter_control = 0;
1559         pinfo.identity_info.logon_id_low = 0;
1560         pinfo.identity_info.logon_id_high = 0;
1561         pinfo.identity_info.account_name.string = lp_parm_string(-1, "torture", "username");
1562         pinfo.identity_info.workstation.string = TEST_MACHINE_NAME;
1563
1564         plain_pass = lp_parm_string(-1, "torture", "password");
1565
1566         E_deshash(plain_pass, pinfo.lmpassword.hash);
1567         E_md4hash(plain_pass, pinfo.ntpassword.hash);
1568
1569         creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
1570         creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
1571
1572         printf("Testing netr_LogonSamLogonWithFlags\n");
1573
1574         status = dcerpc_netr_LogonSamLogonWithFlags(p, mem_ctx, &r);
1575         if (!NT_STATUS_IS_OK(status)) {
1576                 printf("netr_LogonSamLogonWithFlags - %s\n", nt_errstr(status));
1577                 exit(1);
1578                 return False;
1579         }
1580
1581         if (!creds_client_check(creds, &r.out.return_authenticator->cred)) {
1582                 printf("Credential chaining failed\n");
1583                 return False;
1584         }
1585
1586         return True;
1587 }
1588
1589
1590 static BOOL test_GetDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1591 {
1592         NTSTATUS status;
1593         struct netr_LogonGetDomainInfo r;
1594         struct netr_DomainQuery1 q1;
1595         struct netr_Authenticator a;
1596         struct creds_CredentialState creds;
1597
1598         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &creds)) {
1599                 return False;
1600         }
1601
1602         ZERO_STRUCT(r);
1603
1604         creds_client_authenticator(&creds, &a);
1605
1606         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1607         r.in.computer_name = TEST_MACHINE_NAME;
1608         r.in.unknown1 = 512;
1609         r.in.level = 1;
1610         r.in.credential = &a;
1611         r.out.credential = &a;
1612
1613         r.in.i1[0] = 0;
1614         r.in.i1[1] = 0;
1615
1616         r.in.query.query1 = &q1;
1617         ZERO_STRUCT(q1);
1618         
1619         /* this should really be the fully qualified name */
1620         q1.workstation_domain = TEST_MACHINE_NAME;
1621         q1.workstation_site = "Default-First-Site-Name";
1622         q1.blob2.length = 0;
1623         q1.blob2.size = 0;
1624         q1.blob2.data = NULL;
1625         q1.product.string = "product string";
1626
1627         printf("Testing netr_LogonGetDomainInfo\n");
1628
1629         status = dcerpc_netr_LogonGetDomainInfo(p, mem_ctx, &r);
1630         if (!NT_STATUS_IS_OK(status)) {
1631                 printf("netr_LogonGetDomainInfo - %s\n", nt_errstr(status));
1632                 return False;
1633         }
1634
1635         if (!creds_client_check(&creds, &a.cred)) {
1636                 printf("Credential chaining failed\n");
1637                 return False;
1638         }
1639
1640         test_InteractiveLogin(p, mem_ctx, &creds);
1641
1642         return True;
1643 }
1644
1645
1646 static void async_callback(struct rpc_request *req)
1647 {
1648         int *counter = req->async.private;
1649         if (NT_STATUS_IS_OK(req->status)) {
1650                 (*counter)++;
1651         }
1652 }
1653
1654 static BOOL test_GetDomainInfo_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1655 {
1656         NTSTATUS status;
1657         struct netr_LogonGetDomainInfo r;
1658         struct netr_DomainQuery1 q1;
1659         struct netr_Authenticator a;
1660 #define ASYNC_COUNT 100
1661         struct creds_CredentialState creds;
1662         struct creds_CredentialState creds_async[ASYNC_COUNT];
1663         struct rpc_request *req[ASYNC_COUNT];
1664         int i;
1665         int async_counter = 0;
1666
1667         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &creds)) {
1668                 return False;
1669         }
1670
1671         ZERO_STRUCT(r);
1672         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1673         r.in.computer_name = TEST_MACHINE_NAME;
1674         r.in.unknown1 = 512;
1675         r.in.level = 1;
1676         r.in.credential = &a;
1677         r.out.credential = &a;
1678
1679         r.in.i1[0] = 0;
1680         r.in.i1[1] = 0;
1681
1682         r.in.query.query1 = &q1;
1683         ZERO_STRUCT(q1);
1684         
1685         /* this should really be the fully qualified name */
1686         q1.workstation_domain = TEST_MACHINE_NAME;
1687         q1.workstation_site = "Default-First-Site-Name";
1688         q1.blob2.length = 0;
1689         q1.blob2.size = 0;
1690         q1.blob2.data = NULL;
1691         q1.product.string = "product string";
1692
1693         printf("Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT);
1694
1695         for (i=0;i<ASYNC_COUNT;i++) {
1696                 creds_client_authenticator(&creds, &a);
1697
1698                 creds_async[i] = creds;
1699                 req[i] = dcerpc_netr_LogonGetDomainInfo_send(p, mem_ctx, &r);
1700
1701                 req[i]->async.callback = async_callback;
1702                 req[i]->async.private = &async_counter;
1703
1704                 /* even with this flush per request a w2k3 server seems to 
1705                    clag with multiple outstanding requests. bleergh. */
1706                 if (event_loop_once(dcerpc_event_context(p)) != 0) {
1707                         return False;
1708                 }
1709         }
1710
1711         for (i=0;i<ASYNC_COUNT;i++) {
1712                 status = dcerpc_ndr_request_recv(req[i]);
1713                 if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(r.out.result)) {
1714                         printf("netr_LogonGetDomainInfo_async(%d) - %s/%s\n", 
1715                                i, nt_errstr(status), nt_errstr(r.out.result));
1716                         break;
1717                 }
1718
1719                 if (!creds_client_check(&creds_async[i], &a.cred)) {
1720                         printf("Credential chaining failed at async %d\n", i);
1721                         break;
1722                 }
1723         }
1724
1725         printf("Testing netr_LogonGetDomainInfo - async count %d OK\n", async_counter);
1726
1727         return async_counter == ASYNC_COUNT;
1728 }
1729
1730
1731 BOOL torture_rpc_netlogon(void)
1732 {
1733         NTSTATUS status;
1734         struct dcerpc_pipe *p;
1735         TALLOC_CTX *mem_ctx;
1736         BOOL ret = True;
1737         void *join_ctx;
1738
1739         mem_ctx = talloc_init("torture_rpc_netlogon");
1740
1741         join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST, 
1742                                        &machine_password);
1743         if (!join_ctx) {
1744                 printf("Failed to join as BDC\n");
1745                 return False;
1746         }
1747
1748         status = torture_rpc_connection(&p, 
1749                                         DCERPC_NETLOGON_NAME,
1750                                         DCERPC_NETLOGON_UUID,
1751                                         DCERPC_NETLOGON_VERSION);
1752         if (!NT_STATUS_IS_OK(status)) {
1753                 return False;
1754         }
1755
1756         if (!test_LogonUasLogon(p, mem_ctx)) {
1757                 ret = False;
1758         }
1759
1760         if (!test_LogonUasLogoff(p, mem_ctx)) {
1761                 ret = False;
1762         }
1763
1764         if (!test_SetPassword(p, mem_ctx)) {
1765                 ret = False;
1766         }
1767
1768         if (!test_SamLogon(p, mem_ctx)) {
1769                 ret = False;
1770         }
1771
1772         if (!test_GetDomainInfo(p, mem_ctx)) {
1773                 ret = False;
1774         }
1775
1776         if (!test_DatabaseSync(p, mem_ctx)) {
1777                 ret = False;
1778         }
1779
1780         if (!test_DatabaseDeltas(p, mem_ctx)) {
1781                 ret = False;
1782         }
1783
1784         if (!test_AccountDeltas(p, mem_ctx)) {
1785                 ret = False;
1786         }
1787
1788         if (!test_AccountSync(p, mem_ctx)) {
1789                 ret = False;
1790         }
1791
1792         if (!test_GetDcName(p, mem_ctx)) {
1793                 ret = False;
1794         }
1795
1796         if (!test_LogonControl(p, mem_ctx)) {
1797                 ret = False;
1798         }
1799
1800         if (!test_GetAnyDCName(p, mem_ctx)) {
1801                 ret = False;
1802         }
1803
1804         if (!test_LogonControl2(p, mem_ctx)) {
1805                 ret = False;
1806         }
1807
1808         if (!test_DatabaseSync2(p, mem_ctx)) {
1809                 ret = False;
1810         }
1811
1812         if (!test_LogonControl2Ex(p, mem_ctx)) {
1813                 ret = False;
1814         }
1815
1816         if (!test_DsrEnumerateDomainTrusts(p, mem_ctx)) {
1817                 ret = False;
1818         }
1819
1820         if (!test_GetDomainInfo_async(p, mem_ctx)) {
1821                 ret = False;
1822         }
1823
1824         talloc_destroy(mem_ctx);
1825
1826         torture_rpc_close(p);
1827
1828         torture_leave_domain(join_ctx);
1829
1830         return ret;
1831 }