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