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