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.
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)
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));
53 static BOOL test_LogonUasLogoff(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
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));
74 static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
75 struct creds_CredentialState *creds)
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), False);
93 status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
94 if (!NT_STATUS_IS_OK(status)) {
95 printf("ServerReqChallenge - %s\n", nt_errstr(status));
99 plain_pass = machine_password;
101 printf("Unable to fetch machine password!\n");
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));
125 if (!creds_client_check(creds, &credentials3)) {
126 printf("Credential chaining failed\n");
133 static BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
134 uint32_t negotiate_flags,
135 struct creds_CredentialState *creds)
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), False);
153 status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
154 if (!NT_STATUS_IS_OK(status)) {
155 printf("ServerReqChallenge - %s\n", nt_errstr(status));
159 plain_pass = machine_password;
161 printf("Unable to fetch machine password!\n");
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,
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));
187 if (!creds_client_check(creds, &credentials3)) {
188 printf("Credential chaining failed\n");
192 printf("negotiate_flags=0x%08x\n", negotiate_flags);
198 static BOOL test_SetupCredentials3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
199 uint32_t negotiate_flags,
200 struct creds_CredentialState *creds)
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;
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), False);
219 status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
220 if (!NT_STATUS_IS_OK(status)) {
221 printf("ServerReqChallenge - %s\n", nt_errstr(status));
225 plain_pass = machine_password;
227 printf("Unable to fetch machine password!\n");
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;
243 creds_client_init(creds, &credentials1, &credentials2, &mach_password, &credentials3,
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));
254 if (!creds_client_check(creds, &credentials3)) {
255 printf("Credential chaining failed\n");
259 printf("negotiate_flags=0x%08x\n", negotiate_flags);
272 struct samlogon_state {
274 const char *account_name;
275 const char *password;
276 struct dcerpc_pipe *p;
277 struct netr_LogonSamLogon r;
278 struct netr_Authenticator auth, auth2;
279 struct creds_CredentialState creds;
284 Authenticate a user with a challenge/response, checking session key
285 and valid authentication types
288 static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
289 enum ntlm_break break_which,
291 DATA_BLOB *lm_response,
292 DATA_BLOB *nt_response,
294 uint8_t user_session_key[16],
298 struct netr_LogonSamLogon *r = &samlogon_state->r;
299 int levels[] = { 2, 6 };
301 struct netr_NetworkInfo ninfo;
303 for (i=0;i<ARRAY_SIZE(levels);i++) {
304 printf("testing netr_LogonSamLogon with logon level %d\n", levels[i]);
306 samlogon_state->r.in.logon_level = levels[i];
307 samlogon_state->r.in.logon.network = &ninfo;
309 ninfo.logon_info.domain_name.string = lp_workgroup();
310 ninfo.logon_info.parameter_control = 0;
311 ninfo.logon_info.logon_id_low = 0;
312 ninfo.logon_info.logon_id_high = 0;
313 ninfo.logon_info.account_name.string = samlogon_state->account_name;
314 ninfo.logon_info.workstation.string = TEST_MACHINE_NAME;
316 memcpy(ninfo.challenge, chall->data, 8);
318 switch (break_which) {
322 if (lm_response && lm_response->data) {
323 lm_response->data[0]++;
327 if (nt_response && nt_response->data) {
328 nt_response->data[0]++;
332 data_blob_free(lm_response);
335 data_blob_free(nt_response);
340 ninfo.nt.data = nt_response->data;
341 ninfo.nt.length = nt_response->length;
343 ninfo.nt.data = NULL;
348 ninfo.lm.data = lm_response->data;
349 ninfo.lm.length = lm_response->length;
351 ninfo.lm.data = NULL;
355 ZERO_STRUCT(samlogon_state->auth2);
356 creds_client_authenticator(&samlogon_state->creds, &samlogon_state->auth);
358 r->out.authenticator = NULL;
359 status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
360 if (!NT_STATUS_IS_OK(status)) {
362 *error_string = strdup(nt_errstr(status));
366 if (!r->out.authenticator ||
367 !creds_client_check(&samlogon_state->creds, &r->out.authenticator->cred)) {
368 printf("Credential chaining failed\n");
371 if (!NT_STATUS_IS_OK(status)) {
372 /* we cannot check the session key, if the logon failed... */
376 /* find and decyrpt the session keys, return in parameters above */
377 if (r->in.validation_level == 2) {
378 static const char zeros[16];
380 if (memcmp(r->out.validation.sam->LMSessKey.key, zeros,
381 sizeof(r->out.validation.sam->LMSessKey.key)) != 0) {
382 creds_arcfour_crypt(&samlogon_state->creds,
383 r->out.validation.sam->LMSessKey.key,
384 sizeof(r->out.validation.sam->LMSessKey.key));
388 memcpy(lm_key, r->out.validation.sam->LMSessKey.key, 8);
391 if (memcmp(r->out.validation.sam->key.key, zeros, sizeof(r->out.validation.sam->key.key)) != 0) {
392 creds_arcfour_crypt(&samlogon_state->creds,
393 r->out.validation.sam->key.key,
394 sizeof(r->out.validation.sam->key.key));
397 if (user_session_key) {
398 memcpy(user_session_key, r->out.validation.sam->key.key, 16);
401 } else if (r->in.validation_level == 3) {
402 static const char zeros[16];
403 if (memcmp(r->out.validation.sam2->LMSessKey.key, zeros, sizeof(r->out.validation.sam2->LMSessKey.key)) != 0) {
404 creds_arcfour_crypt(&samlogon_state->creds,
405 r->out.validation.sam2->LMSessKey.key,
406 sizeof(r->out.validation.sam2->LMSessKey.key));
410 memcpy(lm_key, r->out.validation.sam2->LMSessKey.key, 8);
413 if (memcmp(r->out.validation.sam2->key.key, zeros, sizeof(r->out.validation.sam2->key.key)) != 0) {
414 creds_arcfour_crypt(&samlogon_state->creds,
415 r->out.validation.sam2->key.key,
416 sizeof(r->out.validation.sam2->key.key));
419 if (user_session_key) {
420 memcpy(user_session_key, r->out.validation.sam2->key.key, 16);
429 * Test the normal 'LM and NTLM' combination
432 static BOOL test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
436 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
437 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
438 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
441 uint8_t user_session_key[16];
446 ZERO_STRUCT(user_session_key);
448 SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
449 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,
458 &samlogon_state->chall,
465 data_blob_free(&lm_response);
467 if (!NT_STATUS_IS_OK(nt_status)) {
468 return break_which == BREAK_NT;
471 if (memcmp(lm_hash, lm_key,
472 sizeof(lm_key)) != 0) {
473 printf("LM Key does not match expectations!\n");
475 dump_data(1, (const char *)lm_key, 8);
476 printf("expected:\n");
477 dump_data(1, (const char *)lm_hash, 8);
481 if (break_which == NO_NT) {
482 char lm_key_expected[16];
483 memcpy(lm_key_expected, lm_hash, 8);
484 memset(lm_key_expected+8, '\0', 8);
485 if (memcmp(lm_key_expected, user_session_key,
487 printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
488 printf("user_session_key:\n");
489 dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
490 printf("expected:\n");
491 dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
495 if (memcmp(session_key.data, user_session_key,
496 sizeof(user_session_key)) != 0) {
497 printf("NT Session Key does not match expectations!\n");
498 printf("user_session_key:\n");
499 dump_data(1, (const char *)user_session_key, 16);
500 printf("expected:\n");
501 dump_data(1, (const char *)session_key.data, session_key.length);
509 * Test LM authentication, no NT response supplied
512 static BOOL test_lm(struct samlogon_state *samlogon_state, char **error_string)
515 return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
519 * Test the NTLM response only, no LM.
522 static BOOL test_ntlm(struct samlogon_state *samlogon_state, char **error_string)
524 return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
528 * Test the NTLM response only, but in the LM field.
531 static BOOL test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string)
535 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
539 uint8_t user_session_key[16];
541 ZERO_STRUCT(user_session_key);
543 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
545 E_deshash(samlogon_state->password, lm_hash);
547 nt_status = check_samlogon(samlogon_state,
549 &samlogon_state->chall,
556 if (!NT_STATUS_IS_OK(nt_status)) {
560 if (memcmp(lm_hash, lm_key,
561 sizeof(lm_key)) != 0) {
562 printf("LM Key does not match expectations!\n");
564 dump_data(1, (const char *)lm_key, 8);
565 printf("expected:\n");
566 dump_data(1, (const char *)lm_hash, 8);
569 if (memcmp(lm_hash, user_session_key, 8) != 0) {
570 char lm_key_expected[16];
571 memcpy(lm_key_expected, lm_hash, 8);
572 memset(lm_key_expected+8, '\0', 8);
573 if (memcmp(lm_key_expected, user_session_key,
575 printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
576 printf("user_session_key:\n");
577 dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
578 printf("expected:\n");
579 dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
587 * Test the NTLM response only, but in the both the NT and LM fields.
590 static BOOL test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string)
594 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
595 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
599 char user_session_key[16];
603 ZERO_STRUCT(user_session_key);
605 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
607 E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
608 SMBsesskeygen_ntv1((const uint8_t *)nt_hash,
611 E_deshash(samlogon_state->password, (uint8_t *)lm_hash);
613 nt_status = check_samlogon(samlogon_state,
615 &samlogon_state->chall,
622 if (!NT_STATUS_IS_OK(nt_status)) {
626 if (memcmp(lm_hash, lm_key,
627 sizeof(lm_key)) != 0) {
628 printf("LM Key does not match expectations!\n");
630 dump_data(1, lm_key, 8);
631 printf("expected:\n");
632 dump_data(1, lm_hash, 8);
635 if (memcmp(session_key.data, user_session_key,
636 sizeof(user_session_key)) != 0) {
637 printf("NT Session Key does not match expectations!\n");
638 printf("user_session_key:\n");
639 dump_data(1, user_session_key, 16);
640 printf("expected:\n");
641 dump_data(1, (const char *)session_key.data, session_key.length);
650 * Test the NTLMv2 and LMv2 responses
653 static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
657 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
658 DATA_BLOB lmv2_response = data_blob(NULL, 0);
659 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
660 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, lp_netbios_name(), lp_workgroup());
662 uint8_t user_session_key[16];
664 ZERO_STRUCT(user_session_key);
666 /* TODO - test with various domain cases, and without domain */
667 if (!SMBNTLMv2encrypt(samlogon_state->account_name, lp_workgroup(),
668 samlogon_state->password, &samlogon_state->chall,
670 &lmv2_response, &ntlmv2_response,
671 &ntlmv2_session_key)) {
672 data_blob_free(&names_blob);
675 data_blob_free(&names_blob);
677 nt_status = check_samlogon(samlogon_state,
679 &samlogon_state->chall,
686 data_blob_free(&lmv2_response);
687 data_blob_free(&ntlmv2_response);
689 if (!NT_STATUS_IS_OK(nt_status)) {
690 return break_which == BREAK_NT;
693 if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key,
694 sizeof(user_session_key)) != 0) {
695 printf("USER (NTLMv2) Session Key does not match expectations!\n");
696 printf("user_session_key:\n");
697 dump_data(1, (const char *)user_session_key, 16);
698 printf("expected:\n");
699 dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length);
706 * Test the NTLMv2 and LMv2 responses
709 static BOOL test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
711 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, error_string);
715 * Test the LMv2 response only
718 static BOOL test_lmv2(struct samlogon_state *samlogon_state, char **error_string)
720 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, error_string);
724 * Test the NTLMv2 response only
727 static BOOL test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
729 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, error_string);
732 static BOOL test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string)
734 return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
737 static BOOL test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string)
739 return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
742 static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string)
744 return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
747 static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
749 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, error_string);
752 static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
754 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, error_string);
757 static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
760 DATA_BLOB nt_response = data_blob(NULL, 0);
761 DATA_BLOB lm_response = data_blob(NULL, 0);
764 smb_ucs2_t *unicodepw;
766 uint8_t user_session_key[16];
768 static const uint8_t zeros[8];
769 DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
771 ZERO_STRUCT(user_session_key);
773 if ((push_ucs2_talloc(samlogon_state->mem_ctx, (smb_ucs2_t **)&unicodepw,
774 samlogon_state->password)) == -1) {
775 DEBUG(0, ("push_ucs2_allocate failed!\n"));
779 nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw,
780 strlen_w(((void *)unicodepw))*sizeof(smb_ucs2_t));
782 password = strdup_upper(samlogon_state->password);
784 if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX,
787 (const void**)&dospw)) == -1) {
788 DEBUG(0, ("push_ascii_allocate failed!\n"));
794 lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
796 nt_status = check_samlogon(samlogon_state,
805 if (!NT_STATUS_IS_OK(nt_status)) {
806 return break_which == BREAK_NT;
812 static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state,
813 char **error_string) {
814 return test_plaintext(samlogon_state, BREAK_NONE, error_string);
817 static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state,
818 char **error_string) {
819 return test_plaintext(samlogon_state, BREAK_LM, error_string);
822 static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state,
823 char **error_string) {
824 return test_plaintext(samlogon_state, BREAK_NT, error_string);
827 static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state,
828 char **error_string) {
829 return test_plaintext(samlogon_state, NO_LM, error_string);
832 static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state,
833 char **error_string) {
834 return test_plaintext(samlogon_state, NO_NT, error_string);
848 - plaintext tests (in challenge-response fields)
850 check we get the correct session key in each case
851 check what values we get for the LM session key
855 static const struct ntlm_tests {
856 BOOL (*fn)(struct samlogon_state *, char **);
860 {test_lm, "LM", False},
861 {test_lm_ntlm, "LM and NTLM", False},
862 {test_ntlm, "NTLM", False},
863 {test_ntlm_in_lm, "NTLM in LM", False},
864 {test_ntlm_in_both, "NTLM in both", False},
865 {test_ntlmv2, "NTLMv2", False},
866 {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
867 {test_lmv2, "LMv2", False},
868 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
869 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
870 {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
871 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
872 {test_plaintext_none_broken, "Plaintext", True},
873 {test_plaintext_lm_broken, "Plaintext LM broken", True},
874 {test_plaintext_nt_broken, "Plaintext NT broken", True},
875 {test_plaintext_nt_only, "Plaintext NT only", True},
876 {test_plaintext_lm_only, "Plaintext LM only", True},
881 try a netlogon SamLogon
883 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
888 struct samlogon_state samlogon_state;
890 samlogon_state.mem_ctx = mem_ctx;
891 samlogon_state.account_name = lp_parm_string(-1, "torture", "username");
892 samlogon_state.password = lp_parm_string(-1, "torture", "password");
893 samlogon_state.p = p;
895 samlogon_state.chall = data_blob_talloc(mem_ctx, NULL, 8);
897 generate_random_buffer(samlogon_state.chall.data,
900 if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
904 if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
908 if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &samlogon_state.creds)) {
912 samlogon_state.r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
913 samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
914 samlogon_state.r.in.credential = &samlogon_state.auth;
915 samlogon_state.r.in.authenticator = &samlogon_state.auth2;
918 samlogon_state.r.in.validation_level = i;
919 for (j=0; test_table[j].fn; j++) {
920 char *error_string = NULL;
921 printf("Testing SamLogon with '%s' at validation level %d\n", test_table[j].name, i);
923 if (!test_table[j].fn(&samlogon_state, &error_string)) {
924 if (test_table[j].expect_fail) {
925 printf("Test %s failed (expected, test incomplete): %s\n", test_table[j].name, error_string);
927 printf("Test %s failed: %s\n", test_table[j].name, error_string);
930 SAFE_FREE(error_string);
940 try a change password for our machine account
942 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
945 struct netr_ServerPasswordSet r;
946 const char *password;
947 struct creds_CredentialState creds;
949 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
953 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
954 r.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
955 r.in.secure_channel_type = SEC_CHAN_BDC;
956 r.in.computer_name = TEST_MACHINE_NAME;
958 password = generate_random_str(mem_ctx, 8);
959 E_md4hash(password, r.in.new_password.hash);
961 creds_des_encrypt(&creds, &r.in.new_password);
963 printf("Testing ServerPasswordSet on machine account\n");
964 printf("Changing machine account password to '%s'\n", password);
966 creds_client_authenticator(&creds, &r.in.credential);
968 status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
969 if (!NT_STATUS_IS_OK(status)) {
970 printf("ServerPasswordSet - %s\n", nt_errstr(status));
974 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
975 printf("Credential chaining failed\n");
978 /* by changing the machine password twice we test the
979 credentials chaining fully, and we verify that the server
980 allows the password to be set to the same value twice in a
981 row (match win2k3) */
982 printf("Testing a second ServerPasswordSet on machine account\n");
983 printf("Changing machine account password to '%s' (same as pervsious run)\n", password);
985 creds_client_authenticator(&creds, &r.in.credential);
987 status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
988 if (!NT_STATUS_IS_OK(status)) {
989 printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
993 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
994 printf("Credential chaining failed\n");
997 machine_password = password;
999 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1000 printf("ServerPasswordSet failed to actually change the password\n");
1008 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
1009 static uint64_t sequence_nums[3];
1012 try a netlogon DatabaseSync
1014 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1017 struct netr_DatabaseSync r;
1018 struct creds_CredentialState creds;
1019 const uint32_t database_ids[] = {0, 1, 2};
1023 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1027 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1028 r.in.computername = TEST_MACHINE_NAME;
1029 r.in.preferredmaximumlength = (uint32_t)-1;
1030 ZERO_STRUCT(r.in.return_authenticator);
1032 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1033 r.in.sync_context = 0;
1034 r.in.database_id = database_ids[i];
1036 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
1039 creds_client_authenticator(&creds, &r.in.credential);
1041 status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
1042 if (!NT_STATUS_IS_OK(status) &&
1043 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1044 printf("DatabaseSync - %s\n", nt_errstr(status));
1049 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1050 printf("Credential chaining failed\n");
1053 r.in.sync_context = r.out.sync_context;
1055 if (r.out.delta_enum_array &&
1056 r.out.delta_enum_array->num_deltas > 0 &&
1057 r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
1058 r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
1059 sequence_nums[r.in.database_id] =
1060 r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
1061 printf("\tsequence_nums[%d]=%llu\n",
1063 sequence_nums[r.in.database_id]);
1065 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1073 try a netlogon DatabaseDeltas
1075 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1078 struct netr_DatabaseDeltas r;
1079 struct creds_CredentialState creds;
1080 const uint32_t database_ids[] = {0, 1, 2};
1084 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1088 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1089 r.in.computername = TEST_MACHINE_NAME;
1090 r.in.preferredmaximumlength = (uint32_t)-1;
1091 ZERO_STRUCT(r.in.return_authenticator);
1093 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1094 r.in.database_id = database_ids[i];
1095 r.in.sequence_num = sequence_nums[r.in.database_id];
1097 if (r.in.sequence_num == 0) continue;
1099 r.in.sequence_num -= 1;
1102 printf("Testing DatabaseDeltas of id %d at %llu\n",
1103 r.in.database_id, r.in.sequence_num);
1106 creds_client_authenticator(&creds, &r.in.credential);
1108 status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
1109 if (!NT_STATUS_IS_OK(status) &&
1110 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1111 printf("DatabaseDeltas - %s\n", nt_errstr(status));
1116 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1117 printf("Credential chaining failed\n");
1120 r.in.sequence_num++;
1121 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1129 try a netlogon AccountDeltas
1131 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1134 struct netr_AccountDeltas r;
1135 struct creds_CredentialState creds;
1138 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1142 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1143 r.in.computername = TEST_MACHINE_NAME;
1144 ZERO_STRUCT(r.in.return_authenticator);
1145 creds_client_authenticator(&creds, &r.in.credential);
1146 ZERO_STRUCT(r.in.uas);
1149 r.in.buffersize=100;
1151 printf("Testing AccountDeltas\n");
1153 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1154 status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
1155 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1156 printf("AccountDeltas - %s\n", nt_errstr(status));
1164 try a netlogon AccountSync
1166 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1169 struct netr_AccountSync r;
1170 struct creds_CredentialState creds;
1173 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1177 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1178 r.in.computername = TEST_MACHINE_NAME;
1179 ZERO_STRUCT(r.in.return_authenticator);
1180 creds_client_authenticator(&creds, &r.in.credential);
1181 ZERO_STRUCT(r.in.recordid);
1184 r.in.buffersize=100;
1186 printf("Testing AccountSync\n");
1188 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1189 status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
1190 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1191 printf("AccountSync - %s\n", nt_errstr(status));
1199 try a netlogon GetDcName
1201 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1204 struct netr_GetDcName r;
1206 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1207 r.in.domainname = lp_workgroup();
1209 printf("Testing GetDcName\n");
1211 status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
1212 if (!NT_STATUS_IS_OK(status)) {
1213 printf("GetDcName - %s\n", nt_errstr(status));
1217 printf("\tDC is at '%s'\n", r.out.dcname);
1223 try a netlogon LogonControl
1225 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1228 struct netr_LogonControl r;
1232 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1233 r.in.function_code = 1;
1238 printf("Testing LogonControl level %d\n", i);
1240 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
1241 if (!NT_STATUS_IS_OK(status)) {
1242 printf("LogonControl - %s\n", nt_errstr(status));
1252 try a netlogon GetAnyDCName
1254 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1257 struct netr_GetAnyDCName r;
1259 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1260 r.in.domainname = lp_workgroup();
1262 printf("Testing GetAnyDCName\n");
1264 status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 printf("GetAnyDCName - %s\n", nt_errstr(status));
1271 printf("\tDC is at '%s'\n", r.out.dcname);
1279 try a netlogon LogonControl2
1281 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1284 struct netr_LogonControl2 r;
1288 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1290 r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1291 r.in.data.domain = lp_workgroup();
1296 printf("Testing LogonControl2 level %d function %d\n",
1297 i, r.in.function_code);
1299 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 printf("LogonControl - %s\n", nt_errstr(status));
1306 r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1307 r.in.data.domain = lp_workgroup();
1312 printf("Testing LogonControl2 level %d function %d\n",
1313 i, r.in.function_code);
1315 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 printf("LogonControl - %s\n", nt_errstr(status));
1322 r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1323 r.in.data.domain = lp_workgroup();
1328 printf("Testing LogonControl2 level %d function %d\n",
1329 i, r.in.function_code);
1331 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1332 if (!NT_STATUS_IS_OK(status)) {
1333 printf("LogonControl - %s\n", nt_errstr(status));
1338 r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1339 r.in.data.debug_level = ~0;
1344 printf("Testing LogonControl2 level %d function %d\n",
1345 i, r.in.function_code);
1347 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1348 if (!NT_STATUS_IS_OK(status)) {
1349 printf("LogonControl - %s\n", nt_errstr(status));
1358 try a netlogon DatabaseSync2
1360 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1363 struct netr_DatabaseSync2 r;
1364 struct creds_CredentialState creds;
1365 const uint32_t database_ids[] = {0, 1, 2};
1369 if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &creds)) {
1373 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1374 r.in.computername = TEST_MACHINE_NAME;
1375 r.in.preferredmaximumlength = (uint32_t)-1;
1376 ZERO_STRUCT(r.in.return_authenticator);
1378 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1379 r.in.sync_context = 0;
1380 r.in.database_id = database_ids[i];
1381 r.in.restart_state = 0;
1383 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
1386 creds_client_authenticator(&creds, &r.in.credential);
1388 status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
1389 if (!NT_STATUS_IS_OK(status) &&
1390 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1391 printf("DatabaseSync2 - %s\n", nt_errstr(status));
1396 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1397 printf("Credential chaining failed\n");
1400 r.in.sync_context = r.out.sync_context;
1401 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1409 try a netlogon LogonControl2Ex
1411 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1414 struct netr_LogonControl2Ex r;
1418 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1420 r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1421 r.in.data.domain = lp_workgroup();
1426 printf("Testing LogonControl2Ex level %d function %d\n",
1427 i, r.in.function_code);
1429 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1430 if (!NT_STATUS_IS_OK(status)) {
1431 printf("LogonControl - %s\n", nt_errstr(status));
1436 r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1437 r.in.data.domain = lp_workgroup();
1442 printf("Testing LogonControl2Ex level %d function %d\n",
1443 i, r.in.function_code);
1445 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1446 if (!NT_STATUS_IS_OK(status)) {
1447 printf("LogonControl - %s\n", nt_errstr(status));
1452 r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1453 r.in.data.domain = lp_workgroup();
1458 printf("Testing LogonControl2Ex level %d function %d\n",
1459 i, r.in.function_code);
1461 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1462 if (!NT_STATUS_IS_OK(status)) {
1463 printf("LogonControl - %s\n", nt_errstr(status));
1468 r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1469 r.in.data.debug_level = ~0;
1474 printf("Testing LogonControl2Ex level %d function %d\n",
1475 i, r.in.function_code);
1477 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1478 if (!NT_STATUS_IS_OK(status)) {
1479 printf("LogonControl - %s\n", nt_errstr(status));
1489 try a netlogon netr_DsrEnumerateDomainTrusts
1491 static BOOL test_DsrEnumerateDomainTrusts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1494 struct netr_DsrEnumerateDomainTrusts r;
1496 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1497 r.in.trust_flags = 0x3f;
1499 printf("Testing netr_DsrEnumerateDomainTrusts\n");
1501 status = dcerpc_netr_DsrEnumerateDomainTrusts(p, mem_ctx, &r);
1502 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1503 printf("netr_DsrEnumerateDomainTrusts - %s/%s\n",
1504 nt_errstr(status), win_errstr(r.out.result));
1513 BOOL torture_rpc_netlogon(int dummy)
1516 struct dcerpc_pipe *p;
1517 TALLOC_CTX *mem_ctx;
1521 mem_ctx = talloc_init("torture_rpc_netlogon");
1523 join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST,
1526 printf("Failed to join as BDC\n");
1530 status = torture_rpc_connection(&p,
1531 DCERPC_NETLOGON_NAME,
1532 DCERPC_NETLOGON_UUID,
1533 DCERPC_NETLOGON_VERSION);
1534 if (!NT_STATUS_IS_OK(status)) {
1538 if (!test_LogonUasLogon(p, mem_ctx)) {
1542 if (!test_LogonUasLogoff(p, mem_ctx)) {
1546 if (!test_SetPassword(p, mem_ctx)) {
1550 if (!test_SamLogon(p, mem_ctx)) {
1554 if (!test_DatabaseSync(p, mem_ctx)) {
1558 if (!test_DatabaseDeltas(p, mem_ctx)) {
1562 if (!test_AccountDeltas(p, mem_ctx)) {
1566 if (!test_AccountSync(p, mem_ctx)) {
1570 if (!test_GetDcName(p, mem_ctx)) {
1574 if (!test_LogonControl(p, mem_ctx)) {
1578 if (!test_GetAnyDCName(p, mem_ctx)) {
1582 if (!test_LogonControl2(p, mem_ctx)) {
1586 if (!test_DatabaseSync2(p, mem_ctx)) {
1590 if (!test_LogonControl2Ex(p, mem_ctx)) {
1594 if (!test_DsrEnumerateDomainTrusts(p, mem_ctx)) {
1598 torture_rpc_close(p);
1600 torture_leave_domain(join_ctx);