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 3 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, see <http://www.gnu.org/licenses/>.
25 #include "librpc/gen_ndr/ndr_netlogon.h"
26 #include "librpc/gen_ndr/ndr_netlogon_c.h"
27 #include "librpc/gen_ndr/ndr_samr_c.h"
28 #include "../lib/crypto/crypto.h"
29 #include "lib/cmdline/popt_common.h"
30 #include "torture/rpc/torture_rpc.h"
31 #include "auth/gensec/gensec.h"
32 #include "auth/gensec/schannel.h"
33 #include "libcli/auth/libcli_auth.h"
34 #include "param/param.h"
36 #define TEST_MACHINE_NAME "samlogontest"
37 #define TEST_USER_NAME "samlogontestuser"
38 #define TEST_USER_NAME_WRONG_WKS "samlogontest2"
39 #define TEST_USER_NAME_WRONG_TIME "samlogontest3"
50 struct samlogon_state
{
52 struct torture_context
*tctx
;
54 const char *account_name
;
55 const char *account_domain
;
56 const char *netbios_name
;
58 const char *workgroup
;
59 struct dcerpc_pipe
*p
;
61 uint32_t parameter_control
;
62 struct netr_LogonSamLogon r
;
63 struct netr_LogonSamLogonEx r_ex
;
64 struct netr_LogonSamLogonWithFlags r_flags
;
65 struct netr_Authenticator auth
, auth2
;
66 struct netlogon_creds_CredentialState
*creds
;
67 NTSTATUS expected_error
;
68 bool old_password
; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
73 Authenticate a user with a challenge/response, checking session key
74 and valid authentication types
76 static NTSTATUS
check_samlogon(struct samlogon_state
*samlogon_state
,
77 enum ntlm_break break_which
,
78 uint32_t parameter_control
,
80 DATA_BLOB
*lm_response
,
81 DATA_BLOB
*nt_response
,
83 uint8_t user_session_key
[16],
87 struct netr_LogonSamLogon
*r
= &samlogon_state
->r
;
88 struct netr_LogonSamLogonEx
*r_ex
= &samlogon_state
->r_ex
;
89 struct netr_LogonSamLogonWithFlags
*r_flags
= &samlogon_state
->r_flags
;
90 struct netr_NetworkInfo ninfo
;
91 struct netr_SamBaseInfo
*base
= NULL
;
92 uint16_t validation_level
= 0;
94 samlogon_state
->r
.in
.logon
->network
= &ninfo
;
95 samlogon_state
->r_ex
.in
.logon
->network
= &ninfo
;
96 samlogon_state
->r_flags
.in
.logon
->network
= &ninfo
;
98 ninfo
.identity_info
.domain_name
.string
= samlogon_state
->account_domain
;
99 ninfo
.identity_info
.parameter_control
= parameter_control
;
100 ninfo
.identity_info
.logon_id_low
= 0;
101 ninfo
.identity_info
.logon_id_high
= 0;
102 ninfo
.identity_info
.account_name
.string
= samlogon_state
->account_name
;
103 ninfo
.identity_info
.workstation
.string
= TEST_MACHINE_NAME
;
105 memcpy(ninfo
.challenge
, chall
->data
, 8);
107 switch (break_which
) {
111 if (lm_response
&& lm_response
->data
) {
112 lm_response
->data
[0]++;
116 if (nt_response
&& nt_response
->data
) {
117 nt_response
->data
[0]++;
121 if (lm_response
&& lm_response
->data
) {
122 lm_response
->data
[0]++;
124 if (nt_response
&& nt_response
->data
) {
125 nt_response
->data
[0]++;
129 data_blob_free(lm_response
);
132 data_blob_free(nt_response
);
137 ninfo
.nt
.data
= nt_response
->data
;
138 ninfo
.nt
.length
= nt_response
->length
;
140 ninfo
.nt
.data
= NULL
;
145 ninfo
.lm
.data
= lm_response
->data
;
146 ninfo
.lm
.length
= lm_response
->length
;
148 ninfo
.lm
.data
= NULL
;
152 switch (samlogon_state
->function_level
) {
153 case NDR_NETR_LOGONSAMLOGON
:
154 ZERO_STRUCT(samlogon_state
->auth2
);
155 netlogon_creds_client_authenticator(samlogon_state
->creds
, &samlogon_state
->auth
);
157 r
->out
.return_authenticator
= NULL
;
158 status
= dcerpc_netr_LogonSamLogon_r(samlogon_state
->p
->binding_handle
,
159 samlogon_state
->mem_ctx
, r
);
160 if (!NT_STATUS_IS_OK(status
)) {
162 *error_string
= strdup(nt_errstr(status
));
166 if (!r
->out
.return_authenticator
||
167 !netlogon_creds_client_check(samlogon_state
->creds
, &r
->out
.return_authenticator
->cred
)) {
168 torture_comment(samlogon_state
->tctx
, "Credential chaining failed\n");
170 if (!NT_STATUS_IS_OK(r
->out
.result
)) {
172 *error_string
= strdup(nt_errstr(r
->out
.result
));
174 return r
->out
.result
;
177 validation_level
= r
->in
.validation_level
;
179 netlogon_creds_decrypt_samlogon_validation(samlogon_state
->creds
,
183 switch (validation_level
) {
185 base
= &r
->out
.validation
->sam2
->base
;
188 base
= &r
->out
.validation
->sam3
->base
;
191 base
= &r
->out
.validation
->sam6
->base
;
195 case NDR_NETR_LOGONSAMLOGONEX
:
196 status
= dcerpc_netr_LogonSamLogonEx_r(samlogon_state
->p
->binding_handle
,
197 samlogon_state
->mem_ctx
, r_ex
);
198 if (!NT_STATUS_IS_OK(status
)) {
200 *error_string
= strdup(nt_errstr(status
));
204 if (!NT_STATUS_IS_OK(r_ex
->out
.result
)) {
206 *error_string
= strdup(nt_errstr(r_ex
->out
.result
));
208 return r_ex
->out
.result
;
211 validation_level
= r_ex
->in
.validation_level
;
213 netlogon_creds_decrypt_samlogon_validation(samlogon_state
->creds
,
215 r_ex
->out
.validation
);
217 switch (validation_level
) {
219 base
= &r_ex
->out
.validation
->sam2
->base
;
222 base
= &r_ex
->out
.validation
->sam3
->base
;
225 base
= &r_ex
->out
.validation
->sam6
->base
;
229 case NDR_NETR_LOGONSAMLOGONWITHFLAGS
:
230 ZERO_STRUCT(samlogon_state
->auth2
);
231 netlogon_creds_client_authenticator(samlogon_state
->creds
, &samlogon_state
->auth
);
233 r_flags
->out
.return_authenticator
= NULL
;
234 status
= dcerpc_netr_LogonSamLogonWithFlags_r(samlogon_state
->p
->binding_handle
,
235 samlogon_state
->mem_ctx
, r_flags
);
236 if (!NT_STATUS_IS_OK(status
)) {
238 *error_string
= strdup(nt_errstr(status
));
242 if (!r_flags
->out
.return_authenticator
||
243 !netlogon_creds_client_check(samlogon_state
->creds
, &r_flags
->out
.return_authenticator
->cred
)) {
244 torture_comment(samlogon_state
->tctx
, "Credential chaining failed\n");
246 if (!NT_STATUS_IS_OK(r_flags
->out
.result
)) {
248 *error_string
= strdup(nt_errstr(r_flags
->out
.result
));
250 return r_flags
->out
.result
;
253 validation_level
= r_flags
->in
.validation_level
;
255 netlogon_creds_decrypt_samlogon_validation(samlogon_state
->creds
,
257 r_flags
->out
.validation
);
259 switch (validation_level
) {
261 base
= &r_flags
->out
.validation
->sam2
->base
;
264 base
= &r_flags
->out
.validation
->sam3
->base
;
267 base
= &r_flags
->out
.validation
->sam6
->base
;
273 return NT_STATUS_INVALID_PARAMETER
;
277 torture_comment(samlogon_state
->tctx
, "No user info returned from 'successful' SamLogon*() call!\n");
278 return NT_STATUS_INVALID_PARAMETER
;
281 if (user_session_key
) {
282 memcpy(user_session_key
, base
->key
.key
, 16);
285 memcpy(lm_key
, base
->LMSessKey
.key
, 8);
293 * Test the normal 'LM and NTLM' combination
296 static bool test_lm_ntlm_broken(struct samlogon_state
*samlogon_state
, enum ntlm_break break_which
, char **error_string
)
301 DATA_BLOB lm_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
302 DATA_BLOB nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
303 DATA_BLOB session_key
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 16);
306 uint8_t user_session_key
[16];
311 ZERO_STRUCT(user_session_key
);
313 lm_good
= SMBencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
, lm_response
.data
);
315 ZERO_STRUCT(lm_hash
);
317 E_deshash(samlogon_state
->password
, lm_hash
);
320 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
, nt_response
.data
);
322 E_md4hash(samlogon_state
->password
, nt_hash
);
323 SMBsesskeygen_ntv1(nt_hash
, session_key
.data
);
325 nt_status
= check_samlogon(samlogon_state
,
327 samlogon_state
->parameter_control
,
328 &samlogon_state
->chall
,
335 data_blob_free(&lm_response
);
337 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
338 /* for 'long' passwords, the LM password is invalid */
339 if (break_which
== NO_NT
&& !lm_good
) {
342 /* for 'old' passwords, we allow the server to be OK or wrong password */
343 if (samlogon_state
->old_password
) {
346 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
));
347 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND
, nt_status
) && strchr_m(samlogon_state
->account_name
, '@')) {
348 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
) || (break_which
== NO_NT
));
349 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
350 SAFE_FREE(*error_string
);
351 asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
353 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
355 } else if (!NT_STATUS_IS_OK(nt_status
)) {
359 if (break_which
== NO_NT
&& !lm_good
) {
360 *error_string
= strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
364 if (memcmp(lm_hash
, lm_key
,
365 sizeof(lm_key
)) != 0) {
366 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations!\n");
367 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
368 dump_data(1, lm_key
, 8);
369 torture_comment(samlogon_state
->tctx
, "expected:\n");
370 dump_data(1, lm_hash
, 8);
374 switch (break_which
) {
377 uint8_t lm_key_expected
[16];
378 memcpy(lm_key_expected
, lm_hash
, 8);
379 memset(lm_key_expected
+8, '\0', 8);
380 if (memcmp(lm_key_expected
, user_session_key
,
382 *error_string
= strdup("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
383 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
384 dump_data(1, user_session_key
, sizeof(user_session_key
));
385 torture_comment(samlogon_state
->tctx
, "expected:\n");
386 dump_data(1, lm_key_expected
, sizeof(lm_key_expected
));
392 if (memcmp(session_key
.data
, user_session_key
,
393 sizeof(user_session_key
)) != 0) {
394 *error_string
= strdup("NT Session Key does not match expectations!\n");
395 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
396 dump_data(1, user_session_key
, 16);
397 torture_comment(samlogon_state
->tctx
, "expected:\n");
398 dump_data(1, session_key
.data
, session_key
.length
);
406 * Test LM authentication, no NT response supplied
409 static bool test_lm(struct samlogon_state
*samlogon_state
, char **error_string
)
412 return test_lm_ntlm_broken(samlogon_state
, NO_NT
, error_string
);
416 * Test the NTLM response only, no LM.
419 static bool test_ntlm(struct samlogon_state
*samlogon_state
, char **error_string
)
421 return test_lm_ntlm_broken(samlogon_state
, NO_LM
, error_string
);
425 * Test the NTLM response only, but in the LM field.
428 static bool test_ntlm_in_lm(struct samlogon_state
*samlogon_state
, char **error_string
)
433 DATA_BLOB nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
434 DATA_BLOB session_key
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 16);
438 uint8_t user_session_key
[16];
442 ZERO_STRUCT(user_session_key
);
444 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
,
446 E_md4hash(samlogon_state
->password
, nt_hash
);
447 SMBsesskeygen_ntv1(nt_hash
,
450 lm_good
= E_deshash(samlogon_state
->password
, lm_hash
);
452 ZERO_STRUCT(lm_hash
);
454 nt_status
= check_samlogon(samlogon_state
,
456 samlogon_state
->parameter_control
,
457 &samlogon_state
->chall
,
464 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
465 /* for 'old' passwords, we allow the server to be OK or wrong password */
466 if (samlogon_state
->old_password
) {
470 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
471 SAFE_FREE(*error_string
);
472 asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
474 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
476 } else if (!NT_STATUS_IS_OK(nt_status
)) {
481 if (memcmp(lm_hash
, lm_key
,
482 sizeof(lm_key
)) != 0) {
483 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations!\n");
484 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
485 dump_data(1, lm_key
, 8);
486 torture_comment(samlogon_state
->tctx
, "expected:\n");
487 dump_data(1, lm_hash
, 8);
492 if (memcmp(session_key
.data
, lm_key
,
493 sizeof(lm_key
)) != 0) {
494 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations (first 8 session key)!\n");
495 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
496 dump_data(1, lm_key
, 8);
497 torture_comment(samlogon_state
->tctx
, "expected:\n");
498 dump_data(1, session_key
.data
, 8);
503 if (lm_good
&& memcmp(lm_hash
, user_session_key
, 8) != 0) {
504 uint8_t lm_key_expected
[16];
505 memcpy(lm_key_expected
, lm_hash
, 8);
506 memset(lm_key_expected
+8, '\0', 8);
507 if (memcmp(lm_key_expected
, user_session_key
,
509 torture_comment(samlogon_state
->tctx
, "NT Session Key does not match expectations (should be first-8 LM hash)!\n");
510 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
511 dump_data(1, user_session_key
, sizeof(user_session_key
));
512 torture_comment(samlogon_state
->tctx
, "expected:\n");
513 dump_data(1, lm_key_expected
, sizeof(lm_key_expected
));
521 * Test the NTLM response only, but in the both the NT and LM fields.
524 static bool test_ntlm_in_both(struct samlogon_state
*samlogon_state
, char **error_string
)
529 DATA_BLOB nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
530 DATA_BLOB session_key
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 16);
534 uint8_t user_session_key
[16];
538 ZERO_STRUCT(user_session_key
);
540 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
,
542 E_md4hash(samlogon_state
->password
, nt_hash
);
543 SMBsesskeygen_ntv1(nt_hash
,
546 lm_good
= E_deshash(samlogon_state
->password
, lm_hash
);
548 ZERO_STRUCT(lm_hash
);
551 nt_status
= check_samlogon(samlogon_state
,
553 samlogon_state
->parameter_control
,
554 &samlogon_state
->chall
,
561 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
562 /* for 'old' passwords, we allow the server to be OK or wrong password */
563 if (samlogon_state
->old_password
) {
567 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
568 SAFE_FREE(*error_string
);
569 asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
571 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
573 } else if (!NT_STATUS_IS_OK(nt_status
)) {
577 if (!NT_STATUS_IS_OK(nt_status
)) {
581 if (memcmp(lm_hash
, lm_key
,
582 sizeof(lm_key
)) != 0) {
583 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations!\n");
584 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
585 dump_data(1, lm_key
, 8);
586 torture_comment(samlogon_state
->tctx
, "expected:\n");
587 dump_data(1, lm_hash
, 8);
590 if (memcmp(session_key
.data
, user_session_key
,
591 sizeof(user_session_key
)) != 0) {
592 torture_comment(samlogon_state
->tctx
, "NT Session Key does not match expectations!\n");
593 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
594 dump_data(1, user_session_key
, 16);
595 torture_comment(samlogon_state
->tctx
, "expected:\n");
596 dump_data(1, session_key
.data
, session_key
.length
);
605 * Test the NTLMv2 and LMv2 responses
613 static bool test_lmv2_ntlmv2_broken(struct samlogon_state
*samlogon_state
,
614 enum ntlm_break break_which
,
615 enum ntlmv2_domain ntlmv2_domain
,
620 DATA_BLOB ntlmv2_response
= data_blob(NULL
, 0);
621 DATA_BLOB lmv2_response
= data_blob(NULL
, 0);
622 DATA_BLOB lmv2_session_key
= data_blob(NULL
, 0);
623 DATA_BLOB ntlmv2_session_key
= data_blob(NULL
, 0);
624 DATA_BLOB names_blob
= NTLMv2_generate_names_blob(samlogon_state
->mem_ctx
, TEST_MACHINE_NAME
, samlogon_state
->workgroup
);
626 uint8_t lm_session_key
[8];
627 uint8_t user_session_key
[16];
629 ZERO_STRUCT(lm_session_key
);
630 ZERO_STRUCT(user_session_key
);
632 switch (ntlmv2_domain
) {
634 if (!SMBNTLMv2encrypt(samlogon_state
->mem_ctx
,
635 samlogon_state
->account_name
, samlogon_state
->account_domain
,
636 samlogon_state
->password
, &samlogon_state
->chall
,
638 &lmv2_response
, &ntlmv2_response
,
639 &lmv2_session_key
, &ntlmv2_session_key
)) {
640 data_blob_free(&names_blob
);
645 if (!SMBNTLMv2encrypt(samlogon_state
->mem_ctx
,
646 samlogon_state
->account_name
, "",
647 samlogon_state
->password
, &samlogon_state
->chall
,
649 &lmv2_response
, &ntlmv2_response
,
650 &lmv2_session_key
, &ntlmv2_session_key
)) {
651 data_blob_free(&names_blob
);
656 data_blob_free(&names_blob
);
658 nt_status
= check_samlogon(samlogon_state
,
660 samlogon_state
->parameter_control
,
661 &samlogon_state
->chall
,
668 data_blob_free(&lmv2_response
);
669 data_blob_free(&ntlmv2_response
);
672 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
673 /* for 'old' passwords, we allow the server to be OK or wrong password */
674 if (samlogon_state
->old_password
) {
677 return break_which
== BREAK_BOTH
;
678 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND
, nt_status
) && strchr_m(samlogon_state
->account_name
, '@')) {
679 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
) || (break_which
== NO_NT
));
680 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
681 SAFE_FREE(*error_string
);
682 asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
684 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
686 } else if (!NT_STATUS_IS_OK(nt_status
)) {
691 switch (break_which
) {
693 if (memcmp(lmv2_session_key
.data
, user_session_key
,
694 sizeof(user_session_key
)) != 0) {
695 torture_comment(samlogon_state
->tctx
, "USER (LMv2) Session Key does not match expectations!\n");
696 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
697 dump_data(1, user_session_key
, 16);
698 torture_comment(samlogon_state
->tctx
, "expected:\n");
699 dump_data(1, lmv2_session_key
.data
, ntlmv2_session_key
.length
);
702 if (memcmp(lmv2_session_key
.data
, lm_session_key
,
703 sizeof(lm_session_key
)) != 0) {
704 torture_comment(samlogon_state
->tctx
, "LM (LMv2) Session Key does not match expectations!\n");
705 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
706 dump_data(1, lm_session_key
, 8);
707 torture_comment(samlogon_state
->tctx
, "expected:\n");
708 dump_data(1, lmv2_session_key
.data
, 8);
713 if (memcmp(ntlmv2_session_key
.data
, user_session_key
,
714 sizeof(user_session_key
)) != 0) {
715 if (memcmp(lmv2_session_key
.data
, user_session_key
,
716 sizeof(user_session_key
)) == 0) {
717 torture_comment(samlogon_state
->tctx
, "USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
718 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
719 dump_data(1, user_session_key
, 16);
720 torture_comment(samlogon_state
->tctx
, "expected:\n");
721 dump_data(1, ntlmv2_session_key
.data
, ntlmv2_session_key
.length
);
725 torture_comment(samlogon_state
->tctx
, "USER (NTLMv2) Session Key does not match expectations!\n");
726 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
727 dump_data(1, user_session_key
, 16);
728 torture_comment(samlogon_state
->tctx
, "expected:\n");
729 dump_data(1, ntlmv2_session_key
.data
, ntlmv2_session_key
.length
);
733 if (memcmp(ntlmv2_session_key
.data
, lm_session_key
,
734 sizeof(lm_session_key
)) != 0) {
735 if (memcmp(lmv2_session_key
.data
, lm_session_key
,
736 sizeof(lm_session_key
)) == 0) {
737 torture_comment(samlogon_state
->tctx
, "LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
738 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
739 dump_data(1, lm_session_key
, 8);
740 torture_comment(samlogon_state
->tctx
, "expected:\n");
741 dump_data(1, ntlmv2_session_key
.data
, 8);
744 torture_comment(samlogon_state
->tctx
, "LM (NTLMv2) Session Key does not match expectations!\n");
745 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
746 dump_data(1, lm_session_key
, 8);
747 torture_comment(samlogon_state
->tctx
, "expected:\n");
748 dump_data(1, ntlmv2_session_key
.data
, 8);
758 * Test the NTLM and LMv2 responses
761 static bool test_lmv2_ntlm_broken(struct samlogon_state
*samlogon_state
,
762 enum ntlm_break break_which
,
763 enum ntlmv2_domain ntlmv2_domain
,
768 DATA_BLOB ntlmv2_response
= data_blob(NULL
, 0);
769 DATA_BLOB lmv2_response
= data_blob(NULL
, 0);
770 DATA_BLOB lmv2_session_key
= data_blob(NULL
, 0);
771 DATA_BLOB ntlmv2_session_key
= data_blob(NULL
, 0);
772 DATA_BLOB names_blob
= NTLMv2_generate_names_blob(samlogon_state
->mem_ctx
, samlogon_state
->netbios_name
, samlogon_state
->workgroup
);
774 DATA_BLOB ntlm_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
775 DATA_BLOB ntlm_session_key
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 16);
779 uint8_t lm_session_key
[8];
780 uint8_t user_session_key
[16];
783 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
,
785 E_md4hash(samlogon_state
->password
, nt_hash
);
786 SMBsesskeygen_ntv1(nt_hash
,
787 ntlm_session_key
.data
);
789 lm_good
= E_deshash(samlogon_state
->password
, lm_hash
);
791 ZERO_STRUCT(lm_hash
);
794 ZERO_STRUCT(lm_session_key
);
795 ZERO_STRUCT(user_session_key
);
797 switch (ntlmv2_domain
) {
799 /* TODO - test with various domain cases, and without domain */
800 if (!SMBNTLMv2encrypt(samlogon_state
->mem_ctx
,
801 samlogon_state
->account_name
, samlogon_state
->account_domain
,
802 samlogon_state
->password
, &samlogon_state
->chall
,
804 &lmv2_response
, &ntlmv2_response
,
805 &lmv2_session_key
, &ntlmv2_session_key
)) {
806 data_blob_free(&names_blob
);
811 /* TODO - test with various domain cases, and without domain */
812 if (!SMBNTLMv2encrypt(samlogon_state
->mem_ctx
,
813 samlogon_state
->account_name
, "",
814 samlogon_state
->password
, &samlogon_state
->chall
,
816 &lmv2_response
, &ntlmv2_response
,
817 &lmv2_session_key
, &ntlmv2_session_key
)) {
818 data_blob_free(&names_blob
);
824 data_blob_free(&names_blob
);
826 nt_status
= check_samlogon(samlogon_state
,
828 samlogon_state
->parameter_control
,
829 &samlogon_state
->chall
,
836 data_blob_free(&lmv2_response
);
837 data_blob_free(&ntlmv2_response
);
840 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
841 /* for 'old' passwords, we allow the server to be OK or wrong password */
842 if (samlogon_state
->old_password
) {
845 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
));
846 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND
, nt_status
) && strchr_m(samlogon_state
->account_name
, '@')) {
847 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
));
848 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
849 SAFE_FREE(*error_string
);
850 asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
852 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
854 } else if (!NT_STATUS_IS_OK(nt_status
)) {
858 switch (break_which
) {
860 if (memcmp(lmv2_session_key
.data
, user_session_key
,
861 sizeof(user_session_key
)) != 0) {
862 torture_comment(samlogon_state
->tctx
, "USER (LMv2) Session Key does not match expectations!\n");
863 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
864 dump_data(1, user_session_key
, 16);
865 torture_comment(samlogon_state
->tctx
, "expected:\n");
866 dump_data(1, lmv2_session_key
.data
, ntlmv2_session_key
.length
);
869 if (memcmp(lmv2_session_key
.data
, lm_session_key
,
870 sizeof(lm_session_key
)) != 0) {
871 torture_comment(samlogon_state
->tctx
, "LM (LMv2) Session Key does not match expectations!\n");
872 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
873 dump_data(1, lm_session_key
, 8);
874 torture_comment(samlogon_state
->tctx
, "expected:\n");
875 dump_data(1, lmv2_session_key
.data
, 8);
880 if (memcmp(ntlm_session_key
.data
, user_session_key
,
881 sizeof(user_session_key
)) != 0) {
882 torture_comment(samlogon_state
->tctx
, "USER (NTLMv2) Session Key does not match expectations!\n");
883 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
884 dump_data(1, user_session_key
, 16);
885 torture_comment(samlogon_state
->tctx
, "expected:\n");
886 dump_data(1, ntlm_session_key
.data
, ntlm_session_key
.length
);
890 if (memcmp(lm_hash
, lm_session_key
,
891 sizeof(lm_session_key
)) != 0) {
892 torture_comment(samlogon_state
->tctx
, "LM Session Key does not match expectations!\n");
893 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
894 dump_data(1, lm_session_key
, 8);
895 torture_comment(samlogon_state
->tctx
, "expected:\n");
896 dump_data(1, lm_hash
, 8);
900 static const uint8_t zeros
[8];
901 if (memcmp(zeros
, lm_session_key
,
902 sizeof(lm_session_key
)) != 0) {
903 torture_comment(samlogon_state
->tctx
, "LM Session Key does not match expectations (zeros)!\n");
904 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
905 dump_data(1, lm_session_key
, 8);
906 torture_comment(samlogon_state
->tctx
, "expected:\n");
907 dump_data(1, zeros
, 8);
913 if (memcmp(ntlm_session_key
.data
, user_session_key
,
914 sizeof(user_session_key
)) != 0) {
915 torture_comment(samlogon_state
->tctx
, "USER (NTLMv2) Session Key does not match expectations!\n");
916 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
917 dump_data(1, user_session_key
, 16);
918 torture_comment(samlogon_state
->tctx
, "expected:\n");
919 dump_data(1, ntlm_session_key
.data
, ntlm_session_key
.length
);
922 if (memcmp(ntlm_session_key
.data
, lm_session_key
,
923 sizeof(lm_session_key
)) != 0) {
924 torture_comment(samlogon_state
->tctx
, "LM (NTLMv2) Session Key does not match expectations!\n");
925 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
926 dump_data(1, lm_session_key
, 8);
927 torture_comment(samlogon_state
->tctx
, "expected:\n");
928 dump_data(1, ntlm_session_key
.data
, 8);
937 * Test the NTLMv2 and LMv2 responses
940 static bool test_lmv2_ntlmv2(struct samlogon_state
*samlogon_state
, char **error_string
)
942 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_NONE
, UPPER_DOMAIN
, error_string
);
946 static bool test_lmv2_ntlmv2_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
948 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_NONE
, NO_DOMAIN
, error_string
);
953 * Test the LMv2 response only
956 static bool test_lmv2(struct samlogon_state
*samlogon_state
, char **error_string
)
958 return test_lmv2_ntlmv2_broken(samlogon_state
, NO_NT
, UPPER_DOMAIN
, error_string
);
961 static bool test_lmv2_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
963 return test_lmv2_ntlmv2_broken(samlogon_state
, NO_NT
, NO_DOMAIN
, error_string
);
967 * Test the NTLMv2 response only
970 static bool test_ntlmv2(struct samlogon_state
*samlogon_state
, char **error_string
)
972 return test_lmv2_ntlmv2_broken(samlogon_state
, NO_LM
, UPPER_DOMAIN
, error_string
);
975 static bool test_ntlmv2_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
977 return test_lmv2_ntlmv2_broken(samlogon_state
, NO_LM
, NO_DOMAIN
, error_string
);
980 static bool test_lm_ntlm(struct samlogon_state
*samlogon_state
, char **error_string
)
982 return test_lm_ntlm_broken(samlogon_state
, BREAK_NONE
, error_string
);
985 static bool test_ntlm_lm_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
987 return test_lm_ntlm_broken(samlogon_state
, BREAK_LM
, error_string
);
990 static bool test_ntlm_ntlm_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
992 return test_lm_ntlm_broken(samlogon_state
, BREAK_NT
, error_string
);
995 static bool test_lm_ntlm_both_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
997 return test_lm_ntlm_broken(samlogon_state
, BREAK_BOTH
, error_string
);
999 static bool test_ntlmv2_lmv2_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1001 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_LM
, UPPER_DOMAIN
, error_string
);
1004 static bool test_ntlmv2_lmv2_broken_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1006 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_LM
, NO_DOMAIN
, error_string
);
1009 static bool test_ntlmv2_ntlmv2_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1011 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_NT
, UPPER_DOMAIN
, error_string
);
1015 static bool test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1017 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_NT
, NO_DOMAIN
, error_string
);
1021 static bool test_ntlmv2_both_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1023 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_BOTH
, UPPER_DOMAIN
, error_string
);
1026 static bool test_ntlmv2_both_broken_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1028 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_BOTH
, NO_DOMAIN
, error_string
);
1031 static bool test_lmv2_ntlm_both_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1033 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_BOTH
, UPPER_DOMAIN
, error_string
);
1036 static bool test_lmv2_ntlm_both_broken_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1038 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_BOTH
, NO_DOMAIN
, error_string
);
1041 static bool test_lmv2_ntlm_break_ntlm(struct samlogon_state
*samlogon_state
, char **error_string
)
1043 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_NT
, UPPER_DOMAIN
, error_string
);
1046 static bool test_lmv2_ntlm_break_ntlm_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1048 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_NT
, NO_DOMAIN
, error_string
);
1051 static bool test_lmv2_ntlm_break_lm(struct samlogon_state
*samlogon_state
, char **error_string
)
1053 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_LM
, UPPER_DOMAIN
, error_string
);
1056 static bool test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1058 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_LM
, NO_DOMAIN
, error_string
);
1062 * Test the NTLM2 response (extra challenge in LM feild)
1064 * This test is the same as the 'break LM' test, but checks that the
1065 * server implements NTLM2 session security in the right place
1066 * (NETLOGON is the wrong place).
1069 static bool test_ntlm2(struct samlogon_state
*samlogon_state
, char **error_string
)
1073 DATA_BLOB lm_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
1074 DATA_BLOB nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
1078 uint8_t nt_hash
[16];
1079 uint8_t lm_hash
[16];
1081 uint8_t user_session_key
[16];
1082 uint8_t expected_user_session_key
[16];
1083 uint8_t session_nonce_hash
[16];
1084 uint8_t client_chall
[8];
1086 MD5_CTX md5_session_nonce_ctx
;
1087 HMACMD5Context hmac_ctx
;
1089 ZERO_STRUCT(user_session_key
);
1090 ZERO_STRUCT(lm_key
);
1091 generate_random_buffer(client_chall
, 8);
1093 MD5Init(&md5_session_nonce_ctx
);
1094 MD5Update(&md5_session_nonce_ctx
, samlogon_state
->chall
.data
, 8);
1095 MD5Update(&md5_session_nonce_ctx
, client_chall
, 8);
1096 MD5Final(session_nonce_hash
, &md5_session_nonce_ctx
);
1098 E_md4hash(samlogon_state
->password
, (uint8_t *)nt_hash
);
1099 lm_good
= E_deshash(samlogon_state
->password
, (uint8_t *)lm_hash
);
1100 SMBsesskeygen_ntv1((const uint8_t *)nt_hash
,
1103 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
, nt_response
.data
);
1105 memcpy(lm_response
.data
, session_nonce_hash
, 8);
1106 memset(lm_response
.data
+ 8, 0, 16);
1108 hmac_md5_init_rfc2104(nt_key
, 16, &hmac_ctx
);
1109 hmac_md5_update(samlogon_state
->chall
.data
, 8, &hmac_ctx
);
1110 hmac_md5_update(client_chall
, 8, &hmac_ctx
);
1111 hmac_md5_final(expected_user_session_key
, &hmac_ctx
);
1113 nt_status
= check_samlogon(samlogon_state
,
1115 samlogon_state
->parameter_control
,
1116 &samlogon_state
->chall
,
1123 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
1124 /* for 'old' passwords, we allow the server to be OK or wrong password */
1125 if (samlogon_state
->old_password
) {
1129 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
1130 SAFE_FREE(*error_string
);
1131 asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
1133 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
1135 } else if (!NT_STATUS_IS_OK(nt_status
)) {
1140 if (memcmp(lm_hash
, lm_key
,
1141 sizeof(lm_key
)) != 0) {
1142 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations!\n");
1143 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
1144 dump_data(1, lm_key
, 8);
1145 torture_comment(samlogon_state
->tctx
, "expected:\n");
1146 dump_data(1, lm_hash
, 8);
1150 static const uint8_t zeros
[8];
1151 if (memcmp(zeros
, lm_key
,
1152 sizeof(lm_key
)) != 0) {
1153 torture_comment(samlogon_state
->tctx
, "LM Session Key does not match expectations (zeros)!\n");
1154 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
1155 dump_data(1, lm_key
, 8);
1156 torture_comment(samlogon_state
->tctx
, "expected:\n");
1157 dump_data(1, zeros
, 8);
1161 if (memcmp(nt_key
, user_session_key
, 16) != 0) {
1162 torture_comment(samlogon_state
->tctx
, "NT Session Key does not match expectations (should be NT Key)!\n");
1163 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
1164 dump_data(1, user_session_key
, sizeof(user_session_key
));
1165 torture_comment(samlogon_state
->tctx
, "expected:\n");
1166 dump_data(1, nt_key
, sizeof(nt_key
));
1172 static bool test_plaintext(struct samlogon_state
*samlogon_state
, enum ntlm_break break_which
, char **error_string
)
1175 DATA_BLOB nt_response
= data_blob(NULL
, 0);
1176 DATA_BLOB lm_response
= data_blob(NULL
, 0);
1179 smb_ucs2_t
*unicodepw
;
1180 size_t converted_size
= 0;
1181 uint8_t user_session_key
[16];
1183 uint8_t lm_hash
[16];
1184 static const uint8_t zeros
[8];
1185 DATA_BLOB chall
= data_blob_talloc(samlogon_state
->mem_ctx
, zeros
, sizeof(zeros
));
1186 bool lm_good
= E_deshash(samlogon_state
->password
, lm_hash
);
1188 ZERO_STRUCT(user_session_key
);
1190 if (!push_ucs2_talloc(samlogon_state
->mem_ctx
,
1191 &unicodepw
, samlogon_state
->password
, &converted_size
)) {
1192 DEBUG(0, ("push_ucs2_allocate failed!\n"));
1196 nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, unicodepw
, strlen_m(samlogon_state
->password
)*2);
1198 password
= strupper_talloc(samlogon_state
->mem_ctx
, samlogon_state
->password
);
1200 if (!convert_string_talloc(samlogon_state
->mem_ctx
,
1202 password
, strlen(password
)+1,
1203 (void**)&dospw
, &converted_size
)) {
1204 DEBUG(0, ("convert_string_talloc failed!\n"));
1208 lm_response
= data_blob_talloc(samlogon_state
->mem_ctx
, dospw
, strlen(dospw
));
1210 nt_status
= check_samlogon(samlogon_state
,
1212 samlogon_state
->parameter_control
| MSV1_0_CLEARTEXT_PASSWORD_ALLOWED
,
1220 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
1221 /* for 'old' passwords, we allow the server to be OK or wrong password */
1222 if (samlogon_state
->old_password
) {
1225 /* for 'long' passwords, the LM password is invalid */
1226 if (break_which
== NO_NT
&& !lm_good
) {
1229 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
));
1230 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND
, nt_status
) && strchr_m(samlogon_state
->account_name
, '@')) {
1231 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
) || (break_which
== NO_NT
));
1232 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
1233 SAFE_FREE(*error_string
);
1234 asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
1236 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
1238 } else if (!NT_STATUS_IS_OK(nt_status
)) {
1242 if (break_which
== NO_NT
&& !lm_good
) {
1243 *error_string
= strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
1250 static bool test_plaintext_none_broken(struct samlogon_state
*samlogon_state
,
1251 char **error_string
) {
1252 return test_plaintext(samlogon_state
, BREAK_NONE
, error_string
);
1255 static bool test_plaintext_lm_broken(struct samlogon_state
*samlogon_state
,
1256 char **error_string
) {
1257 return test_plaintext(samlogon_state
, BREAK_LM
, error_string
);
1260 static bool test_plaintext_nt_broken(struct samlogon_state
*samlogon_state
,
1261 char **error_string
) {
1262 return test_plaintext(samlogon_state
, BREAK_NT
, error_string
);
1265 static bool test_plaintext_nt_only(struct samlogon_state
*samlogon_state
,
1266 char **error_string
) {
1267 return test_plaintext(samlogon_state
, NO_LM
, error_string
);
1270 static bool test_plaintext_lm_only(struct samlogon_state
*samlogon_state
,
1271 char **error_string
) {
1272 return test_plaintext(samlogon_state
, NO_NT
, error_string
);
1286 - plaintext tests (in challenge-response fields)
1288 check we get the correct session key in each case
1289 check what values we get for the LM session key
1293 static const struct ntlm_tests
{
1294 bool (*fn
)(struct samlogon_state
*, char **);
1298 {test_lmv2_ntlmv2
, "NTLMv2 and LMv2", false},
1300 {test_lmv2_ntlmv2_no_dom
, "NTLMv2 and LMv2 (no domain)", false},
1302 {test_lm
, "LM", false},
1303 {test_lm_ntlm
, "LM and NTLM", false},
1304 {test_lm_ntlm_both_broken
, "LM and NTLM, both broken", false},
1305 {test_ntlm
, "NTLM", false},
1306 {test_ntlm_in_lm
, "NTLM in LM", false},
1307 {test_ntlm_in_both
, "NTLM in both", false},
1308 {test_ntlmv2
, "NTLMv2", false},
1309 {test_ntlmv2_no_dom
, "NTLMv2 (no domain)", false},
1310 {test_lmv2
, "LMv2", false},
1311 {test_lmv2_no_dom
, "LMv2 (no domain)", false},
1312 {test_ntlmv2_lmv2_broken
, "NTLMv2 and LMv2, LMv2 broken", false},
1313 {test_ntlmv2_lmv2_broken_no_dom
, "NTLMv2 and LMv2, LMv2 broken (no domain)", false},
1314 {test_ntlmv2_ntlmv2_broken
, "NTLMv2 and LMv2, NTLMv2 broken", false},
1316 {test_ntlmv2_ntlmv2_broken_no_dom
, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", false},
1318 {test_ntlmv2_both_broken
, "NTLMv2 and LMv2, both broken", false},
1319 {test_ntlmv2_both_broken_no_dom
, "NTLMv2 and LMv2, both broken (no domain)", false},
1320 {test_ntlm_lm_broken
, "NTLM and LM, LM broken", false},
1321 {test_ntlm_ntlm_broken
, "NTLM and LM, NTLM broken", false},
1322 {test_ntlm2
, "NTLM2 (NTLMv2 session security)", false},
1323 {test_lmv2_ntlm_both_broken
, "LMv2 and NTLM, both broken", false},
1324 {test_lmv2_ntlm_both_broken_no_dom
, "LMv2 and NTLM, both broken (no domain)", false},
1325 {test_lmv2_ntlm_break_ntlm
, "LMv2 and NTLM, NTLM broken", false},
1326 {test_lmv2_ntlm_break_ntlm_no_dom
, "LMv2 and NTLM, NTLM broken (no domain)", false},
1327 {test_lmv2_ntlm_break_lm
, "LMv2 and NTLM, LMv2 broken", false},
1328 {test_lmv2_ntlm_break_lm_no_dom
, "LMv2 and NTLM, LMv2 broken (no domain)", false},
1329 {test_plaintext_none_broken
, "Plaintext", false},
1330 {test_plaintext_lm_broken
, "Plaintext LM broken", false},
1331 {test_plaintext_nt_broken
, "Plaintext NT broken", false},
1332 {test_plaintext_nt_only
, "Plaintext NT only", false},
1333 {test_plaintext_lm_only
, "Plaintext LM only", false},
1338 try a netlogon SamLogon
1340 static bool test_SamLogon(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
1341 struct torture_context
*tctx
,
1342 struct netlogon_creds_CredentialState
*creds
,
1343 const char *comment
,
1344 const char *account_domain
, const char *account_name
,
1345 const char *plain_pass
, uint32_t parameter_control
,
1346 NTSTATUS expected_error
, bool old_password
,
1349 TALLOC_CTX
*fn_ctx
= talloc_named(mem_ctx
, 0, "test_SamLogon function-level context");
1352 int validation_levels
[] = {2,3,6};
1353 int logon_levels
[] = { NetlogonNetworkInformation
, NetlogonNetworkTransitiveInformation
};
1354 int function_levels
[] = {
1355 NDR_NETR_LOGONSAMLOGON
,
1356 NDR_NETR_LOGONSAMLOGONEX
,
1357 NDR_NETR_LOGONSAMLOGONWITHFLAGS
};
1358 struct samlogon_state samlogon_state
;
1360 union netr_LogonLevel logon
;
1361 union netr_Validation validation
;
1362 uint8_t authoritative
= 0;
1367 torture_comment(tctx
, "Testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1369 samlogon_state
.comment
= comment
;
1370 samlogon_state
.account_name
= account_name
;
1371 samlogon_state
.account_domain
= account_domain
;
1372 samlogon_state
.password
= plain_pass
;
1373 samlogon_state
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
1374 samlogon_state
.netbios_name
= lpcfg_netbios_name(tctx
->lp_ctx
);
1375 samlogon_state
.p
= p
;
1376 samlogon_state
.creds
= creds
;
1377 samlogon_state
.expected_error
= expected_error
;
1378 samlogon_state
.chall
= data_blob_talloc(fn_ctx
, NULL
, 8);
1379 samlogon_state
.parameter_control
= parameter_control
;
1380 samlogon_state
.old_password
= old_password
;
1381 samlogon_state
.tctx
= tctx
;
1383 generate_random_buffer(samlogon_state
.chall
.data
, 8);
1384 samlogon_state
.r_flags
.in
.server_name
= talloc_asprintf(fn_ctx
, "\\\\%s", dcerpc_server_name(p
));
1385 samlogon_state
.r_flags
.in
.computer_name
= TEST_MACHINE_NAME
;
1386 samlogon_state
.r_flags
.in
.credential
= &samlogon_state
.auth
;
1387 samlogon_state
.r_flags
.in
.return_authenticator
= &samlogon_state
.auth2
;
1388 samlogon_state
.r_flags
.in
.flags
= &flags
;
1389 samlogon_state
.r_flags
.in
.logon
= &logon
;
1390 samlogon_state
.r_flags
.out
.validation
= &validation
;
1391 samlogon_state
.r_flags
.out
.authoritative
= &authoritative
;
1392 samlogon_state
.r_flags
.out
.flags
= &flags
;
1394 samlogon_state
.r_ex
.in
.server_name
= talloc_asprintf(fn_ctx
, "\\\\%s", dcerpc_server_name(p
));
1395 samlogon_state
.r_ex
.in
.computer_name
= TEST_MACHINE_NAME
;
1396 samlogon_state
.r_ex
.in
.flags
= &flags
;
1397 samlogon_state
.r_ex
.in
.logon
= &logon
;
1398 samlogon_state
.r_ex
.out
.validation
= &validation
;
1399 samlogon_state
.r_ex
.out
.authoritative
= &authoritative
;
1400 samlogon_state
.r_ex
.out
.flags
= &flags
;
1402 samlogon_state
.r
.in
.server_name
= talloc_asprintf(fn_ctx
, "\\\\%s", dcerpc_server_name(p
));
1403 samlogon_state
.r
.in
.computer_name
= TEST_MACHINE_NAME
;
1404 samlogon_state
.r
.in
.credential
= &samlogon_state
.auth
;
1405 samlogon_state
.r
.in
.return_authenticator
= &samlogon_state
.auth2
;
1406 samlogon_state
.r
.in
.logon
= &logon
;
1407 samlogon_state
.r
.out
.validation
= &validation
;
1408 samlogon_state
.r
.out
.authoritative
= &authoritative
;
1411 for (f
=0;f
<ARRAY_SIZE(function_levels
);f
++) {
1412 for (i
=0; test_table
[i
].fn
; i
++) {
1413 if (n_subtests
&& (i
> n_subtests
)) {
1416 for (v
=0;v
<ARRAY_SIZE(validation_levels
);v
++) {
1417 for (l
=0;l
<ARRAY_SIZE(logon_levels
);l
++) {
1418 char *error_string
= NULL
;
1419 TALLOC_CTX
*tmp_ctx
= talloc_named(fn_ctx
, 0, "test_SamLogon inner loop");
1420 samlogon_state
.mem_ctx
= tmp_ctx
;
1421 samlogon_state
.function_level
= function_levels
[f
];
1422 samlogon_state
.r
.in
.validation_level
= validation_levels
[v
];
1423 samlogon_state
.r
.in
.logon_level
= logon_levels
[l
];
1424 samlogon_state
.r_ex
.in
.validation_level
= validation_levels
[v
];
1425 samlogon_state
.r_ex
.in
.logon_level
= logon_levels
[l
];
1426 samlogon_state
.r_flags
.in
.validation_level
= validation_levels
[v
];
1427 samlogon_state
.r_flags
.in
.logon_level
= logon_levels
[l
];
1428 if (!test_table
[i
].fn(&samlogon_state
, &error_string
)) {
1429 torture_comment(tctx
, "Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
1430 samlogon_state
.comment
,
1431 samlogon_state
.account_domain
,
1432 samlogon_state
.account_name
,
1433 test_table
[i
].name
, validation_levels
[v
],
1434 logon_levels
[l
], function_levels
[f
]);
1436 if (test_table
[i
].expect_fail
) {
1437 torture_comment(tctx
, " failed (expected, test incomplete): %s\n", error_string
);
1439 torture_comment(tctx
, " failed: %s\n", error_string
);
1442 SAFE_FREE(error_string
);
1444 talloc_free(tmp_ctx
);
1449 talloc_free(fn_ctx
);
1454 test an ADS style interactive domain logon
1456 bool test_InteractiveLogon(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
1457 struct torture_context
*tctx
,
1458 struct netlogon_creds_CredentialState
*creds
,
1459 const char *comment
,
1460 const char *workstation_name
,
1461 const char *account_domain
, const char *account_name
,
1462 const char *plain_pass
, uint32_t parameter_control
,
1463 NTSTATUS expected_error
)
1466 TALLOC_CTX
*fn_ctx
= talloc_named(mem_ctx
, 0, "test_InteractiveLogon function-level context");
1468 struct netr_LogonSamLogonWithFlags r
;
1469 struct netr_Authenticator a
, ra
;
1470 struct netr_PasswordInfo pinfo
;
1473 union netr_LogonLevel logon
;
1474 union netr_Validation validation
;
1475 uint8_t authoritative
= 0;
1476 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
1483 ZERO_STRUCT(validation
);
1485 netlogon_creds_client_authenticator(creds
, &a
);
1487 logon
.password
= &pinfo
;
1489 r
.in
.server_name
= talloc_asprintf(fn_ctx
, "\\\\%s", dcerpc_server_name(p
));
1490 r
.in
.computer_name
= TEST_MACHINE_NAME
;
1491 r
.in
.credential
= &a
;
1492 r
.in
.return_authenticator
= &ra
;
1493 r
.in
.logon_level
= NetlogonInteractiveTransitiveInformation
;
1494 r
.in
.logon
= &logon
;
1495 r
.in
.validation_level
= 6;
1496 r
.in
.flags
= &flags
;
1497 r
.out
.validation
= &validation
;
1498 r
.out
.authoritative
= &authoritative
;
1499 r
.out
.flags
= &flags
;
1501 pinfo
.identity_info
.domain_name
.string
= account_domain
;
1502 pinfo
.identity_info
.parameter_control
= parameter_control
;
1503 pinfo
.identity_info
.logon_id_low
= 0;
1504 pinfo
.identity_info
.logon_id_high
= 0;
1505 pinfo
.identity_info
.account_name
.string
= account_name
;
1506 pinfo
.identity_info
.workstation
.string
= workstation_name
;
1508 if (!E_deshash(plain_pass
, pinfo
.lmpassword
.hash
)) {
1509 ZERO_STRUCT(pinfo
.lmpassword
.hash
);
1511 E_md4hash(plain_pass
, pinfo
.ntpassword
.hash
);
1513 if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
1514 netlogon_creds_arcfour_crypt(creds
, pinfo
.lmpassword
.hash
, 16);
1515 netlogon_creds_arcfour_crypt(creds
, pinfo
.ntpassword
.hash
, 16);
1517 netlogon_creds_des_encrypt(creds
, &pinfo
.lmpassword
);
1518 netlogon_creds_des_encrypt(creds
, &pinfo
.ntpassword
);
1521 torture_comment(tctx
, "Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment
);
1523 torture_assert_ntstatus_ok_goto(tctx
,
1524 dcerpc_netr_LogonSamLogonWithFlags_r(b
, fn_ctx
, &r
),
1526 talloc_asprintf(tctx
, "%s: netr_LogonSamLogonWithFlags - %s\n",
1527 __location__
, nt_errstr(status
)));
1529 if (!r
.out
.return_authenticator
) {
1530 talloc_free(fn_ctx
);
1531 torture_fail(tctx
, "no authenticator returned");
1534 torture_assert_goto(tctx
,
1535 netlogon_creds_client_check(creds
, &r
.out
.return_authenticator
->cred
),
1537 "Credential chaining failed\n");
1539 torture_assert_ntstatus_equal(tctx
, r
.out
.result
, expected_error
,
1540 talloc_asprintf(tctx
, "[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n",
1541 account_domain
, account_name
, nt_errstr(expected_error
), nt_errstr(r
.out
.result
)));
1545 talloc_free(fn_ctx
);
1550 /* This sets and resets the "minPwdAge" (in order to allow immediate user
1551 * password changes). The behaviour is controlled by the "set" boolean. */
1552 static bool handle_minPwdAge(struct torture_context
*torture
,
1553 TALLOC_CTX
*mem_ctx
, bool set
)
1555 struct dcerpc_pipe
*p
;
1556 struct policy_handle connect_handle
, domain_handle
;
1557 struct samr_Connect c_r
;
1558 struct samr_LookupDomain ld_r
;
1559 struct samr_OpenDomain od_r
;
1560 struct samr_QueryDomainInfo qdi_r
;
1561 struct samr_SetDomainInfo sdi_r
;
1562 struct samr_Close cl_r
;
1563 struct lsa_String domName
;
1564 struct dom_sid
*domSid
= NULL
;
1565 union samr_DomainInfo
*domInfo
= NULL
;
1566 static int64_t old_minPwdAge
= 0;
1569 status
= torture_rpc_connection(torture
, &p
, &ndr_table_samr
);
1570 if (!NT_STATUS_IS_OK(status
)) {
1574 c_r
.in
.system_name
= 0;
1575 c_r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1576 c_r
.out
.connect_handle
= &connect_handle
;
1578 torture_assert_ntstatus_ok(torture
,
1579 dcerpc_samr_Connect_r(p
->binding_handle
, mem_ctx
, &c_r
),
1581 torture_assert_ntstatus_ok(torture
, c_r
.out
.result
, "Connect failed");
1583 ld_r
.in
.connect_handle
= &connect_handle
;
1584 ld_r
.in
.domain_name
= &domName
;
1585 ld_r
.in
.domain_name
->string
= lpcfg_workgroup(torture
->lp_ctx
);
1586 ld_r
.out
.sid
= &domSid
;
1588 torture_assert_ntstatus_ok(torture
,
1589 dcerpc_samr_LookupDomain_r(p
->binding_handle
, mem_ctx
, &ld_r
),
1590 "LookupDomain failed");
1591 torture_assert_ntstatus_ok(torture
, ld_r
.out
.result
,
1592 "LookupDomain failed");
1594 od_r
.in
.connect_handle
= &connect_handle
;
1595 od_r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1596 od_r
.in
.sid
= *ld_r
.out
.sid
;
1597 od_r
.out
.domain_handle
= &domain_handle
;
1599 torture_assert_ntstatus_ok(torture
,
1600 dcerpc_samr_OpenDomain_r(p
->binding_handle
, mem_ctx
, &od_r
),
1601 "OpenDomain failed");
1602 torture_assert_ntstatus_ok(torture
, od_r
.out
.result
,
1603 "OpenDomain failed");
1605 qdi_r
.in
.domain_handle
= &domain_handle
;
1606 qdi_r
.in
.level
= DomainPasswordInformation
;
1607 qdi_r
.out
.info
= &domInfo
;
1609 torture_assert_ntstatus_ok(torture
,
1610 dcerpc_samr_QueryDomainInfo_r(p
->binding_handle
, mem_ctx
, &qdi_r
),
1611 "QueryDomainInfo failed");
1612 torture_assert_ntstatus_ok(torture
, qdi_r
.out
.result
,
1613 "QueryDomainInfo failed");
1616 old_minPwdAge
= domInfo
->info1
.min_password_age
;
1617 domInfo
->info1
.min_password_age
= 0;
1619 domInfo
->info1
.min_password_age
= old_minPwdAge
;
1622 sdi_r
.in
.domain_handle
= &domain_handle
;
1623 sdi_r
.in
.level
= DomainPasswordInformation
;
1624 sdi_r
.in
.info
= domInfo
;
1626 torture_assert_ntstatus_ok(torture
,
1627 dcerpc_samr_SetDomainInfo_r(p
->binding_handle
, mem_ctx
, &sdi_r
),
1628 "SetDomainInfo failed");
1629 torture_assert_ntstatus_ok(torture
, sdi_r
.out
.result
,
1630 "SetDomainInfo failed");
1632 cl_r
.in
.handle
= &connect_handle
;
1633 cl_r
.out
.handle
= &connect_handle
;
1635 torture_assert_ntstatus_ok(torture
,
1636 dcerpc_samr_Close_r(p
->binding_handle
, mem_ctx
, &cl_r
),
1638 torture_assert_ntstatus_ok(torture
, cl_r
.out
.result
, "Close failed");
1643 bool torture_rpc_samlogon(struct torture_context
*torture
)
1646 struct dcerpc_pipe
*p
;
1647 struct dcerpc_binding
*b
;
1648 struct cli_credentials
*machine_credentials
;
1649 TALLOC_CTX
*mem_ctx
= talloc_init("torture_rpc_netlogon");
1651 struct test_join
*join_ctx
= NULL
;
1652 struct test_join
*user_ctx
= NULL
, *user_ctx_wrong_wks
= NULL
, *user_ctx_wrong_time
= NULL
;
1653 char *user_password
, *user_password_wrong_wks
, *user_password_wrong_time
;
1654 const char *old_user_password
;
1655 char *test_machine_account
;
1656 const char *userdomain
;
1657 struct samr_SetUserInfo s
;
1658 union samr_UserInfo u
;
1662 unsigned int credential_flags
[] = {
1663 NETLOGON_NEG_AUTH2_FLAGS
,
1664 NETLOGON_NEG_ARCFOUR
,
1665 NETLOGON_NEG_ARCFOUR
| NETLOGON_NEG_128BIT
,
1666 NETLOGON_NEG_AUTH2_ADS_FLAGS
,
1667 0 /* yes, this is a valid flag, causes the use of DES */
1670 struct netlogon_creds_CredentialState
*creds
;
1671 struct dcerpc_pipe
*tmp_p
= NULL
;
1673 torture_assert(torture
, handle_minPwdAge(torture
, mem_ctx
, true),
1674 "handle_minPwdAge error!");
1676 test_machine_account
= talloc_asprintf(mem_ctx
, "%s$", TEST_MACHINE_NAME
);
1677 /* We only need to join as a workstation here, and in future,
1678 * if we wish to test against trusted domains, we must be a
1679 * workstation here */
1680 join_ctx
= torture_join_domain(torture
, TEST_MACHINE_NAME
, ACB_WSTRUST
,
1681 &machine_credentials
);
1682 torture_assert(torture
, join_ctx
, "Failed to join as Workstation\n");
1684 userdomain
= torture_setting_string(torture
, "userdomain", lpcfg_workgroup(torture
->lp_ctx
));
1686 user_ctx
= torture_create_testuser(torture
,
1690 (const char **)&user_password
);
1691 torture_assert(torture
, user_ctx
, "Failed to create a test user\n");
1693 old_user_password
= user_password
;
1695 tmp_p
= torture_join_samr_pipe(user_ctx
);
1696 test_ChangePasswordUser3(tmp_p
, torture
,
1697 TEST_USER_NAME
, 16 /* > 14 */, &user_password
,
1700 user_ctx_wrong_wks
= torture_create_testuser(torture
,
1701 TEST_USER_NAME_WRONG_WKS
,
1704 (const char **)&user_password_wrong_wks
);
1705 torture_assert(torture
, user_ctx_wrong_wks
,
1706 "Failed to create a test user (wrong workstation test)\n");
1709 s
.in
.user_handle
= torture_join_samr_user_policy(user_ctx_wrong_wks
);
1713 u
.info21
.fields_present
= SAMR_FIELD_WORKSTATIONS
;
1714 u
.info21
.workstations
.string
= "not" TEST_MACHINE_NAME
;
1716 tmp_p
= torture_join_samr_pipe(user_ctx_wrong_wks
);
1717 status
= dcerpc_samr_SetUserInfo_r(tmp_p
->binding_handle
, mem_ctx
, &s
);
1718 torture_assert_ntstatus_ok_goto(torture
, status
, ret
, failed
,
1719 talloc_asprintf(torture
, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status
)));
1720 torture_assert_ntstatus_ok_goto(torture
, s
.out
.result
, ret
, failed
,
1721 talloc_asprintf(torture
, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s
.out
.result
)));
1724 = torture_create_testuser(torture
, TEST_USER_NAME_WRONG_TIME
,
1727 (const char **)&user_password_wrong_time
);
1728 torture_assert(torture
, user_ctx_wrong_time
,
1729 "Failed to create a test user (wrong workstation test)\n");
1732 s
.in
.user_handle
= torture_join_samr_user_policy(user_ctx_wrong_time
);
1736 u
.info21
.fields_present
= SAMR_FIELD_WORKSTATIONS
| SAMR_FIELD_LOGON_HOURS
;
1737 u
.info21
.workstations
.string
= TEST_MACHINE_NAME
;
1738 u
.info21
.logon_hours
.units_per_week
= 168;
1739 u
.info21
.logon_hours
.bits
= talloc_zero_array(mem_ctx
, uint8_t, 168);
1741 tmp_p
= torture_join_samr_pipe(user_ctx_wrong_time
);
1742 status
= dcerpc_samr_SetUserInfo_r(tmp_p
->binding_handle
, mem_ctx
, &s
);
1743 torture_assert_ntstatus_ok_goto(torture
, status
, ret
, failed
,
1744 talloc_asprintf(torture
, "SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status
)));
1745 torture_assert_ntstatus_ok_goto(torture
, s
.out
.result
, ret
, failed
,
1746 talloc_asprintf(torture
, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s
.out
.result
)));
1748 status
= torture_rpc_binding(torture
, &b
);
1749 if (!NT_STATUS_IS_OK(status
)) {
1754 /* We have to use schannel, otherwise the SamLogonEx fails
1755 * with INTERNAL_ERROR */
1757 b
->flags
&= ~DCERPC_AUTH_OPTIONS
;
1758 b
->flags
|= DCERPC_SCHANNEL
| DCERPC_SIGN
| DCERPC_SCHANNEL_128
;
1760 status
= dcerpc_pipe_connect_b(mem_ctx
, &p
, b
,
1761 &ndr_table_netlogon
,
1762 machine_credentials
, torture
->ev
, torture
->lp_ctx
);
1764 torture_assert_ntstatus_ok_goto(torture
, status
, ret
, failed
,
1765 talloc_asprintf(torture
, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status
)));
1767 status
= dcerpc_schannel_creds(p
->conn
->security_state
.generic_state
, mem_ctx
, &creds
);
1768 if (!NT_STATUS_IS_OK(status
)) {
1776 const char *comment
;
1778 const char *username
;
1779 const char *password
;
1781 NTSTATUS expected_interactive_error
;
1782 NTSTATUS expected_network_error
;
1783 uint32_t parameter_control
;
1784 bool old_password
; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
1787 .comment
= "domain\\user",
1788 .domain
= cli_credentials_get_domain(cmdline_credentials
),
1789 .username
= cli_credentials_get_username(cmdline_credentials
),
1790 .password
= cli_credentials_get_password(cmdline_credentials
),
1791 .network_login
= true,
1792 .expected_interactive_error
= NT_STATUS_OK
,
1793 .expected_network_error
= NT_STATUS_OK
1796 .comment
= "realm\\user",
1797 .domain
= cli_credentials_get_realm(cmdline_credentials
),
1798 .username
= cli_credentials_get_username(cmdline_credentials
),
1799 .password
= cli_credentials_get_password(cmdline_credentials
),
1800 .network_login
= true,
1801 .expected_interactive_error
= NT_STATUS_OK
,
1802 .expected_network_error
= NT_STATUS_OK
1805 .comment
= "user@domain",
1807 .username
= talloc_asprintf(mem_ctx
,
1809 cli_credentials_get_username(cmdline_credentials
),
1810 cli_credentials_get_domain(cmdline_credentials
)
1812 .password
= cli_credentials_get_password(cmdline_credentials
),
1813 .network_login
= false, /* works for some things, but not NTLMv2. Odd */
1814 .expected_interactive_error
= NT_STATUS_OK
,
1815 .expected_network_error
= NT_STATUS_OK
1818 .comment
= "user@realm",
1820 .username
= talloc_asprintf(mem_ctx
,
1822 cli_credentials_get_username(cmdline_credentials
),
1823 cli_credentials_get_realm(cmdline_credentials
)
1825 .password
= cli_credentials_get_password(cmdline_credentials
),
1826 .network_login
= true,
1827 .expected_interactive_error
= NT_STATUS_OK
,
1828 .expected_network_error
= NT_STATUS_OK
1831 .comment
= "machine domain\\user",
1832 .domain
= cli_credentials_get_domain(machine_credentials
),
1833 .username
= cli_credentials_get_username(machine_credentials
),
1834 .password
= cli_credentials_get_password(machine_credentials
),
1835 .network_login
= true,
1836 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1837 .parameter_control
= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1840 .comment
= "machine domain\\user",
1841 .domain
= cli_credentials_get_domain(machine_credentials
),
1842 .username
= cli_credentials_get_username(machine_credentials
),
1843 .password
= cli_credentials_get_password(machine_credentials
),
1844 .network_login
= true,
1845 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1846 .expected_network_error
= NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
1849 .comment
= "machine realm\\user",
1850 .domain
= cli_credentials_get_realm(machine_credentials
),
1851 .username
= cli_credentials_get_username(machine_credentials
),
1852 .password
= cli_credentials_get_password(machine_credentials
),
1853 .network_login
= true,
1854 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1855 .parameter_control
= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1858 .comment
= "machine user@domain",
1860 .username
= talloc_asprintf(mem_ctx
,
1862 cli_credentials_get_username(machine_credentials
),
1863 cli_credentials_get_domain(machine_credentials
)
1865 .password
= cli_credentials_get_password(machine_credentials
),
1866 .network_login
= false, /* works for some things, but not NTLMv2. Odd */
1867 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1868 .parameter_control
= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1871 .comment
= "machine user@realm",
1873 .username
= talloc_asprintf(mem_ctx
,
1875 cli_credentials_get_username(machine_credentials
),
1876 cli_credentials_get_realm(machine_credentials
)
1878 .password
= cli_credentials_get_password(machine_credentials
),
1879 .network_login
= true,
1880 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1881 .parameter_control
= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1884 .comment
= "test user (long pw): domain\\user",
1885 .domain
= userdomain
,
1886 .username
= TEST_USER_NAME
,
1887 .password
= user_password
,
1888 .network_login
= true,
1889 .expected_interactive_error
= NT_STATUS_OK
,
1890 .expected_network_error
= NT_STATUS_OK
1893 .comment
= "test user (long pw): user@realm",
1895 .username
= talloc_asprintf(mem_ctx
,
1898 lpcfg_realm(torture
->lp_ctx
)),
1899 .password
= user_password
,
1900 .network_login
= true,
1901 .expected_interactive_error
= NT_STATUS_OK
,
1902 .expected_network_error
= NT_STATUS_OK
1905 .comment
= "test user (long pw): user@domain",
1907 .username
= talloc_asprintf(mem_ctx
,
1911 .password
= user_password
,
1912 .network_login
= false, /* works for some things, but not NTLMv2. Odd */
1913 .expected_interactive_error
= NT_STATUS_OK
,
1914 .expected_network_error
= NT_STATUS_OK
1916 /* Oddball, can we use the old password ? */
1918 .comment
= "test user: user\\domain OLD PASSWORD",
1919 .domain
= userdomain
,
1920 .username
= TEST_USER_NAME
,
1921 .password
= old_user_password
,
1922 .network_login
= true,
1923 .expected_interactive_error
= NT_STATUS_WRONG_PASSWORD
,
1924 .expected_network_error
= NT_STATUS_OK
,
1925 .old_password
= true
1928 .comment
= "test user (wrong workstation): domain\\user",
1929 .domain
= userdomain
,
1930 .username
= TEST_USER_NAME_WRONG_WKS
,
1931 .password
= user_password_wrong_wks
,
1932 .network_login
= true,
1933 .expected_interactive_error
= NT_STATUS_INVALID_WORKSTATION
,
1934 .expected_network_error
= NT_STATUS_INVALID_WORKSTATION
1938 /* Try all the tests for different username forms */
1939 for (ci
= 0; ci
< ARRAY_SIZE(usercreds
); ci
++) {
1941 if (!test_InteractiveLogon(p
, mem_ctx
, torture
, creds
,
1942 usercreds
[ci
].comment
,
1944 usercreds
[ci
].domain
,
1945 usercreds
[ci
].username
,
1946 usercreds
[ci
].password
,
1947 usercreds
[ci
].parameter_control
,
1948 usercreds
[ci
].expected_interactive_error
)) {
1953 if (usercreds
[ci
].network_login
) {
1954 if (!test_SamLogon(p
, mem_ctx
, torture
, creds
,
1955 usercreds
[ci
].comment
,
1956 usercreds
[ci
].domain
,
1957 usercreds
[ci
].username
,
1958 usercreds
[ci
].password
,
1959 usercreds
[ci
].parameter_control
,
1960 usercreds
[ci
].expected_network_error
,
1961 usercreds
[ci
].old_password
,
1969 /* Using the first username form, try the different
1970 * credentials flag setups, on only one of the tests (checks
1971 * session key encryption) */
1973 for (i
=0; i
< ARRAY_SIZE(credential_flags
); i
++) {
1974 /* TODO: Somehow we lost setting up the different credential flags here! */
1976 torture_comment(torture
,
1977 "Testing with flags: 0x%08x\n",
1978 credential_flags
[i
]);
1980 if (!test_InteractiveLogon(p
, mem_ctx
, torture
, creds
,
1981 usercreds
[0].comment
,
1983 usercreds
[0].domain
,
1984 usercreds
[0].username
,
1985 usercreds
[0].password
,
1986 usercreds
[0].parameter_control
,
1987 usercreds
[0].expected_interactive_error
)) {
1992 if (usercreds
[0].network_login
) {
1993 if (!test_SamLogon(p
, mem_ctx
, torture
, creds
,
1994 usercreds
[0].comment
,
1995 usercreds
[0].domain
,
1996 usercreds
[0].username
,
1997 usercreds
[0].password
,
1998 usercreds
[0].parameter_control
,
1999 usercreds
[0].expected_network_error
,
2000 usercreds
[0].old_password
,
2010 torture_assert(torture
, handle_minPwdAge(torture
, mem_ctx
, false),
2011 "handle_minPwdAge error!");
2013 talloc_free(mem_ctx
);
2015 torture_leave_domain(torture
, join_ctx
);
2016 torture_leave_domain(torture
, user_ctx
);
2017 torture_leave_domain(torture
, user_ctx_wrong_wks
);
2018 torture_leave_domain(torture
, user_ctx_wrong_time
);