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