2 Unix SMB/CIFS implementation.
4 test suite for netlogon SamLogon 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.
26 #include "librpc/gen_ndr/ndr_netlogon.h"
27 #include "auth/auth.h"
28 #include "lib/crypto/crypto.h"
29 #include "lib/cmdline/popt_common.h"
31 #define TEST_MACHINE_NAME "samlogontest"
32 #define TEST_USER_NAME "samlogontestuser"
43 struct samlogon_state {
46 const char *account_name;
47 const char *account_domain;
49 struct dcerpc_pipe *p;
51 uint32_t parameter_control;
52 struct netr_LogonSamLogon r;
53 struct netr_LogonSamLogonEx r_ex;
54 struct netr_LogonSamLogonWithFlags r_flags;
55 struct netr_Authenticator auth, auth2;
56 struct creds_CredentialState *creds;
57 NTSTATUS expected_error;
58 BOOL old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
63 Authenticate a user with a challenge/response, checking session key
64 and valid authentication types
66 static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
67 enum ntlm_break break_which,
68 uint32_t parameter_control,
70 DATA_BLOB *lm_response,
71 DATA_BLOB *nt_response,
73 uint8_t user_session_key[16],
77 struct netr_LogonSamLogon *r = &samlogon_state->r;
78 struct netr_LogonSamLogonEx *r_ex = &samlogon_state->r_ex;
79 struct netr_LogonSamLogonWithFlags *r_flags = &samlogon_state->r_flags;
80 struct netr_NetworkInfo ninfo;
81 struct netr_SamBaseInfo *base = NULL;
82 uint16_t validation_level = 0;
84 samlogon_state->r.in.logon.network = &ninfo;
85 samlogon_state->r_ex.in.logon.network = &ninfo;
86 samlogon_state->r_flags.in.logon.network = &ninfo;
88 ninfo.identity_info.domain_name.string = samlogon_state->account_domain;
89 ninfo.identity_info.parameter_control = parameter_control;
90 ninfo.identity_info.logon_id_low = 0;
91 ninfo.identity_info.logon_id_high = 0;
92 ninfo.identity_info.account_name.string = samlogon_state->account_name;
93 ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
95 memcpy(ninfo.challenge, chall->data, 8);
97 switch (break_which) {
101 if (lm_response && lm_response->data) {
102 lm_response->data[0]++;
106 if (nt_response && nt_response->data) {
107 nt_response->data[0]++;
111 if (lm_response && lm_response->data) {
112 lm_response->data[0]++;
114 if (nt_response && nt_response->data) {
115 nt_response->data[0]++;
119 data_blob_free(lm_response);
122 data_blob_free(nt_response);
127 ninfo.nt.data = nt_response->data;
128 ninfo.nt.length = nt_response->length;
130 ninfo.nt.data = NULL;
135 ninfo.lm.data = lm_response->data;
136 ninfo.lm.length = lm_response->length;
138 ninfo.lm.data = NULL;
142 switch (samlogon_state->function_level) {
143 case DCERPC_NETR_LOGONSAMLOGON:
144 ZERO_STRUCT(samlogon_state->auth2);
145 creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
147 r->out.return_authenticator = NULL;
148 status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
149 if (!r->out.return_authenticator ||
150 !creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) {
151 printf("Credential chaining failed\n");
153 if (!NT_STATUS_IS_OK(status)) {
155 *error_string = strdup(nt_errstr(status));
160 validation_level = r->in.validation_level;
162 creds_decrypt_samlogon(samlogon_state->creds, validation_level, &r->out.validation);
164 switch (validation_level) {
166 base = &r->out.validation.sam2->base;
169 base = &r->out.validation.sam3->base;
172 base = &r->out.validation.sam6->base;
176 case DCERPC_NETR_LOGONSAMLOGONEX:
177 status = dcerpc_netr_LogonSamLogonEx(samlogon_state->p, samlogon_state->mem_ctx, r_ex);
178 if (!NT_STATUS_IS_OK(status)) {
180 *error_string = strdup(nt_errstr(status));
185 validation_level = r_ex->in.validation_level;
187 creds_decrypt_samlogon(samlogon_state->creds, validation_level, &r_ex->out.validation);
189 switch (validation_level) {
191 base = &r_ex->out.validation.sam2->base;
194 base = &r_ex->out.validation.sam3->base;
197 base = &r_ex->out.validation.sam6->base;
201 case DCERPC_NETR_LOGONSAMLOGONWITHFLAGS:
202 ZERO_STRUCT(samlogon_state->auth2);
203 creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
205 r_flags->out.return_authenticator = NULL;
206 status = dcerpc_netr_LogonSamLogonWithFlags(samlogon_state->p, samlogon_state->mem_ctx, r_flags);
207 if (!r_flags->out.return_authenticator ||
208 !creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) {
209 printf("Credential chaining failed\n");
211 if (!NT_STATUS_IS_OK(status)) {
213 *error_string = strdup(nt_errstr(status));
218 validation_level = r_flags->in.validation_level;
220 creds_decrypt_samlogon(samlogon_state->creds, validation_level, &r_flags->out.validation);
222 switch (validation_level) {
224 base = &r_flags->out.validation.sam2->base;
227 base = &r_flags->out.validation.sam3->base;
230 base = &r_flags->out.validation.sam6->base;
237 printf("No user info returned from 'successful' SamLogon*() call!\n");
238 return NT_STATUS_INVALID_PARAMETER;
241 if (user_session_key) {
242 memcpy(user_session_key, base->key.key, 16);
245 memcpy(lm_key, base->LMSessKey.key, 8);
253 * Test the normal 'LM and NTLM' combination
256 static BOOL test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
261 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
262 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
263 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
266 uint8_t user_session_key[16];
271 ZERO_STRUCT(user_session_key);
273 lm_good = SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
275 ZERO_STRUCT(lm_hash);
277 E_deshash(samlogon_state->password, lm_hash);
280 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
282 E_md4hash(samlogon_state->password, nt_hash);
283 SMBsesskeygen_ntv1(nt_hash, session_key.data);
285 nt_status = check_samlogon(samlogon_state,
287 samlogon_state->parameter_control,
288 &samlogon_state->chall,
295 data_blob_free(&lm_response);
297 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
298 /* for 'long' passwords, the LM password is invalid */
299 if (break_which == NO_NT && !lm_good) {
302 /* for 'old' passwords, we allow the server to be OK or wrong password */
303 if (samlogon_state->old_password) {
306 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
307 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
308 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
309 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
310 SAFE_FREE(*error_string);
311 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
313 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
315 } else if (!NT_STATUS_IS_OK(nt_status)) {
319 if (break_which == NO_NT && !lm_good) {
320 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
324 if (memcmp(lm_hash, lm_key,
325 sizeof(lm_key)) != 0) {
326 printf("LM Key does not match expectations!\n");
328 dump_data(1, lm_key, 8);
329 printf("expected:\n");
330 dump_data(1, lm_hash, 8);
334 switch (break_which) {
337 uint8_t lm_key_expected[16];
338 memcpy(lm_key_expected, lm_hash, 8);
339 memset(lm_key_expected+8, '\0', 8);
340 if (memcmp(lm_key_expected, user_session_key,
342 *error_string = strdup("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
343 printf("user_session_key:\n");
344 dump_data(1, user_session_key, sizeof(user_session_key));
345 printf("expected:\n");
346 dump_data(1, lm_key_expected, sizeof(lm_key_expected));
352 if (memcmp(session_key.data, user_session_key,
353 sizeof(user_session_key)) != 0) {
354 *error_string = strdup("NT Session Key does not match expectations!\n");
355 printf("user_session_key:\n");
356 dump_data(1, user_session_key, 16);
357 printf("expected:\n");
358 dump_data(1, session_key.data, session_key.length);
366 * Test LM authentication, no NT response supplied
369 static BOOL test_lm(struct samlogon_state *samlogon_state, char **error_string)
372 return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
376 * Test the NTLM response only, no LM.
379 static BOOL test_ntlm(struct samlogon_state *samlogon_state, char **error_string)
381 return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
385 * Test the NTLM response only, but in the LM field.
388 static BOOL test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string)
393 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
394 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
398 uint8_t user_session_key[16];
402 ZERO_STRUCT(user_session_key);
404 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
406 E_md4hash(samlogon_state->password, nt_hash);
407 SMBsesskeygen_ntv1(nt_hash,
410 lm_good = E_deshash(samlogon_state->password, lm_hash);
412 ZERO_STRUCT(lm_hash);
414 nt_status = check_samlogon(samlogon_state,
416 samlogon_state->parameter_control,
417 &samlogon_state->chall,
424 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
425 /* for 'old' passwords, we allow the server to be OK or wrong password */
426 if (samlogon_state->old_password) {
430 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
431 SAFE_FREE(*error_string);
432 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
434 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
436 } else if (!NT_STATUS_IS_OK(nt_status)) {
441 if (memcmp(lm_hash, lm_key,
442 sizeof(lm_key)) != 0) {
443 printf("LM Key does not match expectations!\n");
445 dump_data(1, lm_key, 8);
446 printf("expected:\n");
447 dump_data(1, lm_hash, 8);
452 if (memcmp(session_key.data, lm_key,
453 sizeof(lm_key)) != 0) {
454 printf("LM Key does not match expectations (first 8 session key)!\n");
456 dump_data(1, lm_key, 8);
457 printf("expected:\n");
458 dump_data(1, session_key.data, 8);
463 if (lm_good && memcmp(lm_hash, user_session_key, 8) != 0) {
464 uint8_t lm_key_expected[16];
465 memcpy(lm_key_expected, lm_hash, 8);
466 memset(lm_key_expected+8, '\0', 8);
467 if (memcmp(lm_key_expected, user_session_key,
469 printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
470 printf("user_session_key:\n");
471 dump_data(1, user_session_key, sizeof(user_session_key));
472 printf("expected:\n");
473 dump_data(1, lm_key_expected, sizeof(lm_key_expected));
481 * Test the NTLM response only, but in the both the NT and LM fields.
484 static BOOL test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string)
489 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
490 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
494 uint8_t user_session_key[16];
498 ZERO_STRUCT(user_session_key);
500 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
502 E_md4hash(samlogon_state->password, nt_hash);
503 SMBsesskeygen_ntv1(nt_hash,
506 lm_good = E_deshash(samlogon_state->password, lm_hash);
508 ZERO_STRUCT(lm_hash);
511 nt_status = check_samlogon(samlogon_state,
513 samlogon_state->parameter_control,
514 &samlogon_state->chall,
521 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
522 /* for 'old' passwords, we allow the server to be OK or wrong password */
523 if (samlogon_state->old_password) {
527 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
528 SAFE_FREE(*error_string);
529 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
531 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
533 } else if (!NT_STATUS_IS_OK(nt_status)) {
537 if (!NT_STATUS_IS_OK(nt_status)) {
541 if (memcmp(lm_hash, lm_key,
542 sizeof(lm_key)) != 0) {
543 printf("LM Key does not match expectations!\n");
545 dump_data(1, lm_key, 8);
546 printf("expected:\n");
547 dump_data(1, lm_hash, 8);
550 if (memcmp(session_key.data, user_session_key,
551 sizeof(user_session_key)) != 0) {
552 printf("NT Session Key does not match expectations!\n");
553 printf("user_session_key:\n");
554 dump_data(1, user_session_key, 16);
555 printf("expected:\n");
556 dump_data(1, session_key.data, session_key.length);
565 * Test the NTLMv2 and LMv2 responses
573 static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state,
574 enum ntlm_break break_which,
575 enum ntlmv2_domain ntlmv2_domain,
580 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
581 DATA_BLOB lmv2_response = data_blob(NULL, 0);
582 DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
583 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
584 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, TEST_MACHINE_NAME, lp_workgroup());
586 uint8_t lm_session_key[8];
587 uint8_t user_session_key[16];
589 ZERO_STRUCT(lm_session_key);
590 ZERO_STRUCT(user_session_key);
592 switch (ntlmv2_domain) {
594 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
595 samlogon_state->account_name, samlogon_state->account_domain,
596 samlogon_state->password, &samlogon_state->chall,
598 &lmv2_response, &ntlmv2_response,
599 &lmv2_session_key, &ntlmv2_session_key)) {
600 data_blob_free(&names_blob);
605 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
606 samlogon_state->account_name, "",
607 samlogon_state->password, &samlogon_state->chall,
609 &lmv2_response, &ntlmv2_response,
610 &lmv2_session_key, &ntlmv2_session_key)) {
611 data_blob_free(&names_blob);
616 data_blob_free(&names_blob);
618 nt_status = check_samlogon(samlogon_state,
620 samlogon_state->parameter_control,
621 &samlogon_state->chall,
628 data_blob_free(&lmv2_response);
629 data_blob_free(&ntlmv2_response);
632 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
633 /* for 'old' passwords, we allow the server to be OK or wrong password */
634 if (samlogon_state->old_password) {
637 return break_which == BREAK_BOTH;
638 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
639 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
640 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
641 SAFE_FREE(*error_string);
642 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
644 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
646 } else if (!NT_STATUS_IS_OK(nt_status)) {
651 switch (break_which) {
653 if (memcmp(lmv2_session_key.data, user_session_key,
654 sizeof(user_session_key)) != 0) {
655 printf("USER (LMv2) Session Key does not match expectations!\n");
656 printf("user_session_key:\n");
657 dump_data(1, user_session_key, 16);
658 printf("expected:\n");
659 dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
662 if (memcmp(lmv2_session_key.data, lm_session_key,
663 sizeof(lm_session_key)) != 0) {
664 printf("LM (LMv2) Session Key does not match expectations!\n");
665 printf("lm_session_key:\n");
666 dump_data(1, lm_session_key, 8);
667 printf("expected:\n");
668 dump_data(1, lmv2_session_key.data, 8);
673 if (memcmp(ntlmv2_session_key.data, user_session_key,
674 sizeof(user_session_key)) != 0) {
675 if (memcmp(lmv2_session_key.data, user_session_key,
676 sizeof(user_session_key)) == 0) {
677 printf("USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
678 printf("user_session_key:\n");
679 dump_data(1, user_session_key, 16);
680 printf("expected:\n");
681 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
685 printf("USER (NTLMv2) Session Key does not match expectations!\n");
686 printf("user_session_key:\n");
687 dump_data(1, user_session_key, 16);
688 printf("expected:\n");
689 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
693 if (memcmp(ntlmv2_session_key.data, lm_session_key,
694 sizeof(lm_session_key)) != 0) {
695 if (memcmp(lmv2_session_key.data, lm_session_key,
696 sizeof(lm_session_key)) == 0) {
697 printf("LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
698 printf("user_session_key:\n");
699 dump_data(1, lm_session_key, 8);
700 printf("expected:\n");
701 dump_data(1, ntlmv2_session_key.data, 8);
704 printf("LM (NTLMv2) Session Key does not match expectations!\n");
705 printf("lm_session_key:\n");
706 dump_data(1, lm_session_key, 8);
707 printf("expected:\n");
708 dump_data(1, ntlmv2_session_key.data, 8);
718 * Test the NTLM and LMv2 responses
721 static BOOL test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state,
722 enum ntlm_break break_which,
723 enum ntlmv2_domain ntlmv2_domain,
728 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
729 DATA_BLOB lmv2_response = data_blob(NULL, 0);
730 DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
731 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
732 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, lp_netbios_name(), lp_workgroup());
734 DATA_BLOB ntlm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
735 DATA_BLOB ntlm_session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
739 uint8_t lm_session_key[8];
740 uint8_t user_session_key[16];
743 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
745 E_md4hash(samlogon_state->password, nt_hash);
746 SMBsesskeygen_ntv1(nt_hash,
747 ntlm_session_key.data);
749 lm_good = E_deshash(samlogon_state->password, lm_hash);
751 ZERO_STRUCT(lm_hash);
754 ZERO_STRUCT(lm_session_key);
755 ZERO_STRUCT(user_session_key);
757 switch (ntlmv2_domain) {
759 /* TODO - test with various domain cases, and without domain */
760 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
761 samlogon_state->account_name, samlogon_state->account_domain,
762 samlogon_state->password, &samlogon_state->chall,
764 &lmv2_response, &ntlmv2_response,
765 &lmv2_session_key, &ntlmv2_session_key)) {
766 data_blob_free(&names_blob);
771 /* TODO - test with various domain cases, and without domain */
772 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
773 samlogon_state->account_name, "",
774 samlogon_state->password, &samlogon_state->chall,
776 &lmv2_response, &ntlmv2_response,
777 &lmv2_session_key, &ntlmv2_session_key)) {
778 data_blob_free(&names_blob);
784 data_blob_free(&names_blob);
786 nt_status = check_samlogon(samlogon_state,
788 samlogon_state->parameter_control,
789 &samlogon_state->chall,
796 data_blob_free(&lmv2_response);
797 data_blob_free(&ntlmv2_response);
800 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
801 /* for 'old' passwords, we allow the server to be OK or wrong password */
802 if (samlogon_state->old_password) {
805 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
806 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
807 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
808 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
809 SAFE_FREE(*error_string);
810 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
812 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
814 } else if (!NT_STATUS_IS_OK(nt_status)) {
818 switch (break_which) {
820 if (memcmp(lmv2_session_key.data, user_session_key,
821 sizeof(user_session_key)) != 0) {
822 printf("USER (LMv2) Session Key does not match expectations!\n");
823 printf("user_session_key:\n");
824 dump_data(1, user_session_key, 16);
825 printf("expected:\n");
826 dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
829 if (memcmp(lmv2_session_key.data, lm_session_key,
830 sizeof(lm_session_key)) != 0) {
831 printf("LM (LMv2) Session Key does not match expectations!\n");
832 printf("lm_session_key:\n");
833 dump_data(1, lm_session_key, 8);
834 printf("expected:\n");
835 dump_data(1, lmv2_session_key.data, 8);
840 if (memcmp(ntlm_session_key.data, user_session_key,
841 sizeof(user_session_key)) != 0) {
842 printf("USER (NTLMv2) Session Key does not match expectations!\n");
843 printf("user_session_key:\n");
844 dump_data(1, user_session_key, 16);
845 printf("expected:\n");
846 dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
850 if (memcmp(lm_hash, lm_session_key,
851 sizeof(lm_session_key)) != 0) {
852 printf("LM Session Key does not match expectations!\n");
853 printf("lm_session_key:\n");
854 dump_data(1, lm_session_key, 8);
855 printf("expected:\n");
856 dump_data(1, lm_hash, 8);
860 static const char zeros[8];
861 if (memcmp(zeros, lm_session_key,
862 sizeof(lm_session_key)) != 0) {
863 printf("LM Session Key does not match expectations (zeros)!\n");
864 printf("lm_session_key:\n");
865 dump_data(1, lm_session_key, 8);
866 printf("expected:\n");
867 dump_data(1, zeros, 8);
873 if (memcmp(ntlm_session_key.data, user_session_key,
874 sizeof(user_session_key)) != 0) {
875 printf("USER (NTLMv2) Session Key does not match expectations!\n");
876 printf("user_session_key:\n");
877 dump_data(1, user_session_key, 16);
878 printf("expected:\n");
879 dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
882 if (memcmp(ntlm_session_key.data, lm_session_key,
883 sizeof(lm_session_key)) != 0) {
884 printf("LM (NTLMv2) Session Key does not match expectations!\n");
885 printf("lm_session_key:\n");
886 dump_data(1, lm_session_key, 8);
887 printf("expected:\n");
888 dump_data(1, ntlm_session_key.data, 8);
897 * Test the NTLMv2 and LMv2 responses
900 static BOOL test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
902 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, UPPER_DOMAIN, error_string);
906 static BOOL test_lmv2_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
908 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, NO_DOMAIN, error_string);
913 * Test the LMv2 response only
916 static BOOL test_lmv2(struct samlogon_state *samlogon_state, char **error_string)
918 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, UPPER_DOMAIN, error_string);
921 static BOOL test_lmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
923 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, NO_DOMAIN, error_string);
927 * Test the NTLMv2 response only
930 static BOOL test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
932 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, UPPER_DOMAIN, error_string);
935 static BOOL test_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
937 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, NO_DOMAIN, error_string);
940 static BOOL test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string)
942 return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
945 static BOOL test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string)
947 return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
950 static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string)
952 return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
955 static BOOL test_lm_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string)
957 return test_lm_ntlm_broken(samlogon_state, BREAK_BOTH, error_string);
959 static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
961 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
964 static BOOL test_ntlmv2_lmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
966 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
969 static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
971 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
975 static BOOL test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
977 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
981 static BOOL test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char **error_string)
983 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
986 static BOOL test_ntlmv2_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
988 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
991 static BOOL test_lmv2_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string)
993 return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
996 static BOOL test_lmv2_ntlm_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
998 return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
1001 static BOOL test_lmv2_ntlm_break_ntlm(struct samlogon_state *samlogon_state, char **error_string)
1003 return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
1006 static BOOL test_lmv2_ntlm_break_ntlm_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1008 return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
1011 static BOOL test_lmv2_ntlm_break_lm(struct samlogon_state *samlogon_state, char **error_string)
1013 return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
1016 static BOOL test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1018 return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
1022 * Test the NTLM2 response (extra challenge in LM feild)
1024 * This test is the same as the 'break LM' test, but checks that the
1025 * server implements NTLM2 session security in the right place
1026 * (NETLOGON is the wrong place).
1029 static BOOL test_ntlm2(struct samlogon_state *samlogon_state, char **error_string)
1033 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1034 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1038 uint8_t nt_hash[16];
1039 uint8_t lm_hash[16];
1041 uint8_t user_session_key[16];
1042 uint8_t expected_user_session_key[16];
1043 uint8_t session_nonce_hash[16];
1044 uint8_t client_chall[8];
1046 struct MD5Context md5_session_nonce_ctx;
1047 HMACMD5Context hmac_ctx;
1049 ZERO_STRUCT(user_session_key);
1050 ZERO_STRUCT(lm_key);
1051 generate_random_buffer(client_chall, 8);
1053 MD5Init(&md5_session_nonce_ctx);
1054 MD5Update(&md5_session_nonce_ctx, samlogon_state->chall.data, 8);
1055 MD5Update(&md5_session_nonce_ctx, client_chall, 8);
1056 MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
1058 E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
1059 lm_good = E_deshash(samlogon_state->password, (uint8_t *)lm_hash);
1060 SMBsesskeygen_ntv1((const uint8_t *)nt_hash,
1063 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
1065 memcpy(lm_response.data, session_nonce_hash, 8);
1066 memset(lm_response.data + 8, 0, 16);
1068 hmac_md5_init_rfc2104(nt_key, 16, &hmac_ctx);
1069 hmac_md5_update(samlogon_state->chall.data, 8, &hmac_ctx);
1070 hmac_md5_update(client_chall, 8, &hmac_ctx);
1071 hmac_md5_final(expected_user_session_key, &hmac_ctx);
1073 nt_status = check_samlogon(samlogon_state,
1075 samlogon_state->parameter_control,
1076 &samlogon_state->chall,
1083 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1084 /* for 'old' passwords, we allow the server to be OK or wrong password */
1085 if (samlogon_state->old_password) {
1089 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1090 SAFE_FREE(*error_string);
1091 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1093 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1095 } else if (!NT_STATUS_IS_OK(nt_status)) {
1100 if (memcmp(lm_hash, lm_key,
1101 sizeof(lm_key)) != 0) {
1102 printf("LM Key does not match expectations!\n");
1103 printf("lm_key:\n");
1104 dump_data(1, lm_key, 8);
1105 printf("expected:\n");
1106 dump_data(1, lm_hash, 8);
1110 static const char zeros[8];
1111 if (memcmp(zeros, lm_key,
1112 sizeof(lm_key)) != 0) {
1113 printf("LM Session Key does not match expectations (zeros)!\n");
1114 printf("lm_key:\n");
1115 dump_data(1, lm_key, 8);
1116 printf("expected:\n");
1117 dump_data(1, zeros, 8);
1121 if (memcmp(nt_key, user_session_key, 16) != 0) {
1122 printf("NT Session Key does not match expectations (should be NT Key)!\n");
1123 printf("user_session_key:\n");
1124 dump_data(1, user_session_key, sizeof(user_session_key));
1125 printf("expected:\n");
1126 dump_data(1, nt_key, sizeof(nt_key));
1132 static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
1135 DATA_BLOB nt_response = data_blob(NULL, 0);
1136 DATA_BLOB lm_response = data_blob(NULL, 0);
1141 uint8_t user_session_key[16];
1143 uint8_t lm_hash[16];
1144 static const uint8_t zeros[8];
1145 DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
1146 BOOL lm_good = E_deshash(samlogon_state->password, lm_hash);
1148 ZERO_STRUCT(user_session_key);
1150 if ((push_ucs2_talloc(samlogon_state->mem_ctx, &unicodepw,
1151 samlogon_state->password)) == -1) {
1152 DEBUG(0, ("push_ucs2_allocate failed!\n"));
1156 nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, strlen_m(samlogon_state->password)*2);
1158 password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password);
1160 if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX,
1163 (void**)&dospw)) == -1) {
1164 DEBUG(0, ("convert_string_talloc failed!\n"));
1168 lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
1170 nt_status = check_samlogon(samlogon_state,
1172 samlogon_state->parameter_control | MSV1_0_CLEARTEXT_PASSWORD_ALLOWED,
1180 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1181 /* for 'old' passwords, we allow the server to be OK or wrong password */
1182 if (samlogon_state->old_password) {
1185 /* for 'long' passwords, the LM password is invalid */
1186 if (break_which == NO_NT && !lm_good) {
1189 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
1190 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
1191 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
1192 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1193 SAFE_FREE(*error_string);
1194 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1196 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1198 } else if (!NT_STATUS_IS_OK(nt_status)) {
1202 if (break_which == NO_NT && !lm_good) {
1203 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
1210 static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state,
1211 char **error_string) {
1212 return test_plaintext(samlogon_state, BREAK_NONE, error_string);
1215 static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state,
1216 char **error_string) {
1217 return test_plaintext(samlogon_state, BREAK_LM, error_string);
1220 static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state,
1221 char **error_string) {
1222 return test_plaintext(samlogon_state, BREAK_NT, error_string);
1225 static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state,
1226 char **error_string) {
1227 return test_plaintext(samlogon_state, NO_LM, error_string);
1230 static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state,
1231 char **error_string) {
1232 return test_plaintext(samlogon_state, NO_NT, error_string);
1246 - plaintext tests (in challenge-response fields)
1248 check we get the correct session key in each case
1249 check what values we get for the LM session key
1253 static const struct ntlm_tests {
1254 BOOL (*fn)(struct samlogon_state *, char **);
1258 {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
1260 {test_lmv2_ntlmv2_no_dom, "NTLMv2 and LMv2 (no domain)", False},
1262 {test_lm, "LM", False},
1263 {test_lm_ntlm, "LM and NTLM", False},
1264 {test_lm_ntlm_both_broken, "LM and NTLM, both broken", False},
1265 {test_ntlm, "NTLM", False},
1266 {test_ntlm_in_lm, "NTLM in LM", False},
1267 {test_ntlm_in_both, "NTLM in both", False},
1268 {test_ntlmv2, "NTLMv2", False},
1269 {test_ntlmv2_no_dom, "NTLMv2 (no domain)", False},
1270 {test_lmv2, "LMv2", False},
1271 {test_lmv2_no_dom, "LMv2 (no domain)", False},
1272 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
1273 {test_ntlmv2_lmv2_broken_no_dom, "NTLMv2 and LMv2, LMv2 broken (no domain)", False},
1274 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
1276 {test_ntlmv2_ntlmv2_broken_no_dom, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", False},
1278 {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", False},
1279 {test_ntlmv2_both_broken_no_dom, "NTLMv2 and LMv2, both broken (no domain)", False},
1280 {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
1281 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
1282 {test_ntlm2, "NTLM2 (NTLMv2 session security)", False},
1283 {test_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", False},
1284 {test_lmv2_ntlm_both_broken_no_dom, "LMv2 and NTLM, both broken (no domain)", False},
1285 {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", False},
1286 {test_lmv2_ntlm_break_ntlm_no_dom, "LMv2 and NTLM, NTLM broken (no domain)", False},
1287 {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", False},
1288 {test_lmv2_ntlm_break_lm_no_dom, "LMv2 and NTLM, LMv2 broken (no domain)", False},
1289 {test_plaintext_none_broken, "Plaintext", False},
1290 {test_plaintext_lm_broken, "Plaintext LM broken", False},
1291 {test_plaintext_nt_broken, "Plaintext NT broken", False},
1292 {test_plaintext_nt_only, "Plaintext NT only", False},
1293 {test_plaintext_lm_only, "Plaintext LM only", False},
1298 try a netlogon SamLogon
1300 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1301 struct creds_CredentialState *creds,
1302 const char *comment,
1303 const char *account_domain, const char *account_name,
1304 const char *plain_pass, uint32_t parameter_control,
1305 NTSTATUS expected_error, BOOL old_password,
1308 TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_SamLogon function-level context");
1311 int validation_levels[] = {2,3,6};
1312 int logon_levels[] = { 2, 6 };
1313 int function_levels[] = {
1314 DCERPC_NETR_LOGONSAMLOGON,
1315 DCERPC_NETR_LOGONSAMLOGONEX,
1316 DCERPC_NETR_LOGONSAMLOGONWITHFLAGS };
1317 struct samlogon_state samlogon_state;
1319 printf("testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1321 samlogon_state.comment = comment;
1322 samlogon_state.account_name = account_name;
1323 samlogon_state.account_domain = account_domain;
1324 samlogon_state.password = plain_pass;
1325 samlogon_state.p = p;
1326 samlogon_state.creds = creds;
1327 samlogon_state.expected_error = expected_error;
1328 samlogon_state.chall = data_blob_talloc(fn_ctx, NULL, 8);
1329 samlogon_state.parameter_control = parameter_control;
1330 samlogon_state.old_password = old_password;
1332 generate_random_buffer(samlogon_state.chall.data, 8);
1333 samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1334 samlogon_state.r_flags.in.workstation = TEST_MACHINE_NAME;
1335 samlogon_state.r_flags.in.credential = &samlogon_state.auth;
1336 samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2;
1337 samlogon_state.r_flags.in.flags = 0;
1339 samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1340 samlogon_state.r_ex.in.workstation = TEST_MACHINE_NAME;
1341 samlogon_state.r_ex.in.flags = 0;
1343 samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1344 samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
1345 samlogon_state.r.in.credential = &samlogon_state.auth;
1346 samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
1348 for (f=0;f<ARRAY_SIZE(function_levels);f++) {
1349 for (i=0; test_table[i].fn; i++) {
1350 if (n_subtests && (i > n_subtests)) {
1353 for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
1354 for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
1355 char *error_string = NULL;
1356 TALLOC_CTX *tmp_ctx = talloc_named(fn_ctx, 0, "test_SamLogon inner loop");
1357 samlogon_state.mem_ctx = tmp_ctx;
1358 samlogon_state.function_level = function_levels[f];
1359 samlogon_state.r.in.validation_level = validation_levels[v];
1360 samlogon_state.r.in.logon_level = logon_levels[l];
1361 samlogon_state.r_ex.in.validation_level = validation_levels[v];
1362 samlogon_state.r_ex.in.logon_level = logon_levels[l];
1363 samlogon_state.r_flags.in.validation_level = validation_levels[v];
1364 samlogon_state.r_flags.in.logon_level = logon_levels[l];
1365 if (!test_table[i].fn(&samlogon_state, &error_string)) {
1366 printf("Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
1367 samlogon_state.comment,
1368 samlogon_state.account_domain,
1369 samlogon_state.account_name,
1370 test_table[i].name, validation_levels[v],
1371 logon_levels[l], function_levels[f]);
1373 if (test_table[i].expect_fail) {
1374 printf(" failed (expected, test incomplete): %s\n", error_string);
1376 printf(" failed: %s\n", error_string);
1379 SAFE_FREE(error_string);
1381 talloc_free(tmp_ctx);
1386 talloc_free(fn_ctx);
1391 test an ADS style interactive domain logon
1393 BOOL test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1394 struct creds_CredentialState *creds,
1395 const char *comment,
1396 const char *workstation_name,
1397 const char *account_domain, const char *account_name,
1398 const char *plain_pass, uint32_t parameter_control,
1399 NTSTATUS expected_error)
1402 TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context");
1403 struct netr_LogonSamLogonWithFlags r;
1404 struct netr_Authenticator a, ra;
1405 struct netr_PasswordInfo pinfo;
1411 creds_client_authenticator(creds, &a);
1413 r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1414 r.in.workstation = TEST_MACHINE_NAME;
1415 r.in.credential = &a;
1416 r.in.return_authenticator = &ra;
1417 r.in.logon_level = 5;
1418 r.in.logon.password = &pinfo;
1419 r.in.validation_level = 6;
1422 pinfo.identity_info.domain_name.string = account_domain;
1423 pinfo.identity_info.parameter_control = parameter_control;
1424 pinfo.identity_info.logon_id_low = 0;
1425 pinfo.identity_info.logon_id_high = 0;
1426 pinfo.identity_info.account_name.string = account_name;
1427 pinfo.identity_info.workstation.string = workstation_name;
1429 if (!E_deshash(plain_pass, pinfo.lmpassword.hash)) {
1430 ZERO_STRUCT(pinfo.lmpassword.hash);
1432 E_md4hash(plain_pass, pinfo.ntpassword.hash);
1434 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1435 creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
1436 creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
1438 creds_des_encrypt(creds, &pinfo.lmpassword);
1439 creds_des_encrypt(creds, &pinfo.ntpassword);
1442 printf("Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment);
1444 status = dcerpc_netr_LogonSamLogonWithFlags(p, fn_ctx, &r);
1445 if (!r.out.return_authenticator
1446 || !creds_client_check(creds, &r.out.return_authenticator->cred)) {
1447 printf("Credential chaining failed\n");
1448 talloc_free(fn_ctx);
1452 talloc_free(fn_ctx);
1454 if (!NT_STATUS_EQUAL(expected_error, status)) {
1455 printf("[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n",
1456 account_domain, account_name, nt_errstr(expected_error), nt_errstr(status));
1465 BOOL torture_rpc_samlogon(void)
1468 struct dcerpc_pipe *p;
1469 struct dcerpc_binding *b;
1470 struct cli_credentials *machine_credentials;
1471 TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon");
1473 struct test_join *join_ctx;
1474 struct test_join *user_ctx;
1475 const char *user_password;
1476 const char *old_user_password;
1477 char *test_machine_account;
1478 const char *binding = lp_parm_string(-1, "torture", "binding");
1479 const char *userdomain;
1483 unsigned int credential_flags[] = {
1484 NETLOGON_NEG_AUTH2_FLAGS,
1485 NETLOGON_NEG_ARCFOUR,
1486 NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
1487 NETLOGON_NEG_AUTH2_ADS_FLAGS,
1488 0 /* yes, this is a valid flag, causes the use of DES */
1491 struct creds_CredentialState *creds;
1493 test_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
1494 /* We only need to join as a workstation here, and in future,
1495 * if we wish to test against trusted domains, we must be a
1496 * workstation here */
1497 join_ctx = torture_join_domain(TEST_MACHINE_NAME, ACB_WSTRUST,
1498 &machine_credentials);
1500 printf("Failed to join as Workstation\n");
1504 userdomain = lp_parm_string(-1, "torture", "userdomain");
1506 userdomain = lp_workgroup();
1509 user_ctx = torture_create_testuser(TEST_USER_NAME,
1514 printf("Failed to join as Workstation\n");
1518 old_user_password = user_password;
1520 test_ChangePasswordUser3(torture_join_samr_pipe(user_ctx), mem_ctx,
1521 TEST_USER_NAME, 16 /* > 14 */, &user_password);
1523 status = dcerpc_parse_binding(mem_ctx, binding, &b);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 printf("Bad binding string %s\n", binding);
1530 /* We have to use schannel, otherwise the SamLogonEx fails
1531 * with INTERNAL_ERROR */
1533 b->flags &= ~DCERPC_AUTH_OPTIONS;
1534 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
1536 status = dcerpc_pipe_connect_b(mem_ctx, &p, b,
1537 DCERPC_NETLOGON_UUID,
1538 DCERPC_NETLOGON_VERSION,
1539 machine_credentials, NULL);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
1547 status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds);
1548 if (!NT_STATUS_IS_OK(status)) {
1556 const char *comment;
1558 const char *username;
1559 const char *password;
1561 NTSTATUS expected_interactive_error;
1562 NTSTATUS expected_network_error;
1563 uint32_t parameter_control;
1564 BOOL old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
1567 .comment = "domain\\user",
1568 .domain = cli_credentials_get_domain(cmdline_credentials),
1569 .username = cli_credentials_get_username(cmdline_credentials),
1570 .password = cli_credentials_get_password(cmdline_credentials),
1571 .network_login = True,
1572 .expected_interactive_error = NT_STATUS_OK,
1573 .expected_network_error = NT_STATUS_OK
1576 .comment = "realm\\user",
1577 .domain = cli_credentials_get_realm(cmdline_credentials),
1578 .username = cli_credentials_get_username(cmdline_credentials),
1579 .password = cli_credentials_get_password(cmdline_credentials),
1580 .network_login = True,
1581 .expected_interactive_error = NT_STATUS_OK,
1582 .expected_network_error = NT_STATUS_OK
1585 .comment = "user@domain",
1587 .username = talloc_asprintf(mem_ctx,
1589 cli_credentials_get_username(cmdline_credentials),
1590 cli_credentials_get_domain(cmdline_credentials)
1592 .password = cli_credentials_get_password(cmdline_credentials),
1593 .network_login = False, /* works for some things, but not NTLMv2. Odd */
1594 .expected_interactive_error = NT_STATUS_OK,
1595 .expected_network_error = NT_STATUS_OK
1598 .comment = "user@realm",
1600 .username = talloc_asprintf(mem_ctx,
1602 cli_credentials_get_username(cmdline_credentials),
1603 cli_credentials_get_realm(cmdline_credentials)
1605 .password = cli_credentials_get_password(cmdline_credentials),
1606 .network_login = True,
1607 .expected_interactive_error = NT_STATUS_OK,
1608 .expected_network_error = NT_STATUS_OK
1611 .comment = "machine domain\\user",
1612 .domain = cli_credentials_get_domain(machine_credentials),
1613 .username = cli_credentials_get_username(machine_credentials),
1614 .password = cli_credentials_get_password(machine_credentials),
1615 .network_login = True,
1616 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1617 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1620 .comment = "machine domain\\user",
1621 .domain = cli_credentials_get_domain(machine_credentials),
1622 .username = cli_credentials_get_username(machine_credentials),
1623 .password = cli_credentials_get_password(machine_credentials),
1624 .network_login = True,
1625 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1626 .expected_network_error = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
1629 .comment = "machine realm\\user",
1630 .domain = cli_credentials_get_realm(machine_credentials),
1631 .username = cli_credentials_get_username(machine_credentials),
1632 .password = cli_credentials_get_password(machine_credentials),
1633 .network_login = True,
1634 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1635 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1638 .comment = "machine user@domain",
1640 .username = talloc_asprintf(mem_ctx,
1642 cli_credentials_get_username(machine_credentials),
1643 cli_credentials_get_domain(machine_credentials)
1645 .password = cli_credentials_get_password(machine_credentials),
1646 .network_login = False, /* works for some things, but not NTLMv2. Odd */
1647 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1648 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1651 .comment = "machine user@realm",
1653 .username = talloc_asprintf(mem_ctx,
1655 cli_credentials_get_username(machine_credentials),
1656 cli_credentials_get_realm(machine_credentials)
1658 .password = cli_credentials_get_password(machine_credentials),
1659 .network_login = True,
1660 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1661 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1664 .comment = "test user (long pw): domain\\user",
1665 .domain = userdomain,
1666 .username = TEST_USER_NAME,
1667 .password = user_password,
1668 .network_login = True,
1669 .expected_interactive_error = NT_STATUS_OK,
1670 .expected_network_error = NT_STATUS_OK
1673 .comment = "test user (long pw): user@realm",
1675 .username = talloc_asprintf(mem_ctx,
1679 .password = user_password,
1680 .network_login = True,
1681 .expected_interactive_error = NT_STATUS_OK,
1682 .expected_network_error = NT_STATUS_OK
1685 .comment = "test user (long pw): user@domain",
1687 .username = talloc_asprintf(mem_ctx,
1691 .password = user_password,
1692 .network_login = False, /* works for some things, but not NTLMv2. Odd */
1693 .expected_interactive_error = NT_STATUS_OK,
1694 .expected_network_error = NT_STATUS_OK
1696 /* Oddball, can we use the old password ? */
1698 .comment = "test user: user\\domain OLD PASSWORD",
1699 .domain = userdomain,
1700 .username = TEST_USER_NAME,
1701 .password = old_user_password,
1702 .network_login = True,
1703 .expected_interactive_error = NT_STATUS_WRONG_PASSWORD,
1704 .expected_network_error = NT_STATUS_OK,
1705 .old_password = True
1709 /* Try all the tests for different username forms */
1710 for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) {
1712 if (!test_InteractiveLogon(p, mem_ctx, creds,
1713 usercreds[ci].comment,
1715 usercreds[ci].domain,
1716 usercreds[ci].username,
1717 usercreds[ci].password,
1718 usercreds[ci].parameter_control,
1719 usercreds[ci].expected_interactive_error)) {
1723 if (usercreds[ci].network_login) {
1724 if (!test_SamLogon(p, mem_ctx, creds,
1725 usercreds[ci].comment,
1726 usercreds[ci].domain,
1727 usercreds[ci].username,
1728 usercreds[ci].password,
1729 usercreds[ci].parameter_control,
1730 usercreds[ci].expected_network_error,
1731 usercreds[ci].old_password,
1738 /* Using the first username form, try the different
1739 * credentials flag setups, on only one of the tests (checks
1740 * session key encryption) */
1742 for (i=0; i < ARRAY_SIZE(credential_flags); i++) {
1743 if (!test_InteractiveLogon(p, mem_ctx, creds,
1744 usercreds[0].comment,
1746 usercreds[0].domain,
1747 usercreds[0].username,
1748 usercreds[0].password,
1749 usercreds[0].parameter_control,
1750 usercreds[0].expected_interactive_error)) {
1754 if (usercreds[ci].network_login) {
1755 if (!test_SamLogon(p, mem_ctx, creds,
1756 usercreds[0].comment,
1757 usercreds[0].domain,
1758 usercreds[0].username,
1759 usercreds[0].password,
1760 usercreds[0].parameter_control,
1761 usercreds[0].expected_network_error,
1762 usercreds[0].old_password,
1771 talloc_free(mem_ctx);
1773 torture_leave_domain(join_ctx);
1774 torture_leave_domain(user_ctx);