bd7a450f586182b08392790d7f419931842727a0
[bbaumbach/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(samlogon_state->mem_ctx, 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(), 
752                               samlogon_state->password, &samlogon_state->chall,
753                               &names_blob,
754                               &lmv2_response, &ntlmv2_response, 
755                               &ntlmv2_session_key)) {
756                 data_blob_free(&names_blob);
757                 return False;
758         }
759         data_blob_free(&names_blob);
760
761         nt_status = check_samlogon(samlogon_state,
762                                    break_which,
763                                    &samlogon_state->chall,
764                                    &lmv2_response,
765                                    &ntlmv2_response,
766                                    NULL, 
767                                    user_session_key,
768                                    error_string);
769         
770         data_blob_free(&lmv2_response);
771         data_blob_free(&ntlmv2_response);
772
773         if (!NT_STATUS_IS_OK(nt_status)) {
774                 return break_which == BREAK_NT;
775         }
776
777         if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key, 
778                    sizeof(user_session_key)) != 0) {
779                 printf("USER (NTLMv2) Session Key does not match expectations!\n");
780                 printf("user_session_key:\n");
781                 dump_data(1, (const char *)user_session_key, 16);
782                 printf("expected:\n");
783                 dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length);
784                 pass = False;
785         }
786         return pass;
787 }
788
789 /* 
790  * Test the NTLMv2 and LMv2 responses
791  */
792
793 static BOOL test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 
794 {
795         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, error_string);
796 }
797
798 /* 
799  * Test the LMv2 response only
800  */
801
802 static BOOL test_lmv2(struct samlogon_state *samlogon_state, char **error_string) 
803 {
804         return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, error_string);
805 }
806
807 /* 
808  * Test the NTLMv2 response only
809  */
810
811 static BOOL test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 
812 {
813         return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, error_string);
814 }
815
816 static BOOL test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
817 {
818         return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
819 }
820
821 static BOOL test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string) 
822 {
823         return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
824 }
825
826 static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string) 
827 {
828         return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
829 }
830
831 static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 
832 {
833         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, error_string);
834 }
835
836 static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 
837 {
838         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, error_string);
839 }
840
841 static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
842 {
843         NTSTATUS nt_status;
844         DATA_BLOB nt_response = data_blob(NULL, 0);
845         DATA_BLOB lm_response = data_blob(NULL, 0);
846         char *password;
847         char *dospw;
848         smb_ucs2_t *unicodepw;
849
850         uchar user_session_key[16];
851         uchar lm_key[16];
852         static const uchar zeros[8];
853         DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
854
855         ZERO_STRUCT(user_session_key);
856         
857         if ((push_ucs2_talloc(samlogon_state->mem_ctx, (smb_ucs2_t **)&unicodepw, 
858                               samlogon_state->password)) == -1) {
859                 DEBUG(0, ("push_ucs2_allocate failed!\n"));
860                 exit(1);
861         }
862
863         nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, 
864                                        strlen_w(((void *)unicodepw))*sizeof(smb_ucs2_t));
865
866         password = strdup_upper(samlogon_state->password);
867
868         if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX, 
869                                    CH_DOS, password,
870                                    strlen(password)+1, 
871                                    (const void**)&dospw)) == -1) {
872                 DEBUG(0, ("push_ascii_allocate failed!\n"));
873                 exit(1);
874         }
875
876         SAFE_FREE(password);
877
878         lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
879
880         nt_status = check_samlogon(samlogon_state,
881                                    break_which,
882                                    &chall,
883                                    &lm_response,
884                                    &nt_response,
885                                    lm_key, 
886                                    user_session_key,
887                                    error_string);
888         
889         if (!NT_STATUS_IS_OK(nt_status)) {
890                 return break_which == BREAK_NT;
891         }
892
893         return True;
894 }
895
896 static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state, 
897                                        char **error_string) {
898         return test_plaintext(samlogon_state, BREAK_NONE, error_string);
899 }
900
901 static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state, 
902                                      char **error_string) {
903         return test_plaintext(samlogon_state, BREAK_LM, error_string);
904 }
905
906 static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state, 
907                                      char **error_string) {
908         return test_plaintext(samlogon_state, BREAK_NT, error_string);
909 }
910
911 static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state, 
912                                    char **error_string) {
913         return test_plaintext(samlogon_state, NO_LM, error_string);
914 }
915
916 static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state, 
917                                    char **error_string) {
918         return test_plaintext(samlogon_state, NO_NT, error_string);
919 }
920
921 /* 
922    Tests:
923    
924    - LM only
925    - NT and LM             
926    - NT
927    - NT in LM field
928    - NT in both fields
929    - NTLMv2
930    - NTLMv2 and LMv2
931    - LMv2
932    - plaintext tests (in challenge-response feilds)
933   
934    check we get the correct session key in each case
935    check what values we get for the LM session key
936    
937 */
938
939 static const struct ntlm_tests {
940         BOOL (*fn)(struct samlogon_state *, char **);
941         const char *name;
942         BOOL expect_fail;
943 } test_table[] = {
944         {test_lm, "LM", False},
945         {test_lm_ntlm, "LM and NTLM", False},
946         {test_ntlm, "NTLM", False},
947         {test_ntlm_in_lm, "NTLM in LM", False},
948         {test_ntlm_in_both, "NTLM in both", False},
949         {test_ntlmv2, "NTLMv2", False},
950         {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
951         {test_lmv2, "LMv2", False},
952         {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
953         {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
954         {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
955         {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
956         {test_plaintext_none_broken, "Plaintext", True},
957         {test_plaintext_lm_broken, "Plaintext LM broken", True},
958         {test_plaintext_nt_broken, "Plaintext NT broken", True},
959         {test_plaintext_nt_only, "Plaintext NT only", True},
960         {test_plaintext_lm_only, "Plaintext LM only", True},
961         {NULL, NULL}
962 };
963
964 /*
965   try a netlogon SamLogon
966 */
967 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
968 {
969         int i, j;
970         BOOL ret = True;
971
972         struct samlogon_state samlogon_state;
973         
974         samlogon_state.mem_ctx = mem_ctx;
975         samlogon_state.username = lp_parm_string(-1, "torture", "username");
976         samlogon_state.password = lp_parm_string(-1, "torture", "password");
977         samlogon_state.p = p;
978
979         samlogon_state.chall = data_blob_talloc(mem_ctx, NULL, 8);
980
981         generate_random_buffer(samlogon_state.chall.data, 
982                                8, False);
983
984         if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
985                 return False;
986         }
987
988         samlogon_state.r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
989         samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
990         samlogon_state.r.in.credential = &samlogon_state.auth;
991         samlogon_state.r.in.authenticator = &samlogon_state.auth2;
992
993         for (i=2;i<=3;i++) {
994                 samlogon_state.r.in.validation_level = i;
995                 for (j=0; test_table[j].fn; j++) {
996                         char *error_string = NULL;
997                         printf("Testing SamLogon with '%s' at validation level %d\n", test_table[j].name, i);
998         
999                         if (!test_table[j].fn(&samlogon_state, &error_string)) {
1000                                 if (test_table[j].expect_fail) {
1001                                         printf("Test %s failed (expected, test incomplete): %s\n", test_table[j].name, error_string);
1002                                 } else {
1003                                         printf("Test %s failed: %s\n", test_table[j].name, error_string);
1004                                         ret = False;
1005                                 }
1006                                 SAFE_FREE(error_string);
1007                         }
1008                 }
1009         }
1010
1011         return ret;
1012 }
1013
1014
1015 /*
1016   try a change password for our machine account
1017 */
1018 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1019 {
1020         NTSTATUS status;
1021         struct netr_ServerPasswordSet r;
1022         const char *password;
1023         struct creds_CredentialState creds;
1024
1025         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1026                 return False;
1027         }
1028
1029         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1030         r.in.username = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
1031         r.in.secure_channel_type = SEC_CHAN_BDC;
1032         r.in.computer_name = TEST_MACHINE_NAME;
1033
1034         password = generate_random_str(mem_ctx, 8);
1035         E_md4hash(password, r.in.new_password.data);
1036
1037         creds_des_encrypt(&creds, &r.in.new_password);
1038
1039         printf("Testing ServerPasswordSet on machine account\n");
1040         printf("Changing machine account password to '%s'\n", password);
1041
1042         creds_client_authenticator(&creds, &r.in.credential);
1043
1044         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
1045         if (!NT_STATUS_IS_OK(status)) {
1046                 printf("ServerPasswordSet - %s\n", nt_errstr(status));
1047                 return False;
1048         }
1049
1050         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1051                 printf("Credential chaining failed\n");
1052         }
1053
1054         /* by changing the machine password twice we test the
1055            credentials chaining fully, and we verify that the server
1056            allows the password to be set to the same value twice in a
1057            row (match win2k3) */
1058         printf("Testing a second ServerPasswordSet on machine account\n");
1059         printf("Changing machine account password to '%s' (same as pervsious run)\n", password);
1060
1061         creds_client_authenticator(&creds, &r.in.credential);
1062
1063         status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
1064         if (!NT_STATUS_IS_OK(status)) {
1065                 printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
1066                 return False;
1067         }
1068
1069         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1070                 printf("Credential chaining failed\n");
1071         }
1072
1073         join.machine_password = password;
1074
1075         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1076                 printf("ServerPasswordSet failed to actually change the password\n");
1077                 return False;
1078         }
1079
1080         return True;
1081 }
1082
1083
1084 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
1085 static uint64_t sequence_nums[3];
1086
1087 /*
1088   try a netlogon DatabaseSync
1089 */
1090 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1091 {
1092         NTSTATUS status;
1093         struct netr_DatabaseSync r;
1094         struct creds_CredentialState creds;
1095         const uint32 database_ids[] = {0, 1, 2}; 
1096         int i;
1097         BOOL ret = True;
1098
1099         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1100                 return False;
1101         }
1102
1103         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1104         r.in.computername = TEST_MACHINE_NAME;
1105         r.in.preferredmaximumlength = (uint32)-1;
1106         ZERO_STRUCT(r.in.return_authenticator);
1107
1108         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1109                 r.in.sync_context = 0;
1110                 r.in.database_id = database_ids[i];
1111
1112                 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
1113
1114                 do {
1115                         creds_client_authenticator(&creds, &r.in.credential);
1116
1117                         status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
1118                         if (!NT_STATUS_IS_OK(status) &&
1119                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1120                                 printf("DatabaseSync - %s\n", nt_errstr(status));
1121                                 ret = False;
1122                                 break;
1123                         }
1124
1125                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1126                                 printf("Credential chaining failed\n");
1127                         }
1128
1129                         r.in.sync_context = r.out.sync_context;
1130
1131                         if (r.out.delta_enum_array &&
1132                             r.out.delta_enum_array->num_deltas > 0 &&
1133                             r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
1134                             r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
1135                                 sequence_nums[r.in.database_id] = 
1136                                         r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
1137                                 printf("\tsequence_nums[%d]=%llu\n",
1138                                        r.in.database_id, 
1139                                        sequence_nums[r.in.database_id]);
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 == 0) continue;
1174
1175                 r.in.sequence_num -= 1;
1176
1177
1178                 printf("Testing DatabaseDeltas of id %d at %llu\n", 
1179                        r.in.database_id, r.in.sequence_num);
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++;
1197                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1198         }
1199
1200         return ret;
1201 }
1202
1203
1204 /*
1205   try a netlogon AccountDeltas
1206 */
1207 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1208 {
1209         NTSTATUS status;
1210         struct netr_AccountDeltas r;
1211         struct creds_CredentialState creds;
1212         BOOL ret = True;
1213
1214         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1215                 return False;
1216         }
1217
1218         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1219         r.in.computername = TEST_MACHINE_NAME;
1220         ZERO_STRUCT(r.in.return_authenticator);
1221         creds_client_authenticator(&creds, &r.in.credential);
1222         ZERO_STRUCT(r.in.uas);
1223         r.in.count=10;
1224         r.in.level=0;
1225         r.in.buffersize=100;
1226
1227         printf("Testing AccountDeltas\n");
1228
1229         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1230         status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
1231         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1232                 printf("AccountDeltas - %s\n", nt_errstr(status));
1233                 ret = False;
1234         }
1235
1236         return ret;
1237 }
1238
1239 /*
1240   try a netlogon AccountSync
1241 */
1242 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1243 {
1244         NTSTATUS status;
1245         struct netr_AccountSync r;
1246         struct creds_CredentialState creds;
1247         BOOL ret = True;
1248
1249         if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1250                 return False;
1251         }
1252
1253         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1254         r.in.computername = TEST_MACHINE_NAME;
1255         ZERO_STRUCT(r.in.return_authenticator);
1256         creds_client_authenticator(&creds, &r.in.credential);
1257         ZERO_STRUCT(r.in.recordid);
1258         r.in.reference=0;
1259         r.in.level=0;
1260         r.in.buffersize=100;
1261
1262         printf("Testing AccountSync\n");
1263
1264         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1265         status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
1266         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1267                 printf("AccountSync - %s\n", nt_errstr(status));
1268                 ret = False;
1269         }
1270
1271         return ret;
1272 }
1273
1274 /*
1275   try a netlogon GetDcName
1276 */
1277 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1278 {
1279         NTSTATUS status;
1280         struct netr_GetDcName r;
1281
1282         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1283         r.in.domainname = lp_workgroup();
1284
1285         printf("Testing GetDcName\n");
1286
1287         status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
1288         if (!NT_STATUS_IS_OK(status)) {
1289                 printf("GetDcName - %s\n", nt_errstr(status));
1290                 return False;
1291         }
1292
1293         printf("\tDC is at '%s'\n", r.out.dcname);
1294
1295         return True;
1296 }
1297
1298 /*
1299   try a netlogon LogonControl 
1300 */
1301 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1302 {
1303         NTSTATUS status;
1304         struct netr_LogonControl r;
1305         BOOL ret = True;
1306         int i;
1307
1308         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1309         r.in.function_code = 1;
1310
1311         for (i=1;i<4;i++) {
1312                 r.in.level = i;
1313
1314                 printf("Testing LogonControl level %d\n", i);
1315
1316                 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
1317                 if (!NT_STATUS_IS_OK(status)) {
1318                         printf("LogonControl - %s\n", nt_errstr(status));
1319                         ret = False;
1320                 }
1321         }
1322
1323         return ret;
1324 }
1325
1326
1327 /*
1328   try a netlogon GetAnyDCName
1329 */
1330 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1331 {
1332         NTSTATUS status;
1333         struct netr_GetAnyDCName r;
1334
1335         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1336         r.in.domainname = lp_workgroup();
1337
1338         printf("Testing GetAnyDCName\n");
1339
1340         status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
1341         if (!NT_STATUS_IS_OK(status)) {
1342                 printf("GetAnyDCName - %s\n", nt_errstr(status));
1343                 return False;
1344         }
1345
1346         if (r.out.dcname) {
1347                 printf("\tDC is at '%s'\n", r.out.dcname);
1348         }
1349
1350         return True;
1351 }
1352
1353
1354 /*
1355   try a netlogon LogonControl2
1356 */
1357 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1358 {
1359         NTSTATUS status;
1360         struct netr_LogonControl2 r;
1361         BOOL ret = True;
1362         int i;
1363
1364         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1365
1366         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1367         r.in.data.domain = lp_workgroup();
1368
1369         for (i=1;i<4;i++) {
1370                 r.in.level = i;
1371
1372                 printf("Testing LogonControl2 level %d function %d\n", 
1373                        i, r.in.function_code);
1374
1375                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1376                 if (!NT_STATUS_IS_OK(status)) {
1377                         printf("LogonControl - %s\n", nt_errstr(status));
1378                         ret = False;
1379                 }
1380         }
1381
1382         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1383         r.in.data.domain = lp_workgroup();
1384
1385         for (i=1;i<4;i++) {
1386                 r.in.level = i;
1387
1388                 printf("Testing LogonControl2 level %d function %d\n", 
1389                        i, r.in.function_code);
1390
1391                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1392                 if (!NT_STATUS_IS_OK(status)) {
1393                         printf("LogonControl - %s\n", nt_errstr(status));
1394                         ret = False;
1395                 }
1396         }
1397
1398         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1399         r.in.data.domain = lp_workgroup();
1400
1401         for (i=1;i<4;i++) {
1402                 r.in.level = i;
1403
1404                 printf("Testing LogonControl2 level %d function %d\n", 
1405                        i, r.in.function_code);
1406
1407                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1408                 if (!NT_STATUS_IS_OK(status)) {
1409                         printf("LogonControl - %s\n", nt_errstr(status));
1410                         ret = False;
1411                 }
1412         }
1413
1414         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1415         r.in.data.debug_level = ~0;
1416
1417         for (i=1;i<4;i++) {
1418                 r.in.level = i;
1419
1420                 printf("Testing LogonControl2 level %d function %d\n", 
1421                        i, r.in.function_code);
1422
1423                 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1424                 if (!NT_STATUS_IS_OK(status)) {
1425                         printf("LogonControl - %s\n", nt_errstr(status));
1426                         ret = False;
1427                 }
1428         }
1429
1430         return ret;
1431 }
1432
1433 /*
1434   try a netlogon DatabaseSync2
1435 */
1436 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1437 {
1438         NTSTATUS status;
1439         struct netr_DatabaseSync2 r;
1440         struct creds_CredentialState creds;
1441         const uint32 database_ids[] = {0, 1, 2}; 
1442         int i;
1443         BOOL ret = True;
1444
1445         if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &creds)) {
1446                 return False;
1447         }
1448
1449         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1450         r.in.computername = TEST_MACHINE_NAME;
1451         r.in.preferredmaximumlength = (uint32)-1;
1452         ZERO_STRUCT(r.in.return_authenticator);
1453
1454         for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1455                 r.in.sync_context = 0;
1456                 r.in.database_id = database_ids[i];
1457                 r.in.restart_state = 0;
1458
1459                 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
1460
1461                 do {
1462                         creds_client_authenticator(&creds, &r.in.credential);
1463
1464                         status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
1465                         if (!NT_STATUS_IS_OK(status) &&
1466                             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1467                                 printf("DatabaseSync2 - %s\n", nt_errstr(status));
1468                                 ret = False;
1469                                 break;
1470                         }
1471
1472                         if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1473                                 printf("Credential chaining failed\n");
1474                         }
1475
1476                         r.in.sync_context = r.out.sync_context;
1477                 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1478         }
1479
1480         return ret;
1481 }
1482
1483
1484 /*
1485   try a netlogon LogonControl2Ex
1486 */
1487 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1488 {
1489         NTSTATUS status;
1490         struct netr_LogonControl2Ex r;
1491         BOOL ret = True;
1492         int i;
1493
1494         r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1495
1496         r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1497         r.in.data.domain = lp_workgroup();
1498
1499         for (i=1;i<4;i++) {
1500                 r.in.level = i;
1501
1502                 printf("Testing LogonControl2Ex level %d function %d\n", 
1503                        i, r.in.function_code);
1504
1505                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1506                 if (!NT_STATUS_IS_OK(status)) {
1507                         printf("LogonControl - %s\n", nt_errstr(status));
1508                         ret = False;
1509                 }
1510         }
1511
1512         r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1513         r.in.data.domain = lp_workgroup();
1514
1515         for (i=1;i<4;i++) {
1516                 r.in.level = i;
1517
1518                 printf("Testing LogonControl2Ex level %d function %d\n", 
1519                        i, r.in.function_code);
1520
1521                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1522                 if (!NT_STATUS_IS_OK(status)) {
1523                         printf("LogonControl - %s\n", nt_errstr(status));
1524                         ret = False;
1525                 }
1526         }
1527
1528         r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1529         r.in.data.domain = lp_workgroup();
1530
1531         for (i=1;i<4;i++) {
1532                 r.in.level = i;
1533
1534                 printf("Testing LogonControl2Ex level %d function %d\n", 
1535                        i, r.in.function_code);
1536
1537                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1538                 if (!NT_STATUS_IS_OK(status)) {
1539                         printf("LogonControl - %s\n", nt_errstr(status));
1540                         ret = False;
1541                 }
1542         }
1543
1544         r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1545         r.in.data.debug_level = ~0;
1546
1547         for (i=1;i<4;i++) {
1548                 r.in.level = i;
1549
1550                 printf("Testing LogonControl2Ex level %d function %d\n", 
1551                        i, r.in.function_code);
1552
1553                 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1554                 if (!NT_STATUS_IS_OK(status)) {
1555                         printf("LogonControl - %s\n", nt_errstr(status));
1556                         ret = False;
1557                 }
1558         }
1559
1560         return ret;
1561 }
1562
1563
1564
1565 BOOL torture_rpc_netlogon(int dummy)
1566 {
1567         NTSTATUS status;
1568         struct dcerpc_pipe *p;
1569         TALLOC_CTX *mem_ctx;
1570         BOOL ret = True;
1571
1572         mem_ctx = talloc_init("torture_rpc_netlogon");
1573
1574         if (!join_domain_bdc(mem_ctx)) {
1575                 printf("Failed to join as BDC\n");
1576                 return False;
1577         }
1578
1579         status = torture_rpc_connection(&p, 
1580                                         DCERPC_NETLOGON_NAME,
1581                                         DCERPC_NETLOGON_UUID,
1582                                         DCERPC_NETLOGON_VERSION);
1583         if (!NT_STATUS_IS_OK(status)) {
1584                 return False;
1585         }
1586
1587         if (!test_LogonUasLogon(p, mem_ctx)) {
1588                 ret = False;
1589         }
1590
1591         if (!test_LogonUasLogoff(p, mem_ctx)) {
1592                 ret = False;
1593         }
1594
1595         if (!test_SetPassword(p, mem_ctx)) {
1596                 ret = False;
1597         }
1598
1599         if (!test_SamLogon(p, mem_ctx)) {
1600                 ret = False;
1601         }
1602
1603         if (!test_DatabaseSync(p, mem_ctx)) {
1604                 ret = False;
1605         }
1606
1607         if (!test_DatabaseDeltas(p, mem_ctx)) {
1608                 ret = False;
1609         }
1610
1611         if (!test_AccountDeltas(p, mem_ctx)) {
1612                 ret = False;
1613         }
1614
1615         if (!test_AccountSync(p, mem_ctx)) {
1616                 ret = False;
1617         }
1618
1619         if (!test_GetDcName(p, mem_ctx)) {
1620                 ret = False;
1621         }
1622
1623         if (!test_LogonControl(p, mem_ctx)) {
1624                 ret = False;
1625         }
1626
1627         if (!test_GetAnyDCName(p, mem_ctx)) {
1628                 ret = False;
1629         }
1630
1631         if (!test_LogonControl2(p, mem_ctx)) {
1632                 ret = False;
1633         }
1634
1635         if (!test_DatabaseSync2(p, mem_ctx)) {
1636                 ret = False;
1637         }
1638
1639         if (!test_LogonControl2Ex(p, mem_ctx)) {
1640                 ret = False;
1641         }
1642
1643         torture_rpc_close(p);
1644
1645         if (!leave_domain_bdc(mem_ctx)) {
1646                 printf("Failed to delete BDC machine account\n");
1647                 return False;
1648         }
1649
1650         return ret;
1651 }