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