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