r2552: Character set conversion and string handling updates.
[samba.git] / source / torture / rpc / netlogon.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    test suite for netlogon rpc operations
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
8    Copyright (C) Tim Potter      2003
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26
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 (samlogon_state->r.in.logon_level == 6 || !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         smb_ucs2_t *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, (smb_ucs2_t **)&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, 
797                                        strlen_w(((void *)unicodepw))*sizeof(smb_ucs2_t));
798
799         password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password);
800
801         if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX, 
802                                    CH_DOS, password,
803                                    strlen(password)+1, 
804                                    (void**)&dospw)) == -1) {
805                 DEBUG(0, ("convert_string_talloc failed!\n"));
806                 exit(1);
807         }
808
809         lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
810
811         nt_status = check_samlogon(samlogon_state,
812                                    break_which,
813                                    &chall,
814                                    &lm_response,
815                                    &nt_response,
816                                    lm_key, 
817                                    user_session_key,
818                                    error_string);
819         
820         if (!NT_STATUS_IS_OK(nt_status)) {
821                 return break_which == BREAK_NT;
822         }
823
824         return True;
825 }
826
827 static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state, 
828                                        char **error_string) {
829         return test_plaintext(samlogon_state, BREAK_NONE, error_string);
830 }
831
832 static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state, 
833                                      char **error_string) {
834         return test_plaintext(samlogon_state, BREAK_LM, error_string);
835 }
836
837 static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state, 
838                                      char **error_string) {
839         return test_plaintext(samlogon_state, BREAK_NT, error_string);
840 }
841
842 static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state, 
843                                    char **error_string) {
844         return test_plaintext(samlogon_state, NO_LM, error_string);
845 }
846
847 static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state, 
848                                    char **error_string) {
849         return test_plaintext(samlogon_state, NO_NT, error_string);
850 }
851
852 /* 
853    Tests:
854    
855    - LM only
856    - NT and LM             
857    - NT
858    - NT in LM field
859    - NT in both fields
860    - NTLMv2
861    - NTLMv2 and LMv2
862    - LMv2
863    - plaintext tests (in challenge-response fields)
864   
865    check we get the correct session key in each case
866    check what values we get for the LM session key
867    
868 */
869
870 static const struct ntlm_tests {
871         BOOL (*fn)(struct samlogon_state *, char **);
872         const char *name;
873         BOOL expect_fail;
874 } test_table[] = {
875         {test_lm, "LM", False},
876         {test_lm_ntlm, "LM and NTLM", False},
877         {test_ntlm, "NTLM", False},
878         {test_ntlm_in_lm, "NTLM in LM", False},
879         {test_ntlm_in_both, "NTLM in both", False},
880         {test_ntlmv2, "NTLMv2", False},
881         {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
882         {test_lmv2, "LMv2", False},
883         {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
884         {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
885         {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
886         {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
887         {test_plaintext_none_broken, "Plaintext", True},
888         {test_plaintext_lm_broken, "Plaintext LM broken", True},
889         {test_plaintext_nt_broken, "Plaintext NT broken", True},
890         {test_plaintext_nt_only, "Plaintext NT only", True},
891         {test_plaintext_lm_only, "Plaintext LM only", True},
892         {NULL, NULL}
893 };
894
895 /*
896   try a netlogon SamLogon
897 */
898 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
899 {
900         int i, v, l;
901         BOOL ret = True;
902         int validation_levels[] = {2,3,6};
903         int logon_levels[] = { 2, 6 };
904         struct samlogon_state samlogon_state;
905         
906         samlogon_state.mem_ctx = mem_ctx;
907         samlogon_state.account_name = lp_parm_string(-1, "torture", "username");
908         samlogon_state.account_domain = lp_parm_string(-1, "torture", "userdomain");
909         samlogon_state.password = lp_parm_string(-1, "torture", "password");
910         samlogon_state.p = p;
911
912         samlogon_state.chall = data_blob_talloc(mem_ctx, NULL, 8);
913
914         generate_random_buffer(samlogon_state.chall.data, 8);
915
916         if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
917                 return False;
918         }
919
920         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
921                 return False;
922         }
923
924         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &samlogon_state.creds)) {
925                 return False;
926         }
927
928         samlogon_state.r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
929         samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
930         samlogon_state.r.in.credential = &samlogon_state.auth;
931         samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
932
933         for (i=0; test_table[i].fn; i++) {
934                 for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
935                         for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
936                                 char *error_string = NULL;
937                                 samlogon_state.r.in.validation_level = validation_levels[v];
938                                 samlogon_state.r.in.logon_level = logon_levels[l];
939                                 printf("Testing SamLogon with '%s' at validation level %d, logon level %d\n", 
940                                        test_table[i].name, validation_levels[v], logon_levels[l]);
941         
942                                 if (!test_table[i].fn(&samlogon_state, &error_string)) {
943                                         if (test_table[i].expect_fail) {
944                                                 printf("Test %s failed (expected, test incomplete): %s\n", test_table[i].name, error_string);
945                                         } else {
946                                                 printf("Test %s failed: %s\n", test_table[i].name, error_string);
947                                                 ret = False;
948                                         }
949                                         SAFE_FREE(error_string);
950                                 }
951                         }
952                 }
953         }
954
955         return ret;
956 }
957
958
959 /*
960   try a change password for our machine account
961 */
962 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
963 {
964         NTSTATUS status;
965         struct netr_ServerPasswordSet r;
966         const char *password;
967         struct creds_CredentialState creds;
968
969         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
970                 return False;
971         }
972
973         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
974         r.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
975         r.in.secure_channel_type = SEC_CHAN_BDC;
976         r.in.computer_name = TEST_MACHINE_NAME;
977
978         password = generate_random_str(mem_ctx, 8);
979         E_md4hash(password, r.in.new_password.hash);
980
981         creds_des_encrypt(&creds, &r.in.new_password);
982
983         printf("Testing ServerPasswordSet on machine account\n");
984         printf("Changing machine account password to '%s'\n", password);
985
986         creds_client_authenticator(&creds, &r.in.credential);
987
988         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
989         if (!NT_STATUS_IS_OK(status)) {
990                 printf("ServerPasswordSet - %s\n", nt_errstr(status));
991                 return False;
992         }
993
994         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
995                 printf("Credential chaining failed\n");
996         }
997
998         /* by changing the machine password twice we test the
999            credentials chaining fully, and we verify that the server
1000            allows the password to be set to the same value twice in a
1001            row (match win2k3) */
1002         printf("Testing a second ServerPasswordSet on machine account\n");
1003         printf("Changing machine account password to '%s' (same as previous run)\n", password);
1004
1005         creds_client_authenticator(&creds, &r.in.credential);
1006
1007         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
1008         if (!NT_STATUS_IS_OK(status)) {
1009                 printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
1010                 return False;
1011         }
1012
1013         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1014                 printf("Credential chaining failed\n");
1015         }
1016
1017         machine_password = password;
1018
1019         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1020                 printf("ServerPasswordSet failed to actually change the password\n");
1021                 return False;
1022         }
1023
1024         return True;
1025 }
1026
1027
1028 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
1029 static uint64_t sequence_nums[3];
1030
1031 /*
1032   try a netlogon DatabaseSync
1033 */
1034 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1035 {
1036         NTSTATUS status;
1037         struct netr_DatabaseSync r;
1038         struct creds_CredentialState creds;
1039         const uint32_t database_ids[] = {0, 1, 2}; 
1040         int i;
1041         BOOL ret = True;
1042
1043         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1044                 return False;
1045         }
1046
1047         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1048         r.in.computername = TEST_MACHINE_NAME;
1049         r.in.preferredmaximumlength = (uint32_t)-1;
1050         ZERO_STRUCT(r.in.return_authenticator);
1051
1052         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1053                 r.in.sync_context = 0;
1054                 r.in.database_id = database_ids[i];
1055
1056                 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
1057
1058                 do {
1059                         creds_client_authenticator(&creds, &r.in.credential);
1060
1061                         status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
1062                         if (!NT_STATUS_IS_OK(status) &&
1063                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1064                                 printf("DatabaseSync - %s\n", nt_errstr(status));
1065                                 ret = False;
1066                                 break;
1067                         }
1068
1069                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1070                                 printf("Credential chaining failed\n");
1071                         }
1072
1073                         r.in.sync_context = r.out.sync_context;
1074
1075                         if (r.out.delta_enum_array &&
1076                             r.out.delta_enum_array->num_deltas > 0 &&
1077                             r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
1078                             r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
1079                                 sequence_nums[r.in.database_id] = 
1080                                         r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
1081                                 printf("\tsequence_nums[%d]=%llu\n",
1082                                        r.in.database_id, 
1083                                        sequence_nums[r.in.database_id]);
1084                         }
1085                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1086         }
1087
1088         return ret;
1089 }
1090
1091
1092 /*
1093   try a netlogon DatabaseDeltas
1094 */
1095 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1096 {
1097         NTSTATUS status;
1098         struct netr_DatabaseDeltas r;
1099         struct creds_CredentialState creds;
1100         const uint32_t database_ids[] = {0, 1, 2}; 
1101         int i;
1102         BOOL ret = True;
1103
1104         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1105                 return False;
1106         }
1107
1108         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1109         r.in.computername = TEST_MACHINE_NAME;
1110         r.in.preferredmaximumlength = (uint32_t)-1;
1111         ZERO_STRUCT(r.in.return_authenticator);
1112
1113         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1114                 r.in.database_id = database_ids[i];
1115                 r.in.sequence_num = sequence_nums[r.in.database_id];
1116
1117                 if (r.in.sequence_num == 0) continue;
1118
1119                 r.in.sequence_num -= 1;
1120
1121
1122                 printf("Testing DatabaseDeltas of id %d at %llu\n", 
1123                        r.in.database_id, r.in.sequence_num);
1124
1125                 do {
1126                         creds_client_authenticator(&creds, &r.in.credential);
1127
1128                         status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
1129                         if (!NT_STATUS_IS_OK(status) &&
1130                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1131                                 printf("DatabaseDeltas - %s\n", nt_errstr(status));
1132                                 ret = False;
1133                                 break;
1134                         }
1135
1136                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1137                                 printf("Credential chaining failed\n");
1138                         }
1139
1140                         r.in.sequence_num++;
1141                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1142         }
1143
1144         return ret;
1145 }
1146
1147
1148 /*
1149   try a netlogon AccountDeltas
1150 */
1151 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1152 {
1153         NTSTATUS status;
1154         struct netr_AccountDeltas r;
1155         struct creds_CredentialState creds;
1156         BOOL ret = True;
1157
1158         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1159                 return False;
1160         }
1161
1162         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1163         r.in.computername = TEST_MACHINE_NAME;
1164         ZERO_STRUCT(r.in.return_authenticator);
1165         creds_client_authenticator(&creds, &r.in.credential);
1166         ZERO_STRUCT(r.in.uas);
1167         r.in.count=10;
1168         r.in.level=0;
1169         r.in.buffersize=100;
1170
1171         printf("Testing AccountDeltas\n");
1172
1173         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1174         status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
1175         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1176                 printf("AccountDeltas - %s\n", nt_errstr(status));
1177                 ret = False;
1178         }
1179
1180         return ret;
1181 }
1182
1183 /*
1184   try a netlogon AccountSync
1185 */
1186 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1187 {
1188         NTSTATUS status;
1189         struct netr_AccountSync r;
1190         struct creds_CredentialState creds;
1191         BOOL ret = True;
1192
1193         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1194                 return False;
1195         }
1196
1197         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1198         r.in.computername = TEST_MACHINE_NAME;
1199         ZERO_STRUCT(r.in.return_authenticator);
1200         creds_client_authenticator(&creds, &r.in.credential);
1201         ZERO_STRUCT(r.in.recordid);
1202         r.in.reference=0;
1203         r.in.level=0;
1204         r.in.buffersize=100;
1205
1206         printf("Testing AccountSync\n");
1207
1208         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1209         status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
1210         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1211                 printf("AccountSync - %s\n", nt_errstr(status));
1212                 ret = False;
1213         }
1214
1215         return ret;
1216 }
1217
1218 /*
1219   try a netlogon GetDcName
1220 */
1221 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1222 {
1223         NTSTATUS status;
1224         struct netr_GetDcName r;
1225
1226         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1227         r.in.domainname = lp_workgroup();
1228
1229         printf("Testing GetDcName\n");
1230
1231         status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
1232         if (!NT_STATUS_IS_OK(status)) {
1233                 printf("GetDcName - %s\n", nt_errstr(status));
1234                 return False;
1235         }
1236
1237         printf("\tDC is at '%s'\n", r.out.dcname);
1238
1239         return True;
1240 }
1241
1242 /*
1243   try a netlogon LogonControl 
1244 */
1245 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1246 {
1247         NTSTATUS status;
1248         struct netr_LogonControl r;
1249         BOOL ret = True;
1250         int i;
1251
1252         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1253         r.in.function_code = 1;
1254
1255         for (i=1;i<4;i++) {
1256                 r.in.level = i;
1257
1258                 printf("Testing LogonControl level %d\n", i);
1259
1260                 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
1261                 if (!NT_STATUS_IS_OK(status)) {
1262                         printf("LogonControl - %s\n", nt_errstr(status));
1263                         ret = False;
1264                 }
1265         }
1266
1267         return ret;
1268 }
1269
1270
1271 /*
1272   try a netlogon GetAnyDCName
1273 */
1274 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1275 {
1276         NTSTATUS status;
1277         struct netr_GetAnyDCName r;
1278
1279         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1280         r.in.domainname = lp_workgroup();
1281
1282         printf("Testing GetAnyDCName\n");
1283
1284         status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
1285         if (!NT_STATUS_IS_OK(status)) {
1286                 printf("GetAnyDCName - %s\n", nt_errstr(status));
1287                 return False;
1288         }
1289
1290         if (r.out.dcname) {
1291                 printf("\tDC is at '%s'\n", r.out.dcname);
1292         }
1293
1294         return True;
1295 }
1296
1297
1298 /*
1299   try a netlogon LogonControl2
1300 */
1301 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1302 {
1303         NTSTATUS status;
1304         struct netr_LogonControl2 r;
1305         BOOL ret = True;
1306         int i;
1307
1308         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1309
1310         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1311         r.in.data.domain = lp_workgroup();
1312
1313         for (i=1;i<4;i++) {
1314                 r.in.level = i;
1315
1316                 printf("Testing LogonControl2 level %d function %d\n", 
1317                        i, r.in.function_code);
1318
1319                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1320                 if (!NT_STATUS_IS_OK(status)) {
1321                         printf("LogonControl - %s\n", nt_errstr(status));
1322                         ret = False;
1323                 }
1324         }
1325
1326         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1327         r.in.data.domain = lp_workgroup();
1328
1329         for (i=1;i<4;i++) {
1330                 r.in.level = i;
1331
1332                 printf("Testing LogonControl2 level %d function %d\n", 
1333                        i, r.in.function_code);
1334
1335                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1336                 if (!NT_STATUS_IS_OK(status)) {
1337                         printf("LogonControl - %s\n", nt_errstr(status));
1338                         ret = False;
1339                 }
1340         }
1341
1342         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1343         r.in.data.domain = lp_workgroup();
1344
1345         for (i=1;i<4;i++) {
1346                 r.in.level = i;
1347
1348                 printf("Testing LogonControl2 level %d function %d\n", 
1349                        i, r.in.function_code);
1350
1351                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1352                 if (!NT_STATUS_IS_OK(status)) {
1353                         printf("LogonControl - %s\n", nt_errstr(status));
1354                         ret = False;
1355                 }
1356         }
1357
1358         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1359         r.in.data.debug_level = ~0;
1360
1361         for (i=1;i<4;i++) {
1362                 r.in.level = i;
1363
1364                 printf("Testing LogonControl2 level %d function %d\n", 
1365                        i, r.in.function_code);
1366
1367                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1368                 if (!NT_STATUS_IS_OK(status)) {
1369                         printf("LogonControl - %s\n", nt_errstr(status));
1370                         ret = False;
1371                 }
1372         }
1373
1374         return ret;
1375 }
1376
1377 /*
1378   try a netlogon DatabaseSync2
1379 */
1380 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1381 {
1382         NTSTATUS status;
1383         struct netr_DatabaseSync2 r;
1384         struct creds_CredentialState creds;
1385         const uint32_t database_ids[] = {0, 1, 2}; 
1386         int i;
1387         BOOL ret = True;
1388
1389         if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &creds)) {
1390                 return False;
1391         }
1392
1393         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1394         r.in.computername = TEST_MACHINE_NAME;
1395         r.in.preferredmaximumlength = (uint32_t)-1;
1396         ZERO_STRUCT(r.in.return_authenticator);
1397
1398         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1399                 r.in.sync_context = 0;
1400                 r.in.database_id = database_ids[i];
1401                 r.in.restart_state = 0;
1402
1403                 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
1404
1405                 do {
1406                         creds_client_authenticator(&creds, &r.in.credential);
1407
1408                         status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
1409                         if (!NT_STATUS_IS_OK(status) &&
1410                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1411                                 printf("DatabaseSync2 - %s\n", nt_errstr(status));
1412                                 ret = False;
1413                                 break;
1414                         }
1415
1416                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1417                                 printf("Credential chaining failed\n");
1418                         }
1419
1420                         r.in.sync_context = r.out.sync_context;
1421                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1422         }
1423
1424         return ret;
1425 }
1426
1427
1428 /*
1429   try a netlogon LogonControl2Ex
1430 */
1431 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1432 {
1433         NTSTATUS status;
1434         struct netr_LogonControl2Ex r;
1435         BOOL ret = True;
1436         int i;
1437
1438         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1439
1440         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1441         r.in.data.domain = lp_workgroup();
1442
1443         for (i=1;i<4;i++) {
1444                 r.in.level = i;
1445
1446                 printf("Testing LogonControl2Ex level %d function %d\n", 
1447                        i, r.in.function_code);
1448
1449                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1450                 if (!NT_STATUS_IS_OK(status)) {
1451                         printf("LogonControl - %s\n", nt_errstr(status));
1452                         ret = False;
1453                 }
1454         }
1455
1456         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1457         r.in.data.domain = lp_workgroup();
1458
1459         for (i=1;i<4;i++) {
1460                 r.in.level = i;
1461
1462                 printf("Testing LogonControl2Ex level %d function %d\n", 
1463                        i, r.in.function_code);
1464
1465                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1466                 if (!NT_STATUS_IS_OK(status)) {
1467                         printf("LogonControl - %s\n", nt_errstr(status));
1468                         ret = False;
1469                 }
1470         }
1471
1472         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1473         r.in.data.domain = lp_workgroup();
1474
1475         for (i=1;i<4;i++) {
1476                 r.in.level = i;
1477
1478                 printf("Testing LogonControl2Ex level %d function %d\n", 
1479                        i, r.in.function_code);
1480
1481                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1482                 if (!NT_STATUS_IS_OK(status)) {
1483                         printf("LogonControl - %s\n", nt_errstr(status));
1484                         ret = False;
1485                 }
1486         }
1487
1488         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1489         r.in.data.debug_level = ~0;
1490
1491         for (i=1;i<4;i++) {
1492                 r.in.level = i;
1493
1494                 printf("Testing LogonControl2Ex level %d function %d\n", 
1495                        i, r.in.function_code);
1496
1497                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1498                 if (!NT_STATUS_IS_OK(status)) {
1499                         printf("LogonControl - %s\n", nt_errstr(status));
1500                         ret = False;
1501                 }
1502         }
1503
1504         return ret;
1505 }
1506
1507
1508 /*
1509   try a netlogon netr_DsrEnumerateDomainTrusts
1510 */
1511 static BOOL test_DsrEnumerateDomainTrusts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1512 {
1513         NTSTATUS status;
1514         struct netr_DsrEnumerateDomainTrusts r;
1515
1516         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1517         r.in.trust_flags = 0x3f;
1518
1519         printf("Testing netr_DsrEnumerateDomainTrusts\n");
1520
1521         status = dcerpc_netr_DsrEnumerateDomainTrusts(p, mem_ctx, &r);
1522         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1523                 printf("netr_DsrEnumerateDomainTrusts - %s/%s\n", 
1524                        nt_errstr(status), win_errstr(r.out.result));
1525                 return False;
1526         }
1527
1528         return True;
1529 }
1530
1531
1532 /*
1533   test an ADS style interactive domain login
1534 */
1535 static BOOL test_InteractiveLogin(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1536                                   struct creds_CredentialState *creds)
1537 {
1538         NTSTATUS status;
1539         struct netr_LogonSamLogonWithFlags r;
1540         struct netr_Authenticator a, ra;
1541         struct netr_PasswordInfo pinfo;
1542         const char *plain_pass;
1543
1544         ZERO_STRUCT(r);
1545         ZERO_STRUCT(ra);
1546
1547         creds_client_authenticator(creds, &a);
1548
1549         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1550         r.in.workstation = TEST_MACHINE_NAME;
1551         r.in.credential = &a;
1552         r.in.return_authenticator = &ra;
1553         r.in.logon_level = 5;
1554         r.in.logon.password = &pinfo;
1555         r.in.validation_level = 6;
1556         r.in.flags = 0;
1557
1558         pinfo.identity_info.domain_name.string = lp_parm_string(-1, "torture", "userdomain");
1559         pinfo.identity_info.parameter_control = 0;
1560         pinfo.identity_info.logon_id_low = 0;
1561         pinfo.identity_info.logon_id_high = 0;
1562         pinfo.identity_info.account_name.string = lp_parm_string(-1, "torture", "username");
1563         pinfo.identity_info.workstation.string = TEST_MACHINE_NAME;
1564
1565         plain_pass = lp_parm_string(-1, "torture", "password");
1566
1567         E_deshash(plain_pass, pinfo.lmpassword.hash);
1568         E_md4hash(plain_pass, pinfo.ntpassword.hash);
1569
1570         creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
1571         creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
1572
1573         printf("Testing netr_LogonSamLogonWithFlags\n");
1574
1575         status = dcerpc_netr_LogonSamLogonWithFlags(p, mem_ctx, &r);
1576         if (!NT_STATUS_IS_OK(status)) {
1577                 printf("netr_LogonSamLogonWithFlags - %s\n", nt_errstr(status));
1578                 exit(1);
1579                 return False;
1580         }
1581
1582         if (!creds_client_check(creds, &r.out.return_authenticator->cred)) {
1583                 printf("Credential chaining failed\n");
1584                 return False;
1585         }
1586
1587         return True;
1588 }
1589
1590
1591 static BOOL test_GetDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1592 {
1593         NTSTATUS status;
1594         struct netr_LogonGetDomainInfo r;
1595         struct netr_DomainQuery1 q1;
1596         struct netr_Authenticator a;
1597         struct creds_CredentialState creds;
1598
1599         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &creds)) {
1600                 return False;
1601         }
1602
1603         ZERO_STRUCT(r);
1604
1605         creds_client_authenticator(&creds, &a);
1606
1607         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1608         r.in.computer_name = TEST_MACHINE_NAME;
1609         r.in.unknown1 = 512;
1610         r.in.level = 1;
1611         r.in.credential = &a;
1612         r.out.credential = &a;
1613
1614         r.in.i1[0] = 0;
1615         r.in.i1[1] = 0;
1616
1617         r.in.query.query1 = &q1;
1618         ZERO_STRUCT(q1);
1619         
1620         /* this should really be the fully qualified name */
1621         q1.workstation_domain = TEST_MACHINE_NAME;
1622         q1.workstation_site = "Default-First-Site-Name";
1623         q1.blob2.length = 0;
1624         q1.blob2.size = 0;
1625         q1.blob2.data = NULL;
1626         q1.product.string = "product string";
1627
1628         printf("Testing netr_LogonGetDomainInfo\n");
1629
1630         status = dcerpc_netr_LogonGetDomainInfo(p, mem_ctx, &r);
1631         if (!NT_STATUS_IS_OK(status)) {
1632                 printf("netr_LogonGetDomainInfo - %s\n", nt_errstr(status));
1633                 return False;
1634         }
1635
1636         if (!creds_client_check(&creds, &a.cred)) {
1637                 printf("Credential chaining failed\n");
1638                 return False;
1639         }
1640
1641         test_InteractiveLogin(p, mem_ctx, &creds);
1642
1643         return True;
1644 }
1645
1646
1647 static void async_callback(struct rpc_request *req)
1648 {
1649         int *counter = req->async.private;
1650         if (NT_STATUS_IS_OK(req->status)) {
1651                 (*counter)++;
1652         }
1653 }
1654
1655 static BOOL test_GetDomainInfo_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1656 {
1657         NTSTATUS status;
1658         struct netr_LogonGetDomainInfo r;
1659         struct netr_DomainQuery1 q1;
1660         struct netr_Authenticator a;
1661 #define ASYNC_COUNT 100
1662         struct creds_CredentialState creds;
1663         struct creds_CredentialState creds_async[ASYNC_COUNT];
1664         struct rpc_request *req[ASYNC_COUNT];
1665         int i;
1666         int async_counter = 0;
1667
1668         if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &creds)) {
1669                 return False;
1670         }
1671
1672         ZERO_STRUCT(r);
1673         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1674         r.in.computer_name = TEST_MACHINE_NAME;
1675         r.in.unknown1 = 512;
1676         r.in.level = 1;
1677         r.in.credential = &a;
1678         r.out.credential = &a;
1679
1680         r.in.i1[0] = 0;
1681         r.in.i1[1] = 0;
1682
1683         r.in.query.query1 = &q1;
1684         ZERO_STRUCT(q1);
1685         
1686         /* this should really be the fully qualified name */
1687         q1.workstation_domain = TEST_MACHINE_NAME;
1688         q1.workstation_site = "Default-First-Site-Name";
1689         q1.blob2.length = 0;
1690         q1.blob2.size = 0;
1691         q1.blob2.data = NULL;
1692         q1.product.string = "product string";
1693
1694         printf("Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT);
1695
1696         for (i=0;i<ASYNC_COUNT;i++) {
1697                 creds_client_authenticator(&creds, &a);
1698
1699                 creds_async[i] = creds;
1700                 req[i] = dcerpc_netr_LogonGetDomainInfo_send(p, mem_ctx, &r);
1701
1702                 req[i]->async.callback = async_callback;
1703                 req[i]->async.private = &async_counter;
1704
1705                 /* even with this flush per request a w2k3 server seems to 
1706                    clag with multiple outstanding requests. bleergh. */
1707                 if (event_loop_once(dcerpc_event_context(p)) != 0) {
1708                         return False;
1709                 }
1710         }
1711
1712         for (i=0;i<ASYNC_COUNT;i++) {
1713                 status = dcerpc_ndr_request_recv(req[i]);
1714                 if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(r.out.result)) {
1715                         printf("netr_LogonGetDomainInfo_async(%d) - %s/%s\n", 
1716                                i, nt_errstr(status), nt_errstr(r.out.result));
1717                         break;
1718                 }
1719
1720                 if (!creds_client_check(&creds_async[i], &a.cred)) {
1721                         printf("Credential chaining failed at async %d\n", i);
1722                         break;
1723                 }
1724         }
1725
1726         printf("Testing netr_LogonGetDomainInfo - async count %d OK\n", async_counter);
1727
1728         return async_counter == ASYNC_COUNT;
1729 }
1730
1731
1732 BOOL torture_rpc_netlogon(int dummy)
1733 {
1734         NTSTATUS status;
1735         struct dcerpc_pipe *p;
1736         TALLOC_CTX *mem_ctx;
1737         BOOL ret = True;
1738         void *join_ctx;
1739
1740         mem_ctx = talloc_init("torture_rpc_netlogon");
1741
1742         join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST, 
1743                                        &machine_password);
1744         if (!join_ctx) {
1745                 printf("Failed to join as BDC\n");
1746                 return False;
1747         }
1748
1749         status = torture_rpc_connection(&p, 
1750                                         DCERPC_NETLOGON_NAME,
1751                                         DCERPC_NETLOGON_UUID,
1752                                         DCERPC_NETLOGON_VERSION);
1753         if (!NT_STATUS_IS_OK(status)) {
1754                 return False;
1755         }
1756
1757         if (!test_LogonUasLogon(p, mem_ctx)) {
1758                 ret = False;
1759         }
1760
1761         if (!test_LogonUasLogoff(p, mem_ctx)) {
1762                 ret = False;
1763         }
1764
1765         if (!test_SetPassword(p, mem_ctx)) {
1766                 ret = False;
1767         }
1768
1769         if (!test_SamLogon(p, mem_ctx)) {
1770                 ret = False;
1771         }
1772
1773         if (!test_GetDomainInfo(p, mem_ctx)) {
1774                 ret = False;
1775         }
1776
1777         if (!test_DatabaseSync(p, mem_ctx)) {
1778                 ret = False;
1779         }
1780
1781         if (!test_DatabaseDeltas(p, mem_ctx)) {
1782                 ret = False;
1783         }
1784
1785         if (!test_AccountDeltas(p, mem_ctx)) {
1786                 ret = False;
1787         }
1788
1789         if (!test_AccountSync(p, mem_ctx)) {
1790                 ret = False;
1791         }
1792
1793         if (!test_GetDcName(p, mem_ctx)) {
1794                 ret = False;
1795         }
1796
1797         if (!test_LogonControl(p, mem_ctx)) {
1798                 ret = False;
1799         }
1800
1801         if (!test_GetAnyDCName(p, mem_ctx)) {
1802                 ret = False;
1803         }
1804
1805         if (!test_LogonControl2(p, mem_ctx)) {
1806                 ret = False;
1807         }
1808
1809         if (!test_DatabaseSync2(p, mem_ctx)) {
1810                 ret = False;
1811         }
1812
1813         if (!test_LogonControl2Ex(p, mem_ctx)) {
1814                 ret = False;
1815         }
1816
1817         if (!test_DsrEnumerateDomainTrusts(p, mem_ctx)) {
1818                 ret = False;
1819         }
1820
1821         if (!test_GetDomainInfo_async(p, mem_ctx)) {
1822                 ret = False;
1823         }
1824
1825         talloc_destroy(mem_ctx);
1826
1827         torture_rpc_close(p);
1828
1829         torture_leave_domain(join_ctx);
1830
1831         return ret;
1832 }