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