r816: - Make use of tridge's new samdb_result_sid_prefix() helper function.
[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 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         /* by changing the machine password twice we test the
1054            credentials chaining fully, and we verify that the server
1055            allows the password to be set to the same value twice in a
1056            row (match win2k3) */
1057         printf("Testing a second ServerPasswordSet on machine account\n");
1058         printf("Changing machine account password to '%s' (same as pervsious run)\n", password);
1059
1060         creds_client_authenticator(&creds, &r.in.credential);
1061
1062         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
1063         if (!NT_STATUS_IS_OK(status)) {
1064                 printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
1065                 return False;
1066         }
1067
1068         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1069                 printf("Credential chaining failed\n");
1070         }
1071
1072         join.machine_password = password;
1073
1074         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1075                 printf("ServerPasswordSet failed to actually change the password\n");
1076                 return False;
1077         }
1078
1079         return True;
1080 }
1081
1082
1083 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
1084 static struct ULONG8 sequence_nums[3];
1085
1086 /*
1087   try a netlogon DatabaseSync
1088 */
1089 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1090 {
1091         NTSTATUS status;
1092         struct netr_DatabaseSync r;
1093         struct creds_CredentialState creds;
1094         const uint32 database_ids[] = {0, 1, 2}; 
1095         int i;
1096         BOOL ret = True;
1097
1098         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1099                 return False;
1100         }
1101
1102         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1103         r.in.computername = TEST_MACHINE_NAME;
1104         r.in.preferredmaximumlength = (uint32)-1;
1105         ZERO_STRUCT(r.in.return_authenticator);
1106
1107         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1108                 r.in.sync_context = 0;
1109                 r.in.database_id = database_ids[i];
1110
1111                 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
1112
1113                 do {
1114                         creds_client_authenticator(&creds, &r.in.credential);
1115
1116                         status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
1117                         if (!NT_STATUS_IS_OK(status) &&
1118                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1119                                 printf("DatabaseSync - %s\n", nt_errstr(status));
1120                                 ret = False;
1121                                 break;
1122                         }
1123
1124                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1125                                 printf("Credential chaining failed\n");
1126                         }
1127
1128                         r.in.sync_context = r.out.sync_context;
1129
1130                         if (r.out.delta_enum_array &&
1131                             r.out.delta_enum_array->num_deltas > 0 &&
1132                             r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
1133                             r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
1134                                 sequence_nums[r.in.database_id] = 
1135                                         r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
1136                                 printf("\tsequence_nums[%d]=0x%08x%08x\n",
1137                                        r.in.database_id, 
1138                                        sequence_nums[r.in.database_id].high,
1139                                        sequence_nums[r.in.database_id].low);
1140                         }
1141                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1142         }
1143
1144         return ret;
1145 }
1146
1147
1148 /*
1149   try a netlogon DatabaseDeltas
1150 */
1151 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1152 {
1153         NTSTATUS status;
1154         struct netr_DatabaseDeltas r;
1155         struct creds_CredentialState creds;
1156         const uint32 database_ids[] = {0, 1, 2}; 
1157         int i;
1158         BOOL ret = True;
1159
1160         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1161                 return False;
1162         }
1163
1164         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1165         r.in.computername = TEST_MACHINE_NAME;
1166         r.in.preferredmaximumlength = (uint32)-1;
1167         ZERO_STRUCT(r.in.return_authenticator);
1168
1169         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1170                 r.in.database_id = database_ids[i];
1171                 r.in.sequence_num = sequence_nums[r.in.database_id];
1172
1173                 if (r.in.sequence_num.low == 0) continue;
1174
1175                 r.in.sequence_num.low -= 1;
1176
1177
1178                 printf("Testing DatabaseDeltas of id %d at %d\n", 
1179                        r.in.database_id, r.in.sequence_num.low);
1180
1181                 do {
1182                         creds_client_authenticator(&creds, &r.in.credential);
1183
1184                         status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
1185                         if (!NT_STATUS_IS_OK(status) &&
1186                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1187                                 printf("DatabaseDeltas - %s\n", nt_errstr(status));
1188                                 ret = False;
1189                                 break;
1190                         }
1191
1192                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1193                                 printf("Credential chaining failed\n");
1194                         }
1195
1196                         r.in.sequence_num.low++;
1197                         r.in.sequence_num.high = 0;
1198                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1199         }
1200
1201         return ret;
1202 }
1203
1204
1205 /*
1206   try a netlogon AccountDeltas
1207 */
1208 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1209 {
1210         NTSTATUS status;
1211         struct netr_AccountDeltas r;
1212         struct creds_CredentialState creds;
1213         BOOL ret = True;
1214
1215         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1216                 return False;
1217         }
1218
1219         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1220         r.in.computername = TEST_MACHINE_NAME;
1221         ZERO_STRUCT(r.in.return_authenticator);
1222         creds_client_authenticator(&creds, &r.in.credential);
1223         ZERO_STRUCT(r.in.uas);
1224         r.in.count=10;
1225         r.in.level=0;
1226         r.in.buffersize=100;
1227
1228         printf("Testing AccountDeltas\n");
1229
1230         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1231         status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
1232         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1233                 printf("AccountDeltas - %s\n", nt_errstr(status));
1234                 ret = False;
1235         }
1236
1237         return ret;
1238 }
1239
1240 /*
1241   try a netlogon AccountSync
1242 */
1243 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1244 {
1245         NTSTATUS status;
1246         struct netr_AccountSync r;
1247         struct creds_CredentialState creds;
1248         BOOL ret = True;
1249
1250         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1251                 return False;
1252         }
1253
1254         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1255         r.in.computername = TEST_MACHINE_NAME;
1256         ZERO_STRUCT(r.in.return_authenticator);
1257         creds_client_authenticator(&creds, &r.in.credential);
1258         ZERO_STRUCT(r.in.recordid);
1259         r.in.reference=0;
1260         r.in.level=0;
1261         r.in.buffersize=100;
1262
1263         printf("Testing AccountSync\n");
1264
1265         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1266         status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
1267         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1268                 printf("AccountSync - %s\n", nt_errstr(status));
1269                 ret = False;
1270         }
1271
1272         return ret;
1273 }
1274
1275 /*
1276   try a netlogon GetDcName
1277 */
1278 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1279 {
1280         NTSTATUS status;
1281         struct netr_GetDcName r;
1282
1283         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1284         r.in.domainname = lp_workgroup();
1285
1286         printf("Testing GetDcName\n");
1287
1288         status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
1289         if (!NT_STATUS_IS_OK(status)) {
1290                 printf("GetDcName - %s\n", nt_errstr(status));
1291                 return False;
1292         }
1293
1294         printf("\tDC is at '%s'\n", r.out.dcname);
1295
1296         return True;
1297 }
1298
1299 /*
1300   try a netlogon LogonControl 
1301 */
1302 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1303 {
1304         NTSTATUS status;
1305         struct netr_LogonControl r;
1306         BOOL ret = True;
1307         int i;
1308
1309         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1310         r.in.function_code = 1;
1311
1312         for (i=1;i<4;i++) {
1313                 r.in.level = i;
1314
1315                 printf("Testing LogonControl level %d\n", i);
1316
1317                 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
1318                 if (!NT_STATUS_IS_OK(status)) {
1319                         printf("LogonControl - %s\n", nt_errstr(status));
1320                         ret = False;
1321                 }
1322         }
1323
1324         return ret;
1325 }
1326
1327
1328 /*
1329   try a netlogon GetAnyDCName
1330 */
1331 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1332 {
1333         NTSTATUS status;
1334         struct netr_GetAnyDCName r;
1335
1336         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1337         r.in.domainname = lp_workgroup();
1338
1339         printf("Testing GetAnyDCName\n");
1340
1341         status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
1342         if (!NT_STATUS_IS_OK(status)) {
1343                 printf("GetAnyDCName - %s\n", nt_errstr(status));
1344                 return False;
1345         }
1346
1347         if (r.out.dcname) {
1348                 printf("\tDC is at '%s'\n", r.out.dcname);
1349         }
1350
1351         return True;
1352 }
1353
1354
1355 /*
1356   try a netlogon LogonControl2
1357 */
1358 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1359 {
1360         NTSTATUS status;
1361         struct netr_LogonControl2 r;
1362         BOOL ret = True;
1363         int i;
1364
1365         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1366
1367         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1368         r.in.data.domain = lp_workgroup();
1369
1370         for (i=1;i<4;i++) {
1371                 r.in.level = i;
1372
1373                 printf("Testing LogonControl2 level %d function %d\n", 
1374                        i, r.in.function_code);
1375
1376                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1377                 if (!NT_STATUS_IS_OK(status)) {
1378                         printf("LogonControl - %s\n", nt_errstr(status));
1379                         ret = False;
1380                 }
1381         }
1382
1383         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1384         r.in.data.domain = lp_workgroup();
1385
1386         for (i=1;i<4;i++) {
1387                 r.in.level = i;
1388
1389                 printf("Testing LogonControl2 level %d function %d\n", 
1390                        i, r.in.function_code);
1391
1392                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1393                 if (!NT_STATUS_IS_OK(status)) {
1394                         printf("LogonControl - %s\n", nt_errstr(status));
1395                         ret = False;
1396                 }
1397         }
1398
1399         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1400         r.in.data.domain = lp_workgroup();
1401
1402         for (i=1;i<4;i++) {
1403                 r.in.level = i;
1404
1405                 printf("Testing LogonControl2 level %d function %d\n", 
1406                        i, r.in.function_code);
1407
1408                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1409                 if (!NT_STATUS_IS_OK(status)) {
1410                         printf("LogonControl - %s\n", nt_errstr(status));
1411                         ret = False;
1412                 }
1413         }
1414
1415         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1416         r.in.data.debug_level = ~0;
1417
1418         for (i=1;i<4;i++) {
1419                 r.in.level = i;
1420
1421                 printf("Testing LogonControl2 level %d function %d\n", 
1422                        i, r.in.function_code);
1423
1424                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1425                 if (!NT_STATUS_IS_OK(status)) {
1426                         printf("LogonControl - %s\n", nt_errstr(status));
1427                         ret = False;
1428                 }
1429         }
1430
1431         return ret;
1432 }
1433
1434 /*
1435   try a netlogon DatabaseSync2
1436 */
1437 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1438 {
1439         NTSTATUS status;
1440         struct netr_DatabaseSync2 r;
1441         struct creds_CredentialState creds;
1442         const uint32 database_ids[] = {0, 1, 2}; 
1443         int i;
1444         BOOL ret = True;
1445
1446         if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &creds)) {
1447                 return False;
1448         }
1449
1450         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1451         r.in.computername = TEST_MACHINE_NAME;
1452         r.in.preferredmaximumlength = (uint32)-1;
1453         ZERO_STRUCT(r.in.return_authenticator);
1454
1455         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1456                 r.in.sync_context = 0;
1457                 r.in.database_id = database_ids[i];
1458                 r.in.restart_state = 0;
1459
1460                 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
1461
1462                 do {
1463                         creds_client_authenticator(&creds, &r.in.credential);
1464
1465                         status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
1466                         if (!NT_STATUS_IS_OK(status) &&
1467                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1468                                 printf("DatabaseSync2 - %s\n", nt_errstr(status));
1469                                 ret = False;
1470                                 break;
1471                         }
1472
1473                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1474                                 printf("Credential chaining failed\n");
1475                         }
1476
1477                         r.in.sync_context = r.out.sync_context;
1478                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1479         }
1480
1481         return ret;
1482 }
1483
1484
1485 /*
1486   try a netlogon LogonControl2Ex
1487 */
1488 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1489 {
1490         NTSTATUS status;
1491         struct netr_LogonControl2Ex r;
1492         BOOL ret = True;
1493         int i;
1494
1495         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1496
1497         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1498         r.in.data.domain = lp_workgroup();
1499
1500         for (i=1;i<4;i++) {
1501                 r.in.level = i;
1502
1503                 printf("Testing LogonControl2Ex level %d function %d\n", 
1504                        i, r.in.function_code);
1505
1506                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1507                 if (!NT_STATUS_IS_OK(status)) {
1508                         printf("LogonControl - %s\n", nt_errstr(status));
1509                         ret = False;
1510                 }
1511         }
1512
1513         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1514         r.in.data.domain = lp_workgroup();
1515
1516         for (i=1;i<4;i++) {
1517                 r.in.level = i;
1518
1519                 printf("Testing LogonControl2Ex level %d function %d\n", 
1520                        i, r.in.function_code);
1521
1522                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1523                 if (!NT_STATUS_IS_OK(status)) {
1524                         printf("LogonControl - %s\n", nt_errstr(status));
1525                         ret = False;
1526                 }
1527         }
1528
1529         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1530         r.in.data.domain = lp_workgroup();
1531
1532         for (i=1;i<4;i++) {
1533                 r.in.level = i;
1534
1535                 printf("Testing LogonControl2Ex level %d function %d\n", 
1536                        i, r.in.function_code);
1537
1538                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1539                 if (!NT_STATUS_IS_OK(status)) {
1540                         printf("LogonControl - %s\n", nt_errstr(status));
1541                         ret = False;
1542                 }
1543         }
1544
1545         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1546         r.in.data.debug_level = ~0;
1547
1548         for (i=1;i<4;i++) {
1549                 r.in.level = i;
1550
1551                 printf("Testing LogonControl2Ex level %d function %d\n", 
1552                        i, r.in.function_code);
1553
1554                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1555                 if (!NT_STATUS_IS_OK(status)) {
1556                         printf("LogonControl - %s\n", nt_errstr(status));
1557                         ret = False;
1558                 }
1559         }
1560
1561         return ret;
1562 }
1563
1564
1565
1566 BOOL torture_rpc_netlogon(int dummy)
1567 {
1568         NTSTATUS status;
1569         struct dcerpc_pipe *p;
1570         TALLOC_CTX *mem_ctx;
1571         BOOL ret = True;
1572
1573         mem_ctx = talloc_init("torture_rpc_netlogon");
1574
1575         if (!join_domain_bdc(mem_ctx)) {
1576                 printf("Failed to join as BDC\n");
1577                 return False;
1578         }
1579
1580         status = torture_rpc_connection(&p, 
1581                                         DCERPC_NETLOGON_NAME,
1582                                         DCERPC_NETLOGON_UUID,
1583                                         DCERPC_NETLOGON_VERSION);
1584         if (!NT_STATUS_IS_OK(status)) {
1585                 return False;
1586         }
1587
1588         if (!test_LogonUasLogon(p, mem_ctx)) {
1589                 ret = False;
1590         }
1591
1592         if (!test_LogonUasLogoff(p, mem_ctx)) {
1593                 ret = False;
1594         }
1595
1596         if (!test_SetPassword(p, mem_ctx)) {
1597                 ret = False;
1598         }
1599
1600         if (!test_SamLogon(p, mem_ctx)) {
1601                 ret = False;
1602         }
1603
1604         if (!test_DatabaseSync(p, mem_ctx)) {
1605                 ret = False;
1606         }
1607
1608         if (!test_DatabaseDeltas(p, mem_ctx)) {
1609                 ret = False;
1610         }
1611
1612         if (!test_AccountDeltas(p, mem_ctx)) {
1613                 ret = False;
1614         }
1615
1616         if (!test_AccountSync(p, mem_ctx)) {
1617                 ret = False;
1618         }
1619
1620         if (!test_GetDcName(p, mem_ctx)) {
1621                 ret = False;
1622         }
1623
1624         if (!test_LogonControl(p, mem_ctx)) {
1625                 ret = False;
1626         }
1627
1628         if (!test_GetAnyDCName(p, mem_ctx)) {
1629                 ret = False;
1630         }
1631
1632         if (!test_LogonControl2(p, mem_ctx)) {
1633                 ret = False;
1634         }
1635
1636         if (!test_DatabaseSync2(p, mem_ctx)) {
1637                 ret = False;
1638         }
1639
1640         if (!test_LogonControl2Ex(p, mem_ctx)) {
1641                 ret = False;
1642         }
1643
1644         torture_rpc_close(p);
1645
1646         if (!leave_domain_bdc(mem_ctx)) {
1647                 printf("Failed to delete BDC machine account\n");
1648                 return False;
1649         }
1650
1651         return ret;
1652 }