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