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