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.identity_info.domain_name.string = lp_workgroup();
310 ninfo.identity_info.parameter_control = 0;
311 ninfo.identity_info.logon_id_low = 0;
312 ninfo.identity_info.logon_id_high = 0;
313 ninfo.identity_info.account_name.string = samlogon_state->account_name;
314 ninfo.identity_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.return_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.return_authenticator ||
367 !creds_client_check(&samlogon_state->creds, &r->out.return_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.sam2->key.key, zeros,
381 sizeof(r->out.validation.sam2->key.key)) != 0) {
382 creds_arcfour_crypt(&samlogon_state->creds,
383 r->out.validation.sam2->key.key,
384 sizeof(r->out.validation.sam2->key.key));
387 if (user_session_key) {
388 memcpy(user_session_key, r->out.validation.sam2->key.key, 16);
391 if (memcmp(r->out.validation.sam2->LMSessKey.key, zeros,
392 sizeof(r->out.validation.sam2->LMSessKey.key)) != 0) {
393 creds_arcfour_crypt(&samlogon_state->creds,
394 r->out.validation.sam2->LMSessKey.key,
395 sizeof(r->out.validation.sam2->LMSessKey.key));
399 memcpy(lm_key, r->out.validation.sam2->LMSessKey.key, 8);
402 } else if (r->in.validation_level == 3) {
403 static const char zeros[16];
404 if (memcmp(r->out.validation.sam3->key.key, zeros,
405 sizeof(r->out.validation.sam3->key.key)) != 0) {
406 creds_arcfour_crypt(&samlogon_state->creds,
407 r->out.validation.sam3->key.key,
408 sizeof(r->out.validation.sam3->key.key));
411 if (user_session_key) {
412 memcpy(user_session_key, r->out.validation.sam3->key.key, 16);
415 if (memcmp(r->out.validation.sam3->LMSessKey.key, zeros,
416 sizeof(r->out.validation.sam3->LMSessKey.key)) != 0) {
417 creds_arcfour_crypt(&samlogon_state->creds,
418 r->out.validation.sam3->LMSessKey.key,
419 sizeof(r->out.validation.sam3->LMSessKey.key));
423 memcpy(lm_key, r->out.validation.sam3->LMSessKey.key, 8);
433 * Test the normal 'LM and NTLM' combination
436 static BOOL test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
440 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
441 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
442 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
445 uint8_t user_session_key[16];
450 ZERO_STRUCT(user_session_key);
452 SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
453 E_deshash(samlogon_state->password, lm_hash);
455 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
457 E_md4hash(samlogon_state->password, nt_hash);
458 SMBsesskeygen_ntv1(nt_hash, session_key.data);
460 nt_status = check_samlogon(samlogon_state,
462 &samlogon_state->chall,
469 data_blob_free(&lm_response);
471 if (!NT_STATUS_IS_OK(nt_status)) {
472 return break_which == BREAK_NT;
475 if (memcmp(lm_hash, lm_key,
476 sizeof(lm_key)) != 0) {
477 printf("LM Key does not match expectations!\n");
479 dump_data(1, (const char *)lm_key, 8);
480 printf("expected:\n");
481 dump_data(1, (const char *)lm_hash, 8);
485 if (break_which == NO_NT) {
486 char lm_key_expected[16];
487 memcpy(lm_key_expected, lm_hash, 8);
488 memset(lm_key_expected+8, '\0', 8);
489 if (memcmp(lm_key_expected, user_session_key,
491 printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
492 printf("user_session_key:\n");
493 dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
494 printf("expected:\n");
495 dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
499 if (memcmp(session_key.data, user_session_key,
500 sizeof(user_session_key)) != 0) {
501 printf("NT Session Key does not match expectations!\n");
502 printf("user_session_key:\n");
503 dump_data(1, (const char *)user_session_key, 16);
504 printf("expected:\n");
505 dump_data(1, (const char *)session_key.data, session_key.length);
513 * Test LM authentication, no NT response supplied
516 static BOOL test_lm(struct samlogon_state *samlogon_state, char **error_string)
519 return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
523 * Test the NTLM response only, no LM.
526 static BOOL test_ntlm(struct samlogon_state *samlogon_state, char **error_string)
528 return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
532 * Test the NTLM response only, but in the LM field.
535 static BOOL test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string)
539 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
543 uint8_t user_session_key[16];
545 ZERO_STRUCT(user_session_key);
547 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
549 E_deshash(samlogon_state->password, lm_hash);
551 nt_status = check_samlogon(samlogon_state,
553 &samlogon_state->chall,
560 if (!NT_STATUS_IS_OK(nt_status)) {
564 if (memcmp(lm_hash, lm_key,
565 sizeof(lm_key)) != 0) {
566 printf("LM Key does not match expectations!\n");
568 dump_data(1, (const char *)lm_key, 8);
569 printf("expected:\n");
570 dump_data(1, (const char *)lm_hash, 8);
573 if (memcmp(lm_hash, user_session_key, 8) != 0) {
574 char lm_key_expected[16];
575 memcpy(lm_key_expected, lm_hash, 8);
576 memset(lm_key_expected+8, '\0', 8);
577 if (memcmp(lm_key_expected, user_session_key,
579 printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
580 printf("user_session_key:\n");
581 dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
582 printf("expected:\n");
583 dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
591 * Test the NTLM response only, but in the both the NT and LM fields.
594 static BOOL test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string)
598 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
599 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
603 char user_session_key[16];
607 ZERO_STRUCT(user_session_key);
609 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
611 E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
612 SMBsesskeygen_ntv1((const uint8_t *)nt_hash,
615 E_deshash(samlogon_state->password, (uint8_t *)lm_hash);
617 nt_status = check_samlogon(samlogon_state,
619 &samlogon_state->chall,
626 if (!NT_STATUS_IS_OK(nt_status)) {
630 if (memcmp(lm_hash, lm_key,
631 sizeof(lm_key)) != 0) {
632 printf("LM Key does not match expectations!\n");
634 dump_data(1, lm_key, 8);
635 printf("expected:\n");
636 dump_data(1, lm_hash, 8);
639 if (memcmp(session_key.data, user_session_key,
640 sizeof(user_session_key)) != 0) {
641 printf("NT Session Key does not match expectations!\n");
642 printf("user_session_key:\n");
643 dump_data(1, user_session_key, 16);
644 printf("expected:\n");
645 dump_data(1, (const char *)session_key.data, session_key.length);
654 * Test the NTLMv2 and LMv2 responses
657 static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
661 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
662 DATA_BLOB lmv2_response = data_blob(NULL, 0);
663 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
664 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, lp_netbios_name(), lp_workgroup());
666 uint8_t user_session_key[16];
668 ZERO_STRUCT(user_session_key);
670 /* TODO - test with various domain cases, and without domain */
671 if (!SMBNTLMv2encrypt(samlogon_state->account_name, lp_workgroup(),
672 samlogon_state->password, &samlogon_state->chall,
674 &lmv2_response, &ntlmv2_response,
675 &ntlmv2_session_key)) {
676 data_blob_free(&names_blob);
679 data_blob_free(&names_blob);
681 nt_status = check_samlogon(samlogon_state,
683 &samlogon_state->chall,
690 data_blob_free(&lmv2_response);
691 data_blob_free(&ntlmv2_response);
693 if (!NT_STATUS_IS_OK(nt_status)) {
694 return break_which == BREAK_NT;
697 if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key,
698 sizeof(user_session_key)) != 0) {
699 printf("USER (NTLMv2) Session Key does not match expectations!\n");
700 printf("user_session_key:\n");
701 dump_data(1, (const char *)user_session_key, 16);
702 printf("expected:\n");
703 dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length);
710 * Test the NTLMv2 and LMv2 responses
713 static BOOL test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
715 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, error_string);
719 * Test the LMv2 response only
722 static BOOL test_lmv2(struct samlogon_state *samlogon_state, char **error_string)
724 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, error_string);
728 * Test the NTLMv2 response only
731 static BOOL test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
733 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, error_string);
736 static BOOL test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string)
738 return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
741 static BOOL test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string)
743 return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
746 static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string)
748 return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
751 static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
753 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, error_string);
756 static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
758 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, error_string);
761 static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
764 DATA_BLOB nt_response = data_blob(NULL, 0);
765 DATA_BLOB lm_response = data_blob(NULL, 0);
768 smb_ucs2_t *unicodepw;
770 uint8_t user_session_key[16];
772 static const uint8_t zeros[8];
773 DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
775 ZERO_STRUCT(user_session_key);
777 if ((push_ucs2_talloc(samlogon_state->mem_ctx, (smb_ucs2_t **)&unicodepw,
778 samlogon_state->password)) == -1) {
779 DEBUG(0, ("push_ucs2_allocate failed!\n"));
783 nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw,
784 strlen_w(((void *)unicodepw))*sizeof(smb_ucs2_t));
786 password = strdup_upper(samlogon_state->password);
788 if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX,
791 (const void**)&dospw)) == -1) {
792 DEBUG(0, ("push_ascii_allocate failed!\n"));
798 lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
800 nt_status = check_samlogon(samlogon_state,
809 if (!NT_STATUS_IS_OK(nt_status)) {
810 return break_which == BREAK_NT;
816 static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state,
817 char **error_string) {
818 return test_plaintext(samlogon_state, BREAK_NONE, error_string);
821 static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state,
822 char **error_string) {
823 return test_plaintext(samlogon_state, BREAK_LM, error_string);
826 static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state,
827 char **error_string) {
828 return test_plaintext(samlogon_state, BREAK_NT, error_string);
831 static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state,
832 char **error_string) {
833 return test_plaintext(samlogon_state, NO_LM, error_string);
836 static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state,
837 char **error_string) {
838 return test_plaintext(samlogon_state, NO_NT, error_string);
852 - plaintext tests (in challenge-response fields)
854 check we get the correct session key in each case
855 check what values we get for the LM session key
859 static const struct ntlm_tests {
860 BOOL (*fn)(struct samlogon_state *, char **);
864 {test_lm, "LM", False},
865 {test_lm_ntlm, "LM and NTLM", False},
866 {test_ntlm, "NTLM", False},
867 {test_ntlm_in_lm, "NTLM in LM", False},
868 {test_ntlm_in_both, "NTLM in both", False},
869 {test_ntlmv2, "NTLMv2", False},
870 {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
871 {test_lmv2, "LMv2", False},
872 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
873 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
874 {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
875 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
876 {test_plaintext_none_broken, "Plaintext", True},
877 {test_plaintext_lm_broken, "Plaintext LM broken", True},
878 {test_plaintext_nt_broken, "Plaintext NT broken", True},
879 {test_plaintext_nt_only, "Plaintext NT only", True},
880 {test_plaintext_lm_only, "Plaintext LM only", True},
885 try a netlogon SamLogon
887 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
892 struct samlogon_state samlogon_state;
894 samlogon_state.mem_ctx = mem_ctx;
895 samlogon_state.account_name = lp_parm_string(-1, "torture", "username");
896 samlogon_state.password = lp_parm_string(-1, "torture", "password");
897 samlogon_state.p = p;
899 samlogon_state.chall = data_blob_talloc(mem_ctx, NULL, 8);
901 generate_random_buffer(samlogon_state.chall.data,
904 if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
908 if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
912 if (!test_SetupCredentials3(p, mem_ctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, &samlogon_state.creds)) {
916 samlogon_state.r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
917 samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
918 samlogon_state.r.in.credential = &samlogon_state.auth;
919 samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
922 samlogon_state.r.in.validation_level = i;
923 for (j=0; test_table[j].fn; j++) {
924 char *error_string = NULL;
925 printf("Testing SamLogon with '%s' at validation level %d\n", test_table[j].name, i);
927 if (!test_table[j].fn(&samlogon_state, &error_string)) {
928 if (test_table[j].expect_fail) {
929 printf("Test %s failed (expected, test incomplete): %s\n", test_table[j].name, error_string);
931 printf("Test %s failed: %s\n", test_table[j].name, error_string);
934 SAFE_FREE(error_string);
944 try a change password for our machine account
946 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
949 struct netr_ServerPasswordSet r;
950 const char *password;
951 struct creds_CredentialState creds;
953 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
957 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
958 r.in.account_name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
959 r.in.secure_channel_type = SEC_CHAN_BDC;
960 r.in.computer_name = TEST_MACHINE_NAME;
962 password = generate_random_str(mem_ctx, 8);
963 E_md4hash(password, r.in.new_password.hash);
965 creds_des_encrypt(&creds, &r.in.new_password);
967 printf("Testing ServerPasswordSet on machine account\n");
968 printf("Changing machine account password to '%s'\n", password);
970 creds_client_authenticator(&creds, &r.in.credential);
972 status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
973 if (!NT_STATUS_IS_OK(status)) {
974 printf("ServerPasswordSet - %s\n", nt_errstr(status));
978 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
979 printf("Credential chaining failed\n");
982 /* by changing the machine password twice we test the
983 credentials chaining fully, and we verify that the server
984 allows the password to be set to the same value twice in a
985 row (match win2k3) */
986 printf("Testing a second ServerPasswordSet on machine account\n");
987 printf("Changing machine account password to '%s' (same as pervsious run)\n", password);
989 creds_client_authenticator(&creds, &r.in.credential);
991 status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
992 if (!NT_STATUS_IS_OK(status)) {
993 printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
997 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
998 printf("Credential chaining failed\n");
1001 machine_password = password;
1003 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1004 printf("ServerPasswordSet failed to actually change the password\n");
1012 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
1013 static uint64_t sequence_nums[3];
1016 try a netlogon DatabaseSync
1018 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1021 struct netr_DatabaseSync r;
1022 struct creds_CredentialState creds;
1023 const uint32_t database_ids[] = {0, 1, 2};
1027 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1031 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1032 r.in.computername = TEST_MACHINE_NAME;
1033 r.in.preferredmaximumlength = (uint32_t)-1;
1034 ZERO_STRUCT(r.in.return_authenticator);
1036 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1037 r.in.sync_context = 0;
1038 r.in.database_id = database_ids[i];
1040 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
1043 creds_client_authenticator(&creds, &r.in.credential);
1045 status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
1046 if (!NT_STATUS_IS_OK(status) &&
1047 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1048 printf("DatabaseSync - %s\n", nt_errstr(status));
1053 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1054 printf("Credential chaining failed\n");
1057 r.in.sync_context = r.out.sync_context;
1059 if (r.out.delta_enum_array &&
1060 r.out.delta_enum_array->num_deltas > 0 &&
1061 r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
1062 r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
1063 sequence_nums[r.in.database_id] =
1064 r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
1065 printf("\tsequence_nums[%d]=%llu\n",
1067 sequence_nums[r.in.database_id]);
1069 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1077 try a netlogon DatabaseDeltas
1079 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1082 struct netr_DatabaseDeltas r;
1083 struct creds_CredentialState creds;
1084 const uint32_t database_ids[] = {0, 1, 2};
1088 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1092 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1093 r.in.computername = TEST_MACHINE_NAME;
1094 r.in.preferredmaximumlength = (uint32_t)-1;
1095 ZERO_STRUCT(r.in.return_authenticator);
1097 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1098 r.in.database_id = database_ids[i];
1099 r.in.sequence_num = sequence_nums[r.in.database_id];
1101 if (r.in.sequence_num == 0) continue;
1103 r.in.sequence_num -= 1;
1106 printf("Testing DatabaseDeltas of id %d at %llu\n",
1107 r.in.database_id, r.in.sequence_num);
1110 creds_client_authenticator(&creds, &r.in.credential);
1112 status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
1113 if (!NT_STATUS_IS_OK(status) &&
1114 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1115 printf("DatabaseDeltas - %s\n", nt_errstr(status));
1120 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1121 printf("Credential chaining failed\n");
1124 r.in.sequence_num++;
1125 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1133 try a netlogon AccountDeltas
1135 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1138 struct netr_AccountDeltas r;
1139 struct creds_CredentialState creds;
1142 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1146 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1147 r.in.computername = TEST_MACHINE_NAME;
1148 ZERO_STRUCT(r.in.return_authenticator);
1149 creds_client_authenticator(&creds, &r.in.credential);
1150 ZERO_STRUCT(r.in.uas);
1153 r.in.buffersize=100;
1155 printf("Testing AccountDeltas\n");
1157 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1158 status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
1159 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1160 printf("AccountDeltas - %s\n", nt_errstr(status));
1168 try a netlogon AccountSync
1170 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1173 struct netr_AccountSync r;
1174 struct creds_CredentialState creds;
1177 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1181 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1182 r.in.computername = TEST_MACHINE_NAME;
1183 ZERO_STRUCT(r.in.return_authenticator);
1184 creds_client_authenticator(&creds, &r.in.credential);
1185 ZERO_STRUCT(r.in.recordid);
1188 r.in.buffersize=100;
1190 printf("Testing AccountSync\n");
1192 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1193 status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
1194 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1195 printf("AccountSync - %s\n", nt_errstr(status));
1203 try a netlogon GetDcName
1205 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1208 struct netr_GetDcName r;
1210 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1211 r.in.domainname = lp_workgroup();
1213 printf("Testing GetDcName\n");
1215 status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
1216 if (!NT_STATUS_IS_OK(status)) {
1217 printf("GetDcName - %s\n", nt_errstr(status));
1221 printf("\tDC is at '%s'\n", r.out.dcname);
1227 try a netlogon LogonControl
1229 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1232 struct netr_LogonControl r;
1236 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1237 r.in.function_code = 1;
1242 printf("Testing LogonControl level %d\n", i);
1244 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
1245 if (!NT_STATUS_IS_OK(status)) {
1246 printf("LogonControl - %s\n", nt_errstr(status));
1256 try a netlogon GetAnyDCName
1258 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1261 struct netr_GetAnyDCName r;
1263 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1264 r.in.domainname = lp_workgroup();
1266 printf("Testing GetAnyDCName\n");
1268 status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
1269 if (!NT_STATUS_IS_OK(status)) {
1270 printf("GetAnyDCName - %s\n", nt_errstr(status));
1275 printf("\tDC is at '%s'\n", r.out.dcname);
1283 try a netlogon LogonControl2
1285 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1288 struct netr_LogonControl2 r;
1292 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1294 r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1295 r.in.data.domain = lp_workgroup();
1300 printf("Testing LogonControl2 level %d function %d\n",
1301 i, r.in.function_code);
1303 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1304 if (!NT_STATUS_IS_OK(status)) {
1305 printf("LogonControl - %s\n", nt_errstr(status));
1310 r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1311 r.in.data.domain = lp_workgroup();
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));
1326 r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1327 r.in.data.domain = lp_workgroup();
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));
1342 r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1343 r.in.data.debug_level = ~0;
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));
1362 try a netlogon DatabaseSync2
1364 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1367 struct netr_DatabaseSync2 r;
1368 struct creds_CredentialState creds;
1369 const uint32_t database_ids[] = {0, 1, 2};
1373 if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &creds)) {
1377 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1378 r.in.computername = TEST_MACHINE_NAME;
1379 r.in.preferredmaximumlength = (uint32_t)-1;
1380 ZERO_STRUCT(r.in.return_authenticator);
1382 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1383 r.in.sync_context = 0;
1384 r.in.database_id = database_ids[i];
1385 r.in.restart_state = 0;
1387 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
1390 creds_client_authenticator(&creds, &r.in.credential);
1392 status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
1393 if (!NT_STATUS_IS_OK(status) &&
1394 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1395 printf("DatabaseSync2 - %s\n", nt_errstr(status));
1400 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1401 printf("Credential chaining failed\n");
1404 r.in.sync_context = r.out.sync_context;
1405 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1413 try a netlogon LogonControl2Ex
1415 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1418 struct netr_LogonControl2Ex r;
1422 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1424 r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1425 r.in.data.domain = lp_workgroup();
1430 printf("Testing LogonControl2Ex level %d function %d\n",
1431 i, r.in.function_code);
1433 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1434 if (!NT_STATUS_IS_OK(status)) {
1435 printf("LogonControl - %s\n", nt_errstr(status));
1440 r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1441 r.in.data.domain = lp_workgroup();
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));
1456 r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1457 r.in.data.domain = lp_workgroup();
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));
1472 r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1473 r.in.data.debug_level = ~0;
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));
1493 try a netlogon netr_DsrEnumerateDomainTrusts
1495 static BOOL test_DsrEnumerateDomainTrusts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1498 struct netr_DsrEnumerateDomainTrusts r;
1500 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1501 r.in.trust_flags = 0x3f;
1503 printf("Testing netr_DsrEnumerateDomainTrusts\n");
1505 status = dcerpc_netr_DsrEnumerateDomainTrusts(p, mem_ctx, &r);
1506 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
1507 printf("netr_DsrEnumerateDomainTrusts - %s/%s\n",
1508 nt_errstr(status), win_errstr(r.out.result));
1516 static BOOL test_GetDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1519 struct netr_LogonGetDomainInfo r;
1520 struct netr_DomainQuery1 q1;
1521 struct netr_Authenticator a;
1523 struct creds_CredentialState creds;
1525 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1531 creds_client_authenticator(&creds, &a);
1533 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1534 r.in.computer_name = TEST_MACHINE_NAME;
1535 r.in.unknown1 = 512;
1537 r.in.credential = &a;
1538 r.out.credential = &a;
1543 r.in.query.query1 = &q1;
1546 /* this should really be the fully qualified name */
1547 q1.workstation_domain = TEST_MACHINE_NAME;
1548 q1.workstation_site = "Default-First-Site-Name";
1550 q1.blob2.length = 0;
1552 q1.blob2.data = NULL;
1553 q1.product.string = "product string";
1557 printf("Testing netr_LogonGetDomainInfo\n");
1559 status = dcerpc_netr_LogonGetDomainInfo(p, mem_ctx, &r);
1561 if (!creds_client_check(&creds, &a.cred)) {
1562 printf("Credential chaining failed\n");
1565 printf("fault code 0x%x status=%s\n", p->last_fault_code, nt_errstr(status));
1572 BOOL torture_rpc_netlogon(int dummy)
1575 struct dcerpc_pipe *p;
1576 TALLOC_CTX *mem_ctx;
1580 mem_ctx = talloc_init("torture_rpc_netlogon");
1582 join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST,
1585 printf("Failed to join as BDC\n");
1589 status = torture_rpc_connection(&p,
1590 DCERPC_NETLOGON_NAME,
1591 DCERPC_NETLOGON_UUID,
1592 DCERPC_NETLOGON_VERSION);
1593 if (!NT_STATUS_IS_OK(status)) {
1597 if (!test_GetDomainInfo(p, mem_ctx)) {
1601 if (!test_LogonUasLogon(p, mem_ctx)) {
1605 if (!test_LogonUasLogoff(p, mem_ctx)) {
1609 if (!test_SetPassword(p, mem_ctx)) {
1613 if (!test_SamLogon(p, mem_ctx)) {
1617 if (!test_DatabaseSync(p, mem_ctx)) {
1621 if (!test_DatabaseDeltas(p, mem_ctx)) {
1625 if (!test_AccountDeltas(p, mem_ctx)) {
1629 if (!test_AccountSync(p, mem_ctx)) {
1633 if (!test_GetDcName(p, mem_ctx)) {
1637 if (!test_LogonControl(p, mem_ctx)) {
1641 if (!test_GetAnyDCName(p, mem_ctx)) {
1645 if (!test_LogonControl2(p, mem_ctx)) {
1649 if (!test_DatabaseSync2(p, mem_ctx)) {
1653 if (!test_LogonControl2Ex(p, mem_ctx)) {
1657 if (!test_DsrEnumerateDomainTrusts(p, mem_ctx)) {
1661 torture_rpc_close(p);
1663 torture_leave_domain(join_ctx);