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/cmdline/cmdline.h"
29 #include "torture/rpc/torture_rpc.h"
30 #include "auth/gensec/gensec.h"
31 #include "libcli/auth/libcli_auth.h"
32 #include "param/param.h"
34 #include <gnutls/gnutls.h>
35 #include <gnutls/crypto.h>
37 #define TEST_MACHINE_NAME "samlogontest"
38 #define TEST_USER_NAME "samlogontestuser"
39 #define TEST_USER_NAME_WRONG_WKS "samlogontest2"
40 #define TEST_USER_NAME_WRONG_TIME "samlogontest3"
51 struct samlogon_state
{
53 struct torture_context
*tctx
;
55 const char *account_name
;
56 const char *account_domain
;
57 const char *netbios_name
;
59 const char *workgroup
;
60 struct dcerpc_pipe
*p
;
62 uint32_t parameter_control
;
63 struct netr_LogonSamLogon r
;
64 struct netr_LogonSamLogonEx r_ex
;
65 struct netr_LogonSamLogonWithFlags r_flags
;
66 struct netr_Authenticator auth
, auth2
;
67 struct netlogon_creds_CredentialState
*creds
;
68 NTSTATUS expected_error
;
69 bool old_password
; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
74 Authenticate a user with a challenge/response, checking session key
75 and valid authentication types
77 static NTSTATUS
check_samlogon(struct samlogon_state
*samlogon_state
,
78 enum ntlm_break break_which
,
79 uint32_t parameter_control
,
81 DATA_BLOB
*lm_response
,
82 DATA_BLOB
*nt_response
,
84 uint8_t user_session_key
[16],
88 struct netr_LogonSamLogon
*r
= &samlogon_state
->r
;
89 struct netr_LogonSamLogonEx
*r_ex
= &samlogon_state
->r_ex
;
90 struct netr_LogonSamLogonWithFlags
*r_flags
= &samlogon_state
->r_flags
;
91 struct netr_NetworkInfo ninfo
;
92 struct netr_SamBaseInfo
*base
= NULL
;
93 uint16_t validation_level
= 0;
95 samlogon_state
->r
.in
.logon
->network
= &ninfo
;
96 samlogon_state
->r_ex
.in
.logon
->network
= &ninfo
;
97 samlogon_state
->r_flags
.in
.logon
->network
= &ninfo
;
99 ninfo
.identity_info
.domain_name
.string
= samlogon_state
->account_domain
;
100 ninfo
.identity_info
.parameter_control
= parameter_control
;
101 ninfo
.identity_info
.logon_id
= 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 status
= netlogon_creds_decrypt_samlogon_validation(samlogon_state
->creds
,
182 if (!NT_STATUS_IS_OK(status
)) {
184 *error_string
= strdup(nt_errstr(status
));
189 switch (validation_level
) {
191 base
= &r
->out
.validation
->sam2
->base
;
194 base
= &r
->out
.validation
->sam3
->base
;
197 base
= &r
->out
.validation
->sam6
->base
;
201 case NDR_NETR_LOGONSAMLOGONEX
:
202 status
= dcerpc_netr_LogonSamLogonEx_r(samlogon_state
->p
->binding_handle
,
203 samlogon_state
->mem_ctx
, r_ex
);
204 if (!NT_STATUS_IS_OK(status
)) {
206 *error_string
= strdup(nt_errstr(status
));
210 if (!NT_STATUS_IS_OK(r_ex
->out
.result
)) {
212 *error_string
= strdup(nt_errstr(r_ex
->out
.result
));
214 return r_ex
->out
.result
;
217 validation_level
= r_ex
->in
.validation_level
;
219 status
= netlogon_creds_decrypt_samlogon_validation(samlogon_state
->creds
,
221 r_ex
->out
.validation
);
222 if (!NT_STATUS_IS_OK(status
)) {
224 *error_string
= strdup(nt_errstr(status
));
229 switch (validation_level
) {
231 base
= &r_ex
->out
.validation
->sam2
->base
;
234 base
= &r_ex
->out
.validation
->sam3
->base
;
237 base
= &r_ex
->out
.validation
->sam6
->base
;
241 case NDR_NETR_LOGONSAMLOGONWITHFLAGS
:
242 ZERO_STRUCT(samlogon_state
->auth2
);
243 netlogon_creds_client_authenticator(samlogon_state
->creds
, &samlogon_state
->auth
);
245 r_flags
->out
.return_authenticator
= NULL
;
246 status
= dcerpc_netr_LogonSamLogonWithFlags_r(samlogon_state
->p
->binding_handle
,
247 samlogon_state
->mem_ctx
, r_flags
);
248 if (!NT_STATUS_IS_OK(status
)) {
250 *error_string
= strdup(nt_errstr(status
));
254 if (!r_flags
->out
.return_authenticator
||
255 !netlogon_creds_client_check(samlogon_state
->creds
, &r_flags
->out
.return_authenticator
->cred
)) {
256 torture_comment(samlogon_state
->tctx
, "Credential chaining failed\n");
258 if (!NT_STATUS_IS_OK(r_flags
->out
.result
)) {
260 *error_string
= strdup(nt_errstr(r_flags
->out
.result
));
262 return r_flags
->out
.result
;
265 validation_level
= r_flags
->in
.validation_level
;
267 status
= netlogon_creds_decrypt_samlogon_validation(samlogon_state
->creds
,
269 r_flags
->out
.validation
);
270 if (!NT_STATUS_IS_OK(status
)) {
272 *error_string
= strdup(nt_errstr(status
));
277 switch (validation_level
) {
279 base
= &r_flags
->out
.validation
->sam2
->base
;
282 base
= &r_flags
->out
.validation
->sam3
->base
;
285 base
= &r_flags
->out
.validation
->sam6
->base
;
291 return NT_STATUS_INVALID_PARAMETER
;
295 torture_comment(samlogon_state
->tctx
, "No user info returned from 'successful' SamLogon*() call!\n");
296 return NT_STATUS_INVALID_PARAMETER
;
299 if (user_session_key
) {
300 memcpy(user_session_key
, base
->key
.key
, 16);
303 memcpy(lm_key
, base
->LMSessKey
.key
, 8);
311 * Test the normal 'LM and NTLM' combination
314 static bool test_lm_ntlm_broken(struct samlogon_state
*samlogon_state
, enum ntlm_break break_which
, char **error_string
)
319 DATA_BLOB lm_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
320 DATA_BLOB nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
321 DATA_BLOB session_key
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 16);
324 uint8_t user_session_key
[16];
329 ZERO_STRUCT(user_session_key
);
331 lm_good
= SMBencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
, lm_response
.data
);
333 ZERO_STRUCT(lm_hash
);
335 E_deshash(samlogon_state
->password
, lm_hash
);
338 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
, nt_response
.data
);
340 E_md4hash(samlogon_state
->password
, nt_hash
);
341 SMBsesskeygen_ntv1(nt_hash
, session_key
.data
);
343 nt_status
= check_samlogon(samlogon_state
,
345 samlogon_state
->parameter_control
,
346 &samlogon_state
->chall
,
353 data_blob_free(&lm_response
);
355 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
356 /* for 'long' passwords, the LM password is invalid */
357 if (break_which
== NO_NT
&& !lm_good
) {
360 /* for modern servers, the LM password is invalid */
361 if (break_which
== NO_NT
362 && !torture_setting_bool(samlogon_state
->tctx
, "samba3", false)) {
366 /* for 'old' passwords, we allow the server to be OK or wrong password */
367 if (samlogon_state
->old_password
) {
370 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
));
371 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND
, nt_status
) && strchr_m(samlogon_state
->account_name
, '@')) {
372 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
) || (break_which
== NO_NT
));
373 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
376 SAFE_FREE(*error_string
);
377 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
379 *error_string
= NULL
;
382 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
384 } else if (!NT_STATUS_IS_OK(nt_status
)) {
388 if (break_which
== NO_NT
&& !lm_good
) {
389 *error_string
= strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
393 /* for modern servers, the LM password is invalid */
394 if (break_which
== NO_NT
395 && !torture_setting_bool(samlogon_state
->tctx
, "samba3", false)) {
396 *error_string
= strdup("LM password is OK but should have failed against a modern server");
400 if (!all_zero(lm_key
, sizeof(lm_key
)) != 0) {
401 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations!\n");
402 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
403 dump_data(1, lm_key
, 8);
404 torture_comment(samlogon_state
->tctx
, "expected (all zeros):\n");
408 switch (break_which
) {
411 uint8_t lm_key_expected
[16];
412 memcpy(lm_key_expected
, session_key
.data
, 8);
413 memset(lm_key_expected
+8, '\0', 8);
414 if (memcmp(lm_key_expected
, user_session_key
,
416 *error_string
= strdup("NT Session Key does not match expectations (should be first-8 session key)!\n");
417 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
418 dump_data(1, user_session_key
, sizeof(user_session_key
));
419 torture_comment(samlogon_state
->tctx
, "expected:\n");
420 dump_data(1, lm_key_expected
, sizeof(lm_key_expected
));
426 if (memcmp(session_key
.data
, user_session_key
,
427 sizeof(user_session_key
)) != 0) {
428 *error_string
= strdup("NT Session Key does not match expectations!\n");
429 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
430 dump_data(1, user_session_key
, 16);
431 torture_comment(samlogon_state
->tctx
, "expected:\n");
432 dump_data(1, session_key
.data
, session_key
.length
);
440 * Test LM authentication, no NT response supplied
443 static bool test_lm(struct samlogon_state
*samlogon_state
, char **error_string
)
446 return test_lm_ntlm_broken(samlogon_state
, NO_NT
, error_string
);
450 * Test the NTLM response only, no LM.
453 static bool test_ntlm(struct samlogon_state
*samlogon_state
, char **error_string
)
455 return test_lm_ntlm_broken(samlogon_state
, NO_LM
, error_string
);
459 * Test the NTLM response only, but in the LM field.
462 static bool test_ntlm_in_lm(struct samlogon_state
*samlogon_state
, char **error_string
)
467 DATA_BLOB nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
468 DATA_BLOB session_key
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 16);
472 uint8_t user_session_key
[16];
476 ZERO_STRUCT(user_session_key
);
478 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
,
480 E_md4hash(samlogon_state
->password
, nt_hash
);
481 SMBsesskeygen_ntv1(nt_hash
,
484 lm_good
= E_deshash(samlogon_state
->password
, lm_hash
);
486 ZERO_STRUCT(lm_hash
);
488 nt_status
= check_samlogon(samlogon_state
,
490 samlogon_state
->parameter_control
,
491 &samlogon_state
->chall
,
498 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
499 /* for 'old' passwords, we allow the server to be OK or wrong password */
500 if (samlogon_state
->old_password
) {
504 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
507 SAFE_FREE(*error_string
);
508 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
510 *error_string
= NULL
;
513 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
515 } else if (!NT_STATUS_IS_OK(nt_status
)) {
519 if (torture_setting_bool(samlogon_state
->tctx
, "samba4", false)) {
520 if (!all_zero(lm_key
, sizeof(lm_key
)) != 0) {
521 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations!\n");
522 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
523 dump_data(1, lm_key
, 8);
524 torture_comment(samlogon_state
->tctx
, "expected (all zeros):\n");
529 if (!all_zero(user_session_key
, sizeof(user_session_key
)) != 0) {
530 torture_comment(samlogon_state
->tctx
, "NT Key does not match expectations!\n");
531 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
532 dump_data(1, user_session_key
, sizeof(user_session_key
));
533 torture_comment(samlogon_state
->tctx
, "expected (all zeros):\n");
538 if (memcmp(lm_hash
, lm_key
,
539 sizeof(lm_key
)) != 0) {
540 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations!\n");
541 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
542 dump_data(1, lm_key
, 8);
543 torture_comment(samlogon_state
->tctx
, "expected:\n");
544 dump_data(1, lm_hash
, 8);
549 if (memcmp(session_key
.data
, lm_key
,
550 sizeof(lm_key
)) != 0) {
551 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations (first 8 session key)!\n");
552 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
553 dump_data(1, lm_key
, 8);
554 torture_comment(samlogon_state
->tctx
, "expected:\n");
555 dump_data(1, session_key
.data
, 8);
560 if (lm_good
&& memcmp(lm_hash
, user_session_key
, 8) != 0) {
561 uint8_t lm_key_expected
[16];
562 memcpy(lm_key_expected
, lm_hash
, 8);
563 memset(lm_key_expected
+8, '\0', 8);
564 if (memcmp(lm_key_expected
, user_session_key
,
566 torture_comment(samlogon_state
->tctx
, "NT Session Key does not match expectations (should be first-8 LM hash)!\n");
567 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
568 dump_data(1, user_session_key
, sizeof(user_session_key
));
569 torture_comment(samlogon_state
->tctx
, "expected:\n");
570 dump_data(1, lm_key_expected
, sizeof(lm_key_expected
));
579 * Test the NTLM response only, but in the both the NT and LM fields.
582 static bool test_ntlm_in_both(struct samlogon_state
*samlogon_state
, char **error_string
)
587 DATA_BLOB nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
588 DATA_BLOB session_key
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 16);
592 uint8_t user_session_key
[16];
596 ZERO_STRUCT(user_session_key
);
598 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
,
600 E_md4hash(samlogon_state
->password
, nt_hash
);
601 SMBsesskeygen_ntv1(nt_hash
,
604 lm_good
= E_deshash(samlogon_state
->password
, lm_hash
);
606 ZERO_STRUCT(lm_hash
);
609 nt_status
= check_samlogon(samlogon_state
,
611 samlogon_state
->parameter_control
,
612 &samlogon_state
->chall
,
619 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
620 /* for 'old' passwords, we allow the server to be OK or wrong password */
621 if (samlogon_state
->old_password
) {
625 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
628 SAFE_FREE(*error_string
);
629 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
631 *error_string
= NULL
;
634 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
636 } else if (!NT_STATUS_IS_OK(nt_status
)) {
640 if (!NT_STATUS_IS_OK(nt_status
)) {
644 if (!all_zero(lm_key
,
645 sizeof(lm_key
)) != 0) {
646 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations!\n");
647 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
648 dump_data(1, lm_key
, 8);
649 torture_comment(samlogon_state
->tctx
, "expected (all zero)\n");
652 if (memcmp(session_key
.data
, user_session_key
,
653 sizeof(user_session_key
)) != 0) {
654 torture_comment(samlogon_state
->tctx
, "NT Session Key does not match expectations!\n");
655 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
656 dump_data(1, user_session_key
, 16);
657 torture_comment(samlogon_state
->tctx
, "expected:\n");
658 dump_data(1, session_key
.data
, session_key
.length
);
667 * Test the NTLMv2 and LMv2 responses
675 static bool test_lmv2_ntlmv2_broken(struct samlogon_state
*samlogon_state
,
676 enum ntlm_break break_which
,
677 enum ntlmv2_domain ntlmv2_domain
,
682 DATA_BLOB ntlmv2_response
= data_blob(NULL
, 0);
683 DATA_BLOB lmv2_response
= data_blob(NULL
, 0);
684 DATA_BLOB lmv2_session_key
= data_blob(NULL
, 0);
685 DATA_BLOB ntlmv2_session_key
= data_blob(NULL
, 0);
686 DATA_BLOB names_blob
= NTLMv2_generate_names_blob(samlogon_state
->mem_ctx
, TEST_MACHINE_NAME
, samlogon_state
->workgroup
);
688 uint8_t lm_session_key
[8];
689 uint8_t user_session_key
[16];
691 ZERO_STRUCT(lm_session_key
);
692 ZERO_STRUCT(user_session_key
);
694 switch (ntlmv2_domain
) {
696 if (!SMBNTLMv2encrypt(samlogon_state
->mem_ctx
,
697 samlogon_state
->account_name
, samlogon_state
->account_domain
,
698 samlogon_state
->password
, &samlogon_state
->chall
,
700 &lmv2_response
, &ntlmv2_response
,
701 &lmv2_session_key
, &ntlmv2_session_key
)) {
702 data_blob_free(&names_blob
);
707 if (!SMBNTLMv2encrypt(samlogon_state
->mem_ctx
,
708 samlogon_state
->account_name
, "",
709 samlogon_state
->password
, &samlogon_state
->chall
,
711 &lmv2_response
, &ntlmv2_response
,
712 &lmv2_session_key
, &ntlmv2_session_key
)) {
713 data_blob_free(&names_blob
);
718 data_blob_free(&names_blob
);
720 nt_status
= check_samlogon(samlogon_state
,
722 samlogon_state
->parameter_control
,
723 &samlogon_state
->chall
,
730 data_blob_free(&lmv2_response
);
731 data_blob_free(&ntlmv2_response
);
734 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
735 /* for 'old' passwords, we allow the server to be OK or wrong password */
736 if (samlogon_state
->old_password
) {
739 return break_which
== BREAK_BOTH
;
740 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND
, nt_status
) && strchr_m(samlogon_state
->account_name
, '@')) {
741 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
) || (break_which
== NO_NT
));
742 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
745 SAFE_FREE(*error_string
);
746 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
748 *error_string
= NULL
;
751 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
753 } else if (!NT_STATUS_IS_OK(nt_status
)) {
758 switch (break_which
) {
760 if (memcmp(lmv2_session_key
.data
, user_session_key
,
761 sizeof(user_session_key
)) != 0) {
762 torture_comment(samlogon_state
->tctx
, "USER (LMv2) Session Key does not match expectations!\n");
763 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
764 dump_data(1, user_session_key
, 16);
765 torture_comment(samlogon_state
->tctx
, "expected:\n");
766 dump_data(1, lmv2_session_key
.data
, ntlmv2_session_key
.length
);
769 if (memcmp(lmv2_session_key
.data
, lm_session_key
,
770 sizeof(lm_session_key
)) != 0) {
771 torture_comment(samlogon_state
->tctx
, "LM (LMv2) Session Key does not match expectations!\n");
772 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
773 dump_data(1, lm_session_key
, 8);
774 torture_comment(samlogon_state
->tctx
, "expected:\n");
775 dump_data(1, lmv2_session_key
.data
, 8);
780 if (memcmp(ntlmv2_session_key
.data
, user_session_key
,
781 sizeof(user_session_key
)) != 0) {
782 if (memcmp(lmv2_session_key
.data
, user_session_key
,
783 sizeof(user_session_key
)) == 0) {
784 torture_comment(samlogon_state
->tctx
, "USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
785 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
786 dump_data(1, user_session_key
, 16);
787 torture_comment(samlogon_state
->tctx
, "expected:\n");
788 dump_data(1, ntlmv2_session_key
.data
, ntlmv2_session_key
.length
);
792 torture_comment(samlogon_state
->tctx
, "USER (NTLMv2) Session Key does not match expectations!\n");
793 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
794 dump_data(1, user_session_key
, 16);
795 torture_comment(samlogon_state
->tctx
, "expected:\n");
796 dump_data(1, ntlmv2_session_key
.data
, ntlmv2_session_key
.length
);
800 if (memcmp(ntlmv2_session_key
.data
, lm_session_key
,
801 sizeof(lm_session_key
)) != 0) {
802 if (memcmp(lmv2_session_key
.data
, lm_session_key
,
803 sizeof(lm_session_key
)) == 0) {
804 torture_comment(samlogon_state
->tctx
, "LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
805 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
806 dump_data(1, lm_session_key
, 8);
807 torture_comment(samlogon_state
->tctx
, "expected:\n");
808 dump_data(1, ntlmv2_session_key
.data
, 8);
811 torture_comment(samlogon_state
->tctx
, "LM (NTLMv2) Session Key does not match expectations!\n");
812 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
813 dump_data(1, lm_session_key
, 8);
814 torture_comment(samlogon_state
->tctx
, "expected:\n");
815 dump_data(1, ntlmv2_session_key
.data
, 8);
825 * Test the NTLM and LMv2 responses
828 static bool test_lmv2_ntlm_broken(struct samlogon_state
*samlogon_state
,
829 enum ntlm_break break_which
,
830 enum ntlmv2_domain ntlmv2_domain
,
835 DATA_BLOB ntlmv2_response
= data_blob(NULL
, 0);
836 DATA_BLOB lmv2_response
= data_blob(NULL
, 0);
837 DATA_BLOB lmv2_session_key
= data_blob(NULL
, 0);
838 DATA_BLOB ntlmv2_session_key
= data_blob(NULL
, 0);
839 DATA_BLOB names_blob
= NTLMv2_generate_names_blob(samlogon_state
->mem_ctx
, samlogon_state
->netbios_name
, samlogon_state
->workgroup
);
841 DATA_BLOB ntlm_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
842 DATA_BLOB ntlm_session_key
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 16);
846 uint8_t lm_session_key
[8];
847 uint8_t user_session_key
[16];
850 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
,
852 E_md4hash(samlogon_state
->password
, nt_hash
);
853 SMBsesskeygen_ntv1(nt_hash
,
854 ntlm_session_key
.data
);
856 lm_good
= E_deshash(samlogon_state
->password
, lm_hash
);
858 ZERO_STRUCT(lm_hash
);
861 ZERO_STRUCT(lm_session_key
);
862 ZERO_STRUCT(user_session_key
);
864 switch (ntlmv2_domain
) {
866 /* TODO - test with various domain cases, and without domain */
867 if (!SMBNTLMv2encrypt(samlogon_state
->mem_ctx
,
868 samlogon_state
->account_name
, samlogon_state
->account_domain
,
869 samlogon_state
->password
, &samlogon_state
->chall
,
871 &lmv2_response
, &ntlmv2_response
,
872 &lmv2_session_key
, &ntlmv2_session_key
)) {
873 data_blob_free(&names_blob
);
878 /* TODO - test with various domain cases, and without domain */
879 if (!SMBNTLMv2encrypt(samlogon_state
->mem_ctx
,
880 samlogon_state
->account_name
, "",
881 samlogon_state
->password
, &samlogon_state
->chall
,
883 &lmv2_response
, &ntlmv2_response
,
884 &lmv2_session_key
, &ntlmv2_session_key
)) {
885 data_blob_free(&names_blob
);
891 data_blob_free(&names_blob
);
893 nt_status
= check_samlogon(samlogon_state
,
895 samlogon_state
->parameter_control
,
896 &samlogon_state
->chall
,
903 data_blob_free(&lmv2_response
);
904 data_blob_free(&ntlmv2_response
);
907 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
908 /* for 'old' passwords, we allow the server to be OK or wrong password */
909 if (samlogon_state
->old_password
) {
912 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
));
913 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND
, nt_status
) && strchr_m(samlogon_state
->account_name
, '@')) {
914 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
));
915 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
918 SAFE_FREE(*error_string
);
919 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
921 *error_string
= NULL
;
924 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
926 } else if (!NT_STATUS_IS_OK(nt_status
)) {
930 switch (break_which
) {
932 if (memcmp(lmv2_session_key
.data
, user_session_key
,
933 sizeof(user_session_key
)) != 0) {
934 torture_comment(samlogon_state
->tctx
, "USER (LMv2) Session Key does not match expectations!\n");
935 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
936 dump_data(1, user_session_key
, 16);
937 torture_comment(samlogon_state
->tctx
, "expected:\n");
938 dump_data(1, lmv2_session_key
.data
, ntlmv2_session_key
.length
);
941 if (memcmp(lmv2_session_key
.data
, lm_session_key
,
942 sizeof(lm_session_key
)) != 0) {
943 torture_comment(samlogon_state
->tctx
, "LM (LMv2) Session Key does not match expectations!\n");
944 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
945 dump_data(1, lm_session_key
, 8);
946 torture_comment(samlogon_state
->tctx
, "expected:\n");
947 dump_data(1, lmv2_session_key
.data
, 8);
952 if (memcmp(ntlm_session_key
.data
, user_session_key
,
953 sizeof(user_session_key
)) != 0) {
954 torture_comment(samlogon_state
->tctx
, "USER (NTLMv2) Session Key does not match expectations!\n");
955 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
956 dump_data(1, user_session_key
, 16);
957 torture_comment(samlogon_state
->tctx
, "expected:\n");
958 dump_data(1, ntlm_session_key
.data
, ntlm_session_key
.length
);
961 if (!all_zero(lm_session_key
,
962 sizeof(lm_session_key
))) {
963 torture_comment(samlogon_state
->tctx
, "LM Session Key does not match expectations (zeros)!\n");
964 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
965 dump_data(1, lm_session_key
, 8);
970 if (memcmp(ntlm_session_key
.data
, user_session_key
,
971 sizeof(user_session_key
)) != 0) {
972 torture_comment(samlogon_state
->tctx
, "USER (NTLMv2) Session Key does not match expectations!\n");
973 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
974 dump_data(1, user_session_key
, 16);
975 torture_comment(samlogon_state
->tctx
, "expected:\n");
976 dump_data(1, ntlm_session_key
.data
, ntlm_session_key
.length
);
979 if (memcmp(ntlm_session_key
.data
, lm_session_key
,
980 sizeof(lm_session_key
)) != 0) {
981 torture_comment(samlogon_state
->tctx
, "LM (NTLMv2) Session Key does not match expectations!\n");
982 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
983 dump_data(1, lm_session_key
, 8);
984 torture_comment(samlogon_state
->tctx
, "expected:\n");
985 dump_data(1, ntlm_session_key
.data
, 8);
994 * Test the NTLMv2 and LMv2 responses
997 static bool test_lmv2_ntlmv2(struct samlogon_state
*samlogon_state
, char **error_string
)
999 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_NONE
, UPPER_DOMAIN
, error_string
);
1003 static bool test_lmv2_ntlmv2_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1005 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_NONE
, NO_DOMAIN
, error_string
);
1010 * Test the LMv2 response only
1013 static bool test_lmv2(struct samlogon_state
*samlogon_state
, char **error_string
)
1015 return test_lmv2_ntlmv2_broken(samlogon_state
, NO_NT
, UPPER_DOMAIN
, error_string
);
1018 static bool test_lmv2_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1020 return test_lmv2_ntlmv2_broken(samlogon_state
, NO_NT
, NO_DOMAIN
, error_string
);
1024 * Test the NTLMv2 response only
1027 static bool test_ntlmv2(struct samlogon_state
*samlogon_state
, char **error_string
)
1029 return test_lmv2_ntlmv2_broken(samlogon_state
, NO_LM
, UPPER_DOMAIN
, error_string
);
1032 static bool test_ntlmv2_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1034 return test_lmv2_ntlmv2_broken(samlogon_state
, NO_LM
, NO_DOMAIN
, error_string
);
1037 static bool test_lm_ntlm(struct samlogon_state
*samlogon_state
, char **error_string
)
1039 return test_lm_ntlm_broken(samlogon_state
, BREAK_NONE
, error_string
);
1042 static bool test_ntlm_lm_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1044 return test_lm_ntlm_broken(samlogon_state
, BREAK_LM
, error_string
);
1047 static bool test_ntlm_ntlm_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1049 return test_lm_ntlm_broken(samlogon_state
, BREAK_NT
, error_string
);
1052 static bool test_lm_ntlm_both_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1054 return test_lm_ntlm_broken(samlogon_state
, BREAK_BOTH
, error_string
);
1056 static bool test_ntlmv2_lmv2_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1058 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_LM
, UPPER_DOMAIN
, error_string
);
1061 static bool test_ntlmv2_lmv2_broken_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1063 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_LM
, NO_DOMAIN
, error_string
);
1066 static bool test_ntlmv2_ntlmv2_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1068 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_NT
, UPPER_DOMAIN
, error_string
);
1072 static bool test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1074 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_NT
, NO_DOMAIN
, error_string
);
1078 static bool test_ntlmv2_both_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1080 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_BOTH
, UPPER_DOMAIN
, error_string
);
1083 static bool test_ntlmv2_both_broken_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1085 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_BOTH
, NO_DOMAIN
, error_string
);
1088 static bool test_lmv2_ntlm_both_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1090 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_BOTH
, UPPER_DOMAIN
, error_string
);
1093 static bool test_lmv2_ntlm_both_broken_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1095 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_BOTH
, NO_DOMAIN
, error_string
);
1098 static bool test_lmv2_ntlm_break_ntlm(struct samlogon_state
*samlogon_state
, char **error_string
)
1100 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_NT
, UPPER_DOMAIN
, error_string
);
1103 static bool test_lmv2_ntlm_break_ntlm_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1105 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_NT
, NO_DOMAIN
, error_string
);
1108 static bool test_lmv2_ntlm_break_lm(struct samlogon_state
*samlogon_state
, char **error_string
)
1110 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_LM
, UPPER_DOMAIN
, error_string
);
1113 static bool test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1115 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_LM
, NO_DOMAIN
, error_string
);
1119 * Test the NTLM2 response (extra challenge in LM feild)
1121 * This test is the same as the 'break LM' test, but checks that the
1122 * server implements NTLM2 session security in the right place
1123 * (NETLOGON is the wrong place).
1126 static bool test_ntlm2(struct samlogon_state
*samlogon_state
, char **error_string
)
1130 DATA_BLOB lm_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
1131 DATA_BLOB nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
1134 uint8_t nt_hash
[16];
1135 uint8_t lm_hash
[16];
1137 uint8_t user_session_key
[16];
1138 uint8_t expected_user_session_key
[16];
1139 uint8_t session_nonce_hash
[16];
1140 uint8_t client_chall
[8];
1142 gnutls_hmac_hd_t hmac_hnd
;
1143 gnutls_hash_hd_t hash_hnd
;
1145 ZERO_STRUCT(user_session_key
);
1146 ZERO_STRUCT(lm_key
);
1147 generate_random_buffer(client_chall
, 8);
1149 gnutls_hash_init(&hash_hnd
, GNUTLS_DIG_MD5
);
1150 gnutls_hash(hash_hnd
, samlogon_state
->chall
.data
, 8);
1151 gnutls_hash(hash_hnd
, client_chall
, 8);
1152 gnutls_hash_deinit(hash_hnd
, session_nonce_hash
);
1154 E_md4hash(samlogon_state
->password
, (uint8_t *)nt_hash
);
1155 E_deshash(samlogon_state
->password
, (uint8_t *)lm_hash
);
1156 SMBsesskeygen_ntv1((const uint8_t *)nt_hash
,
1159 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
, nt_response
.data
);
1161 memcpy(lm_response
.data
, session_nonce_hash
, 8);
1162 memset(lm_response
.data
+ 8, 0, 16);
1164 gnutls_hmac_init(&hmac_hnd
,
1168 gnutls_hmac(hmac_hnd
, samlogon_state
->chall
.data
, 8);
1169 gnutls_hmac(hmac_hnd
, client_chall
, 8);
1170 gnutls_hmac_deinit(hmac_hnd
, expected_user_session_key
);
1172 nt_status
= check_samlogon(samlogon_state
,
1174 samlogon_state
->parameter_control
,
1175 &samlogon_state
->chall
,
1182 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
1183 /* for 'old' passwords, we allow the server to be OK or wrong password */
1184 if (samlogon_state
->old_password
) {
1188 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
1191 SAFE_FREE(*error_string
);
1192 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
1194 *error_string
= NULL
;
1197 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
1199 } else if (!NT_STATUS_IS_OK(nt_status
)) {
1203 if (!all_zero(lm_key
, sizeof(lm_key
))) {
1204 torture_comment(samlogon_state
->tctx
, "LM Session Key does not match expectations (zeros)!\n");
1205 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
1206 dump_data(1, lm_key
, 8);
1209 if (memcmp(nt_key
, user_session_key
, 16) != 0) {
1210 torture_comment(samlogon_state
->tctx
, "NT Session Key does not match expectations (should be NT Key)!\n");
1211 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
1212 dump_data(1, user_session_key
, sizeof(user_session_key
));
1213 torture_comment(samlogon_state
->tctx
, "expected:\n");
1214 dump_data(1, nt_key
, sizeof(nt_key
));
1220 static bool test_plaintext(struct samlogon_state
*samlogon_state
, enum ntlm_break break_which
, char **error_string
)
1223 DATA_BLOB nt_response
= data_blob(NULL
, 0);
1224 DATA_BLOB lm_response
= data_blob(NULL
, 0);
1227 smb_ucs2_t
*unicodepw
;
1228 size_t converted_size
= 0;
1229 uint8_t user_session_key
[16];
1231 uint8_t lm_hash
[16];
1232 DATA_BLOB chall
= data_blob_talloc_zero(samlogon_state
->mem_ctx
, 8);
1233 bool lm_good
= E_deshash(samlogon_state
->password
, lm_hash
);
1235 ZERO_STRUCT(user_session_key
);
1237 if (!push_ucs2_talloc(samlogon_state
->mem_ctx
,
1238 &unicodepw
, samlogon_state
->password
, &converted_size
)) {
1239 DEBUG(0, ("push_ucs2_allocate failed!\n"));
1243 nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, unicodepw
, strlen_m(samlogon_state
->password
)*2);
1245 password
= strupper_talloc(samlogon_state
->mem_ctx
, samlogon_state
->password
);
1247 if (!convert_string_talloc(samlogon_state
->mem_ctx
,
1249 password
, strlen(password
)+1,
1250 (void**)&dospw
, &converted_size
)) {
1251 DEBUG(0, ("convert_string_talloc failed!\n"));
1255 lm_response
= data_blob_talloc(samlogon_state
->mem_ctx
, dospw
, strlen(dospw
));
1257 nt_status
= check_samlogon(samlogon_state
,
1259 samlogon_state
->parameter_control
| MSV1_0_CLEARTEXT_PASSWORD_ALLOWED
,
1267 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
1268 /* for 'old' passwords, we allow the server to be OK or wrong password */
1269 if (samlogon_state
->old_password
) {
1272 /* for 'long' passwords, the LM password is invalid */
1273 if (break_which
== NO_NT
&& !lm_good
) {
1276 /* for modern servers, the LM password is invalid */
1277 if (break_which
== NO_NT
1278 && !torture_setting_bool(samlogon_state
->tctx
, "samba3", false)) {
1282 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
));
1283 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND
, nt_status
) && strchr_m(samlogon_state
->account_name
, '@')) {
1284 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
) || (break_which
== NO_NT
));
1285 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
1288 SAFE_FREE(*error_string
);
1289 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
1291 *error_string
= NULL
;
1294 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
1296 } else if (!NT_STATUS_IS_OK(nt_status
)) {
1300 if (break_which
== NO_NT
&& !lm_good
) {
1301 *error_string
= strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
1305 /* for modern servers, the LM password is invalid */
1306 if (break_which
== NO_NT
1307 && !torture_setting_bool(samlogon_state
->tctx
, "samba3", false)) {
1308 *error_string
= strdup("LM password is OK but should have failed against a modern server");
1315 static bool test_plaintext_none_broken(struct samlogon_state
*samlogon_state
,
1316 char **error_string
) {
1317 return test_plaintext(samlogon_state
, BREAK_NONE
, error_string
);
1320 static bool test_plaintext_lm_broken(struct samlogon_state
*samlogon_state
,
1321 char **error_string
) {
1322 return test_plaintext(samlogon_state
, BREAK_LM
, error_string
);
1325 static bool test_plaintext_nt_broken(struct samlogon_state
*samlogon_state
,
1326 char **error_string
) {
1327 return test_plaintext(samlogon_state
, BREAK_NT
, error_string
);
1330 static bool test_plaintext_nt_only(struct samlogon_state
*samlogon_state
,
1331 char **error_string
) {
1332 return test_plaintext(samlogon_state
, NO_LM
, error_string
);
1335 static bool test_plaintext_lm_only(struct samlogon_state
*samlogon_state
,
1336 char **error_string
) {
1337 return test_plaintext(samlogon_state
, NO_NT
, error_string
);
1351 - plaintext tests (in challenge-response fields)
1353 check we get the correct session key in each case
1354 check what values we get for the LM session key
1358 static const struct ntlm_tests
{
1359 bool (*fn
)(struct samlogon_state
*, char **);
1363 {test_lmv2_ntlmv2
, "NTLMv2 and LMv2", false},
1365 {test_lmv2_ntlmv2_no_dom
, "NTLMv2 and LMv2 (no domain)", false},
1367 {test_lm
, "LM", false},
1368 {test_lm_ntlm
, "LM and NTLM", false},
1369 {test_lm_ntlm_both_broken
, "LM and NTLM, both broken", false},
1370 {test_ntlm
, "NTLM", false},
1371 {test_ntlm_in_lm
, "NTLM in LM", false},
1372 {test_ntlm_in_both
, "NTLM in both", false},
1373 {test_ntlmv2
, "NTLMv2", false},
1374 {test_ntlmv2_no_dom
, "NTLMv2 (no domain)", false},
1375 {test_lmv2
, "LMv2", false},
1376 {test_lmv2_no_dom
, "LMv2 (no domain)", false},
1377 {test_ntlmv2_lmv2_broken
, "NTLMv2 and LMv2, LMv2 broken", false},
1378 {test_ntlmv2_lmv2_broken_no_dom
, "NTLMv2 and LMv2, LMv2 broken (no domain)", false},
1379 {test_ntlmv2_ntlmv2_broken
, "NTLMv2 and LMv2, NTLMv2 broken", false},
1381 {test_ntlmv2_ntlmv2_broken_no_dom
, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", false},
1383 {test_ntlmv2_both_broken
, "NTLMv2 and LMv2, both broken", false},
1384 {test_ntlmv2_both_broken_no_dom
, "NTLMv2 and LMv2, both broken (no domain)", false},
1385 {test_ntlm_lm_broken
, "NTLM and LM, LM broken", false},
1386 {test_ntlm_ntlm_broken
, "NTLM and LM, NTLM broken", false},
1387 {test_ntlm2
, "NTLM2 (NTLMv2 session security)", false},
1388 {test_lmv2_ntlm_both_broken
, "LMv2 and NTLM, both broken", false},
1389 {test_lmv2_ntlm_both_broken_no_dom
, "LMv2 and NTLM, both broken (no domain)", false},
1390 {test_lmv2_ntlm_break_ntlm
, "LMv2 and NTLM, NTLM broken", false},
1391 {test_lmv2_ntlm_break_ntlm_no_dom
, "LMv2 and NTLM, NTLM broken (no domain)", false},
1392 {test_lmv2_ntlm_break_lm
, "LMv2 and NTLM, LMv2 broken", false},
1393 {test_lmv2_ntlm_break_lm_no_dom
, "LMv2 and NTLM, LMv2 broken (no domain)", false},
1394 {test_plaintext_none_broken
, "Plaintext", false},
1395 {test_plaintext_lm_broken
, "Plaintext LM broken", false},
1396 {test_plaintext_nt_broken
, "Plaintext NT broken", false},
1397 {test_plaintext_nt_only
, "Plaintext NT only", false},
1398 {test_plaintext_lm_only
, "Plaintext LM only", false},
1403 try a netlogon SamLogon
1405 static bool test_SamLogon(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
1406 struct torture_context
*tctx
,
1407 struct netlogon_creds_CredentialState
*creds
,
1408 const char *comment
,
1409 const char *account_domain
, const char *account_name
,
1410 const char *plain_pass
, uint32_t parameter_control
,
1411 NTSTATUS expected_error
, bool old_password
,
1414 TALLOC_CTX
*fn_ctx
= talloc_named(mem_ctx
, 0, "test_SamLogon function-level context");
1417 int validation_levels
[] = {2,3,6};
1418 int logon_levels
[] = { NetlogonNetworkInformation
, NetlogonNetworkTransitiveInformation
};
1419 int function_levels
[] = {
1420 NDR_NETR_LOGONSAMLOGON
,
1421 NDR_NETR_LOGONSAMLOGONEX
,
1422 NDR_NETR_LOGONSAMLOGONWITHFLAGS
};
1423 struct samlogon_state samlogon_state
;
1425 union netr_LogonLevel logon
;
1426 union netr_Validation validation
;
1427 uint8_t authoritative
= 1;
1432 torture_comment(tctx
, "Testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1434 samlogon_state
.comment
= comment
;
1435 samlogon_state
.account_name
= account_name
;
1436 samlogon_state
.account_domain
= account_domain
;
1437 samlogon_state
.password
= plain_pass
;
1438 samlogon_state
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
1439 samlogon_state
.netbios_name
= lpcfg_netbios_name(tctx
->lp_ctx
);
1440 samlogon_state
.p
= p
;
1441 samlogon_state
.creds
= creds
;
1442 samlogon_state
.expected_error
= expected_error
;
1443 samlogon_state
.chall
= data_blob_talloc(fn_ctx
, NULL
, 8);
1444 samlogon_state
.parameter_control
= parameter_control
;
1445 samlogon_state
.old_password
= old_password
;
1446 samlogon_state
.tctx
= tctx
;
1448 generate_random_buffer(samlogon_state
.chall
.data
, 8);
1449 samlogon_state
.r_flags
.in
.server_name
= talloc_asprintf(fn_ctx
, "\\\\%s", dcerpc_server_name(p
));
1450 samlogon_state
.r_flags
.in
.computer_name
= TEST_MACHINE_NAME
;
1451 samlogon_state
.r_flags
.in
.credential
= &samlogon_state
.auth
;
1452 samlogon_state
.r_flags
.in
.return_authenticator
= &samlogon_state
.auth2
;
1453 samlogon_state
.r_flags
.in
.flags
= &flags
;
1454 samlogon_state
.r_flags
.in
.logon
= &logon
;
1455 samlogon_state
.r_flags
.out
.validation
= &validation
;
1456 samlogon_state
.r_flags
.out
.authoritative
= &authoritative
;
1457 samlogon_state
.r_flags
.out
.flags
= &flags
;
1459 samlogon_state
.r_ex
.in
.server_name
= talloc_asprintf(fn_ctx
, "\\\\%s", dcerpc_server_name(p
));
1460 samlogon_state
.r_ex
.in
.computer_name
= TEST_MACHINE_NAME
;
1461 samlogon_state
.r_ex
.in
.flags
= &flags
;
1462 samlogon_state
.r_ex
.in
.logon
= &logon
;
1463 samlogon_state
.r_ex
.out
.validation
= &validation
;
1464 samlogon_state
.r_ex
.out
.authoritative
= &authoritative
;
1465 samlogon_state
.r_ex
.out
.flags
= &flags
;
1467 samlogon_state
.r
.in
.server_name
= talloc_asprintf(fn_ctx
, "\\\\%s", dcerpc_server_name(p
));
1468 samlogon_state
.r
.in
.computer_name
= TEST_MACHINE_NAME
;
1469 samlogon_state
.r
.in
.credential
= &samlogon_state
.auth
;
1470 samlogon_state
.r
.in
.return_authenticator
= &samlogon_state
.auth2
;
1471 samlogon_state
.r
.in
.logon
= &logon
;
1472 samlogon_state
.r
.out
.validation
= &validation
;
1473 samlogon_state
.r
.out
.authoritative
= &authoritative
;
1476 for (f
=0;f
<ARRAY_SIZE(function_levels
);f
++) {
1477 for (i
=0; test_table
[i
].fn
; i
++) {
1478 if (n_subtests
&& (i
> n_subtests
)) {
1481 for (v
=0;v
<ARRAY_SIZE(validation_levels
);v
++) {
1482 for (l
=0;l
<ARRAY_SIZE(logon_levels
);l
++) {
1483 char *error_string
= NULL
;
1484 TALLOC_CTX
*tmp_ctx
= talloc_named(fn_ctx
, 0, "test_SamLogon inner loop");
1485 samlogon_state
.mem_ctx
= tmp_ctx
;
1486 samlogon_state
.function_level
= function_levels
[f
];
1487 samlogon_state
.r
.in
.validation_level
= validation_levels
[v
];
1488 samlogon_state
.r
.in
.logon_level
= logon_levels
[l
];
1489 samlogon_state
.r_ex
.in
.validation_level
= validation_levels
[v
];
1490 samlogon_state
.r_ex
.in
.logon_level
= logon_levels
[l
];
1491 samlogon_state
.r_flags
.in
.validation_level
= validation_levels
[v
];
1492 samlogon_state
.r_flags
.in
.logon_level
= logon_levels
[l
];
1493 if (!test_table
[i
].fn(&samlogon_state
, &error_string
)) {
1494 torture_comment(tctx
, "Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
1495 samlogon_state
.comment
,
1496 samlogon_state
.account_domain
,
1497 samlogon_state
.account_name
,
1498 test_table
[i
].name
, validation_levels
[v
],
1499 logon_levels
[l
], function_levels
[f
]);
1501 if (test_table
[i
].expect_fail
) {
1502 torture_comment(tctx
, " failed (expected, test incomplete): %s\n", error_string
);
1504 torture_comment(tctx
, " failed: %s\n", error_string
);
1507 SAFE_FREE(error_string
);
1509 talloc_free(tmp_ctx
);
1514 talloc_free(fn_ctx
);
1519 test an ADS style interactive domain logon
1521 bool test_InteractiveLogon(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
1522 struct torture_context
*tctx
,
1523 struct netlogon_creds_CredentialState
*creds
,
1524 const char *comment
,
1525 const char *workstation_name
,
1526 const char *account_domain
, const char *account_name
,
1527 const char *plain_pass
, uint32_t parameter_control
,
1528 NTSTATUS expected_error
)
1531 TALLOC_CTX
*fn_ctx
= talloc_named(mem_ctx
, 0, "test_InteractiveLogon function-level context");
1533 struct netr_LogonSamLogonWithFlags r
;
1534 struct netr_Authenticator a
, ra
;
1535 struct netr_PasswordInfo pinfo
;
1538 union netr_LogonLevel logon
;
1539 union netr_Validation validation
;
1540 uint8_t authoritative
= 1;
1541 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
1548 ZERO_STRUCT(validation
);
1550 netlogon_creds_client_authenticator(creds
, &a
);
1552 logon
.password
= &pinfo
;
1554 r
.in
.server_name
= talloc_asprintf(fn_ctx
, "\\\\%s", dcerpc_server_name(p
));
1555 r
.in
.computer_name
= TEST_MACHINE_NAME
;
1556 r
.in
.credential
= &a
;
1557 r
.in
.return_authenticator
= &ra
;
1558 r
.in
.logon_level
= NetlogonInteractiveTransitiveInformation
;
1559 r
.in
.logon
= &logon
;
1560 r
.in
.validation_level
= 6;
1561 r
.in
.flags
= &flags
;
1562 r
.out
.validation
= &validation
;
1563 r
.out
.authoritative
= &authoritative
;
1564 r
.out
.flags
= &flags
;
1566 pinfo
.identity_info
.domain_name
.string
= account_domain
;
1567 pinfo
.identity_info
.parameter_control
= parameter_control
;
1568 pinfo
.identity_info
.logon_id
= 0;
1569 pinfo
.identity_info
.account_name
.string
= account_name
;
1570 pinfo
.identity_info
.workstation
.string
= workstation_name
;
1572 if (!E_deshash(plain_pass
, pinfo
.lmpassword
.hash
)) {
1573 ZERO_STRUCT(pinfo
.lmpassword
.hash
);
1575 E_md4hash(plain_pass
, pinfo
.ntpassword
.hash
);
1577 if (creds
->negotiate_flags
& NETLOGON_NEG_ARCFOUR
) {
1578 netlogon_creds_arcfour_crypt(creds
, pinfo
.lmpassword
.hash
, 16);
1579 netlogon_creds_arcfour_crypt(creds
, pinfo
.ntpassword
.hash
, 16);
1581 netlogon_creds_des_encrypt(creds
, &pinfo
.lmpassword
);
1582 netlogon_creds_des_encrypt(creds
, &pinfo
.ntpassword
);
1585 torture_comment(tctx
, "Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment
);
1587 status
= dcerpc_netr_LogonSamLogonWithFlags_r(b
, fn_ctx
, &r
);
1588 torture_assert_ntstatus_ok_goto(tctx
,
1591 talloc_asprintf(tctx
, "%s: netr_LogonSamLogonWithFlags - %s\n",
1592 __location__
, nt_errstr(status
)));
1594 if (!r
.out
.return_authenticator
) {
1595 talloc_free(fn_ctx
);
1596 torture_fail(tctx
, "no authenticator returned");
1599 torture_assert_goto(tctx
,
1600 netlogon_creds_client_check(creds
, &r
.out
.return_authenticator
->cred
),
1602 "Credential chaining failed\n");
1604 torture_assert_ntstatus_equal(tctx
, r
.out
.result
, expected_error
,
1605 talloc_asprintf(tctx
, "[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n",
1606 account_domain
, account_name
, nt_errstr(expected_error
), nt_errstr(r
.out
.result
)));
1610 talloc_free(fn_ctx
);
1615 /* This sets and resets the "minPwdAge" (in order to allow immediate user
1616 * password changes). The behaviour is controlled by the "set" boolean. */
1617 static bool handle_minPwdAge(struct torture_context
*torture
,
1618 TALLOC_CTX
*mem_ctx
, bool set
)
1620 struct dcerpc_pipe
*p
;
1621 struct policy_handle connect_handle
, domain_handle
;
1622 struct samr_Connect c_r
;
1623 struct samr_LookupDomain ld_r
;
1624 struct samr_OpenDomain od_r
;
1625 struct samr_QueryDomainInfo qdi_r
;
1626 struct samr_SetDomainInfo sdi_r
;
1627 struct samr_Close cl_r
;
1628 struct lsa_String domName
;
1629 struct dom_sid
*domSid
= NULL
;
1630 union samr_DomainInfo
*domInfo
= NULL
;
1631 static int64_t old_minPwdAge
= 0;
1634 status
= torture_rpc_connection(torture
, &p
, &ndr_table_samr
);
1635 if (!NT_STATUS_IS_OK(status
)) {
1639 c_r
.in
.system_name
= 0;
1640 c_r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1641 c_r
.out
.connect_handle
= &connect_handle
;
1643 torture_assert_ntstatus_ok(torture
,
1644 dcerpc_samr_Connect_r(p
->binding_handle
, mem_ctx
, &c_r
),
1646 torture_assert_ntstatus_ok(torture
, c_r
.out
.result
, "Connect failed");
1648 ld_r
.in
.connect_handle
= &connect_handle
;
1649 ld_r
.in
.domain_name
= &domName
;
1650 ld_r
.in
.domain_name
->string
= lpcfg_workgroup(torture
->lp_ctx
);
1651 ld_r
.out
.sid
= &domSid
;
1653 torture_assert_ntstatus_ok(torture
,
1654 dcerpc_samr_LookupDomain_r(p
->binding_handle
, mem_ctx
, &ld_r
),
1655 "LookupDomain failed");
1656 torture_assert_ntstatus_ok(torture
, ld_r
.out
.result
,
1657 "LookupDomain failed");
1659 od_r
.in
.connect_handle
= &connect_handle
;
1660 od_r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1661 od_r
.in
.sid
= *ld_r
.out
.sid
;
1662 od_r
.out
.domain_handle
= &domain_handle
;
1664 torture_assert_ntstatus_ok(torture
,
1665 dcerpc_samr_OpenDomain_r(p
->binding_handle
, mem_ctx
, &od_r
),
1666 "OpenDomain failed");
1667 torture_assert_ntstatus_ok(torture
, od_r
.out
.result
,
1668 "OpenDomain failed");
1670 qdi_r
.in
.domain_handle
= &domain_handle
;
1671 qdi_r
.in
.level
= DomainPasswordInformation
;
1672 qdi_r
.out
.info
= &domInfo
;
1674 torture_assert_ntstatus_ok(torture
,
1675 dcerpc_samr_QueryDomainInfo_r(p
->binding_handle
, mem_ctx
, &qdi_r
),
1676 "QueryDomainInfo failed");
1677 torture_assert_ntstatus_ok(torture
, qdi_r
.out
.result
,
1678 "QueryDomainInfo failed");
1681 old_minPwdAge
= domInfo
->info1
.min_password_age
;
1682 domInfo
->info1
.min_password_age
= 0;
1684 domInfo
->info1
.min_password_age
= old_minPwdAge
;
1687 sdi_r
.in
.domain_handle
= &domain_handle
;
1688 sdi_r
.in
.level
= DomainPasswordInformation
;
1689 sdi_r
.in
.info
= domInfo
;
1691 torture_assert_ntstatus_ok(torture
,
1692 dcerpc_samr_SetDomainInfo_r(p
->binding_handle
, mem_ctx
, &sdi_r
),
1693 "SetDomainInfo failed");
1694 torture_assert_ntstatus_ok(torture
, sdi_r
.out
.result
,
1695 "SetDomainInfo failed");
1697 cl_r
.in
.handle
= &connect_handle
;
1698 cl_r
.out
.handle
= &connect_handle
;
1700 torture_assert_ntstatus_ok(torture
,
1701 dcerpc_samr_Close_r(p
->binding_handle
, mem_ctx
, &cl_r
),
1703 torture_assert_ntstatus_ok(torture
, cl_r
.out
.result
, "Close failed");
1708 bool torture_rpc_samlogon(struct torture_context
*torture
)
1711 struct dcerpc_pipe
*p
;
1712 struct dcerpc_binding
*b
;
1713 struct cli_credentials
*machine_credentials
;
1714 TALLOC_CTX
*mem_ctx
= talloc_init("torture_rpc_netlogon");
1716 struct test_join
*join_ctx
= NULL
;
1717 struct test_join
*user_ctx
= NULL
, *user_ctx_wrong_wks
= NULL
, *user_ctx_wrong_time
= NULL
;
1718 const char *old_user_password
, *user_password_wrong_wks
, *user_password_wrong_time
;
1719 char *user_password
;
1720 const char *userdomain
;
1721 struct samr_SetUserInfo s
;
1722 union samr_UserInfo u
;
1726 unsigned int credential_flags
[] = {
1727 NETLOGON_NEG_AUTH2_FLAGS
,
1728 NETLOGON_NEG_ARCFOUR
,
1729 NETLOGON_NEG_ARCFOUR
| NETLOGON_NEG_128BIT
,
1730 NETLOGON_NEG_AUTH2_ADS_FLAGS
,
1731 0 /* yes, this is a valid flag, causes the use of DES */
1734 struct netlogon_creds_CredentialState
*creds
;
1735 struct dcerpc_pipe
*tmp_p
= NULL
;
1737 torture_assert(torture
, handle_minPwdAge(torture
, mem_ctx
, true),
1738 "handle_minPwdAge error!");
1740 /* We only need to join as a workstation here, and in future,
1741 * if we wish to test against trusted domains, we must be a
1742 * workstation here */
1743 join_ctx
= torture_join_domain(torture
, TEST_MACHINE_NAME
, ACB_WSTRUST
,
1744 &machine_credentials
);
1745 torture_assert(torture
, join_ctx
, "Failed to join as Workstation\n");
1747 userdomain
= torture_setting_string(torture
, "userdomain", lpcfg_workgroup(torture
->lp_ctx
));
1749 user_ctx
= torture_create_testuser(torture
,
1753 &old_user_password
);
1754 torture_assert(torture
, user_ctx
, "Failed to create a test user\n");
1756 user_password
= talloc_strdup(torture
, old_user_password
);
1757 torture_assert(torture
, user_password
!= NULL
, "Failed to copy old_user_password\n");
1759 tmp_p
= torture_join_samr_pipe(user_ctx
);
1760 torture_assert(torture
, tmp_p
, "torture_join_samr_pipe failed\n");
1761 test_ChangePasswordUser3(tmp_p
, torture
,
1762 TEST_USER_NAME
, 16 /* > 14 */, &user_password
,
1765 user_ctx_wrong_wks
= torture_create_testuser(torture
,
1766 TEST_USER_NAME_WRONG_WKS
,
1769 &user_password_wrong_wks
);
1770 torture_assert(torture
, user_ctx_wrong_wks
,
1771 "Failed to create a test user (wrong workstation test)\n");
1774 s
.in
.user_handle
= torture_join_samr_user_policy(user_ctx_wrong_wks
);
1778 u
.info21
.fields_present
= SAMR_FIELD_WORKSTATIONS
;
1779 u
.info21
.workstations
.string
= "not" TEST_MACHINE_NAME
;
1781 tmp_p
= torture_join_samr_pipe(user_ctx_wrong_wks
);
1782 status
= dcerpc_samr_SetUserInfo_r(tmp_p
->binding_handle
, mem_ctx
, &s
);
1783 torture_assert_ntstatus_ok_goto(torture
, status
, ret
, failed
,
1784 talloc_asprintf(torture
, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status
)));
1785 torture_assert_ntstatus_ok_goto(torture
, s
.out
.result
, ret
, failed
,
1786 talloc_asprintf(torture
, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s
.out
.result
)));
1789 = torture_create_testuser(torture
, TEST_USER_NAME_WRONG_TIME
,
1792 &user_password_wrong_time
);
1793 torture_assert(torture
, user_ctx_wrong_time
,
1794 "Failed to create a test user (wrong workstation test)\n");
1797 s
.in
.user_handle
= torture_join_samr_user_policy(user_ctx_wrong_time
);
1801 u
.info21
.fields_present
= SAMR_FIELD_WORKSTATIONS
| SAMR_FIELD_LOGON_HOURS
;
1802 u
.info21
.workstations
.string
= TEST_MACHINE_NAME
;
1803 u
.info21
.logon_hours
.units_per_week
= 168;
1804 u
.info21
.logon_hours
.bits
= talloc_zero_array(mem_ctx
, uint8_t, 168);
1806 tmp_p
= torture_join_samr_pipe(user_ctx_wrong_time
);
1807 status
= dcerpc_samr_SetUserInfo_r(tmp_p
->binding_handle
, mem_ctx
, &s
);
1808 torture_assert_ntstatus_ok_goto(torture
, status
, ret
, failed
,
1809 talloc_asprintf(torture
, "SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status
)));
1810 torture_assert_ntstatus_ok_goto(torture
, s
.out
.result
, ret
, failed
,
1811 talloc_asprintf(torture
, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s
.out
.result
)));
1814 torture_assert_ntstatus_ok_goto(torture
,
1815 torture_rpc_binding(torture
, &b
),
1818 "Obtaining binding");
1820 /* We have to use schannel, otherwise the SamLogonEx fails
1821 * with INTERNAL_ERROR */
1823 status
= dcerpc_binding_set_flags(b
,
1825 DCERPC_SIGN
| DCERPC_SEAL
|
1826 DCERPC_SCHANNEL_128
,
1827 DCERPC_AUTH_OPTIONS
);
1828 torture_assert_ntstatus_ok(torture
, status
, "set flags");
1830 status
= dcerpc_pipe_connect_b(mem_ctx
, &p
, b
,
1831 &ndr_table_netlogon
,
1832 machine_credentials
, torture
->ev
, torture
->lp_ctx
);
1834 torture_assert_ntstatus_ok_goto(torture
, status
, ret
, failed
,
1835 talloc_asprintf(torture
, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status
)));
1837 torture_assert_not_null_goto(torture
,
1838 creds
= cli_credentials_get_netlogon_creds(machine_credentials
),
1841 "obtaining credentails");
1846 const char *comment
;
1848 const char *username
;
1849 const char *password
;
1851 NTSTATUS expected_interactive_error
;
1852 NTSTATUS expected_network_error
;
1853 uint32_t parameter_control
;
1854 bool old_password
; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
1857 .comment
= "domain\\user",
1858 .domain
= cli_credentials_get_domain(
1859 samba_cmdline_get_creds()),
1860 .username
= cli_credentials_get_username(
1861 samba_cmdline_get_creds()),
1862 .password
= cli_credentials_get_password(
1863 samba_cmdline_get_creds()),
1864 .network_login
= true,
1865 .expected_interactive_error
= NT_STATUS_OK
,
1866 .expected_network_error
= NT_STATUS_OK
,
1867 .parameter_control
= 0,
1870 .comment
= "realm\\user",
1871 .domain
= cli_credentials_get_realm(
1872 samba_cmdline_get_creds()),
1873 .username
= cli_credentials_get_username(
1874 samba_cmdline_get_creds()),
1875 .password
= cli_credentials_get_password(
1876 samba_cmdline_get_creds()),
1877 .network_login
= true,
1878 .expected_interactive_error
= NT_STATUS_OK
,
1879 .expected_network_error
= NT_STATUS_OK
,
1880 .parameter_control
= 0,
1883 .comment
= "user@domain",
1885 .username
= talloc_asprintf(mem_ctx
,
1887 cli_credentials_get_username(
1888 samba_cmdline_get_creds()),
1889 cli_credentials_get_domain(
1890 samba_cmdline_get_creds())
1892 .password
= cli_credentials_get_password(
1893 samba_cmdline_get_creds()),
1894 .network_login
= false, /* works for some things, but not NTLMv2. Odd */
1895 .expected_interactive_error
= NT_STATUS_OK
,
1896 .expected_network_error
= NT_STATUS_OK
,
1897 .parameter_control
= 0,
1900 .comment
= "user@realm",
1902 .username
= talloc_asprintf(mem_ctx
,
1904 cli_credentials_get_username(
1905 samba_cmdline_get_creds()),
1906 cli_credentials_get_realm(
1907 samba_cmdline_get_creds())
1909 .password
= cli_credentials_get_password(
1910 samba_cmdline_get_creds()),
1911 .network_login
= true,
1912 .expected_interactive_error
= NT_STATUS_OK
,
1913 .expected_network_error
= NT_STATUS_OK
,
1914 .parameter_control
= 0,
1917 .comment
= "machine domain\\user",
1918 .domain
= cli_credentials_get_domain(machine_credentials
),
1919 .username
= cli_credentials_get_username(machine_credentials
),
1920 .password
= cli_credentials_get_password(machine_credentials
),
1921 .network_login
= true,
1922 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1923 .parameter_control
= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1926 .comment
= "machine domain\\user",
1927 .domain
= cli_credentials_get_domain(machine_credentials
),
1928 .username
= cli_credentials_get_username(machine_credentials
),
1929 .password
= cli_credentials_get_password(machine_credentials
),
1930 .network_login
= true,
1931 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1932 .expected_network_error
= NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
,
1933 .parameter_control
= 0,
1936 .comment
= "machine realm\\user",
1937 .domain
= cli_credentials_get_realm(machine_credentials
),
1938 .username
= cli_credentials_get_username(machine_credentials
),
1939 .password
= cli_credentials_get_password(machine_credentials
),
1940 .network_login
= true,
1941 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1942 .parameter_control
= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1945 .comment
= "machine user@domain",
1947 .username
= talloc_asprintf(mem_ctx
,
1949 cli_credentials_get_username(machine_credentials
),
1950 cli_credentials_get_domain(machine_credentials
)
1952 .password
= cli_credentials_get_password(machine_credentials
),
1953 .network_login
= false, /* works for some things, but not NTLMv2. Odd */
1954 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1955 .parameter_control
= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1958 .comment
= "machine user@realm",
1960 .username
= talloc_asprintf(mem_ctx
,
1962 cli_credentials_get_username(machine_credentials
),
1963 cli_credentials_get_realm(machine_credentials
)
1965 .password
= cli_credentials_get_password(machine_credentials
),
1966 .network_login
= true,
1967 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1968 .parameter_control
= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1971 .comment
= "test user (long pw): domain\\user",
1972 .domain
= userdomain
,
1973 .username
= TEST_USER_NAME
,
1974 .password
= user_password
,
1975 .network_login
= true,
1976 .expected_interactive_error
= NT_STATUS_OK
,
1977 .expected_network_error
= NT_STATUS_OK
,
1978 .parameter_control
= 0,
1981 .comment
= "test user (long pw): user@realm",
1983 .username
= talloc_asprintf(mem_ctx
,
1986 lpcfg_realm(torture
->lp_ctx
)),
1987 .password
= user_password
,
1988 .network_login
= true,
1989 .expected_interactive_error
= NT_STATUS_OK
,
1990 .expected_network_error
= NT_STATUS_OK
,
1991 .parameter_control
= 0,
1994 .comment
= "test user (long pw): user@domain",
1996 .username
= talloc_asprintf(mem_ctx
,
2000 .password
= user_password
,
2001 .network_login
= false, /* works for some things, but not NTLMv2. Odd */
2002 .expected_interactive_error
= NT_STATUS_OK
,
2003 .expected_network_error
= NT_STATUS_OK
,
2004 .parameter_control
= 0,
2006 /* Oddball, can we use the old password ? */
2008 .comment
= "test user: user\\domain OLD PASSWORD",
2009 .domain
= userdomain
,
2010 .username
= TEST_USER_NAME
,
2011 .password
= old_user_password
,
2012 .network_login
= true,
2013 .expected_interactive_error
= NT_STATUS_WRONG_PASSWORD
,
2014 .expected_network_error
= NT_STATUS_OK
,
2015 .old_password
= true
2018 .comment
= "test user (wrong workstation): domain\\user",
2019 .domain
= userdomain
,
2020 .username
= TEST_USER_NAME_WRONG_WKS
,
2021 .password
= user_password_wrong_wks
,
2022 .network_login
= true,
2023 .expected_interactive_error
= NT_STATUS_INVALID_WORKSTATION
,
2024 .expected_network_error
= NT_STATUS_INVALID_WORKSTATION
,
2025 .parameter_control
= 0,
2029 /* Try all the tests for different username forms */
2030 for (ci
= 0; ci
< ARRAY_SIZE(usercreds
); ci
++) {
2032 torture_assert_goto(torture
,
2033 test_InteractiveLogon(p
, mem_ctx
, torture
, creds
,
2034 usercreds
[ci
].comment
,
2036 usercreds
[ci
].domain
,
2037 usercreds
[ci
].username
,
2038 usercreds
[ci
].password
,
2039 usercreds
[ci
].parameter_control
,
2040 usercreds
[ci
].expected_interactive_error
),
2043 talloc_asprintf(mem_ctx
, "InteractiveLogon: %s",
2044 usercreds
[ci
].comment
));
2046 if (usercreds
[ci
].network_login
) {
2047 torture_assert_goto(torture
,
2048 test_SamLogon(p
, mem_ctx
, torture
, creds
,
2049 usercreds
[ci
].comment
,
2050 usercreds
[ci
].domain
,
2051 usercreds
[ci
].username
,
2052 usercreds
[ci
].password
,
2053 usercreds
[ci
].parameter_control
,
2054 usercreds
[ci
].expected_network_error
,
2055 usercreds
[ci
].old_password
,
2059 talloc_asprintf(mem_ctx
, "SamLogon: %s",
2060 usercreds
[ci
].comment
));
2064 /* Using the first username form, try the different
2065 * credentials flag setups, on only one of the tests (checks
2066 * session key encryption) */
2068 for (i
=0; i
< ARRAY_SIZE(credential_flags
); i
++) {
2069 /* TODO: Somehow we lost setting up the different credential flags here! */
2071 torture_comment(torture
,
2072 "Testing with flags: 0x%08x\n",
2073 credential_flags
[i
]);
2075 torture_assert_goto(torture
,
2076 test_InteractiveLogon(p
, mem_ctx
, torture
, creds
,
2077 usercreds
[0].comment
,
2079 usercreds
[0].domain
,
2080 usercreds
[0].username
,
2081 usercreds
[0].password
,
2082 usercreds
[0].parameter_control
,
2083 usercreds
[0].expected_interactive_error
),
2086 talloc_asprintf(mem_ctx
,
2087 "Testing InteractiveLogon with flags: 0x%08x\n",
2088 credential_flags
[i
]));
2090 if (usercreds
[0].network_login
) {
2091 torture_assert_goto(torture
,
2092 test_SamLogon(p
, mem_ctx
, torture
, creds
,
2093 usercreds
[0].comment
,
2094 usercreds
[0].domain
,
2095 usercreds
[0].username
,
2096 usercreds
[0].password
,
2097 usercreds
[0].parameter_control
,
2098 usercreds
[0].expected_network_error
,
2099 usercreds
[0].old_password
,
2103 talloc_asprintf(mem_ctx
,
2104 "Testing SamLogon with flags: 0x%08x\n",
2105 credential_flags
[i
]));
2111 torture_assert(torture
, handle_minPwdAge(torture
, mem_ctx
, false),
2112 "handle_minPwdAge error!");
2114 talloc_free(mem_ctx
);
2116 torture_leave_domain(torture
, join_ctx
);
2117 torture_leave_domain(torture
, user_ctx
);
2118 torture_leave_domain(torture
, user_ctx_wrong_wks
);
2119 torture_leave_domain(torture
, user_ctx_wrong_time
);