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