r2552: Character set conversion and string handling updates.
[Samba/gebeck_regimport.git] / source4 / torture / rpc / netlogon.c
blob16ba679be9676adff269d83259aa5a5327758beb
1 /*
2 Unix SMB/CIFS implementation.
4 test suite for netlogon rpc operations
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
8 Copyright (C) Tim Potter 2003
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.
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.
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.
25 #include "includes.h"
28 static const char *machine_password;
30 #define TEST_MACHINE_NAME "torturetest"
32 static BOOL test_LogonUasLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
34 NTSTATUS status;
35 struct netr_LogonUasLogon r;
37 r.in.server_name = NULL;
38 r.in.account_name = lp_parm_string(-1, "torture", "username");
39 r.in.workstation = TEST_MACHINE_NAME;
41 printf("Testing LogonUasLogon\n");
43 status = dcerpc_netr_LogonUasLogon(p, mem_ctx, &r);
44 if (!NT_STATUS_IS_OK(status)) {
45 printf("LogonUasLogon - %s\n", nt_errstr(status));
46 return False;
49 return True;
53 static BOOL test_LogonUasLogoff(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
55 NTSTATUS status;
56 struct netr_LogonUasLogoff r;
58 r.in.server_name = NULL;
59 r.in.account_name = lp_parm_string(-1, "torture", "username");
60 r.in.workstation = TEST_MACHINE_NAME;
62 printf("Testing LogonUasLogoff\n");
64 status = dcerpc_netr_LogonUasLogoff(p, mem_ctx, &r);
65 if (!NT_STATUS_IS_OK(status)) {
66 printf("LogonUasLogoff - %s\n", nt_errstr(status));
67 return False;
70 return True;
74 static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
75 struct creds_CredentialState *creds)
77 NTSTATUS status;
78 struct netr_ServerReqChallenge r;
79 struct netr_ServerAuthenticate a;
80 struct netr_Credential credentials1, credentials2, credentials3;
81 const char *plain_pass;
82 struct samr_Password mach_password;
84 printf("Testing ServerReqChallenge\n");
86 r.in.server_name = NULL;
87 r.in.computer_name = TEST_MACHINE_NAME;
88 r.in.credentials = &credentials1;
89 r.out.credentials = &credentials2;
91 generate_random_buffer(credentials1.data, sizeof(credentials1.data));
93 status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
94 if (!NT_STATUS_IS_OK(status)) {
95 printf("ServerReqChallenge - %s\n", nt_errstr(status));
96 return False;
99 plain_pass = machine_password;
100 if (!plain_pass) {
101 printf("Unable to fetch machine password!\n");
102 return False;
105 E_md4hash(plain_pass, mach_password.hash);
107 a.in.server_name = NULL;
108 a.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
109 a.in.secure_channel_type = SEC_CHAN_BDC;
110 a.in.computer_name = TEST_MACHINE_NAME;
111 a.in.credentials = &credentials3;
112 a.out.credentials = &credentials3;
114 creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3,
115 NETLOGON_NEG_AUTH2_FLAGS);
117 printf("Testing ServerAuthenticate\n");
119 status = dcerpc_netr_ServerAuthenticate(p, mem_ctx, &a);
120 if (!NT_STATUS_IS_OK(status)) {
121 printf("ServerAuthenticate - %s\n", nt_errstr(status));
122 return False;
125 if (!creds_client_check(creds, &credentials3)) {
126 printf("Credential chaining failed\n");
127 return False;
130 return True;
133 static BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
134 uint32_t negotiate_flags,
135 struct creds_CredentialState *creds)
137 NTSTATUS status;
138 struct netr_ServerReqChallenge r;
139 struct netr_ServerAuthenticate2 a;
140 struct netr_Credential credentials1, credentials2, credentials3;
141 const char *plain_pass;
142 struct samr_Password mach_password;
144 printf("Testing ServerReqChallenge\n");
146 r.in.server_name = NULL;
147 r.in.computer_name = TEST_MACHINE_NAME;
148 r.in.credentials = &credentials1;
149 r.out.credentials = &credentials2;
151 generate_random_buffer(credentials1.data, sizeof(credentials1.data));
153 status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
154 if (!NT_STATUS_IS_OK(status)) {
155 printf("ServerReqChallenge - %s\n", nt_errstr(status));
156 return False;
159 plain_pass = machine_password;
160 if (!plain_pass) {
161 printf("Unable to fetch machine password!\n");
162 return False;
165 E_md4hash(plain_pass, mach_password.hash);
167 a.in.server_name = NULL;
168 a.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
169 a.in.secure_channel_type = SEC_CHAN_BDC;
170 a.in.computer_name = TEST_MACHINE_NAME;
171 a.in.negotiate_flags = &negotiate_flags;
172 a.out.negotiate_flags = &negotiate_flags;
173 a.in.credentials = &credentials3;
174 a.out.credentials = &credentials3;
176 creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3,
177 negotiate_flags);
179 printf("Testing ServerAuthenticate2\n");
181 status = dcerpc_netr_ServerAuthenticate2(p, mem_ctx, &a);
182 if (!NT_STATUS_IS_OK(status)) {
183 printf("ServerAuthenticate2 - %s\n", nt_errstr(status));
184 return False;
187 if (!creds_client_check(creds, &credentials3)) {
188 printf("Credential chaining failed\n");
189 return False;
192 printf("negotiate_flags=0x%08x\n", negotiate_flags);
194 return True;
198 static BOOL test_SetupCredentials3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
199 uint32_t negotiate_flags,
200 struct creds_CredentialState *creds)
202 NTSTATUS status;
203 struct netr_ServerReqChallenge r;
204 struct netr_ServerAuthenticate3 a;
205 struct netr_Credential credentials1, credentials2, credentials3;
206 const char *plain_pass;
207 struct samr_Password mach_password;
208 uint32 rid;
210 printf("Testing ServerReqChallenge\n");
212 r.in.server_name = NULL;
213 r.in.computer_name = TEST_MACHINE_NAME;
214 r.in.credentials = &credentials1;
215 r.out.credentials = &credentials2;
217 generate_random_buffer(credentials1.data, sizeof(credentials1.data));
219 status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
220 if (!NT_STATUS_IS_OK(status)) {
221 printf("ServerReqChallenge - %s\n", nt_errstr(status));
222 return False;
225 plain_pass = machine_password;
226 if (!plain_pass) {
227 printf("Unable to fetch machine password!\n");
228 return False;
231 E_md4hash(plain_pass, mach_password.hash);
233 a.in.server_name = NULL;
234 a.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
235 a.in.secure_channel_type = SEC_CHAN_BDC;
236 a.in.computer_name = TEST_MACHINE_NAME;
237 a.in.negotiate_flags = &negotiate_flags;
238 a.in.credentials = &credentials3;
239 a.out.credentials = &credentials3;
240 a.out.negotiate_flags = &negotiate_flags;
241 a.out.rid = &rid;
243 creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3,
244 negotiate_flags);
246 printf("Testing ServerAuthenticate3\n");
248 status = dcerpc_netr_ServerAuthenticate3(p, mem_ctx, &a);
249 if (!NT_STATUS_IS_OK(status)) {
250 printf("ServerAuthenticate3 - %s\n", nt_errstr(status));
251 return False;
254 if (!creds_client_check(creds, &credentials3)) {
255 printf("Credential chaining failed\n");
256 return False;
259 printf("negotiate_flags=0x%08x\n", negotiate_flags);
261 return True;
264 enum ntlm_break {
265 BREAK_NONE,
266 BREAK_LM,
267 BREAK_NT,
268 NO_LM,
269 NO_NT
272 struct samlogon_state {
273 TALLOC_CTX *mem_ctx;
274 const char *account_name;
275 const char *account_domain;
276 const char *password;
277 struct dcerpc_pipe *p;
278 struct netr_LogonSamLogon r;
279 struct netr_Authenticator auth, auth2;
280 struct creds_CredentialState creds;
281 DATA_BLOB chall;
285 Authenticate a user with a challenge/response, checking session key
286 and valid authentication types
288 static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
289 enum ntlm_break break_which,
290 DATA_BLOB *chall,
291 DATA_BLOB *lm_response,
292 DATA_BLOB *nt_response,
293 uint8_t lm_key[8],
294 uint8_t user_session_key[16],
295 char **error_string)
297 NTSTATUS status;
298 struct netr_LogonSamLogon *r = &samlogon_state->r;
299 struct netr_NetworkInfo ninfo;
301 struct netr_SamBaseInfo *base;
303 printf("testing netr_LogonSamLogon\n");
305 samlogon_state->r.in.logon.network = &ninfo;
307 ninfo.identity_info.domain_name.string = samlogon_state->account_domain;
308 ninfo.identity_info.parameter_control = 0;
309 ninfo.identity_info.logon_id_low = 0;
310 ninfo.identity_info.logon_id_high = 0;
311 ninfo.identity_info.account_name.string = samlogon_state->account_name;
312 ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
314 memcpy(ninfo.challenge, chall->data, 8);
316 switch (break_which) {
317 case BREAK_NONE:
318 break;
319 case BREAK_LM:
320 if (lm_response && lm_response->data) {
321 lm_response->data[0]++;
323 break;
324 case BREAK_NT:
325 if (nt_response && nt_response->data) {
326 nt_response->data[0]++;
328 break;
329 case NO_LM:
330 data_blob_free(lm_response);
331 break;
332 case NO_NT:
333 data_blob_free(nt_response);
334 break;
337 if (nt_response) {
338 ninfo.nt.data = nt_response->data;
339 ninfo.nt.length = nt_response->length;
340 } else {
341 ninfo.nt.data = NULL;
342 ninfo.nt.length = 0;
345 if (lm_response) {
346 ninfo.lm.data = lm_response->data;
347 ninfo.lm.length = lm_response->length;
348 } else {
349 ninfo.lm.data = NULL;
350 ninfo.lm.length = 0;
353 ZERO_STRUCT(samlogon_state->auth2);
354 creds_client_authenticator(&samlogon_state->creds, &samlogon_state->auth);
356 r->out.return_authenticator = NULL;
357 status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
358 if (!NT_STATUS_IS_OK(status)) {
359 if (error_string) {
360 *error_string = strdup(nt_errstr(status));
364 if (!r->out.return_authenticator ||
365 !creds_client_check(&samlogon_state->creds, &r->out.return_authenticator->cred)) {
366 printf("Credential chaining failed\n");
369 if (!NT_STATUS_IS_OK(status)) {
370 /* we cannot check the session key, if the logon failed... */
371 return status;
374 /* find and decyrpt the session keys, return in parameters above */
375 if (r->in.validation_level == 2) {
376 base = &r->out.validation.sam2->base;
377 } else if (r->in.validation_level == 3) {
378 base = &r->out.validation.sam3->base;
379 } else if (r->in.validation_level == 6) {
380 base = &r->out.validation.sam6->base;
381 } else {
382 base = NULL;
385 if (r->in.validation_level != 6) {
386 static const char zeros[16];
388 if (memcmp(base->key.key, zeros,
389 sizeof(base->key.key)) != 0) {
390 creds_arcfour_crypt(&samlogon_state->creds,
391 base->key.key,
392 sizeof(base->key.key));
395 if (user_session_key) {
396 memcpy(user_session_key, base->key.key, 16);
399 if (memcmp(base->LMSessKey.key, zeros,
400 sizeof(base->LMSessKey.key)) != 0) {
401 creds_arcfour_crypt(&samlogon_state->creds,
402 base->LMSessKey.key,
403 sizeof(base->LMSessKey.key));
406 if (lm_key) {
407 memcpy(lm_key, base->LMSessKey.key, 8);
409 } else {
410 /* they aren't encrypted! */
411 if (user_session_key) {
412 memcpy(user_session_key, base->key.key, 16);
414 if (lm_key) {
415 memcpy(lm_key, base->LMSessKey.key, 8);
419 return status;
424 * Test the normal 'LM and NTLM' combination
427 static BOOL test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
429 BOOL pass = True;
430 BOOL lm_good;
431 NTSTATUS nt_status;
432 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
433 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
434 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
436 uint8_t lm_key[8];
437 uint8_t user_session_key[16];
438 uint8_t lm_hash[16];
439 uint8_t nt_hash[16];
441 ZERO_STRUCT(lm_key);
442 ZERO_STRUCT(user_session_key);
444 lm_good = SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
445 if (samlogon_state->r.in.logon_level == 6 || !lm_good) {
446 ZERO_STRUCT(lm_hash);
447 } else {
448 E_deshash(samlogon_state->password, lm_hash);
451 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
453 E_md4hash(samlogon_state->password, nt_hash);
454 SMBsesskeygen_ntv1(nt_hash, session_key.data);
456 nt_status = check_samlogon(samlogon_state,
457 break_which,
458 &samlogon_state->chall,
459 &lm_response,
460 &nt_response,
461 lm_key,
462 user_session_key,
463 error_string);
465 data_blob_free(&lm_response);
467 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
468 /* for 'long' passwords, the LM password is invalid */
469 if (break_which == NO_NT && !lm_good) {
470 return True;
472 return break_which == BREAK_NT;
475 if (!NT_STATUS_IS_OK(nt_status)) {
476 return False;
479 if (break_which == NO_NT && !lm_good) {
480 printf("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
481 return False;
484 if (memcmp(lm_hash, lm_key,
485 sizeof(lm_key)) != 0) {
486 printf("LM Key does not match expectations!\n");
487 printf("lm_key:\n");
488 dump_data(1, (const char *)lm_key, 8);
489 printf("expected:\n");
490 dump_data(1, (const char *)lm_hash, 8);
491 pass = False;
494 if (break_which == NO_NT) {
495 char lm_key_expected[16];
496 memcpy(lm_key_expected, lm_hash, 8);
497 memset(lm_key_expected+8, '\0', 8);
498 if (memcmp(lm_key_expected, user_session_key,
499 16) != 0) {
500 printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
501 printf("user_session_key:\n");
502 dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
503 printf("expected:\n");
504 dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
505 pass = False;
507 } else {
508 if (memcmp(session_key.data, user_session_key,
509 sizeof(user_session_key)) != 0) {
510 printf("NT Session Key does not match expectations!\n");
511 printf("user_session_key:\n");
512 dump_data(1, (const char *)user_session_key, 16);
513 printf("expected:\n");
514 dump_data(1, (const char *)session_key.data, session_key.length);
515 pass = False;
518 return pass;
522 * Test LM authentication, no NT response supplied
525 static BOOL test_lm(struct samlogon_state *samlogon_state, char **error_string)
528 return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
532 * Test the NTLM response only, no LM.
535 static BOOL test_ntlm(struct samlogon_state *samlogon_state, char **error_string)
537 return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
541 * Test the NTLM response only, but in the LM field.
544 static BOOL test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string)
546 BOOL pass = True;
547 NTSTATUS nt_status;
548 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
550 uint8_t lm_key[8];
551 uint8_t lm_hash[16];
552 uint8_t user_session_key[16];
554 ZERO_STRUCT(user_session_key);
556 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
558 E_deshash(samlogon_state->password, lm_hash);
560 nt_status = check_samlogon(samlogon_state,
561 BREAK_NONE,
562 &samlogon_state->chall,
563 &nt_response,
564 NULL,
565 lm_key,
566 user_session_key,
567 error_string);
569 if (!NT_STATUS_IS_OK(nt_status)) {
570 return False;
573 if (memcmp(lm_hash, lm_key,
574 sizeof(lm_key)) != 0) {
575 printf("LM Key does not match expectations!\n");
576 printf("lm_key:\n");
577 dump_data(1, (const char *)lm_key, 8);
578 printf("expected:\n");
579 dump_data(1, (const char *)lm_hash, 8);
580 pass = False;
582 if (memcmp(lm_hash, user_session_key, 8) != 0) {
583 char lm_key_expected[16];
584 memcpy(lm_key_expected, lm_hash, 8);
585 memset(lm_key_expected+8, '\0', 8);
586 if (memcmp(lm_key_expected, user_session_key,
587 16) != 0) {
588 printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
589 printf("user_session_key:\n");
590 dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
591 printf("expected:\n");
592 dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
593 pass = False;
596 return pass;
600 * Test the NTLM response only, but in the both the NT and LM fields.
603 static BOOL test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string)
605 BOOL pass = True;
606 BOOL lm_good;
607 NTSTATUS nt_status;
608 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
609 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
611 char lm_key[8];
612 char lm_hash[16];
613 char user_session_key[16];
614 char nt_hash[16];
616 ZERO_STRUCT(lm_key);
617 ZERO_STRUCT(user_session_key);
619 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
620 nt_response.data);
621 E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
622 SMBsesskeygen_ntv1((const uint8_t *)nt_hash,
623 session_key.data);
625 lm_good = E_deshash(samlogon_state->password, (uint8_t *)lm_hash);
626 if (!lm_good) {
627 ZERO_STRUCT(lm_hash);
630 nt_status = check_samlogon(samlogon_state,
631 BREAK_NONE,
632 &samlogon_state->chall,
633 NULL,
634 &nt_response,
635 lm_key,
636 user_session_key,
637 error_string);
639 if (!NT_STATUS_IS_OK(nt_status)) {
640 return False;
643 if (memcmp(lm_hash, lm_key,
644 sizeof(lm_key)) != 0) {
645 printf("LM Key does not match expectations!\n");
646 printf("lm_key:\n");
647 dump_data(1, lm_key, 8);
648 printf("expected:\n");
649 dump_data(1, lm_hash, 8);
650 pass = False;
652 if (memcmp(session_key.data, user_session_key,
653 sizeof(user_session_key)) != 0) {
654 printf("NT Session Key does not match expectations!\n");
655 printf("user_session_key:\n");
656 dump_data(1, user_session_key, 16);
657 printf("expected:\n");
658 dump_data(1, (const char *)session_key.data, session_key.length);
659 pass = False;
663 return pass;
667 * Test the NTLMv2 and LMv2 responses
670 static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
672 BOOL pass = True;
673 NTSTATUS nt_status;
674 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
675 DATA_BLOB lmv2_response = data_blob(NULL, 0);
676 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
677 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, lp_netbios_name(), lp_workgroup());
679 uint8_t user_session_key[16];
681 ZERO_STRUCT(user_session_key);
683 /* TODO - test with various domain cases, and without domain */
684 if (!SMBNTLMv2encrypt(samlogon_state->account_name, samlogon_state->account_domain,
685 samlogon_state->password, &samlogon_state->chall,
686 &names_blob,
687 &lmv2_response, &ntlmv2_response,
688 &ntlmv2_session_key)) {
689 data_blob_free(&names_blob);
690 return False;
692 data_blob_free(&names_blob);
694 nt_status = check_samlogon(samlogon_state,
695 break_which,
696 &samlogon_state->chall,
697 &lmv2_response,
698 &ntlmv2_response,
699 NULL,
700 user_session_key,
701 error_string);
703 data_blob_free(&lmv2_response);
704 data_blob_free(&ntlmv2_response);
706 if (!NT_STATUS_IS_OK(nt_status)) {
707 return break_which == BREAK_NT;
710 if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key,
711 sizeof(user_session_key)) != 0) {
712 printf("USER (NTLMv2) Session Key does not match expectations!\n");
713 printf("user_session_key:\n");
714 dump_data(1, (const char *)user_session_key, 16);
715 printf("expected:\n");
716 dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length);
717 pass = False;
719 return pass;
723 * Test the NTLMv2 and LMv2 responses
726 static BOOL test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
728 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, error_string);
732 * Test the LMv2 response only
735 static BOOL test_lmv2(struct samlogon_state *samlogon_state, char **error_string)
737 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, error_string);
741 * Test the NTLMv2 response only
744 static BOOL test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
746 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, error_string);
749 static BOOL test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string)
751 return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
754 static BOOL test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string)
756 return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
759 static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string)
761 return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
764 static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
766 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, error_string);
769 static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
771 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, error_string);
774 static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
776 NTSTATUS nt_status;
777 DATA_BLOB nt_response = data_blob(NULL, 0);
778 DATA_BLOB lm_response = data_blob(NULL, 0);
779 char *password;
780 char *dospw;
781 smb_ucs2_t *unicodepw;
783 uint8_t user_session_key[16];
784 uint8_t lm_key[16];
785 static const uint8_t zeros[8];
786 DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
788 ZERO_STRUCT(user_session_key);
790 if ((push_ucs2_talloc(samlogon_state->mem_ctx, (smb_ucs2_t **)&unicodepw,
791 samlogon_state->password)) == -1) {
792 DEBUG(0, ("push_ucs2_allocate failed!\n"));
793 exit(1);
796 nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw,
797 strlen_w(((void *)unicodepw))*sizeof(smb_ucs2_t));
799 password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password);
801 if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX,
802 CH_DOS, password,
803 strlen(password)+1,
804 (void**)&dospw)) == -1) {
805 DEBUG(0, ("convert_string_talloc failed!\n"));
806 exit(1);
809 lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
811 nt_status = check_samlogon(samlogon_state,
812 break_which,
813 &chall,
814 &lm_response,
815 &nt_response,
816 lm_key,
817 user_session_key,
818 error_string);
820 if (!NT_STATUS_IS_OK(nt_status)) {
821 return break_which == BREAK_NT;
824 return True;
827 static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state,
828 char **error_string) {
829 return test_plaintext(samlogon_state, BREAK_NONE, error_string);
832 static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state,
833 char **error_string) {
834 return test_plaintext(samlogon_state, BREAK_LM, error_string);
837 static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state,
838 char **error_string) {
839 return test_plaintext(samlogon_state, BREAK_NT, error_string);
842 static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state,
843 char **error_string) {
844 return test_plaintext(samlogon_state, NO_LM, error_string);
847 static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state,
848 char **error_string) {
849 return test_plaintext(samlogon_state, NO_NT, error_string);
853 Tests:
855 - LM only
856 - NT and LM
857 - NT
858 - NT in LM field
859 - NT in both fields
860 - NTLMv2
861 - NTLMv2 and LMv2
862 - LMv2
863 - plaintext tests (in challenge-response fields)
865 check we get the correct session key in each case
866 check what values we get for the LM session key
870 static const struct ntlm_tests {
871 BOOL (*fn)(struct samlogon_state *, char **);
872 const char *name;
873 BOOL expect_fail;
874 } test_table[] = {
875 {test_lm, "LM", False},
876 {test_lm_ntlm, "LM and NTLM", False},
877 {test_ntlm, "NTLM", False},
878 {test_ntlm_in_lm, "NTLM in LM", False},
879 {test_ntlm_in_both, "NTLM in both", False},
880 {test_ntlmv2, "NTLMv2", False},
881 {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
882 {test_lmv2, "LMv2", False},
883 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
884 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
885 {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
886 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
887 {test_plaintext_none_broken, "Plaintext", True},
888 {test_plaintext_lm_broken, "Plaintext LM broken", True},
889 {test_plaintext_nt_broken, "Plaintext NT broken", True},
890 {test_plaintext_nt_only, "Plaintext NT only", True},
891 {test_plaintext_lm_only, "Plaintext LM only", True},
892 {NULL, NULL}
896 try a netlogon SamLogon
898 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
900 int i, v, l;
901 BOOL ret = True;
902 int validation_levels[] = {2,3,6};
903 int logon_levels[] = { 2, 6 };
904 struct samlogon_state samlogon_state;
906 samlogon_state.mem_ctx = mem_ctx;
907 samlogon_state.account_name = lp_parm_string(-1, "torture", "username");
908 samlogon_state.account_domain = lp_parm_string(-1, "torture", "userdomain");
909 samlogon_state.password = lp_parm_string(-1, "torture", "password");
910 samlogon_state.p = p;
912 samlogon_state.chall = data_blob_talloc(mem_ctx, NULL, 8);
914 generate_random_buffer(samlogon_state.chall.data, 8);
916 if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
917 return False;
920 if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
921 return False;
924 if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &samlogon_state.creds)) {
925 return False;
928 samlogon_state.r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
929 samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
930 samlogon_state.r.in.credential = &samlogon_state.auth;
931 samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
933 for (i=0; test_table[i].fn; i++) {
934 for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
935 for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
936 char *error_string = NULL;
937 samlogon_state.r.in.validation_level = validation_levels[v];
938 samlogon_state.r.in.logon_level = logon_levels[l];
939 printf("Testing SamLogon with '%s' at validation level %d, logon level %d\n",
940 test_table[i].name, validation_levels[v], logon_levels[l]);
942 if (!test_table[i].fn(&samlogon_state, &error_string)) {
943 if (test_table[i].expect_fail) {
944 printf("Test %s failed (expected, test incomplete): %s\n", test_table[i].name, error_string);
945 } else {
946 printf("Test %s failed: %s\n", test_table[i].name, error_string);
947 ret = False;
949 SAFE_FREE(error_string);
955 return ret;
960 try a change password for our machine account
962 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
964 NTSTATUS status;
965 struct netr_ServerPasswordSet r;
966 const char *password;
967 struct creds_CredentialState creds;
969 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
970 return False;
973 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
974 r.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
975 r.in.secure_channel_type = SEC_CHAN_BDC;
976 r.in.computer_name = TEST_MACHINE_NAME;
978 password = generate_random_str(mem_ctx, 8);
979 E_md4hash(password, r.in.new_password.hash);
981 creds_des_encrypt(&creds, &r.in.new_password);
983 printf("Testing ServerPasswordSet on machine account\n");
984 printf("Changing machine account password to '%s'\n", password);
986 creds_client_authenticator(&creds, &r.in.credential);
988 status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
989 if (!NT_STATUS_IS_OK(status)) {
990 printf("ServerPasswordSet - %s\n", nt_errstr(status));
991 return False;
994 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
995 printf("Credential chaining failed\n");
998 /* by changing the machine password twice we test the
999 credentials chaining fully, and we verify that the server
1000 allows the password to be set to the same value twice in a
1001 row (match win2k3) */
1002 printf("Testing a second ServerPasswordSet on machine account\n");
1003 printf("Changing machine account password to '%s' (same as previous run)\n", password);
1005 creds_client_authenticator(&creds, &r.in.credential);
1007 status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
1008 if (!NT_STATUS_IS_OK(status)) {
1009 printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
1010 return False;
1013 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1014 printf("Credential chaining failed\n");
1017 machine_password = password;
1019 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1020 printf("ServerPasswordSet failed to actually change the password\n");
1021 return False;
1024 return True;
1028 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
1029 static uint64_t sequence_nums[3];
1032 try a netlogon DatabaseSync
1034 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1036 NTSTATUS status;
1037 struct netr_DatabaseSync r;
1038 struct creds_CredentialState creds;
1039 const uint32_t database_ids[] = {0, 1, 2};
1040 int i;
1041 BOOL ret = True;
1043 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1044 return False;
1047 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1048 r.in.computername = TEST_MACHINE_NAME;
1049 r.in.preferredmaximumlength = (uint32_t)-1;
1050 ZERO_STRUCT(r.in.return_authenticator);
1052 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1053 r.in.sync_context = 0;
1054 r.in.database_id = database_ids[i];
1056 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
1058 do {
1059 creds_client_authenticator(&creds, &r.in.credential);
1061 status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
1062 if (!NT_STATUS_IS_OK(status) &&
1063 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1064 printf("DatabaseSync - %s\n", nt_errstr(status));
1065 ret = False;
1066 break;
1069 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1070 printf("Credential chaining failed\n");
1073 r.in.sync_context = r.out.sync_context;
1075 if (r.out.delta_enum_array &&
1076 r.out.delta_enum_array->num_deltas > 0 &&
1077 r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
1078 r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
1079 sequence_nums[r.in.database_id] =
1080 r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
1081 printf("\tsequence_nums[%d]=%llu\n",
1082 r.in.database_id,
1083 sequence_nums[r.in.database_id]);
1085 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1088 return ret;
1093 try a netlogon DatabaseDeltas
1095 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1097 NTSTATUS status;
1098 struct netr_DatabaseDeltas r;
1099 struct creds_CredentialState creds;
1100 const uint32_t database_ids[] = {0, 1, 2};
1101 int i;
1102 BOOL ret = True;
1104 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1105 return False;
1108 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1109 r.in.computername = TEST_MACHINE_NAME;
1110 r.in.preferredmaximumlength = (uint32_t)-1;
1111 ZERO_STRUCT(r.in.return_authenticator);
1113 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1114 r.in.database_id = database_ids[i];
1115 r.in.sequence_num = sequence_nums[r.in.database_id];
1117 if (r.in.sequence_num == 0) continue;
1119 r.in.sequence_num -= 1;
1122 printf("Testing DatabaseDeltas of id %d at %llu\n",
1123 r.in.database_id, r.in.sequence_num);
1125 do {
1126 creds_client_authenticator(&creds, &r.in.credential);
1128 status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
1129 if (!NT_STATUS_IS_OK(status) &&
1130 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1131 printf("DatabaseDeltas - %s\n", nt_errstr(status));
1132 ret = False;
1133 break;
1136 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1137 printf("Credential chaining failed\n");
1140 r.in.sequence_num++;
1141 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1144 return ret;
1149 try a netlogon AccountDeltas
1151 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1153 NTSTATUS status;
1154 struct netr_AccountDeltas r;
1155 struct creds_CredentialState creds;
1156 BOOL ret = True;
1158 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1159 return False;
1162 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1163 r.in.computername = TEST_MACHINE_NAME;
1164 ZERO_STRUCT(r.in.return_authenticator);
1165 creds_client_authenticator(&creds, &r.in.credential);
1166 ZERO_STRUCT(r.in.uas);
1167 r.in.count=10;
1168 r.in.level=0;
1169 r.in.buffersize=100;
1171 printf("Testing AccountDeltas\n");
1173 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1174 status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
1175 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1176 printf("AccountDeltas - %s\n", nt_errstr(status));
1177 ret = False;
1180 return ret;
1184 try a netlogon AccountSync
1186 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1188 NTSTATUS status;
1189 struct netr_AccountSync r;
1190 struct creds_CredentialState creds;
1191 BOOL ret = True;
1193 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1194 return False;
1197 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1198 r.in.computername = TEST_MACHINE_NAME;
1199 ZERO_STRUCT(r.in.return_authenticator);
1200 creds_client_authenticator(&creds, &r.in.credential);
1201 ZERO_STRUCT(r.in.recordid);
1202 r.in.reference=0;
1203 r.in.level=0;
1204 r.in.buffersize=100;
1206 printf("Testing AccountSync\n");
1208 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1209 status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
1210 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1211 printf("AccountSync - %s\n", nt_errstr(status));
1212 ret = False;
1215 return ret;
1219 try a netlogon GetDcName
1221 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1223 NTSTATUS status;
1224 struct netr_GetDcName r;
1226 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1227 r.in.domainname = lp_workgroup();
1229 printf("Testing GetDcName\n");
1231 status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
1232 if (!NT_STATUS_IS_OK(status)) {
1233 printf("GetDcName - %s\n", nt_errstr(status));
1234 return False;
1237 printf("\tDC is at '%s'\n", r.out.dcname);
1239 return True;
1243 try a netlogon LogonControl
1245 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1247 NTSTATUS status;
1248 struct netr_LogonControl r;
1249 BOOL ret = True;
1250 int i;
1252 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1253 r.in.function_code = 1;
1255 for (i=1;i<4;i++) {
1256 r.in.level = i;
1258 printf("Testing LogonControl level %d\n", i);
1260 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
1261 if (!NT_STATUS_IS_OK(status)) {
1262 printf("LogonControl - %s\n", nt_errstr(status));
1263 ret = False;
1267 return ret;
1272 try a netlogon GetAnyDCName
1274 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1276 NTSTATUS status;
1277 struct netr_GetAnyDCName r;
1279 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1280 r.in.domainname = lp_workgroup();
1282 printf("Testing GetAnyDCName\n");
1284 status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
1285 if (!NT_STATUS_IS_OK(status)) {
1286 printf("GetAnyDCName - %s\n", nt_errstr(status));
1287 return False;
1290 if (r.out.dcname) {
1291 printf("\tDC is at '%s'\n", r.out.dcname);
1294 return True;
1299 try a netlogon LogonControl2
1301 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1303 NTSTATUS status;
1304 struct netr_LogonControl2 r;
1305 BOOL ret = True;
1306 int i;
1308 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1310 r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1311 r.in.data.domain = lp_workgroup();
1313 for (i=1;i<4;i++) {
1314 r.in.level = i;
1316 printf("Testing LogonControl2 level %d function %d\n",
1317 i, r.in.function_code);
1319 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1320 if (!NT_STATUS_IS_OK(status)) {
1321 printf("LogonControl - %s\n", nt_errstr(status));
1322 ret = False;
1326 r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1327 r.in.data.domain = lp_workgroup();
1329 for (i=1;i<4;i++) {
1330 r.in.level = i;
1332 printf("Testing LogonControl2 level %d function %d\n",
1333 i, r.in.function_code);
1335 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1336 if (!NT_STATUS_IS_OK(status)) {
1337 printf("LogonControl - %s\n", nt_errstr(status));
1338 ret = False;
1342 r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1343 r.in.data.domain = lp_workgroup();
1345 for (i=1;i<4;i++) {
1346 r.in.level = i;
1348 printf("Testing LogonControl2 level %d function %d\n",
1349 i, r.in.function_code);
1351 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 printf("LogonControl - %s\n", nt_errstr(status));
1354 ret = False;
1358 r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1359 r.in.data.debug_level = ~0;
1361 for (i=1;i<4;i++) {
1362 r.in.level = i;
1364 printf("Testing LogonControl2 level %d function %d\n",
1365 i, r.in.function_code);
1367 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1368 if (!NT_STATUS_IS_OK(status)) {
1369 printf("LogonControl - %s\n", nt_errstr(status));
1370 ret = False;
1374 return ret;
1378 try a netlogon DatabaseSync2
1380 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1382 NTSTATUS status;
1383 struct netr_DatabaseSync2 r;
1384 struct creds_CredentialState creds;
1385 const uint32_t database_ids[] = {0, 1, 2};
1386 int i;
1387 BOOL ret = True;
1389 if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &creds)) {
1390 return False;
1393 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1394 r.in.computername = TEST_MACHINE_NAME;
1395 r.in.preferredmaximumlength = (uint32_t)-1;
1396 ZERO_STRUCT(r.in.return_authenticator);
1398 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1399 r.in.sync_context = 0;
1400 r.in.database_id = database_ids[i];
1401 r.in.restart_state = 0;
1403 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
1405 do {
1406 creds_client_authenticator(&creds, &r.in.credential);
1408 status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
1409 if (!NT_STATUS_IS_OK(status) &&
1410 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1411 printf("DatabaseSync2 - %s\n", nt_errstr(status));
1412 ret = False;
1413 break;
1416 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1417 printf("Credential chaining failed\n");
1420 r.in.sync_context = r.out.sync_context;
1421 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1424 return ret;
1429 try a netlogon LogonControl2Ex
1431 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1433 NTSTATUS status;
1434 struct netr_LogonControl2Ex r;
1435 BOOL ret = True;
1436 int i;
1438 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1440 r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1441 r.in.data.domain = lp_workgroup();
1443 for (i=1;i<4;i++) {
1444 r.in.level = i;
1446 printf("Testing LogonControl2Ex level %d function %d\n",
1447 i, r.in.function_code);
1449 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1450 if (!NT_STATUS_IS_OK(status)) {
1451 printf("LogonControl - %s\n", nt_errstr(status));
1452 ret = False;
1456 r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1457 r.in.data.domain = lp_workgroup();
1459 for (i=1;i<4;i++) {
1460 r.in.level = i;
1462 printf("Testing LogonControl2Ex level %d function %d\n",
1463 i, r.in.function_code);
1465 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1466 if (!NT_STATUS_IS_OK(status)) {
1467 printf("LogonControl - %s\n", nt_errstr(status));
1468 ret = False;
1472 r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1473 r.in.data.domain = lp_workgroup();
1475 for (i=1;i<4;i++) {
1476 r.in.level = i;
1478 printf("Testing LogonControl2Ex level %d function %d\n",
1479 i, r.in.function_code);
1481 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 printf("LogonControl - %s\n", nt_errstr(status));
1484 ret = False;
1488 r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1489 r.in.data.debug_level = ~0;
1491 for (i=1;i<4;i++) {
1492 r.in.level = i;
1494 printf("Testing LogonControl2Ex level %d function %d\n",
1495 i, r.in.function_code);
1497 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1498 if (!NT_STATUS_IS_OK(status)) {
1499 printf("LogonControl - %s\n", nt_errstr(status));
1500 ret = False;
1504 return ret;
1509 try a netlogon netr_DsrEnumerateDomainTrusts
1511 static BOOL test_DsrEnumerateDomainTrusts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1513 NTSTATUS status;
1514 struct netr_DsrEnumerateDomainTrusts r;
1516 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1517 r.in.trust_flags = 0x3f;
1519 printf("Testing netr_DsrEnumerateDomainTrusts\n");
1521 status = dcerpc_netr_DsrEnumerateDomainTrusts(p, mem_ctx, &r);
1522 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1523 printf("netr_DsrEnumerateDomainTrusts - %s/%s\n",
1524 nt_errstr(status), win_errstr(r.out.result));
1525 return False;
1528 return True;
1533 test an ADS style interactive domain login
1535 static BOOL test_InteractiveLogin(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1536 struct creds_CredentialState *creds)
1538 NTSTATUS status;
1539 struct netr_LogonSamLogonWithFlags r;
1540 struct netr_Authenticator a, ra;
1541 struct netr_PasswordInfo pinfo;
1542 const char *plain_pass;
1544 ZERO_STRUCT(r);
1545 ZERO_STRUCT(ra);
1547 creds_client_authenticator(creds, &a);
1549 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1550 r.in.workstation = TEST_MACHINE_NAME;
1551 r.in.credential = &a;
1552 r.in.return_authenticator = &ra;
1553 r.in.logon_level = 5;
1554 r.in.logon.password = &pinfo;
1555 r.in.validation_level = 6;
1556 r.in.flags = 0;
1558 pinfo.identity_info.domain_name.string = lp_parm_string(-1, "torture", "userdomain");
1559 pinfo.identity_info.parameter_control = 0;
1560 pinfo.identity_info.logon_id_low = 0;
1561 pinfo.identity_info.logon_id_high = 0;
1562 pinfo.identity_info.account_name.string = lp_parm_string(-1, "torture", "username");
1563 pinfo.identity_info.workstation.string = TEST_MACHINE_NAME;
1565 plain_pass = lp_parm_string(-1, "torture", "password");
1567 E_deshash(plain_pass, pinfo.lmpassword.hash);
1568 E_md4hash(plain_pass, pinfo.ntpassword.hash);
1570 creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
1571 creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
1573 printf("Testing netr_LogonSamLogonWithFlags\n");
1575 status = dcerpc_netr_LogonSamLogonWithFlags(p, mem_ctx, &r);
1576 if (!NT_STATUS_IS_OK(status)) {
1577 printf("netr_LogonSamLogonWithFlags - %s\n", nt_errstr(status));
1578 exit(1);
1579 return False;
1582 if (!creds_client_check(creds, &r.out.return_authenticator->cred)) {
1583 printf("Credential chaining failed\n");
1584 return False;
1587 return True;
1591 static BOOL test_GetDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1593 NTSTATUS status;
1594 struct netr_LogonGetDomainInfo r;
1595 struct netr_DomainQuery1 q1;
1596 struct netr_Authenticator a;
1597 struct creds_CredentialState creds;
1599 if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &creds)) {
1600 return False;
1603 ZERO_STRUCT(r);
1605 creds_client_authenticator(&creds, &a);
1607 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1608 r.in.computer_name = TEST_MACHINE_NAME;
1609 r.in.unknown1 = 512;
1610 r.in.level = 1;
1611 r.in.credential = &a;
1612 r.out.credential = &a;
1614 r.in.i1[0] = 0;
1615 r.in.i1[1] = 0;
1617 r.in.query.query1 = &q1;
1618 ZERO_STRUCT(q1);
1620 /* this should really be the fully qualified name */
1621 q1.workstation_domain = TEST_MACHINE_NAME;
1622 q1.workstation_site = "Default-First-Site-Name";
1623 q1.blob2.length = 0;
1624 q1.blob2.size = 0;
1625 q1.blob2.data = NULL;
1626 q1.product.string = "product string";
1628 printf("Testing netr_LogonGetDomainInfo\n");
1630 status = dcerpc_netr_LogonGetDomainInfo(p, mem_ctx, &r);
1631 if (!NT_STATUS_IS_OK(status)) {
1632 printf("netr_LogonGetDomainInfo - %s\n", nt_errstr(status));
1633 return False;
1636 if (!creds_client_check(&creds, &a.cred)) {
1637 printf("Credential chaining failed\n");
1638 return False;
1641 test_InteractiveLogin(p, mem_ctx, &creds);
1643 return True;
1647 static void async_callback(struct rpc_request *req)
1649 int *counter = req->async.private;
1650 if (NT_STATUS_IS_OK(req->status)) {
1651 (*counter)++;
1655 static BOOL test_GetDomainInfo_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1657 NTSTATUS status;
1658 struct netr_LogonGetDomainInfo r;
1659 struct netr_DomainQuery1 q1;
1660 struct netr_Authenticator a;
1661 #define ASYNC_COUNT 100
1662 struct creds_CredentialState creds;
1663 struct creds_CredentialState creds_async[ASYNC_COUNT];
1664 struct rpc_request *req[ASYNC_COUNT];
1665 int i;
1666 int async_counter = 0;
1668 if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &creds)) {
1669 return False;
1672 ZERO_STRUCT(r);
1673 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1674 r.in.computer_name = TEST_MACHINE_NAME;
1675 r.in.unknown1 = 512;
1676 r.in.level = 1;
1677 r.in.credential = &a;
1678 r.out.credential = &a;
1680 r.in.i1[0] = 0;
1681 r.in.i1[1] = 0;
1683 r.in.query.query1 = &q1;
1684 ZERO_STRUCT(q1);
1686 /* this should really be the fully qualified name */
1687 q1.workstation_domain = TEST_MACHINE_NAME;
1688 q1.workstation_site = "Default-First-Site-Name";
1689 q1.blob2.length = 0;
1690 q1.blob2.size = 0;
1691 q1.blob2.data = NULL;
1692 q1.product.string = "product string";
1694 printf("Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT);
1696 for (i=0;i<ASYNC_COUNT;i++) {
1697 creds_client_authenticator(&creds, &a);
1699 creds_async[i] = creds;
1700 req[i] = dcerpc_netr_LogonGetDomainInfo_send(p, mem_ctx, &r);
1702 req[i]->async.callback = async_callback;
1703 req[i]->async.private = &async_counter;
1705 /* even with this flush per request a w2k3 server seems to
1706 clag with multiple outstanding requests. bleergh. */
1707 if (event_loop_once(dcerpc_event_context(p)) != 0) {
1708 return False;
1712 for (i=0;i<ASYNC_COUNT;i++) {
1713 status = dcerpc_ndr_request_recv(req[i]);
1714 if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(r.out.result)) {
1715 printf("netr_LogonGetDomainInfo_async(%d) - %s/%s\n",
1716 i, nt_errstr(status), nt_errstr(r.out.result));
1717 break;
1720 if (!creds_client_check(&creds_async[i], &a.cred)) {
1721 printf("Credential chaining failed at async %d\n", i);
1722 break;
1726 printf("Testing netr_LogonGetDomainInfo - async count %d OK\n", async_counter);
1728 return async_counter == ASYNC_COUNT;
1732 BOOL torture_rpc_netlogon(int dummy)
1734 NTSTATUS status;
1735 struct dcerpc_pipe *p;
1736 TALLOC_CTX *mem_ctx;
1737 BOOL ret = True;
1738 void *join_ctx;
1740 mem_ctx = talloc_init("torture_rpc_netlogon");
1742 join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST,
1743 &machine_password);
1744 if (!join_ctx) {
1745 printf("Failed to join as BDC\n");
1746 return False;
1749 status = torture_rpc_connection(&p,
1750 DCERPC_NETLOGON_NAME,
1751 DCERPC_NETLOGON_UUID,
1752 DCERPC_NETLOGON_VERSION);
1753 if (!NT_STATUS_IS_OK(status)) {
1754 return False;
1757 if (!test_LogonUasLogon(p, mem_ctx)) {
1758 ret = False;
1761 if (!test_LogonUasLogoff(p, mem_ctx)) {
1762 ret = False;
1765 if (!test_SetPassword(p, mem_ctx)) {
1766 ret = False;
1769 if (!test_SamLogon(p, mem_ctx)) {
1770 ret = False;
1773 if (!test_GetDomainInfo(p, mem_ctx)) {
1774 ret = False;
1777 if (!test_DatabaseSync(p, mem_ctx)) {
1778 ret = False;
1781 if (!test_DatabaseDeltas(p, mem_ctx)) {
1782 ret = False;
1785 if (!test_AccountDeltas(p, mem_ctx)) {
1786 ret = False;
1789 if (!test_AccountSync(p, mem_ctx)) {
1790 ret = False;
1793 if (!test_GetDcName(p, mem_ctx)) {
1794 ret = False;
1797 if (!test_LogonControl(p, mem_ctx)) {
1798 ret = False;
1801 if (!test_GetAnyDCName(p, mem_ctx)) {
1802 ret = False;
1805 if (!test_LogonControl2(p, mem_ctx)) {
1806 ret = False;
1809 if (!test_DatabaseSync2(p, mem_ctx)) {
1810 ret = False;
1813 if (!test_LogonControl2Ex(p, mem_ctx)) {
1814 ret = False;
1817 if (!test_DsrEnumerateDomainTrusts(p, mem_ctx)) {
1818 ret = False;
1821 if (!test_GetDomainInfo_async(p, mem_ctx)) {
1822 ret = False;
1825 talloc_destroy(mem_ctx);
1827 torture_rpc_close(p);
1829 torture_leave_domain(join_ctx);
1831 return ret;