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