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;
94 enum dcerpc_AuthType auth_type
;
95 enum dcerpc_AuthLevel auth_level
;
97 dcerpc_binding_handle_auth_info(samlogon_state
->p
->binding_handle
,
101 samlogon_state
->r
.in
.logon
->network
= &ninfo
;
102 samlogon_state
->r_ex
.in
.logon
->network
= &ninfo
;
103 samlogon_state
->r_flags
.in
.logon
->network
= &ninfo
;
105 ninfo
.identity_info
.domain_name
.string
= samlogon_state
->account_domain
;
106 ninfo
.identity_info
.parameter_control
= parameter_control
;
107 ninfo
.identity_info
.logon_id
= 0;
108 ninfo
.identity_info
.account_name
.string
= samlogon_state
->account_name
;
109 ninfo
.identity_info
.workstation
.string
= TEST_MACHINE_NAME
;
111 memcpy(ninfo
.challenge
, chall
->data
, 8);
113 switch (break_which
) {
117 if (lm_response
&& lm_response
->data
) {
118 lm_response
->data
[0]++;
122 if (nt_response
&& nt_response
->data
) {
123 nt_response
->data
[0]++;
127 if (lm_response
&& lm_response
->data
) {
128 lm_response
->data
[0]++;
130 if (nt_response
&& nt_response
->data
) {
131 nt_response
->data
[0]++;
135 data_blob_free(lm_response
);
138 data_blob_free(nt_response
);
143 ninfo
.nt
.data
= nt_response
->data
;
144 ninfo
.nt
.length
= nt_response
->length
;
146 ninfo
.nt
.data
= NULL
;
151 ninfo
.lm
.data
= lm_response
->data
;
152 ninfo
.lm
.length
= lm_response
->length
;
154 ninfo
.lm
.data
= NULL
;
158 switch (samlogon_state
->function_level
) {
159 case NDR_NETR_LOGONSAMLOGON
:
160 ZERO_STRUCT(samlogon_state
->auth2
);
161 netlogon_creds_client_authenticator(samlogon_state
->creds
, &samlogon_state
->auth
);
163 r
->out
.return_authenticator
= NULL
;
164 status
= dcerpc_netr_LogonSamLogon_r(samlogon_state
->p
->binding_handle
,
165 samlogon_state
->mem_ctx
, r
);
166 if (!NT_STATUS_IS_OK(status
)) {
168 *error_string
= strdup(nt_errstr(status
));
172 if (r
->out
.return_authenticator
== NULL
) {
173 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
175 *error_string
= strdup(nt_errstr(status
));
179 status
= netlogon_creds_client_verify(samlogon_state
->creds
,
180 &r
->out
.return_authenticator
->cred
,
183 if (!NT_STATUS_IS_OK(status
)) {
185 *error_string
= strdup(nt_errstr(status
));
189 if (!NT_STATUS_IS_OK(r
->out
.result
)) {
191 *error_string
= strdup(nt_errstr(r
->out
.result
));
193 return r
->out
.result
;
196 validation_level
= r
->in
.validation_level
;
198 status
= netlogon_creds_decrypt_samlogon_validation(samlogon_state
->creds
,
203 if (!NT_STATUS_IS_OK(status
)) {
205 *error_string
= strdup(nt_errstr(status
));
210 switch (validation_level
) {
212 base
= &r
->out
.validation
->sam2
->base
;
215 base
= &r
->out
.validation
->sam3
->base
;
218 base
= &r
->out
.validation
->sam6
->base
;
222 case NDR_NETR_LOGONSAMLOGONEX
:
223 status
= dcerpc_netr_LogonSamLogonEx_r(samlogon_state
->p
->binding_handle
,
224 samlogon_state
->mem_ctx
, r_ex
);
225 if (!NT_STATUS_IS_OK(status
)) {
227 *error_string
= strdup(nt_errstr(status
));
231 if (!NT_STATUS_IS_OK(r_ex
->out
.result
)) {
233 *error_string
= strdup(nt_errstr(r_ex
->out
.result
));
235 return r_ex
->out
.result
;
238 validation_level
= r_ex
->in
.validation_level
;
240 status
= netlogon_creds_decrypt_samlogon_validation(samlogon_state
->creds
,
242 r_ex
->out
.validation
,
245 if (!NT_STATUS_IS_OK(status
)) {
247 *error_string
= strdup(nt_errstr(status
));
252 switch (validation_level
) {
254 base
= &r_ex
->out
.validation
->sam2
->base
;
257 base
= &r_ex
->out
.validation
->sam3
->base
;
260 base
= &r_ex
->out
.validation
->sam6
->base
;
264 case NDR_NETR_LOGONSAMLOGONWITHFLAGS
:
265 ZERO_STRUCT(samlogon_state
->auth2
);
266 netlogon_creds_client_authenticator(samlogon_state
->creds
, &samlogon_state
->auth
);
268 r_flags
->out
.return_authenticator
= NULL
;
269 status
= dcerpc_netr_LogonSamLogonWithFlags_r(samlogon_state
->p
->binding_handle
,
270 samlogon_state
->mem_ctx
, r_flags
);
271 if (!NT_STATUS_IS_OK(status
)) {
273 *error_string
= strdup(nt_errstr(status
));
277 if (r_flags
->out
.return_authenticator
== NULL
) {
278 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
280 *error_string
= strdup(nt_errstr(status
));
284 status
= netlogon_creds_client_verify(samlogon_state
->creds
,
285 &r_flags
->out
.return_authenticator
->cred
,
288 if (!NT_STATUS_IS_OK(status
)) {
290 *error_string
= strdup(nt_errstr(status
));
294 if (!NT_STATUS_IS_OK(r_flags
->out
.result
)) {
296 *error_string
= strdup(nt_errstr(r_flags
->out
.result
));
298 return r_flags
->out
.result
;
301 validation_level
= r_flags
->in
.validation_level
;
303 status
= netlogon_creds_decrypt_samlogon_validation(samlogon_state
->creds
,
305 r_flags
->out
.validation
,
308 if (!NT_STATUS_IS_OK(status
)) {
310 *error_string
= strdup(nt_errstr(status
));
315 switch (validation_level
) {
317 base
= &r_flags
->out
.validation
->sam2
->base
;
320 base
= &r_flags
->out
.validation
->sam3
->base
;
323 base
= &r_flags
->out
.validation
->sam6
->base
;
329 return NT_STATUS_INVALID_PARAMETER
;
333 torture_comment(samlogon_state
->tctx
, "No user info returned from 'successful' SamLogon*() call!\n");
334 return NT_STATUS_INVALID_PARAMETER
;
337 if (user_session_key
) {
338 memcpy(user_session_key
, base
->key
.key
, 16);
341 memcpy(lm_key
, base
->LMSessKey
.key
, 8);
349 * Test the normal 'LM and NTLM' combination
352 static bool test_lm_ntlm_broken(struct samlogon_state
*samlogon_state
, enum ntlm_break break_which
, char **error_string
)
357 DATA_BLOB lm_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
358 DATA_BLOB nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
359 DATA_BLOB session_key
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 16);
362 uint8_t user_session_key
[16];
367 ZERO_STRUCT(user_session_key
);
369 lm_good
= SMBencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
, lm_response
.data
);
371 ZERO_STRUCT(lm_hash
);
373 E_deshash(samlogon_state
->password
, lm_hash
);
376 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
, nt_response
.data
);
378 E_md4hash(samlogon_state
->password
, nt_hash
);
379 SMBsesskeygen_ntv1(nt_hash
, session_key
.data
);
381 nt_status
= check_samlogon(samlogon_state
,
383 samlogon_state
->parameter_control
,
384 &samlogon_state
->chall
,
391 data_blob_free(&lm_response
);
393 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
394 /* for 'long' passwords, the LM password is invalid */
395 if (break_which
== NO_NT
&& !lm_good
) {
398 /* for modern servers, the LM password is invalid */
399 if (break_which
== NO_NT
400 && !torture_setting_bool(samlogon_state
->tctx
, "samba3", false)) {
404 /* for 'old' passwords, we allow the server to be OK or wrong password */
405 if (samlogon_state
->old_password
) {
408 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
));
409 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND
, nt_status
) && strchr_m(samlogon_state
->account_name
, '@')) {
410 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
) || (break_which
== NO_NT
));
411 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
414 SAFE_FREE(*error_string
);
415 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
417 *error_string
= NULL
;
420 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
422 } else if (!NT_STATUS_IS_OK(nt_status
)) {
426 if (break_which
== NO_NT
&& !lm_good
) {
427 *error_string
= strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
431 /* for modern servers, the LM password is invalid */
432 if (break_which
== NO_NT
433 && !torture_setting_bool(samlogon_state
->tctx
, "samba3", false)) {
434 *error_string
= strdup("LM password is OK but should have failed against a modern server");
438 if (!all_zero(lm_key
, sizeof(lm_key
)) != 0) {
439 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations!\n");
440 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
441 dump_data(1, lm_key
, 8);
442 torture_comment(samlogon_state
->tctx
, "expected (all zeros):\n");
446 switch (break_which
) {
449 uint8_t lm_key_expected
[16];
450 memcpy(lm_key_expected
, session_key
.data
, 8);
451 memset(lm_key_expected
+8, '\0', 8);
452 if (memcmp(lm_key_expected
, user_session_key
,
454 *error_string
= strdup("NT Session Key does not match expectations (should be first-8 session key)!\n");
455 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
456 dump_data(1, user_session_key
, sizeof(user_session_key
));
457 torture_comment(samlogon_state
->tctx
, "expected:\n");
458 dump_data(1, lm_key_expected
, sizeof(lm_key_expected
));
464 if (memcmp(session_key
.data
, user_session_key
,
465 sizeof(user_session_key
)) != 0) {
466 *error_string
= strdup("NT Session Key does not match expectations!\n");
467 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
468 dump_data(1, user_session_key
, 16);
469 torture_comment(samlogon_state
->tctx
, "expected:\n");
470 dump_data(1, session_key
.data
, session_key
.length
);
478 * Test LM authentication, no NT response supplied
481 static bool test_lm(struct samlogon_state
*samlogon_state
, char **error_string
)
484 return test_lm_ntlm_broken(samlogon_state
, NO_NT
, error_string
);
488 * Test the NTLM response only, no LM.
491 static bool test_ntlm(struct samlogon_state
*samlogon_state
, char **error_string
)
493 return test_lm_ntlm_broken(samlogon_state
, NO_LM
, error_string
);
497 * Test the NTLM response only, but in the LM field.
500 static bool test_ntlm_in_lm(struct samlogon_state
*samlogon_state
, char **error_string
)
505 DATA_BLOB nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
506 DATA_BLOB session_key
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 16);
510 uint8_t user_session_key
[16];
514 ZERO_STRUCT(user_session_key
);
516 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
,
518 E_md4hash(samlogon_state
->password
, nt_hash
);
519 SMBsesskeygen_ntv1(nt_hash
,
522 lm_good
= E_deshash(samlogon_state
->password
, lm_hash
);
524 ZERO_STRUCT(lm_hash
);
526 nt_status
= check_samlogon(samlogon_state
,
528 samlogon_state
->parameter_control
,
529 &samlogon_state
->chall
,
536 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
537 /* for 'old' passwords, we allow the server to be OK or wrong password */
538 if (samlogon_state
->old_password
) {
542 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
545 SAFE_FREE(*error_string
);
546 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
548 *error_string
= NULL
;
551 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
553 } else if (!NT_STATUS_IS_OK(nt_status
)) {
557 if (torture_setting_bool(samlogon_state
->tctx
, "samba4", false)) {
558 if (!all_zero(lm_key
, sizeof(lm_key
)) != 0) {
559 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations!\n");
560 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
561 dump_data(1, lm_key
, 8);
562 torture_comment(samlogon_state
->tctx
, "expected (all zeros):\n");
567 if (!all_zero(user_session_key
, sizeof(user_session_key
)) != 0) {
568 torture_comment(samlogon_state
->tctx
, "NT Key does not match expectations!\n");
569 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
570 dump_data(1, user_session_key
, sizeof(user_session_key
));
571 torture_comment(samlogon_state
->tctx
, "expected (all zeros):\n");
576 if (memcmp(lm_hash
, lm_key
,
577 sizeof(lm_key
)) != 0) {
578 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations!\n");
579 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
580 dump_data(1, lm_key
, 8);
581 torture_comment(samlogon_state
->tctx
, "expected:\n");
582 dump_data(1, lm_hash
, 8);
587 if (memcmp(session_key
.data
, lm_key
,
588 sizeof(lm_key
)) != 0) {
589 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations (first 8 session key)!\n");
590 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
591 dump_data(1, lm_key
, 8);
592 torture_comment(samlogon_state
->tctx
, "expected:\n");
593 dump_data(1, session_key
.data
, 8);
598 if (lm_good
&& memcmp(lm_hash
, user_session_key
, 8) != 0) {
599 uint8_t lm_key_expected
[16];
600 memcpy(lm_key_expected
, lm_hash
, 8);
601 memset(lm_key_expected
+8, '\0', 8);
602 if (memcmp(lm_key_expected
, user_session_key
,
604 torture_comment(samlogon_state
->tctx
, "NT Session Key does not match expectations (should be first-8 LM hash)!\n");
605 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
606 dump_data(1, user_session_key
, sizeof(user_session_key
));
607 torture_comment(samlogon_state
->tctx
, "expected:\n");
608 dump_data(1, lm_key_expected
, sizeof(lm_key_expected
));
617 * Test the NTLM response only, but in the both the NT and LM fields.
620 static bool test_ntlm_in_both(struct samlogon_state
*samlogon_state
, char **error_string
)
625 DATA_BLOB nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
626 DATA_BLOB session_key
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 16);
630 uint8_t user_session_key
[16];
634 ZERO_STRUCT(user_session_key
);
636 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
,
638 E_md4hash(samlogon_state
->password
, nt_hash
);
639 SMBsesskeygen_ntv1(nt_hash
,
642 lm_good
= E_deshash(samlogon_state
->password
, lm_hash
);
644 ZERO_STRUCT(lm_hash
);
647 nt_status
= check_samlogon(samlogon_state
,
649 samlogon_state
->parameter_control
,
650 &samlogon_state
->chall
,
657 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
658 /* for 'old' passwords, we allow the server to be OK or wrong password */
659 if (samlogon_state
->old_password
) {
663 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
666 SAFE_FREE(*error_string
);
667 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
669 *error_string
= NULL
;
672 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
674 } else if (!NT_STATUS_IS_OK(nt_status
)) {
678 if (!NT_STATUS_IS_OK(nt_status
)) {
682 if (!all_zero(lm_key
,
683 sizeof(lm_key
)) != 0) {
684 torture_comment(samlogon_state
->tctx
, "LM Key does not match expectations!\n");
685 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
686 dump_data(1, lm_key
, 8);
687 torture_comment(samlogon_state
->tctx
, "expected (all zero)\n");
690 if (memcmp(session_key
.data
, user_session_key
,
691 sizeof(user_session_key
)) != 0) {
692 torture_comment(samlogon_state
->tctx
, "NT Session Key does not match expectations!\n");
693 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
694 dump_data(1, user_session_key
, 16);
695 torture_comment(samlogon_state
->tctx
, "expected:\n");
696 dump_data(1, session_key
.data
, session_key
.length
);
705 * Test the NTLMv2 and LMv2 responses
713 static bool test_lmv2_ntlmv2_broken(struct samlogon_state
*samlogon_state
,
714 enum ntlm_break break_which
,
715 enum ntlmv2_domain ntlmv2_domain
,
720 DATA_BLOB ntlmv2_response
= data_blob(NULL
, 0);
721 DATA_BLOB lmv2_response
= data_blob(NULL
, 0);
722 DATA_BLOB lmv2_session_key
= data_blob(NULL
, 0);
723 DATA_BLOB ntlmv2_session_key
= data_blob(NULL
, 0);
724 DATA_BLOB names_blob
= NTLMv2_generate_names_blob(samlogon_state
->mem_ctx
, TEST_MACHINE_NAME
, samlogon_state
->workgroup
);
726 uint8_t lm_session_key
[8];
727 uint8_t user_session_key
[16];
729 ZERO_STRUCT(lm_session_key
);
730 ZERO_STRUCT(user_session_key
);
732 switch (ntlmv2_domain
) {
734 if (!SMBNTLMv2encrypt(samlogon_state
->mem_ctx
,
735 samlogon_state
->account_name
, samlogon_state
->account_domain
,
736 samlogon_state
->password
, &samlogon_state
->chall
,
738 &lmv2_response
, &ntlmv2_response
,
739 &lmv2_session_key
, &ntlmv2_session_key
)) {
740 data_blob_free(&names_blob
);
745 if (!SMBNTLMv2encrypt(samlogon_state
->mem_ctx
,
746 samlogon_state
->account_name
, "",
747 samlogon_state
->password
, &samlogon_state
->chall
,
749 &lmv2_response
, &ntlmv2_response
,
750 &lmv2_session_key
, &ntlmv2_session_key
)) {
751 data_blob_free(&names_blob
);
756 data_blob_free(&names_blob
);
758 nt_status
= check_samlogon(samlogon_state
,
760 samlogon_state
->parameter_control
,
761 &samlogon_state
->chall
,
768 data_blob_free(&lmv2_response
);
769 data_blob_free(&ntlmv2_response
);
772 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
773 /* for 'old' passwords, we allow the server to be OK or wrong password */
774 if (samlogon_state
->old_password
) {
777 return break_which
== BREAK_BOTH
;
778 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND
, nt_status
) && strchr_m(samlogon_state
->account_name
, '@')) {
779 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
) || (break_which
== NO_NT
));
780 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
783 SAFE_FREE(*error_string
);
784 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
786 *error_string
= NULL
;
789 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
791 } else if (!NT_STATUS_IS_OK(nt_status
)) {
796 switch (break_which
) {
798 if (memcmp(lmv2_session_key
.data
, user_session_key
,
799 sizeof(user_session_key
)) != 0) {
800 torture_comment(samlogon_state
->tctx
, "USER (LMv2) Session Key does not match expectations!\n");
801 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
802 dump_data(1, user_session_key
, 16);
803 torture_comment(samlogon_state
->tctx
, "expected:\n");
804 dump_data(1, lmv2_session_key
.data
, ntlmv2_session_key
.length
);
807 if (memcmp(lmv2_session_key
.data
, lm_session_key
,
808 sizeof(lm_session_key
)) != 0) {
809 torture_comment(samlogon_state
->tctx
, "LM (LMv2) Session Key does not match expectations!\n");
810 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
811 dump_data(1, lm_session_key
, 8);
812 torture_comment(samlogon_state
->tctx
, "expected:\n");
813 dump_data(1, lmv2_session_key
.data
, 8);
818 if (memcmp(ntlmv2_session_key
.data
, user_session_key
,
819 sizeof(user_session_key
)) != 0) {
820 if (memcmp(lmv2_session_key
.data
, user_session_key
,
821 sizeof(user_session_key
)) == 0) {
822 torture_comment(samlogon_state
->tctx
, "USER (NTLMv2) Session Key expected, got LMv2 session key instead:\n");
823 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
824 dump_data(1, user_session_key
, 16);
825 torture_comment(samlogon_state
->tctx
, "expected:\n");
826 dump_data(1, ntlmv2_session_key
.data
, ntlmv2_session_key
.length
);
830 torture_comment(samlogon_state
->tctx
, "USER (NTLMv2) Session Key does not match expectations!\n");
831 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
832 dump_data(1, user_session_key
, 16);
833 torture_comment(samlogon_state
->tctx
, "expected:\n");
834 dump_data(1, ntlmv2_session_key
.data
, ntlmv2_session_key
.length
);
838 if (memcmp(ntlmv2_session_key
.data
, lm_session_key
,
839 sizeof(lm_session_key
)) != 0) {
840 if (memcmp(lmv2_session_key
.data
, lm_session_key
,
841 sizeof(lm_session_key
)) == 0) {
842 torture_comment(samlogon_state
->tctx
, "LM (NTLMv2) Session Key expected, got LMv2 session key instead:\n");
843 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
844 dump_data(1, lm_session_key
, 8);
845 torture_comment(samlogon_state
->tctx
, "expected:\n");
846 dump_data(1, ntlmv2_session_key
.data
, 8);
849 torture_comment(samlogon_state
->tctx
, "LM (NTLMv2) Session Key does not match expectations!\n");
850 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
851 dump_data(1, lm_session_key
, 8);
852 torture_comment(samlogon_state
->tctx
, "expected:\n");
853 dump_data(1, ntlmv2_session_key
.data
, 8);
863 * Test the NTLM and LMv2 responses
866 static bool test_lmv2_ntlm_broken(struct samlogon_state
*samlogon_state
,
867 enum ntlm_break break_which
,
868 enum ntlmv2_domain ntlmv2_domain
,
873 DATA_BLOB ntlmv2_response
= data_blob(NULL
, 0);
874 DATA_BLOB lmv2_response
= data_blob(NULL
, 0);
875 DATA_BLOB lmv2_session_key
= data_blob(NULL
, 0);
876 DATA_BLOB ntlmv2_session_key
= data_blob(NULL
, 0);
877 DATA_BLOB names_blob
= NTLMv2_generate_names_blob(samlogon_state
->mem_ctx
, samlogon_state
->netbios_name
, samlogon_state
->workgroup
);
879 DATA_BLOB ntlm_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
880 DATA_BLOB ntlm_session_key
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 16);
884 uint8_t lm_session_key
[8];
885 uint8_t user_session_key
[16];
888 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
,
890 E_md4hash(samlogon_state
->password
, nt_hash
);
891 SMBsesskeygen_ntv1(nt_hash
,
892 ntlm_session_key
.data
);
894 lm_good
= E_deshash(samlogon_state
->password
, lm_hash
);
896 ZERO_STRUCT(lm_hash
);
899 ZERO_STRUCT(lm_session_key
);
900 ZERO_STRUCT(user_session_key
);
902 switch (ntlmv2_domain
) {
904 /* TODO - test with various domain cases, and without domain */
905 if (!SMBNTLMv2encrypt(samlogon_state
->mem_ctx
,
906 samlogon_state
->account_name
, samlogon_state
->account_domain
,
907 samlogon_state
->password
, &samlogon_state
->chall
,
909 &lmv2_response
, &ntlmv2_response
,
910 &lmv2_session_key
, &ntlmv2_session_key
)) {
911 data_blob_free(&names_blob
);
916 /* TODO - test with various domain cases, and without domain */
917 if (!SMBNTLMv2encrypt(samlogon_state
->mem_ctx
,
918 samlogon_state
->account_name
, "",
919 samlogon_state
->password
, &samlogon_state
->chall
,
921 &lmv2_response
, &ntlmv2_response
,
922 &lmv2_session_key
, &ntlmv2_session_key
)) {
923 data_blob_free(&names_blob
);
929 data_blob_free(&names_blob
);
931 nt_status
= check_samlogon(samlogon_state
,
933 samlogon_state
->parameter_control
,
934 &samlogon_state
->chall
,
941 data_blob_free(&lmv2_response
);
942 data_blob_free(&ntlmv2_response
);
945 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
946 /* for 'old' passwords, we allow the server to be OK or wrong password */
947 if (samlogon_state
->old_password
) {
950 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
));
951 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND
, nt_status
) && strchr_m(samlogon_state
->account_name
, '@')) {
952 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
));
953 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
956 SAFE_FREE(*error_string
);
957 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
959 *error_string
= NULL
;
962 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
964 } else if (!NT_STATUS_IS_OK(nt_status
)) {
968 switch (break_which
) {
970 if (memcmp(lmv2_session_key
.data
, user_session_key
,
971 sizeof(user_session_key
)) != 0) {
972 torture_comment(samlogon_state
->tctx
, "USER (LMv2) 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, lmv2_session_key
.data
, ntlmv2_session_key
.length
);
979 if (memcmp(lmv2_session_key
.data
, lm_session_key
,
980 sizeof(lm_session_key
)) != 0) {
981 torture_comment(samlogon_state
->tctx
, "LM (LMv2) 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, lmv2_session_key
.data
, 8);
990 if (memcmp(ntlm_session_key
.data
, user_session_key
,
991 sizeof(user_session_key
)) != 0) {
992 torture_comment(samlogon_state
->tctx
, "USER (NTLMv2) Session Key does not match expectations!\n");
993 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
994 dump_data(1, user_session_key
, 16);
995 torture_comment(samlogon_state
->tctx
, "expected:\n");
996 dump_data(1, ntlm_session_key
.data
, ntlm_session_key
.length
);
999 if (!all_zero(lm_session_key
,
1000 sizeof(lm_session_key
))) {
1001 torture_comment(samlogon_state
->tctx
, "LM Session Key does not match expectations (zeros)!\n");
1002 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
1003 dump_data(1, lm_session_key
, 8);
1008 if (memcmp(ntlm_session_key
.data
, user_session_key
,
1009 sizeof(user_session_key
)) != 0) {
1010 torture_comment(samlogon_state
->tctx
, "USER (NTLMv2) Session Key does not match expectations!\n");
1011 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
1012 dump_data(1, user_session_key
, 16);
1013 torture_comment(samlogon_state
->tctx
, "expected:\n");
1014 dump_data(1, ntlm_session_key
.data
, ntlm_session_key
.length
);
1017 if (memcmp(ntlm_session_key
.data
, lm_session_key
,
1018 sizeof(lm_session_key
)) != 0) {
1019 torture_comment(samlogon_state
->tctx
, "LM (NTLMv2) Session Key does not match expectations!\n");
1020 torture_comment(samlogon_state
->tctx
, "lm_session_key:\n");
1021 dump_data(1, lm_session_key
, 8);
1022 torture_comment(samlogon_state
->tctx
, "expected:\n");
1023 dump_data(1, ntlm_session_key
.data
, 8);
1032 * Test the NTLMv2 and LMv2 responses
1035 static bool test_lmv2_ntlmv2(struct samlogon_state
*samlogon_state
, char **error_string
)
1037 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_NONE
, UPPER_DOMAIN
, error_string
);
1041 static bool test_lmv2_ntlmv2_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1043 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_NONE
, NO_DOMAIN
, error_string
);
1048 * Test the LMv2 response only
1051 static bool test_lmv2(struct samlogon_state
*samlogon_state
, char **error_string
)
1053 return test_lmv2_ntlmv2_broken(samlogon_state
, NO_NT
, UPPER_DOMAIN
, error_string
);
1056 static bool test_lmv2_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1058 return test_lmv2_ntlmv2_broken(samlogon_state
, NO_NT
, NO_DOMAIN
, error_string
);
1062 * Test the NTLMv2 response only
1065 static bool test_ntlmv2(struct samlogon_state
*samlogon_state
, char **error_string
)
1067 return test_lmv2_ntlmv2_broken(samlogon_state
, NO_LM
, UPPER_DOMAIN
, error_string
);
1070 static bool test_ntlmv2_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1072 return test_lmv2_ntlmv2_broken(samlogon_state
, NO_LM
, NO_DOMAIN
, error_string
);
1075 static bool test_lm_ntlm(struct samlogon_state
*samlogon_state
, char **error_string
)
1077 return test_lm_ntlm_broken(samlogon_state
, BREAK_NONE
, error_string
);
1080 static bool test_ntlm_lm_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1082 return test_lm_ntlm_broken(samlogon_state
, BREAK_LM
, error_string
);
1085 static bool test_ntlm_ntlm_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1087 return test_lm_ntlm_broken(samlogon_state
, BREAK_NT
, error_string
);
1090 static bool test_lm_ntlm_both_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1092 return test_lm_ntlm_broken(samlogon_state
, BREAK_BOTH
, error_string
);
1094 static bool test_ntlmv2_lmv2_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1096 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_LM
, UPPER_DOMAIN
, error_string
);
1099 static bool test_ntlmv2_lmv2_broken_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1101 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_LM
, NO_DOMAIN
, error_string
);
1104 static bool test_ntlmv2_ntlmv2_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1106 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_NT
, UPPER_DOMAIN
, error_string
);
1110 static bool test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1112 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_NT
, NO_DOMAIN
, error_string
);
1116 static bool test_ntlmv2_both_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1118 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_BOTH
, UPPER_DOMAIN
, error_string
);
1121 static bool test_ntlmv2_both_broken_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1123 return test_lmv2_ntlmv2_broken(samlogon_state
, BREAK_BOTH
, NO_DOMAIN
, error_string
);
1126 static bool test_lmv2_ntlm_both_broken(struct samlogon_state
*samlogon_state
, char **error_string
)
1128 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_BOTH
, UPPER_DOMAIN
, error_string
);
1131 static bool test_lmv2_ntlm_both_broken_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1133 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_BOTH
, NO_DOMAIN
, error_string
);
1136 static bool test_lmv2_ntlm_break_ntlm(struct samlogon_state
*samlogon_state
, char **error_string
)
1138 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_NT
, UPPER_DOMAIN
, error_string
);
1141 static bool test_lmv2_ntlm_break_ntlm_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1143 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_NT
, NO_DOMAIN
, error_string
);
1146 static bool test_lmv2_ntlm_break_lm(struct samlogon_state
*samlogon_state
, char **error_string
)
1148 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_LM
, UPPER_DOMAIN
, error_string
);
1151 static bool test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state
*samlogon_state
, char **error_string
)
1153 return test_lmv2_ntlm_broken(samlogon_state
, BREAK_LM
, NO_DOMAIN
, error_string
);
1157 * Test the NTLM2 response (extra challenge in LM field)
1159 * This test is the same as the 'break LM' test, but checks that the
1160 * server implements NTLM2 session security in the right place
1161 * (NETLOGON is the wrong place).
1164 static bool test_ntlm2(struct samlogon_state
*samlogon_state
, char **error_string
)
1168 DATA_BLOB lm_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
1169 DATA_BLOB nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, NULL
, 24);
1172 uint8_t nt_hash
[16];
1173 uint8_t lm_hash
[16];
1175 uint8_t user_session_key
[16];
1176 uint8_t expected_user_session_key
[16];
1177 uint8_t session_nonce_hash
[16];
1178 uint8_t client_chall
[8];
1180 gnutls_hmac_hd_t hmac_hnd
;
1181 gnutls_hash_hd_t hash_hnd
;
1183 ZERO_STRUCT(user_session_key
);
1184 ZERO_STRUCT(lm_key
);
1185 generate_random_buffer(client_chall
, 8);
1187 gnutls_hash_init(&hash_hnd
, GNUTLS_DIG_MD5
);
1188 gnutls_hash(hash_hnd
, samlogon_state
->chall
.data
, 8);
1189 gnutls_hash(hash_hnd
, client_chall
, 8);
1190 gnutls_hash_deinit(hash_hnd
, session_nonce_hash
);
1192 E_md4hash(samlogon_state
->password
, (uint8_t *)nt_hash
);
1193 E_deshash(samlogon_state
->password
, (uint8_t *)lm_hash
);
1194 SMBsesskeygen_ntv1((const uint8_t *)nt_hash
,
1197 SMBNTencrypt(samlogon_state
->password
, samlogon_state
->chall
.data
, nt_response
.data
);
1199 memcpy(lm_response
.data
, session_nonce_hash
, 8);
1200 memset(lm_response
.data
+ 8, 0, 16);
1202 gnutls_hmac_init(&hmac_hnd
,
1206 gnutls_hmac(hmac_hnd
, samlogon_state
->chall
.data
, 8);
1207 gnutls_hmac(hmac_hnd
, client_chall
, 8);
1208 gnutls_hmac_deinit(hmac_hnd
, expected_user_session_key
);
1210 nt_status
= check_samlogon(samlogon_state
,
1212 samlogon_state
->parameter_control
,
1213 &samlogon_state
->chall
,
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
) {
1226 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
1229 SAFE_FREE(*error_string
);
1230 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
1232 *error_string
= NULL
;
1235 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
1237 } else if (!NT_STATUS_IS_OK(nt_status
)) {
1241 if (!all_zero(lm_key
, sizeof(lm_key
))) {
1242 torture_comment(samlogon_state
->tctx
, "LM Session Key does not match expectations (zeros)!\n");
1243 torture_comment(samlogon_state
->tctx
, "lm_key:\n");
1244 dump_data(1, lm_key
, 8);
1247 if (memcmp(nt_key
, user_session_key
, 16) != 0) {
1248 torture_comment(samlogon_state
->tctx
, "NT Session Key does not match expectations (should be NT Key)!\n");
1249 torture_comment(samlogon_state
->tctx
, "user_session_key:\n");
1250 dump_data(1, user_session_key
, sizeof(user_session_key
));
1251 torture_comment(samlogon_state
->tctx
, "expected:\n");
1252 dump_data(1, nt_key
, sizeof(nt_key
));
1258 static bool test_plaintext(struct samlogon_state
*samlogon_state
, enum ntlm_break break_which
, char **error_string
)
1261 DATA_BLOB nt_response
= data_blob(NULL
, 0);
1262 DATA_BLOB lm_response
= data_blob(NULL
, 0);
1265 smb_ucs2_t
*unicodepw
;
1266 size_t converted_size
= 0;
1267 uint8_t user_session_key
[16];
1269 uint8_t lm_hash
[16];
1270 DATA_BLOB chall
= data_blob_talloc_zero(samlogon_state
->mem_ctx
, 8);
1271 bool lm_good
= E_deshash(samlogon_state
->password
, lm_hash
);
1273 ZERO_STRUCT(user_session_key
);
1275 if (!push_ucs2_talloc(samlogon_state
->mem_ctx
,
1276 &unicodepw
, samlogon_state
->password
, &converted_size
)) {
1277 DEBUG(0, ("push_ucs2_allocate failed!\n"));
1281 nt_response
= data_blob_talloc(samlogon_state
->mem_ctx
, unicodepw
, strlen_m(samlogon_state
->password
)*2);
1283 password
= strupper_talloc(samlogon_state
->mem_ctx
, samlogon_state
->password
);
1285 if (!convert_string_talloc(samlogon_state
->mem_ctx
,
1287 password
, strlen(password
)+1,
1288 (void**)&dospw
, &converted_size
)) {
1289 DEBUG(0, ("convert_string_talloc failed!\n"));
1293 lm_response
= data_blob_talloc(samlogon_state
->mem_ctx
, dospw
, strlen(dospw
));
1295 nt_status
= check_samlogon(samlogon_state
,
1297 samlogon_state
->parameter_control
| MSV1_0_CLEARTEXT_PASSWORD_ALLOWED
,
1305 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD
, nt_status
)) {
1306 /* for 'old' passwords, we allow the server to be OK or wrong password */
1307 if (samlogon_state
->old_password
) {
1310 /* for 'long' passwords, the LM password is invalid */
1311 if (break_which
== NO_NT
&& !lm_good
) {
1314 /* for modern servers, the LM password is invalid */
1315 if (break_which
== NO_NT
1316 && !torture_setting_bool(samlogon_state
->tctx
, "samba3", false)) {
1320 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
));
1321 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND
, nt_status
) && strchr_m(samlogon_state
->account_name
, '@')) {
1322 return ((break_which
== BREAK_NT
) || (break_which
== BREAK_BOTH
) || (break_which
== NO_NT
));
1323 } else if (!NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
)) {
1326 SAFE_FREE(*error_string
);
1327 ret
= asprintf(error_string
, "Expected error: %s, got %s", nt_errstr(samlogon_state
->expected_error
), nt_errstr(nt_status
));
1329 *error_string
= NULL
;
1332 } else if (NT_STATUS_EQUAL(samlogon_state
->expected_error
, nt_status
) && !NT_STATUS_IS_OK(nt_status
)) {
1334 } else if (!NT_STATUS_IS_OK(nt_status
)) {
1338 if (break_which
== NO_NT
&& !lm_good
) {
1339 *error_string
= strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
1343 /* for modern servers, the LM password is invalid */
1344 if (break_which
== NO_NT
1345 && !torture_setting_bool(samlogon_state
->tctx
, "samba3", false)) {
1346 *error_string
= strdup("LM password is OK but should have failed against a modern server");
1353 static bool test_plaintext_none_broken(struct samlogon_state
*samlogon_state
,
1354 char **error_string
) {
1355 return test_plaintext(samlogon_state
, BREAK_NONE
, error_string
);
1358 static bool test_plaintext_lm_broken(struct samlogon_state
*samlogon_state
,
1359 char **error_string
) {
1360 return test_plaintext(samlogon_state
, BREAK_LM
, error_string
);
1363 static bool test_plaintext_nt_broken(struct samlogon_state
*samlogon_state
,
1364 char **error_string
) {
1365 return test_plaintext(samlogon_state
, BREAK_NT
, error_string
);
1368 static bool test_plaintext_nt_only(struct samlogon_state
*samlogon_state
,
1369 char **error_string
) {
1370 return test_plaintext(samlogon_state
, NO_LM
, error_string
);
1373 static bool test_plaintext_lm_only(struct samlogon_state
*samlogon_state
,
1374 char **error_string
) {
1375 return test_plaintext(samlogon_state
, NO_NT
, error_string
);
1389 - plaintext tests (in challenge-response fields)
1391 check we get the correct session key in each case
1392 check what values we get for the LM session key
1396 static const struct ntlm_tests
{
1397 bool (*fn
)(struct samlogon_state
*, char **);
1401 {test_lmv2_ntlmv2
, "NTLMv2 and LMv2", false},
1403 {test_lmv2_ntlmv2_no_dom
, "NTLMv2 and LMv2 (no domain)", false},
1405 {test_lm
, "LM", false},
1406 {test_lm_ntlm
, "LM and NTLM", false},
1407 {test_lm_ntlm_both_broken
, "LM and NTLM, both broken", false},
1408 {test_ntlm
, "NTLM", false},
1409 {test_ntlm_in_lm
, "NTLM in LM", false},
1410 {test_ntlm_in_both
, "NTLM in both", false},
1411 {test_ntlmv2
, "NTLMv2", false},
1412 {test_ntlmv2_no_dom
, "NTLMv2 (no domain)", false},
1413 {test_lmv2
, "LMv2", false},
1414 {test_lmv2_no_dom
, "LMv2 (no domain)", false},
1415 {test_ntlmv2_lmv2_broken
, "NTLMv2 and LMv2, LMv2 broken", false},
1416 {test_ntlmv2_lmv2_broken_no_dom
, "NTLMv2 and LMv2, LMv2 broken (no domain)", false},
1417 {test_ntlmv2_ntlmv2_broken
, "NTLMv2 and LMv2, NTLMv2 broken", false},
1419 {test_ntlmv2_ntlmv2_broken_no_dom
, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", false},
1421 {test_ntlmv2_both_broken
, "NTLMv2 and LMv2, both broken", false},
1422 {test_ntlmv2_both_broken_no_dom
, "NTLMv2 and LMv2, both broken (no domain)", false},
1423 {test_ntlm_lm_broken
, "NTLM and LM, LM broken", false},
1424 {test_ntlm_ntlm_broken
, "NTLM and LM, NTLM broken", false},
1425 {test_ntlm2
, "NTLM2 (NTLMv2 session security)", false},
1426 {test_lmv2_ntlm_both_broken
, "LMv2 and NTLM, both broken", false},
1427 {test_lmv2_ntlm_both_broken_no_dom
, "LMv2 and NTLM, both broken (no domain)", false},
1428 {test_lmv2_ntlm_break_ntlm
, "LMv2 and NTLM, NTLM broken", false},
1429 {test_lmv2_ntlm_break_ntlm_no_dom
, "LMv2 and NTLM, NTLM broken (no domain)", false},
1430 {test_lmv2_ntlm_break_lm
, "LMv2 and NTLM, LMv2 broken", false},
1431 {test_lmv2_ntlm_break_lm_no_dom
, "LMv2 and NTLM, LMv2 broken (no domain)", false},
1432 {test_plaintext_none_broken
, "Plaintext", false},
1433 {test_plaintext_lm_broken
, "Plaintext LM broken", false},
1434 {test_plaintext_nt_broken
, "Plaintext NT broken", false},
1435 {test_plaintext_nt_only
, "Plaintext NT only", false},
1436 {test_plaintext_lm_only
, "Plaintext LM only", false},
1441 try a netlogon SamLogon
1443 static bool test_SamLogon(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
1444 struct torture_context
*tctx
,
1445 struct netlogon_creds_CredentialState
*creds
,
1446 const char *comment
,
1447 const char *account_domain
, const char *account_name
,
1448 const char *plain_pass
, uint32_t parameter_control
,
1449 NTSTATUS expected_error
, bool old_password
,
1452 TALLOC_CTX
*fn_ctx
= talloc_named(mem_ctx
, 0, "test_SamLogon function-level context");
1455 int validation_levels
[] = {2,3,6};
1456 int logon_levels
[] = { NetlogonNetworkInformation
, NetlogonNetworkTransitiveInformation
};
1457 int function_levels
[] = {
1458 NDR_NETR_LOGONSAMLOGON
,
1459 NDR_NETR_LOGONSAMLOGONEX
,
1460 NDR_NETR_LOGONSAMLOGONWITHFLAGS
};
1461 struct samlogon_state samlogon_state
;
1463 union netr_LogonLevel logon
;
1464 union netr_Validation validation
;
1465 uint8_t authoritative
= 1;
1470 torture_comment(tctx
, "Testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1472 samlogon_state
.comment
= comment
;
1473 samlogon_state
.account_name
= account_name
;
1474 samlogon_state
.account_domain
= account_domain
;
1475 samlogon_state
.password
= plain_pass
;
1476 samlogon_state
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
1477 samlogon_state
.netbios_name
= lpcfg_netbios_name(tctx
->lp_ctx
);
1478 samlogon_state
.p
= p
;
1479 samlogon_state
.creds
= creds
;
1480 samlogon_state
.expected_error
= expected_error
;
1481 samlogon_state
.chall
= data_blob_talloc(fn_ctx
, NULL
, 8);
1482 samlogon_state
.parameter_control
= parameter_control
;
1483 samlogon_state
.old_password
= old_password
;
1484 samlogon_state
.tctx
= tctx
;
1486 generate_random_buffer(samlogon_state
.chall
.data
, 8);
1487 samlogon_state
.r_flags
.in
.server_name
= talloc_asprintf(fn_ctx
, "\\\\%s", dcerpc_server_name(p
));
1488 samlogon_state
.r_flags
.in
.computer_name
= TEST_MACHINE_NAME
;
1489 samlogon_state
.r_flags
.in
.credential
= &samlogon_state
.auth
;
1490 samlogon_state
.r_flags
.in
.return_authenticator
= &samlogon_state
.auth2
;
1491 samlogon_state
.r_flags
.in
.flags
= &flags
;
1492 samlogon_state
.r_flags
.in
.logon
= &logon
;
1493 samlogon_state
.r_flags
.out
.validation
= &validation
;
1494 samlogon_state
.r_flags
.out
.authoritative
= &authoritative
;
1495 samlogon_state
.r_flags
.out
.flags
= &flags
;
1497 samlogon_state
.r_ex
.in
.server_name
= talloc_asprintf(fn_ctx
, "\\\\%s", dcerpc_server_name(p
));
1498 samlogon_state
.r_ex
.in
.computer_name
= TEST_MACHINE_NAME
;
1499 samlogon_state
.r_ex
.in
.flags
= &flags
;
1500 samlogon_state
.r_ex
.in
.logon
= &logon
;
1501 samlogon_state
.r_ex
.out
.validation
= &validation
;
1502 samlogon_state
.r_ex
.out
.authoritative
= &authoritative
;
1503 samlogon_state
.r_ex
.out
.flags
= &flags
;
1505 samlogon_state
.r
.in
.server_name
= talloc_asprintf(fn_ctx
, "\\\\%s", dcerpc_server_name(p
));
1506 samlogon_state
.r
.in
.computer_name
= TEST_MACHINE_NAME
;
1507 samlogon_state
.r
.in
.credential
= &samlogon_state
.auth
;
1508 samlogon_state
.r
.in
.return_authenticator
= &samlogon_state
.auth2
;
1509 samlogon_state
.r
.in
.logon
= &logon
;
1510 samlogon_state
.r
.out
.validation
= &validation
;
1511 samlogon_state
.r
.out
.authoritative
= &authoritative
;
1514 for (f
=0;f
<ARRAY_SIZE(function_levels
);f
++) {
1515 for (i
=0; test_table
[i
].fn
; i
++) {
1516 if (n_subtests
&& (i
> n_subtests
)) {
1519 for (v
=0;v
<ARRAY_SIZE(validation_levels
);v
++) {
1520 for (l
=0;l
<ARRAY_SIZE(logon_levels
);l
++) {
1521 char *error_string
= NULL
;
1522 TALLOC_CTX
*tmp_ctx
= talloc_named(fn_ctx
, 0, "test_SamLogon inner loop");
1523 samlogon_state
.mem_ctx
= tmp_ctx
;
1524 samlogon_state
.function_level
= function_levels
[f
];
1525 samlogon_state
.r
.in
.validation_level
= validation_levels
[v
];
1526 samlogon_state
.r
.in
.logon_level
= logon_levels
[l
];
1527 samlogon_state
.r_ex
.in
.validation_level
= validation_levels
[v
];
1528 samlogon_state
.r_ex
.in
.logon_level
= logon_levels
[l
];
1529 samlogon_state
.r_flags
.in
.validation_level
= validation_levels
[v
];
1530 samlogon_state
.r_flags
.in
.logon_level
= logon_levels
[l
];
1531 if (!test_table
[i
].fn(&samlogon_state
, &error_string
)) {
1532 torture_comment(tctx
, "Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
1533 samlogon_state
.comment
,
1534 samlogon_state
.account_domain
,
1535 samlogon_state
.account_name
,
1536 test_table
[i
].name
, validation_levels
[v
],
1537 logon_levels
[l
], function_levels
[f
]);
1539 if (test_table
[i
].expect_fail
) {
1540 torture_comment(tctx
, " failed (expected, test incomplete): %s\n", error_string
);
1542 torture_comment(tctx
, " failed: %s\n", error_string
);
1545 SAFE_FREE(error_string
);
1547 talloc_free(tmp_ctx
);
1552 talloc_free(fn_ctx
);
1557 test an ADS style interactive domain logon
1559 bool test_InteractiveLogon(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
1560 struct torture_context
*tctx
,
1561 struct netlogon_creds_CredentialState
*creds
,
1562 const char *comment
,
1563 const char *workstation_name
,
1564 const char *account_domain
, const char *account_name
,
1565 const char *plain_pass
, uint32_t parameter_control
,
1566 NTSTATUS expected_error
)
1569 TALLOC_CTX
*fn_ctx
= talloc_named(mem_ctx
, 0, "test_InteractiveLogon function-level context");
1571 struct netr_LogonSamLogonWithFlags r
;
1572 struct netr_Authenticator a
, ra
;
1573 struct netr_PasswordInfo pinfo
;
1576 union netr_LogonLevel logon
;
1577 union netr_Validation validation
;
1578 uint8_t authoritative
= 1;
1579 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
1580 enum dcerpc_AuthType auth_type
;
1581 enum dcerpc_AuthLevel auth_level
;
1583 dcerpc_binding_handle_auth_info(b
, &auth_type
, &auth_level
);
1590 ZERO_STRUCT(validation
);
1592 netlogon_creds_client_authenticator(creds
, &a
);
1594 logon
.password
= &pinfo
;
1596 r
.in
.server_name
= talloc_asprintf(fn_ctx
, "\\\\%s", dcerpc_server_name(p
));
1597 r
.in
.computer_name
= TEST_MACHINE_NAME
;
1598 r
.in
.credential
= &a
;
1599 r
.in
.return_authenticator
= &ra
;
1600 r
.in
.logon_level
= NetlogonInteractiveTransitiveInformation
;
1601 r
.in
.logon
= &logon
;
1602 r
.in
.validation_level
= 6;
1603 r
.in
.flags
= &flags
;
1604 r
.out
.validation
= &validation
;
1605 r
.out
.authoritative
= &authoritative
;
1606 r
.out
.flags
= &flags
;
1608 pinfo
.identity_info
.domain_name
.string
= account_domain
;
1609 pinfo
.identity_info
.parameter_control
= parameter_control
;
1610 pinfo
.identity_info
.logon_id
= 0;
1611 pinfo
.identity_info
.account_name
.string
= account_name
;
1612 pinfo
.identity_info
.workstation
.string
= workstation_name
;
1614 if (!E_deshash(plain_pass
, pinfo
.lmpassword
.hash
)) {
1615 ZERO_STRUCT(pinfo
.lmpassword
.hash
);
1617 E_md4hash(plain_pass
, pinfo
.ntpassword
.hash
);
1619 status
= netlogon_creds_encrypt_samlogon_logon(creds
,
1624 torture_assert_ntstatus_ok_goto(tctx
,
1627 "netlogon_creds_encrypt_samlogon_logon");
1629 torture_comment(tctx
, "Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment
);
1631 status
= dcerpc_netr_LogonSamLogonWithFlags_r(b
, fn_ctx
, &r
);
1632 torture_assert_ntstatus_ok_goto(tctx
,
1635 talloc_asprintf(tctx
, "%s: netr_LogonSamLogonWithFlags - %s\n",
1636 __location__
, nt_errstr(status
)));
1638 if (!r
.out
.return_authenticator
) {
1639 talloc_free(fn_ctx
);
1640 torture_fail(tctx
, "no authenticator returned");
1643 status
= netlogon_creds_client_verify(creds
,
1644 &r
.out
.return_authenticator
->cred
,
1647 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, failed
,
1648 "Credential chaining failed\n");
1650 torture_assert_ntstatus_equal(tctx
, r
.out
.result
, expected_error
,
1651 talloc_asprintf(tctx
, "[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n",
1652 account_domain
, account_name
, nt_errstr(expected_error
), nt_errstr(r
.out
.result
)));
1656 talloc_free(fn_ctx
);
1661 /* This sets and resets the "minPwdAge" (in order to allow immediate user
1662 * password changes). The behaviour is controlled by the "set" boolean. */
1663 static bool handle_minPwdAge(struct torture_context
*torture
,
1664 TALLOC_CTX
*mem_ctx
, bool set
)
1666 struct dcerpc_pipe
*p
;
1667 struct policy_handle connect_handle
, domain_handle
;
1668 struct samr_Connect c_r
;
1669 struct samr_LookupDomain ld_r
;
1670 struct samr_OpenDomain od_r
;
1671 struct samr_QueryDomainInfo qdi_r
;
1672 struct samr_SetDomainInfo sdi_r
;
1673 struct samr_Close cl_r
;
1674 struct lsa_String domName
;
1675 struct dom_sid
*domSid
= NULL
;
1676 union samr_DomainInfo
*domInfo
= NULL
;
1677 static int64_t old_minPwdAge
= 0;
1680 status
= torture_rpc_connection(torture
, &p
, &ndr_table_samr
);
1681 if (!NT_STATUS_IS_OK(status
)) {
1685 c_r
.in
.system_name
= 0;
1686 c_r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1687 c_r
.out
.connect_handle
= &connect_handle
;
1689 torture_assert_ntstatus_ok(torture
,
1690 dcerpc_samr_Connect_r(p
->binding_handle
, mem_ctx
, &c_r
),
1692 torture_assert_ntstatus_ok(torture
, c_r
.out
.result
, "Connect failed");
1694 ld_r
.in
.connect_handle
= &connect_handle
;
1695 ld_r
.in
.domain_name
= &domName
;
1696 ld_r
.in
.domain_name
->string
= lpcfg_workgroup(torture
->lp_ctx
);
1697 ld_r
.out
.sid
= &domSid
;
1699 torture_assert_ntstatus_ok(torture
,
1700 dcerpc_samr_LookupDomain_r(p
->binding_handle
, mem_ctx
, &ld_r
),
1701 "LookupDomain failed");
1702 torture_assert_ntstatus_ok(torture
, ld_r
.out
.result
,
1703 "LookupDomain failed");
1705 od_r
.in
.connect_handle
= &connect_handle
;
1706 od_r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1707 od_r
.in
.sid
= *ld_r
.out
.sid
;
1708 od_r
.out
.domain_handle
= &domain_handle
;
1710 torture_assert_ntstatus_ok(torture
,
1711 dcerpc_samr_OpenDomain_r(p
->binding_handle
, mem_ctx
, &od_r
),
1712 "OpenDomain failed");
1713 torture_assert_ntstatus_ok(torture
, od_r
.out
.result
,
1714 "OpenDomain failed");
1716 qdi_r
.in
.domain_handle
= &domain_handle
;
1717 qdi_r
.in
.level
= DomainPasswordInformation
;
1718 qdi_r
.out
.info
= &domInfo
;
1720 torture_assert_ntstatus_ok(torture
,
1721 dcerpc_samr_QueryDomainInfo_r(p
->binding_handle
, mem_ctx
, &qdi_r
),
1722 "QueryDomainInfo failed");
1723 torture_assert_ntstatus_ok(torture
, qdi_r
.out
.result
,
1724 "QueryDomainInfo failed");
1727 old_minPwdAge
= domInfo
->info1
.min_password_age
;
1728 domInfo
->info1
.min_password_age
= 0;
1730 domInfo
->info1
.min_password_age
= old_minPwdAge
;
1733 sdi_r
.in
.domain_handle
= &domain_handle
;
1734 sdi_r
.in
.level
= DomainPasswordInformation
;
1735 sdi_r
.in
.info
= domInfo
;
1737 torture_assert_ntstatus_ok(torture
,
1738 dcerpc_samr_SetDomainInfo_r(p
->binding_handle
, mem_ctx
, &sdi_r
),
1739 "SetDomainInfo failed");
1740 torture_assert_ntstatus_ok(torture
, sdi_r
.out
.result
,
1741 "SetDomainInfo failed");
1743 cl_r
.in
.handle
= &connect_handle
;
1744 cl_r
.out
.handle
= &connect_handle
;
1746 torture_assert_ntstatus_ok(torture
,
1747 dcerpc_samr_Close_r(p
->binding_handle
, mem_ctx
, &cl_r
),
1749 torture_assert_ntstatus_ok(torture
, cl_r
.out
.result
, "Close failed");
1754 bool torture_rpc_samlogon(struct torture_context
*torture
)
1757 struct dcerpc_pipe
*p
;
1758 struct dcerpc_binding
*b
;
1759 struct cli_credentials
*machine_credentials
;
1760 TALLOC_CTX
*mem_ctx
= talloc_init("torture_rpc_netlogon");
1762 struct test_join
*join_ctx
= NULL
;
1763 struct test_join
*user_ctx
= NULL
, *user_ctx_wrong_wks
= NULL
, *user_ctx_wrong_time
= NULL
;
1764 const char *old_user_password
, *user_password_wrong_wks
, *user_password_wrong_time
;
1765 char *user_password
;
1766 const char *userdomain
;
1767 struct samr_SetUserInfo s
;
1768 union samr_UserInfo u
;
1772 unsigned int credential_flags
[] = {
1773 NETLOGON_NEG_AUTH2_FLAGS
,
1774 NETLOGON_NEG_ARCFOUR
,
1775 NETLOGON_NEG_ARCFOUR
| NETLOGON_NEG_128BIT
,
1776 NETLOGON_NEG_AUTH2_ADS_FLAGS
,
1777 0 /* yes, this is a valid flag, causes the use of DES */
1780 struct netlogon_creds_CredentialState
*creds
;
1781 struct dcerpc_pipe
*tmp_p
= NULL
;
1783 torture_assert(torture
, handle_minPwdAge(torture
, mem_ctx
, true),
1784 "handle_minPwdAge error!");
1786 /* We only need to join as a workstation here, and in future,
1787 * if we wish to test against trusted domains, we must be a
1788 * workstation here */
1789 join_ctx
= torture_join_domain(torture
, TEST_MACHINE_NAME
, ACB_WSTRUST
,
1790 &machine_credentials
);
1791 torture_assert(torture
, join_ctx
, "Failed to join as Workstation\n");
1793 userdomain
= torture_setting_string(torture
, "userdomain", lpcfg_workgroup(torture
->lp_ctx
));
1795 user_ctx
= torture_create_testuser(torture
,
1799 &old_user_password
);
1800 torture_assert(torture
, user_ctx
, "Failed to create a test user\n");
1802 user_password
= talloc_strdup(torture
, old_user_password
);
1803 torture_assert(torture
, user_password
!= NULL
, "Failed to copy old_user_password\n");
1805 tmp_p
= torture_join_samr_pipe(user_ctx
);
1806 torture_assert(torture
, tmp_p
, "torture_join_samr_pipe failed\n");
1807 test_ChangePasswordUser3(tmp_p
, torture
,
1808 TEST_USER_NAME
, 16 /* > 14 */, &user_password
,
1811 user_ctx_wrong_wks
= torture_create_testuser(torture
,
1812 TEST_USER_NAME_WRONG_WKS
,
1815 &user_password_wrong_wks
);
1816 torture_assert(torture
, user_ctx_wrong_wks
,
1817 "Failed to create a test user (wrong workstation test)\n");
1820 s
.in
.user_handle
= torture_join_samr_user_policy(user_ctx_wrong_wks
);
1824 u
.info21
.fields_present
= SAMR_FIELD_WORKSTATIONS
;
1825 u
.info21
.workstations
.string
= "not" TEST_MACHINE_NAME
;
1827 tmp_p
= torture_join_samr_pipe(user_ctx_wrong_wks
);
1828 status
= dcerpc_samr_SetUserInfo_r(tmp_p
->binding_handle
, mem_ctx
, &s
);
1829 torture_assert_ntstatus_ok_goto(torture
, status
, ret
, failed
,
1830 talloc_asprintf(torture
, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status
)));
1831 torture_assert_ntstatus_ok_goto(torture
, s
.out
.result
, ret
, failed
,
1832 talloc_asprintf(torture
, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s
.out
.result
)));
1835 = torture_create_testuser(torture
, TEST_USER_NAME_WRONG_TIME
,
1838 &user_password_wrong_time
);
1839 torture_assert(torture
, user_ctx_wrong_time
,
1840 "Failed to create a test user (wrong workstation test)\n");
1843 s
.in
.user_handle
= torture_join_samr_user_policy(user_ctx_wrong_time
);
1847 u
.info21
.fields_present
= SAMR_FIELD_WORKSTATIONS
| SAMR_FIELD_LOGON_HOURS
;
1848 u
.info21
.workstations
.string
= TEST_MACHINE_NAME
;
1849 u
.info21
.logon_hours
.units_per_week
= 168;
1850 u
.info21
.logon_hours
.bits
= talloc_zero_array(mem_ctx
, uint8_t, 168);
1852 tmp_p
= torture_join_samr_pipe(user_ctx_wrong_time
);
1853 status
= dcerpc_samr_SetUserInfo_r(tmp_p
->binding_handle
, mem_ctx
, &s
);
1854 torture_assert_ntstatus_ok_goto(torture
, status
, ret
, failed
,
1855 talloc_asprintf(torture
, "SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status
)));
1856 torture_assert_ntstatus_ok_goto(torture
, s
.out
.result
, ret
, failed
,
1857 talloc_asprintf(torture
, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s
.out
.result
)));
1860 torture_assert_ntstatus_ok_goto(torture
,
1861 torture_rpc_binding(torture
, &b
),
1864 "Obtaining binding");
1866 /* We have to use schannel, otherwise the SamLogonEx fails
1867 * with INTERNAL_ERROR */
1869 status
= dcerpc_binding_set_flags(b
,
1871 DCERPC_SIGN
| DCERPC_SEAL
|
1872 DCERPC_SCHANNEL_128
,
1873 DCERPC_AUTH_OPTIONS
);
1874 torture_assert_ntstatus_ok(torture
, status
, "set flags");
1876 status
= dcerpc_pipe_connect_b(mem_ctx
, &p
, b
,
1877 &ndr_table_netlogon
,
1878 machine_credentials
, torture
->ev
, torture
->lp_ctx
);
1880 torture_assert_ntstatus_ok_goto(torture
, status
, ret
, failed
,
1881 talloc_asprintf(torture
, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status
)));
1883 torture_assert_not_null_goto(torture
,
1884 creds
= cli_credentials_get_netlogon_creds(machine_credentials
),
1887 "obtaining credentials");
1892 const char *comment
;
1894 const char *username
;
1895 const char *password
;
1897 NTSTATUS expected_interactive_error
;
1898 NTSTATUS expected_network_error
;
1899 uint32_t parameter_control
;
1900 bool old_password
; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
1903 .comment
= "domain\\user",
1904 .domain
= cli_credentials_get_domain(
1905 samba_cmdline_get_creds()),
1906 .username
= cli_credentials_get_username(
1907 samba_cmdline_get_creds()),
1908 .password
= cli_credentials_get_password(
1909 samba_cmdline_get_creds()),
1910 .network_login
= true,
1911 .expected_interactive_error
= NT_STATUS_OK
,
1912 .expected_network_error
= NT_STATUS_OK
,
1913 .parameter_control
= 0,
1916 .comment
= "realm\\user",
1917 .domain
= cli_credentials_get_realm(
1918 samba_cmdline_get_creds()),
1919 .username
= cli_credentials_get_username(
1920 samba_cmdline_get_creds()),
1921 .password
= cli_credentials_get_password(
1922 samba_cmdline_get_creds()),
1923 .network_login
= true,
1924 .expected_interactive_error
= NT_STATUS_OK
,
1925 .expected_network_error
= NT_STATUS_OK
,
1926 .parameter_control
= 0,
1929 .comment
= "user@domain",
1931 .username
= talloc_asprintf(mem_ctx
,
1933 cli_credentials_get_username(
1934 samba_cmdline_get_creds()),
1935 cli_credentials_get_domain(
1936 samba_cmdline_get_creds())
1938 .password
= cli_credentials_get_password(
1939 samba_cmdline_get_creds()),
1940 .network_login
= false, /* works for some things, but not NTLMv2. Odd */
1941 .expected_interactive_error
= NT_STATUS_OK
,
1942 .expected_network_error
= NT_STATUS_OK
,
1943 .parameter_control
= 0,
1946 .comment
= "user@realm",
1948 .username
= talloc_asprintf(mem_ctx
,
1950 cli_credentials_get_username(
1951 samba_cmdline_get_creds()),
1952 cli_credentials_get_realm(
1953 samba_cmdline_get_creds())
1955 .password
= cli_credentials_get_password(
1956 samba_cmdline_get_creds()),
1957 .network_login
= true,
1958 .expected_interactive_error
= NT_STATUS_OK
,
1959 .expected_network_error
= NT_STATUS_OK
,
1960 .parameter_control
= 0,
1963 .comment
= "machine domain\\user",
1964 .domain
= cli_credentials_get_domain(machine_credentials
),
1965 .username
= cli_credentials_get_username(machine_credentials
),
1966 .password
= cli_credentials_get_password(machine_credentials
),
1967 .network_login
= true,
1968 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1969 .parameter_control
= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1972 .comment
= "machine domain\\user",
1973 .domain
= cli_credentials_get_domain(machine_credentials
),
1974 .username
= cli_credentials_get_username(machine_credentials
),
1975 .password
= cli_credentials_get_password(machine_credentials
),
1976 .network_login
= true,
1977 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1978 .expected_network_error
= NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
,
1979 .parameter_control
= 0,
1982 .comment
= "machine realm\\user",
1983 .domain
= cli_credentials_get_realm(machine_credentials
),
1984 .username
= cli_credentials_get_username(machine_credentials
),
1985 .password
= cli_credentials_get_password(machine_credentials
),
1986 .network_login
= true,
1987 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
1988 .parameter_control
= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1991 .comment
= "machine user@domain",
1993 .username
= talloc_asprintf(mem_ctx
,
1995 cli_credentials_get_username(machine_credentials
),
1996 cli_credentials_get_domain(machine_credentials
)
1998 .password
= cli_credentials_get_password(machine_credentials
),
1999 .network_login
= false, /* works for some things, but not NTLMv2. Odd */
2000 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
2001 .parameter_control
= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
2004 .comment
= "machine user@realm",
2006 .username
= talloc_asprintf(mem_ctx
,
2008 cli_credentials_get_username(machine_credentials
),
2009 cli_credentials_get_realm(machine_credentials
)
2011 .password
= cli_credentials_get_password(machine_credentials
),
2012 .network_login
= true,
2013 .expected_interactive_error
= NT_STATUS_NO_SUCH_USER
,
2014 .parameter_control
= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
2017 .comment
= "test user (long pw): domain\\user",
2018 .domain
= userdomain
,
2019 .username
= TEST_USER_NAME
,
2020 .password
= user_password
,
2021 .network_login
= true,
2022 .expected_interactive_error
= NT_STATUS_OK
,
2023 .expected_network_error
= NT_STATUS_OK
,
2024 .parameter_control
= 0,
2027 .comment
= "test user (long pw): user@realm",
2029 .username
= talloc_asprintf(mem_ctx
,
2032 lpcfg_realm(torture
->lp_ctx
)),
2033 .password
= user_password
,
2034 .network_login
= true,
2035 .expected_interactive_error
= NT_STATUS_OK
,
2036 .expected_network_error
= NT_STATUS_OK
,
2037 .parameter_control
= 0,
2040 .comment
= "test user (long pw): user@domain",
2042 .username
= talloc_asprintf(mem_ctx
,
2046 .password
= user_password
,
2047 .network_login
= false, /* works for some things, but not NTLMv2. Odd */
2048 .expected_interactive_error
= NT_STATUS_OK
,
2049 .expected_network_error
= NT_STATUS_OK
,
2050 .parameter_control
= 0,
2052 /* Oddball, can we use the old password ? */
2054 .comment
= "test user: user\\domain OLD PASSWORD",
2055 .domain
= userdomain
,
2056 .username
= TEST_USER_NAME
,
2057 .password
= old_user_password
,
2058 .network_login
= true,
2059 .expected_interactive_error
= NT_STATUS_WRONG_PASSWORD
,
2060 .expected_network_error
= NT_STATUS_OK
,
2061 .old_password
= true
2064 .comment
= "test user (wrong workstation): domain\\user",
2065 .domain
= userdomain
,
2066 .username
= TEST_USER_NAME_WRONG_WKS
,
2067 .password
= user_password_wrong_wks
,
2068 .network_login
= true,
2069 .expected_interactive_error
= NT_STATUS_INVALID_WORKSTATION
,
2070 .expected_network_error
= NT_STATUS_INVALID_WORKSTATION
,
2071 .parameter_control
= 0,
2075 /* Try all the tests for different username forms */
2076 for (ci
= 0; ci
< ARRAY_SIZE(usercreds
); ci
++) {
2078 torture_assert_goto(torture
,
2079 test_InteractiveLogon(p
, mem_ctx
, torture
, creds
,
2080 usercreds
[ci
].comment
,
2082 usercreds
[ci
].domain
,
2083 usercreds
[ci
].username
,
2084 usercreds
[ci
].password
,
2085 usercreds
[ci
].parameter_control
,
2086 usercreds
[ci
].expected_interactive_error
),
2089 talloc_asprintf(mem_ctx
, "InteractiveLogon: %s",
2090 usercreds
[ci
].comment
));
2092 if (usercreds
[ci
].network_login
) {
2093 torture_assert_goto(torture
,
2094 test_SamLogon(p
, mem_ctx
, torture
, creds
,
2095 usercreds
[ci
].comment
,
2096 usercreds
[ci
].domain
,
2097 usercreds
[ci
].username
,
2098 usercreds
[ci
].password
,
2099 usercreds
[ci
].parameter_control
,
2100 usercreds
[ci
].expected_network_error
,
2101 usercreds
[ci
].old_password
,
2105 talloc_asprintf(mem_ctx
, "SamLogon: %s",
2106 usercreds
[ci
].comment
));
2110 /* Using the first username form, try the different
2111 * credentials flag setups, on only one of the tests (checks
2112 * session key encryption) */
2114 for (i
=0; i
< ARRAY_SIZE(credential_flags
); i
++) {
2115 torture_comment(torture
,
2116 "Testing with flags: 0x%08x\n",
2117 credential_flags
[i
]);
2119 ret
= test_SetupCredentials2(p
,
2121 credential_flags
[i
],
2122 machine_credentials
,
2125 torture_assert_goto(torture
, ret
, ret
, failed
, "test_SetupCredentials2()\n");
2127 torture_assert_goto(torture
,
2128 test_InteractiveLogon(p
, mem_ctx
, torture
, creds
,
2129 usercreds
[0].comment
,
2131 usercreds
[0].domain
,
2132 usercreds
[0].username
,
2133 usercreds
[0].password
,
2134 usercreds
[0].parameter_control
,
2135 usercreds
[0].expected_interactive_error
),
2138 talloc_asprintf(mem_ctx
,
2139 "Testing InteractiveLogon with flags: 0x%08x\n",
2140 credential_flags
[i
]));
2142 if (usercreds
[0].network_login
) {
2143 torture_assert_goto(torture
,
2144 test_SamLogon(p
, mem_ctx
, torture
, creds
,
2145 usercreds
[0].comment
,
2146 usercreds
[0].domain
,
2147 usercreds
[0].username
,
2148 usercreds
[0].password
,
2149 usercreds
[0].parameter_control
,
2150 usercreds
[0].expected_network_error
,
2151 usercreds
[0].old_password
,
2155 talloc_asprintf(mem_ctx
,
2156 "Testing SamLogon with flags: 0x%08x\n",
2157 credential_flags
[i
]));
2161 torture_comment(torture
, "Testing with krb5\n");
2163 cli_credentials_set_netlogon_creds(machine_credentials
, NULL
);
2164 status
= dcerpc_binding_set_flags(b
,
2166 DCERPC_SIGN
| DCERPC_SEAL
|
2167 DCERPC_SCHANNEL_KRB5
,
2168 DCERPC_AUTH_OPTIONS
);
2169 torture_assert_ntstatus_ok(torture
, status
, "set flags");
2171 status
= dcerpc_pipe_connect_b(mem_ctx
, &p
, b
,
2172 &ndr_table_netlogon
,
2173 machine_credentials
, torture
->ev
, torture
->lp_ctx
);
2175 torture_assert_ntstatus_ok_goto(torture
, status
, ret
, failed
,
2176 talloc_asprintf(torture
, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status
)));
2178 torture_assert_not_null_goto(torture
,
2179 creds
= cli_credentials_get_netlogon_creds(machine_credentials
),
2182 "obtaining credentials");
2184 torture_assert_goto(torture
,
2185 test_InteractiveLogon(p
, mem_ctx
, torture
, creds
,
2186 usercreds
[0].comment
,
2188 usercreds
[0].domain
,
2189 usercreds
[0].username
,
2190 usercreds
[0].password
,
2191 usercreds
[0].parameter_control
,
2192 usercreds
[0].expected_interactive_error
),
2195 talloc_asprintf(mem_ctx
,
2196 "Testing InteractiveLogon with krb5\n"
2199 if (usercreds
[0].network_login
) {
2200 torture_assert_goto(torture
,
2201 test_SamLogon(p
, mem_ctx
, torture
, creds
,
2202 usercreds
[0].comment
,
2203 usercreds
[0].domain
,
2204 usercreds
[0].username
,
2205 usercreds
[0].password
,
2206 usercreds
[0].parameter_control
,
2207 usercreds
[0].expected_network_error
,
2208 usercreds
[0].old_password
,
2212 talloc_asprintf(mem_ctx
,
2213 "Testing SamLogon with krb5\n"
2218 torture_assert(torture
, handle_minPwdAge(torture
, mem_ctx
, false),
2219 "handle_minPwdAge error!");
2221 talloc_free(mem_ctx
);
2223 torture_leave_domain(torture
, join_ctx
);
2224 torture_leave_domain(torture
, user_ctx
);
2225 torture_leave_domain(torture
, user_ctx_wrong_wks
);
2226 torture_leave_domain(torture
, user_ctx_wrong_time
);