Move waf into third_party/.
[Samba.git] / source4 / torture / rpc / samlogon.c
blobd552fa6050be6baa19f1351553f5d8d5e2a68469
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 "libcli/auth/libcli_auth.h"
33 #include "param/param.h"
35 #define TEST_MACHINE_NAME "samlogontest"
36 #define TEST_USER_NAME "samlogontestuser"
37 #define TEST_USER_NAME_WRONG_WKS "samlogontest2"
38 #define TEST_USER_NAME_WRONG_TIME "samlogontest3"
40 enum ntlm_break {
41 BREAK_BOTH,
42 BREAK_NONE,
43 BREAK_LM,
44 BREAK_NT,
45 NO_LM,
46 NO_NT
49 struct samlogon_state {
50 TALLOC_CTX *mem_ctx;
51 struct torture_context *tctx;
52 const char *comment;
53 const char *account_name;
54 const char *account_domain;
55 const char *netbios_name;
56 const char *password;
57 const char *workgroup;
58 struct dcerpc_pipe *p;
59 int function_level;
60 uint32_t parameter_control;
61 struct netr_LogonSamLogon r;
62 struct netr_LogonSamLogonEx r_ex;
63 struct netr_LogonSamLogonWithFlags r_flags;
64 struct netr_Authenticator auth, auth2;
65 struct netlogon_creds_CredentialState *creds;
66 NTSTATUS expected_error;
67 bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
68 DATA_BLOB chall;
72 Authenticate a user with a challenge/response, checking session key
73 and valid authentication types
75 static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
76 enum ntlm_break break_which,
77 uint32_t parameter_control,
78 DATA_BLOB *chall,
79 DATA_BLOB *lm_response,
80 DATA_BLOB *nt_response,
81 uint8_t lm_key[8],
82 uint8_t user_session_key[16],
83 char **error_string)
85 NTSTATUS status;
86 struct netr_LogonSamLogon *r = &samlogon_state->r;
87 struct netr_LogonSamLogonEx *r_ex = &samlogon_state->r_ex;
88 struct netr_LogonSamLogonWithFlags *r_flags = &samlogon_state->r_flags;
89 struct netr_NetworkInfo ninfo;
90 struct netr_SamBaseInfo *base = NULL;
91 uint16_t validation_level = 0;
93 samlogon_state->r.in.logon->network = &ninfo;
94 samlogon_state->r_ex.in.logon->network = &ninfo;
95 samlogon_state->r_flags.in.logon->network = &ninfo;
97 ninfo.identity_info.domain_name.string = samlogon_state->account_domain;
98 ninfo.identity_info.parameter_control = parameter_control;
99 ninfo.identity_info.logon_id_low = 0;
100 ninfo.identity_info.logon_id_high = 0;
101 ninfo.identity_info.account_name.string = samlogon_state->account_name;
102 ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
104 memcpy(ninfo.challenge, chall->data, 8);
106 switch (break_which) {
107 case BREAK_NONE:
108 break;
109 case BREAK_LM:
110 if (lm_response && lm_response->data) {
111 lm_response->data[0]++;
113 break;
114 case BREAK_NT:
115 if (nt_response && nt_response->data) {
116 nt_response->data[0]++;
118 break;
119 case BREAK_BOTH:
120 if (lm_response && lm_response->data) {
121 lm_response->data[0]++;
123 if (nt_response && nt_response->data) {
124 nt_response->data[0]++;
126 break;
127 case NO_LM:
128 data_blob_free(lm_response);
129 break;
130 case NO_NT:
131 data_blob_free(nt_response);
132 break;
135 if (nt_response) {
136 ninfo.nt.data = nt_response->data;
137 ninfo.nt.length = nt_response->length;
138 } else {
139 ninfo.nt.data = NULL;
140 ninfo.nt.length = 0;
143 if (lm_response) {
144 ninfo.lm.data = lm_response->data;
145 ninfo.lm.length = lm_response->length;
146 } else {
147 ninfo.lm.data = NULL;
148 ninfo.lm.length = 0;
151 switch (samlogon_state->function_level) {
152 case NDR_NETR_LOGONSAMLOGON:
153 ZERO_STRUCT(samlogon_state->auth2);
154 netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
156 r->out.return_authenticator = NULL;
157 status = dcerpc_netr_LogonSamLogon_r(samlogon_state->p->binding_handle,
158 samlogon_state->mem_ctx, r);
159 if (!NT_STATUS_IS_OK(status)) {
160 if (error_string) {
161 *error_string = strdup(nt_errstr(status));
163 return status;
165 if (!r->out.return_authenticator ||
166 !netlogon_creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) {
167 torture_comment(samlogon_state->tctx, "Credential chaining failed\n");
169 if (!NT_STATUS_IS_OK(r->out.result)) {
170 if (error_string) {
171 *error_string = strdup(nt_errstr(r->out.result));
173 return r->out.result;
176 validation_level = r->in.validation_level;
178 netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds,
179 validation_level,
180 r->out.validation);
182 switch (validation_level) {
183 case 2:
184 base = &r->out.validation->sam2->base;
185 break;
186 case 3:
187 base = &r->out.validation->sam3->base;
188 break;
189 case 6:
190 base = &r->out.validation->sam6->base;
191 break;
193 break;
194 case NDR_NETR_LOGONSAMLOGONEX:
195 status = dcerpc_netr_LogonSamLogonEx_r(samlogon_state->p->binding_handle,
196 samlogon_state->mem_ctx, r_ex);
197 if (!NT_STATUS_IS_OK(status)) {
198 if (error_string) {
199 *error_string = strdup(nt_errstr(status));
201 return status;
203 if (!NT_STATUS_IS_OK(r_ex->out.result)) {
204 if (error_string) {
205 *error_string = strdup(nt_errstr(r_ex->out.result));
207 return r_ex->out.result;
210 validation_level = r_ex->in.validation_level;
212 netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds,
213 validation_level,
214 r_ex->out.validation);
216 switch (validation_level) {
217 case 2:
218 base = &r_ex->out.validation->sam2->base;
219 break;
220 case 3:
221 base = &r_ex->out.validation->sam3->base;
222 break;
223 case 6:
224 base = &r_ex->out.validation->sam6->base;
225 break;
227 break;
228 case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
229 ZERO_STRUCT(samlogon_state->auth2);
230 netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
232 r_flags->out.return_authenticator = NULL;
233 status = dcerpc_netr_LogonSamLogonWithFlags_r(samlogon_state->p->binding_handle,
234 samlogon_state->mem_ctx, r_flags);
235 if (!NT_STATUS_IS_OK(status)) {
236 if (error_string) {
237 *error_string = strdup(nt_errstr(status));
239 return status;
241 if (!r_flags->out.return_authenticator ||
242 !netlogon_creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) {
243 torture_comment(samlogon_state->tctx, "Credential chaining failed\n");
245 if (!NT_STATUS_IS_OK(r_flags->out.result)) {
246 if (error_string) {
247 *error_string = strdup(nt_errstr(r_flags->out.result));
249 return r_flags->out.result;
252 validation_level = r_flags->in.validation_level;
254 netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds,
255 validation_level,
256 r_flags->out.validation);
258 switch (validation_level) {
259 case 2:
260 base = &r_flags->out.validation->sam2->base;
261 break;
262 case 3:
263 base = &r_flags->out.validation->sam3->base;
264 break;
265 case 6:
266 base = &r_flags->out.validation->sam6->base;
267 break;
269 break;
270 default:
271 /* can't happen */
272 return NT_STATUS_INVALID_PARAMETER;
275 if (!base) {
276 torture_comment(samlogon_state->tctx, "No user info returned from 'successful' SamLogon*() call!\n");
277 return NT_STATUS_INVALID_PARAMETER;
280 if (user_session_key) {
281 memcpy(user_session_key, base->key.key, 16);
283 if (lm_key) {
284 memcpy(lm_key, base->LMSessKey.key, 8);
287 return status;
292 * Test the normal 'LM and NTLM' combination
295 static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
297 bool pass = true;
298 bool lm_good;
299 NTSTATUS nt_status;
300 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
301 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
302 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
304 uint8_t lm_key[8];
305 uint8_t user_session_key[16];
306 uint8_t lm_hash[16];
307 uint8_t nt_hash[16];
309 ZERO_STRUCT(lm_key);
310 ZERO_STRUCT(user_session_key);
312 lm_good = SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
313 if (!lm_good) {
314 ZERO_STRUCT(lm_hash);
315 } else {
316 E_deshash(samlogon_state->password, lm_hash);
319 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
321 E_md4hash(samlogon_state->password, nt_hash);
322 SMBsesskeygen_ntv1(nt_hash, session_key.data);
324 nt_status = check_samlogon(samlogon_state,
325 break_which,
326 samlogon_state->parameter_control,
327 &samlogon_state->chall,
328 &lm_response,
329 &nt_response,
330 lm_key,
331 user_session_key,
332 error_string);
334 data_blob_free(&lm_response);
336 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
337 /* for 'long' passwords, the LM password is invalid */
338 if (break_which == NO_NT && !lm_good) {
339 return true;
341 /* for 'old' passwords, we allow the server to be OK or wrong password */
342 if (samlogon_state->old_password) {
343 return true;
345 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
346 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
347 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
348 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
349 SAFE_FREE(*error_string);
350 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
351 return false;
352 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
353 return true;
354 } else if (!NT_STATUS_IS_OK(nt_status)) {
355 return false;
358 if (break_which == NO_NT && !lm_good) {
359 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
360 return false;
363 if (memcmp(lm_hash, lm_key,
364 sizeof(lm_key)) != 0) {
365 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
366 torture_comment(samlogon_state->tctx, "lm_key:\n");
367 dump_data(1, lm_key, 8);
368 torture_comment(samlogon_state->tctx, "expected:\n");
369 dump_data(1, lm_hash, 8);
370 pass = false;
373 switch (break_which) {
374 case NO_NT:
376 uint8_t lm_key_expected[16];
377 memcpy(lm_key_expected, lm_hash, 8);
378 memset(lm_key_expected+8, '\0', 8);
379 if (memcmp(lm_key_expected, user_session_key,
380 16) != 0) {
381 *error_string = strdup("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
382 torture_comment(samlogon_state->tctx, "user_session_key:\n");
383 dump_data(1, user_session_key, sizeof(user_session_key));
384 torture_comment(samlogon_state->tctx, "expected:\n");
385 dump_data(1, lm_key_expected, sizeof(lm_key_expected));
386 pass = false;
388 break;
390 default:
391 if (memcmp(session_key.data, user_session_key,
392 sizeof(user_session_key)) != 0) {
393 *error_string = strdup("NT Session Key does not match expectations!\n");
394 torture_comment(samlogon_state->tctx, "user_session_key:\n");
395 dump_data(1, user_session_key, 16);
396 torture_comment(samlogon_state->tctx, "expected:\n");
397 dump_data(1, session_key.data, session_key.length);
398 pass = false;
401 return pass;
405 * Test LM authentication, no NT response supplied
408 static bool test_lm(struct samlogon_state *samlogon_state, char **error_string)
411 return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
415 * Test the NTLM response only, no LM.
418 static bool test_ntlm(struct samlogon_state *samlogon_state, char **error_string)
420 return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
424 * Test the NTLM response only, but in the LM field.
427 static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string)
429 bool lm_good;
430 bool pass = true;
431 NTSTATUS nt_status;
432 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
433 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
435 uint8_t lm_key[8];
436 uint8_t lm_hash[16];
437 uint8_t user_session_key[16];
438 uint8_t nt_hash[16];
440 ZERO_STRUCT(lm_key);
441 ZERO_STRUCT(user_session_key);
443 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
444 nt_response.data);
445 E_md4hash(samlogon_state->password, nt_hash);
446 SMBsesskeygen_ntv1(nt_hash,
447 session_key.data);
449 lm_good = E_deshash(samlogon_state->password, lm_hash);
450 if (!lm_good) {
451 ZERO_STRUCT(lm_hash);
453 nt_status = check_samlogon(samlogon_state,
454 BREAK_NONE,
455 samlogon_state->parameter_control,
456 &samlogon_state->chall,
457 &nt_response,
458 NULL,
459 lm_key,
460 user_session_key,
461 error_string);
463 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
464 /* for 'old' passwords, we allow the server to be OK or wrong password */
465 if (samlogon_state->old_password) {
466 return true;
468 return false;
469 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
470 SAFE_FREE(*error_string);
471 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
472 return false;
473 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
474 return true;
475 } else if (!NT_STATUS_IS_OK(nt_status)) {
476 return false;
479 if (lm_good) {
480 if (memcmp(lm_hash, lm_key,
481 sizeof(lm_key)) != 0) {
482 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
483 torture_comment(samlogon_state->tctx, "lm_key:\n");
484 dump_data(1, lm_key, 8);
485 torture_comment(samlogon_state->tctx, "expected:\n");
486 dump_data(1, lm_hash, 8);
487 pass = false;
489 #if 0
490 } else {
491 if (memcmp(session_key.data, lm_key,
492 sizeof(lm_key)) != 0) {
493 torture_comment(samlogon_state->tctx, "LM Key does not match expectations (first 8 session key)!\n");
494 torture_comment(samlogon_state->tctx, "lm_key:\n");
495 dump_data(1, lm_key, 8);
496 torture_comment(samlogon_state->tctx, "expected:\n");
497 dump_data(1, session_key.data, 8);
498 pass = false;
500 #endif
502 if (lm_good && memcmp(lm_hash, user_session_key, 8) != 0) {
503 uint8_t lm_key_expected[16];
504 memcpy(lm_key_expected, lm_hash, 8);
505 memset(lm_key_expected+8, '\0', 8);
506 if (memcmp(lm_key_expected, user_session_key,
507 16) != 0) {
508 torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations (should be first-8 LM hash)!\n");
509 torture_comment(samlogon_state->tctx, "user_session_key:\n");
510 dump_data(1, user_session_key, sizeof(user_session_key));
511 torture_comment(samlogon_state->tctx, "expected:\n");
512 dump_data(1, lm_key_expected, sizeof(lm_key_expected));
513 pass = false;
516 return pass;
520 * Test the NTLM response only, but in the both the NT and LM fields.
523 static bool test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string)
525 bool pass = true;
526 bool lm_good;
527 NTSTATUS nt_status;
528 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
529 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
531 uint8_t lm_key[8];
532 uint8_t lm_hash[16];
533 uint8_t user_session_key[16];
534 uint8_t nt_hash[16];
536 ZERO_STRUCT(lm_key);
537 ZERO_STRUCT(user_session_key);
539 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
540 nt_response.data);
541 E_md4hash(samlogon_state->password, nt_hash);
542 SMBsesskeygen_ntv1(nt_hash,
543 session_key.data);
545 lm_good = E_deshash(samlogon_state->password, lm_hash);
546 if (!lm_good) {
547 ZERO_STRUCT(lm_hash);
550 nt_status = check_samlogon(samlogon_state,
551 BREAK_NONE,
552 samlogon_state->parameter_control,
553 &samlogon_state->chall,
554 NULL,
555 &nt_response,
556 lm_key,
557 user_session_key,
558 error_string);
560 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
561 /* for 'old' passwords, we allow the server to be OK or wrong password */
562 if (samlogon_state->old_password) {
563 return true;
565 return false;
566 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
567 SAFE_FREE(*error_string);
568 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
569 return false;
570 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
571 return true;
572 } else if (!NT_STATUS_IS_OK(nt_status)) {
573 return false;
576 if (!NT_STATUS_IS_OK(nt_status)) {
577 return false;
580 if (memcmp(lm_hash, lm_key,
581 sizeof(lm_key)) != 0) {
582 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
583 torture_comment(samlogon_state->tctx, "lm_key:\n");
584 dump_data(1, lm_key, 8);
585 torture_comment(samlogon_state->tctx, "expected:\n");
586 dump_data(1, lm_hash, 8);
587 pass = false;
589 if (memcmp(session_key.data, user_session_key,
590 sizeof(user_session_key)) != 0) {
591 torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations!\n");
592 torture_comment(samlogon_state->tctx, "user_session_key:\n");
593 dump_data(1, user_session_key, 16);
594 torture_comment(samlogon_state->tctx, "expected:\n");
595 dump_data(1, session_key.data, session_key.length);
596 pass = false;
600 return pass;
604 * Test the NTLMv2 and LMv2 responses
607 enum ntlmv2_domain {
608 UPPER_DOMAIN,
609 NO_DOMAIN
612 static bool test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state,
613 enum ntlm_break break_which,
614 enum ntlmv2_domain ntlmv2_domain,
615 char **error_string)
617 bool pass = true;
618 NTSTATUS nt_status;
619 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
620 DATA_BLOB lmv2_response = data_blob(NULL, 0);
621 DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
622 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
623 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, TEST_MACHINE_NAME, samlogon_state->workgroup);
625 uint8_t lm_session_key[8];
626 uint8_t user_session_key[16];
628 ZERO_STRUCT(lm_session_key);
629 ZERO_STRUCT(user_session_key);
631 switch (ntlmv2_domain) {
632 case UPPER_DOMAIN:
633 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
634 samlogon_state->account_name, samlogon_state->account_domain,
635 samlogon_state->password, &samlogon_state->chall,
636 &names_blob,
637 &lmv2_response, &ntlmv2_response,
638 &lmv2_session_key, &ntlmv2_session_key)) {
639 data_blob_free(&names_blob);
640 return false;
642 break;
643 case NO_DOMAIN:
644 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
645 samlogon_state->account_name, "",
646 samlogon_state->password, &samlogon_state->chall,
647 &names_blob,
648 &lmv2_response, &ntlmv2_response,
649 &lmv2_session_key, &ntlmv2_session_key)) {
650 data_blob_free(&names_blob);
651 return false;
653 break;
655 data_blob_free(&names_blob);
657 nt_status = check_samlogon(samlogon_state,
658 break_which,
659 samlogon_state->parameter_control,
660 &samlogon_state->chall,
661 &lmv2_response,
662 &ntlmv2_response,
663 lm_session_key,
664 user_session_key,
665 error_string);
667 data_blob_free(&lmv2_response);
668 data_blob_free(&ntlmv2_response);
671 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
672 /* for 'old' passwords, we allow the server to be OK or wrong password */
673 if (samlogon_state->old_password) {
674 return true;
676 return break_which == BREAK_BOTH;
677 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
678 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
679 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
680 SAFE_FREE(*error_string);
681 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
682 return false;
683 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
684 return true;
685 } else if (!NT_STATUS_IS_OK(nt_status)) {
686 return false;
690 switch (break_which) {
691 case NO_NT:
692 if (memcmp(lmv2_session_key.data, user_session_key,
693 sizeof(user_session_key)) != 0) {
694 torture_comment(samlogon_state->tctx, "USER (LMv2) Session Key does not match expectations!\n");
695 torture_comment(samlogon_state->tctx, "user_session_key:\n");
696 dump_data(1, user_session_key, 16);
697 torture_comment(samlogon_state->tctx, "expected:\n");
698 dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
699 pass = false;
701 if (memcmp(lmv2_session_key.data, lm_session_key,
702 sizeof(lm_session_key)) != 0) {
703 torture_comment(samlogon_state->tctx, "LM (LMv2) Session Key does not match expectations!\n");
704 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
705 dump_data(1, lm_session_key, 8);
706 torture_comment(samlogon_state->tctx, "expected:\n");
707 dump_data(1, lmv2_session_key.data, 8);
708 pass = false;
710 break;
711 default:
712 if (memcmp(ntlmv2_session_key.data, user_session_key,
713 sizeof(user_session_key)) != 0) {
714 if (memcmp(lmv2_session_key.data, user_session_key,
715 sizeof(user_session_key)) == 0) {
716 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
717 torture_comment(samlogon_state->tctx, "user_session_key:\n");
718 dump_data(1, user_session_key, 16);
719 torture_comment(samlogon_state->tctx, "expected:\n");
720 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
721 pass = false;
723 } else {
724 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n");
725 torture_comment(samlogon_state->tctx, "user_session_key:\n");
726 dump_data(1, user_session_key, 16);
727 torture_comment(samlogon_state->tctx, "expected:\n");
728 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
729 pass = false;
732 if (memcmp(ntlmv2_session_key.data, lm_session_key,
733 sizeof(lm_session_key)) != 0) {
734 if (memcmp(lmv2_session_key.data, lm_session_key,
735 sizeof(lm_session_key)) == 0) {
736 torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
737 torture_comment(samlogon_state->tctx, "user_session_key:\n");
738 dump_data(1, lm_session_key, 8);
739 torture_comment(samlogon_state->tctx, "expected:\n");
740 dump_data(1, ntlmv2_session_key.data, 8);
741 pass = false;
742 } else {
743 torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key does not match expectations!\n");
744 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
745 dump_data(1, lm_session_key, 8);
746 torture_comment(samlogon_state->tctx, "expected:\n");
747 dump_data(1, ntlmv2_session_key.data, 8);
748 pass = false;
753 return pass;
757 * Test the NTLM and LMv2 responses
760 static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state,
761 enum ntlm_break break_which,
762 enum ntlmv2_domain ntlmv2_domain,
763 char **error_string)
765 bool pass = true;
766 NTSTATUS nt_status;
767 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
768 DATA_BLOB lmv2_response = data_blob(NULL, 0);
769 DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
770 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
771 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, samlogon_state->netbios_name, samlogon_state->workgroup);
773 DATA_BLOB ntlm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
774 DATA_BLOB ntlm_session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
776 bool lm_good;
777 uint8_t lm_hash[16];
778 uint8_t lm_session_key[8];
779 uint8_t user_session_key[16];
780 uint8_t nt_hash[16];
782 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
783 ntlm_response.data);
784 E_md4hash(samlogon_state->password, nt_hash);
785 SMBsesskeygen_ntv1(nt_hash,
786 ntlm_session_key.data);
788 lm_good = E_deshash(samlogon_state->password, lm_hash);
789 if (!lm_good) {
790 ZERO_STRUCT(lm_hash);
793 ZERO_STRUCT(lm_session_key);
794 ZERO_STRUCT(user_session_key);
796 switch (ntlmv2_domain) {
797 case UPPER_DOMAIN:
798 /* TODO - test with various domain cases, and without domain */
799 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
800 samlogon_state->account_name, samlogon_state->account_domain,
801 samlogon_state->password, &samlogon_state->chall,
802 &names_blob,
803 &lmv2_response, &ntlmv2_response,
804 &lmv2_session_key, &ntlmv2_session_key)) {
805 data_blob_free(&names_blob);
806 return false;
808 break;
809 case NO_DOMAIN:
810 /* TODO - test with various domain cases, and without domain */
811 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
812 samlogon_state->account_name, "",
813 samlogon_state->password, &samlogon_state->chall,
814 &names_blob,
815 &lmv2_response, &ntlmv2_response,
816 &lmv2_session_key, &ntlmv2_session_key)) {
817 data_blob_free(&names_blob);
818 return false;
820 break;
823 data_blob_free(&names_blob);
825 nt_status = check_samlogon(samlogon_state,
826 break_which,
827 samlogon_state->parameter_control,
828 &samlogon_state->chall,
829 &lmv2_response,
830 &ntlm_response,
831 lm_session_key,
832 user_session_key,
833 error_string);
835 data_blob_free(&lmv2_response);
836 data_blob_free(&ntlmv2_response);
839 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
840 /* for 'old' passwords, we allow the server to be OK or wrong password */
841 if (samlogon_state->old_password) {
842 return true;
844 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
845 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
846 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
847 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
848 SAFE_FREE(*error_string);
849 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
850 return false;
851 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
852 return true;
853 } else if (!NT_STATUS_IS_OK(nt_status)) {
854 return false;
857 switch (break_which) {
858 case NO_NT:
859 if (memcmp(lmv2_session_key.data, user_session_key,
860 sizeof(user_session_key)) != 0) {
861 torture_comment(samlogon_state->tctx, "USER (LMv2) Session Key does not match expectations!\n");
862 torture_comment(samlogon_state->tctx, "user_session_key:\n");
863 dump_data(1, user_session_key, 16);
864 torture_comment(samlogon_state->tctx, "expected:\n");
865 dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
866 pass = false;
868 if (memcmp(lmv2_session_key.data, lm_session_key,
869 sizeof(lm_session_key)) != 0) {
870 torture_comment(samlogon_state->tctx, "LM (LMv2) Session Key does not match expectations!\n");
871 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
872 dump_data(1, lm_session_key, 8);
873 torture_comment(samlogon_state->tctx, "expected:\n");
874 dump_data(1, lmv2_session_key.data, 8);
875 pass = false;
877 break;
878 case BREAK_LM:
879 if (memcmp(ntlm_session_key.data, user_session_key,
880 sizeof(user_session_key)) != 0) {
881 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n");
882 torture_comment(samlogon_state->tctx, "user_session_key:\n");
883 dump_data(1, user_session_key, 16);
884 torture_comment(samlogon_state->tctx, "expected:\n");
885 dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
886 pass = false;
888 if (lm_good) {
889 if (memcmp(lm_hash, lm_session_key,
890 sizeof(lm_session_key)) != 0) {
891 torture_comment(samlogon_state->tctx, "LM Session Key does not match expectations!\n");
892 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
893 dump_data(1, lm_session_key, 8);
894 torture_comment(samlogon_state->tctx, "expected:\n");
895 dump_data(1, lm_hash, 8);
896 pass = false;
898 } else {
899 static const uint8_t zeros[8];
900 if (memcmp(zeros, lm_session_key,
901 sizeof(lm_session_key)) != 0) {
902 torture_comment(samlogon_state->tctx, "LM Session Key does not match expectations (zeros)!\n");
903 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
904 dump_data(1, lm_session_key, 8);
905 torture_comment(samlogon_state->tctx, "expected:\n");
906 dump_data(1, zeros, 8);
907 pass = false;
910 break;
911 default:
912 if (memcmp(ntlm_session_key.data, user_session_key,
913 sizeof(user_session_key)) != 0) {
914 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n");
915 torture_comment(samlogon_state->tctx, "user_session_key:\n");
916 dump_data(1, user_session_key, 16);
917 torture_comment(samlogon_state->tctx, "expected:\n");
918 dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
919 pass = false;
921 if (memcmp(ntlm_session_key.data, lm_session_key,
922 sizeof(lm_session_key)) != 0) {
923 torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key does not match expectations!\n");
924 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
925 dump_data(1, lm_session_key, 8);
926 torture_comment(samlogon_state->tctx, "expected:\n");
927 dump_data(1, ntlm_session_key.data, 8);
928 pass = false;
932 return pass;
936 * Test the NTLMv2 and LMv2 responses
939 static bool test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
941 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, UPPER_DOMAIN, error_string);
944 #if 0
945 static bool test_lmv2_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
947 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, NO_DOMAIN, error_string);
949 #endif
952 * Test the LMv2 response only
955 static bool test_lmv2(struct samlogon_state *samlogon_state, char **error_string)
957 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, UPPER_DOMAIN, error_string);
960 static bool test_lmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
962 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, NO_DOMAIN, error_string);
966 * Test the NTLMv2 response only
969 static bool test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
971 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, UPPER_DOMAIN, error_string);
974 static bool test_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
976 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, NO_DOMAIN, error_string);
979 static bool test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string)
981 return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
984 static bool test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string)
986 return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
989 static bool test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string)
991 return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
994 static bool test_lm_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string)
996 return test_lm_ntlm_broken(samlogon_state, BREAK_BOTH, error_string);
998 static bool test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
1000 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
1003 static bool test_ntlmv2_lmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1005 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
1008 static bool test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
1010 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
1013 #if 0
1014 static bool test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1016 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
1018 #endif
1020 static bool test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char **error_string)
1022 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
1025 static bool test_ntlmv2_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1027 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
1030 static bool test_lmv2_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string)
1032 return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
1035 static bool test_lmv2_ntlm_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1037 return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
1040 static bool test_lmv2_ntlm_break_ntlm(struct samlogon_state *samlogon_state, char **error_string)
1042 return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
1045 static bool test_lmv2_ntlm_break_ntlm_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1047 return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
1050 static bool test_lmv2_ntlm_break_lm(struct samlogon_state *samlogon_state, char **error_string)
1052 return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
1055 static bool test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1057 return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
1061 * Test the NTLM2 response (extra challenge in LM feild)
1063 * This test is the same as the 'break LM' test, but checks that the
1064 * server implements NTLM2 session security in the right place
1065 * (NETLOGON is the wrong place).
1068 static bool test_ntlm2(struct samlogon_state *samlogon_state, char **error_string)
1070 bool pass = true;
1071 NTSTATUS nt_status;
1072 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1073 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1075 bool lm_good;
1076 uint8_t lm_key[8];
1077 uint8_t nt_hash[16];
1078 uint8_t lm_hash[16];
1079 uint8_t nt_key[16];
1080 uint8_t user_session_key[16];
1081 uint8_t expected_user_session_key[16];
1082 uint8_t session_nonce_hash[16];
1083 uint8_t client_chall[8];
1085 MD5_CTX md5_session_nonce_ctx;
1086 HMACMD5Context hmac_ctx;
1088 ZERO_STRUCT(user_session_key);
1089 ZERO_STRUCT(lm_key);
1090 generate_random_buffer(client_chall, 8);
1092 MD5Init(&md5_session_nonce_ctx);
1093 MD5Update(&md5_session_nonce_ctx, samlogon_state->chall.data, 8);
1094 MD5Update(&md5_session_nonce_ctx, client_chall, 8);
1095 MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
1097 E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
1098 lm_good = E_deshash(samlogon_state->password, (uint8_t *)lm_hash);
1099 SMBsesskeygen_ntv1((const uint8_t *)nt_hash,
1100 nt_key);
1102 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
1104 memcpy(lm_response.data, session_nonce_hash, 8);
1105 memset(lm_response.data + 8, 0, 16);
1107 hmac_md5_init_rfc2104(nt_key, 16, &hmac_ctx);
1108 hmac_md5_update(samlogon_state->chall.data, 8, &hmac_ctx);
1109 hmac_md5_update(client_chall, 8, &hmac_ctx);
1110 hmac_md5_final(expected_user_session_key, &hmac_ctx);
1112 nt_status = check_samlogon(samlogon_state,
1113 BREAK_NONE,
1114 samlogon_state->parameter_control,
1115 &samlogon_state->chall,
1116 &lm_response,
1117 &nt_response,
1118 lm_key,
1119 user_session_key,
1120 error_string);
1122 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1123 /* for 'old' passwords, we allow the server to be OK or wrong password */
1124 if (samlogon_state->old_password) {
1125 return true;
1127 return false;
1128 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1129 SAFE_FREE(*error_string);
1130 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1131 return false;
1132 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1133 return true;
1134 } else if (!NT_STATUS_IS_OK(nt_status)) {
1135 return false;
1138 if (lm_good) {
1139 if (memcmp(lm_hash, lm_key,
1140 sizeof(lm_key)) != 0) {
1141 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
1142 torture_comment(samlogon_state->tctx, "lm_key:\n");
1143 dump_data(1, lm_key, 8);
1144 torture_comment(samlogon_state->tctx, "expected:\n");
1145 dump_data(1, lm_hash, 8);
1146 pass = false;
1148 } else {
1149 static const uint8_t zeros[8];
1150 if (memcmp(zeros, lm_key,
1151 sizeof(lm_key)) != 0) {
1152 torture_comment(samlogon_state->tctx, "LM Session Key does not match expectations (zeros)!\n");
1153 torture_comment(samlogon_state->tctx, "lm_key:\n");
1154 dump_data(1, lm_key, 8);
1155 torture_comment(samlogon_state->tctx, "expected:\n");
1156 dump_data(1, zeros, 8);
1157 pass = false;
1160 if (memcmp(nt_key, user_session_key, 16) != 0) {
1161 torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations (should be NT Key)!\n");
1162 torture_comment(samlogon_state->tctx, "user_session_key:\n");
1163 dump_data(1, user_session_key, sizeof(user_session_key));
1164 torture_comment(samlogon_state->tctx, "expected:\n");
1165 dump_data(1, nt_key, sizeof(nt_key));
1166 pass = false;
1168 return pass;
1171 static bool test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
1173 NTSTATUS nt_status;
1174 DATA_BLOB nt_response = data_blob(NULL, 0);
1175 DATA_BLOB lm_response = data_blob(NULL, 0);
1176 char *password;
1177 char *dospw;
1178 smb_ucs2_t *unicodepw;
1179 size_t converted_size = 0;
1180 uint8_t user_session_key[16];
1181 uint8_t lm_key[16];
1182 uint8_t lm_hash[16];
1183 static const uint8_t zeros[8];
1184 DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
1185 bool lm_good = E_deshash(samlogon_state->password, lm_hash);
1187 ZERO_STRUCT(user_session_key);
1189 if (!push_ucs2_talloc(samlogon_state->mem_ctx,
1190 &unicodepw, samlogon_state->password, &converted_size)) {
1191 DEBUG(0, ("push_ucs2_allocate failed!\n"));
1192 exit(1);
1195 nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, strlen_m(samlogon_state->password)*2);
1197 password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password);
1199 if (!convert_string_talloc(samlogon_state->mem_ctx,
1200 CH_UNIX, CH_DOS,
1201 password, strlen(password)+1,
1202 (void**)&dospw, &converted_size)) {
1203 DEBUG(0, ("convert_string_talloc failed!\n"));
1204 exit(1);
1207 lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
1209 nt_status = check_samlogon(samlogon_state,
1210 break_which,
1211 samlogon_state->parameter_control | MSV1_0_CLEARTEXT_PASSWORD_ALLOWED,
1212 &chall,
1213 &lm_response,
1214 &nt_response,
1215 lm_key,
1216 user_session_key,
1217 error_string);
1219 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1220 /* for 'old' passwords, we allow the server to be OK or wrong password */
1221 if (samlogon_state->old_password) {
1222 return true;
1224 /* for 'long' passwords, the LM password is invalid */
1225 if (break_which == NO_NT && !lm_good) {
1226 return true;
1228 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
1229 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
1230 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
1231 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1232 SAFE_FREE(*error_string);
1233 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1234 return false;
1235 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1236 return true;
1237 } else if (!NT_STATUS_IS_OK(nt_status)) {
1238 return false;
1241 if (break_which == NO_NT && !lm_good) {
1242 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
1243 return false;
1246 return true;
1249 static bool test_plaintext_none_broken(struct samlogon_state *samlogon_state,
1250 char **error_string) {
1251 return test_plaintext(samlogon_state, BREAK_NONE, error_string);
1254 static bool test_plaintext_lm_broken(struct samlogon_state *samlogon_state,
1255 char **error_string) {
1256 return test_plaintext(samlogon_state, BREAK_LM, error_string);
1259 static bool test_plaintext_nt_broken(struct samlogon_state *samlogon_state,
1260 char **error_string) {
1261 return test_plaintext(samlogon_state, BREAK_NT, error_string);
1264 static bool test_plaintext_nt_only(struct samlogon_state *samlogon_state,
1265 char **error_string) {
1266 return test_plaintext(samlogon_state, NO_LM, error_string);
1269 static bool test_plaintext_lm_only(struct samlogon_state *samlogon_state,
1270 char **error_string) {
1271 return test_plaintext(samlogon_state, NO_NT, error_string);
1275 Tests:
1277 - LM only
1278 - NT and LM
1279 - NT
1280 - NT in LM field
1281 - NT in both fields
1282 - NTLMv2
1283 - NTLMv2 and LMv2
1284 - LMv2
1285 - plaintext tests (in challenge-response fields)
1287 check we get the correct session key in each case
1288 check what values we get for the LM session key
1292 static const struct ntlm_tests {
1293 bool (*fn)(struct samlogon_state *, char **);
1294 const char *name;
1295 bool expect_fail;
1296 } test_table[] = {
1297 {test_lmv2_ntlmv2, "NTLMv2 and LMv2", false},
1298 #if 0
1299 {test_lmv2_ntlmv2_no_dom, "NTLMv2 and LMv2 (no domain)", false},
1300 #endif
1301 {test_lm, "LM", false},
1302 {test_lm_ntlm, "LM and NTLM", false},
1303 {test_lm_ntlm_both_broken, "LM and NTLM, both broken", false},
1304 {test_ntlm, "NTLM", false},
1305 {test_ntlm_in_lm, "NTLM in LM", false},
1306 {test_ntlm_in_both, "NTLM in both", false},
1307 {test_ntlmv2, "NTLMv2", false},
1308 {test_ntlmv2_no_dom, "NTLMv2 (no domain)", false},
1309 {test_lmv2, "LMv2", false},
1310 {test_lmv2_no_dom, "LMv2 (no domain)", false},
1311 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", false},
1312 {test_ntlmv2_lmv2_broken_no_dom, "NTLMv2 and LMv2, LMv2 broken (no domain)", false},
1313 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", false},
1314 #if 0
1315 {test_ntlmv2_ntlmv2_broken_no_dom, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", false},
1316 #endif
1317 {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", false},
1318 {test_ntlmv2_both_broken_no_dom, "NTLMv2 and LMv2, both broken (no domain)", false},
1319 {test_ntlm_lm_broken, "NTLM and LM, LM broken", false},
1320 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", false},
1321 {test_ntlm2, "NTLM2 (NTLMv2 session security)", false},
1322 {test_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", false},
1323 {test_lmv2_ntlm_both_broken_no_dom, "LMv2 and NTLM, both broken (no domain)", false},
1324 {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", false},
1325 {test_lmv2_ntlm_break_ntlm_no_dom, "LMv2 and NTLM, NTLM broken (no domain)", false},
1326 {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", false},
1327 {test_lmv2_ntlm_break_lm_no_dom, "LMv2 and NTLM, LMv2 broken (no domain)", false},
1328 {test_plaintext_none_broken, "Plaintext", false},
1329 {test_plaintext_lm_broken, "Plaintext LM broken", false},
1330 {test_plaintext_nt_broken, "Plaintext NT broken", false},
1331 {test_plaintext_nt_only, "Plaintext NT only", false},
1332 {test_plaintext_lm_only, "Plaintext LM only", false},
1333 {NULL, NULL}
1337 try a netlogon SamLogon
1339 static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1340 struct torture_context *tctx,
1341 struct netlogon_creds_CredentialState *creds,
1342 const char *comment,
1343 const char *account_domain, const char *account_name,
1344 const char *plain_pass, uint32_t parameter_control,
1345 NTSTATUS expected_error, bool old_password,
1346 int n_subtests)
1348 TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_SamLogon function-level context");
1349 int i, v, l, f;
1350 bool ret = true;
1351 int validation_levels[] = {2,3,6};
1352 int logon_levels[] = { NetlogonNetworkInformation, NetlogonNetworkTransitiveInformation };
1353 int function_levels[] = {
1354 NDR_NETR_LOGONSAMLOGON,
1355 NDR_NETR_LOGONSAMLOGONEX,
1356 NDR_NETR_LOGONSAMLOGONWITHFLAGS };
1357 struct samlogon_state samlogon_state;
1359 union netr_LogonLevel logon;
1360 union netr_Validation validation;
1361 uint8_t authoritative = 0;
1362 uint32_t flags = 0;
1364 ZERO_STRUCT(logon);
1366 torture_comment(tctx, "Testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1368 samlogon_state.comment = comment;
1369 samlogon_state.account_name = account_name;
1370 samlogon_state.account_domain = account_domain;
1371 samlogon_state.password = plain_pass;
1372 samlogon_state.workgroup = lpcfg_workgroup(tctx->lp_ctx);
1373 samlogon_state.netbios_name = lpcfg_netbios_name(tctx->lp_ctx);
1374 samlogon_state.p = p;
1375 samlogon_state.creds = creds;
1376 samlogon_state.expected_error = expected_error;
1377 samlogon_state.chall = data_blob_talloc(fn_ctx, NULL, 8);
1378 samlogon_state.parameter_control = parameter_control;
1379 samlogon_state.old_password = old_password;
1380 samlogon_state.tctx = tctx;
1382 generate_random_buffer(samlogon_state.chall.data, 8);
1383 samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1384 samlogon_state.r_flags.in.computer_name = TEST_MACHINE_NAME;
1385 samlogon_state.r_flags.in.credential = &samlogon_state.auth;
1386 samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2;
1387 samlogon_state.r_flags.in.flags = &flags;
1388 samlogon_state.r_flags.in.logon = &logon;
1389 samlogon_state.r_flags.out.validation = &validation;
1390 samlogon_state.r_flags.out.authoritative = &authoritative;
1391 samlogon_state.r_flags.out.flags = &flags;
1393 samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1394 samlogon_state.r_ex.in.computer_name = TEST_MACHINE_NAME;
1395 samlogon_state.r_ex.in.flags = &flags;
1396 samlogon_state.r_ex.in.logon = &logon;
1397 samlogon_state.r_ex.out.validation = &validation;
1398 samlogon_state.r_ex.out.authoritative = &authoritative;
1399 samlogon_state.r_ex.out.flags = &flags;
1401 samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1402 samlogon_state.r.in.computer_name = TEST_MACHINE_NAME;
1403 samlogon_state.r.in.credential = &samlogon_state.auth;
1404 samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
1405 samlogon_state.r.in.logon = &logon;
1406 samlogon_state.r.out.validation = &validation;
1407 samlogon_state.r.out.authoritative = &authoritative;
1410 for (f=0;f<ARRAY_SIZE(function_levels);f++) {
1411 for (i=0; test_table[i].fn; i++) {
1412 if (n_subtests && (i > n_subtests)) {
1413 continue;
1415 for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
1416 for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
1417 char *error_string = NULL;
1418 TALLOC_CTX *tmp_ctx = talloc_named(fn_ctx, 0, "test_SamLogon inner loop");
1419 samlogon_state.mem_ctx = tmp_ctx;
1420 samlogon_state.function_level = function_levels[f];
1421 samlogon_state.r.in.validation_level = validation_levels[v];
1422 samlogon_state.r.in.logon_level = logon_levels[l];
1423 samlogon_state.r_ex.in.validation_level = validation_levels[v];
1424 samlogon_state.r_ex.in.logon_level = logon_levels[l];
1425 samlogon_state.r_flags.in.validation_level = validation_levels[v];
1426 samlogon_state.r_flags.in.logon_level = logon_levels[l];
1427 if (!test_table[i].fn(&samlogon_state, &error_string)) {
1428 torture_comment(tctx, "Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
1429 samlogon_state.comment,
1430 samlogon_state.account_domain,
1431 samlogon_state.account_name,
1432 test_table[i].name, validation_levels[v],
1433 logon_levels[l], function_levels[f]);
1435 if (test_table[i].expect_fail) {
1436 torture_comment(tctx, " failed (expected, test incomplete): %s\n", error_string);
1437 } else {
1438 torture_comment(tctx, " failed: %s\n", error_string);
1439 ret = false;
1441 SAFE_FREE(error_string);
1443 talloc_free(tmp_ctx);
1448 talloc_free(fn_ctx);
1449 return ret;
1453 test an ADS style interactive domain logon
1455 bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1456 struct torture_context *tctx,
1457 struct netlogon_creds_CredentialState *creds,
1458 const char *comment,
1459 const char *workstation_name,
1460 const char *account_domain, const char *account_name,
1461 const char *plain_pass, uint32_t parameter_control,
1462 NTSTATUS expected_error)
1464 NTSTATUS status;
1465 TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context");
1466 bool ret = true;
1467 struct netr_LogonSamLogonWithFlags r;
1468 struct netr_Authenticator a, ra;
1469 struct netr_PasswordInfo pinfo;
1470 uint32_t flags = 0;
1472 union netr_LogonLevel logon;
1473 union netr_Validation validation;
1474 uint8_t authoritative = 0;
1475 struct dcerpc_binding_handle *b = p->binding_handle;
1477 ZERO_STRUCT(a);
1478 ZERO_STRUCT(r);
1479 ZERO_STRUCT(ra);
1481 ZERO_STRUCT(logon);
1482 ZERO_STRUCT(validation);
1484 netlogon_creds_client_authenticator(creds, &a);
1486 logon.password = &pinfo;
1488 r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1489 r.in.computer_name = TEST_MACHINE_NAME;
1490 r.in.credential = &a;
1491 r.in.return_authenticator = &ra;
1492 r.in.logon_level = NetlogonInteractiveTransitiveInformation;
1493 r.in.logon = &logon;
1494 r.in.validation_level = 6;
1495 r.in.flags = &flags;
1496 r.out.validation = &validation;
1497 r.out.authoritative = &authoritative;
1498 r.out.flags = &flags;
1500 pinfo.identity_info.domain_name.string = account_domain;
1501 pinfo.identity_info.parameter_control = parameter_control;
1502 pinfo.identity_info.logon_id_low = 0;
1503 pinfo.identity_info.logon_id_high = 0;
1504 pinfo.identity_info.account_name.string = account_name;
1505 pinfo.identity_info.workstation.string = workstation_name;
1507 if (!E_deshash(plain_pass, pinfo.lmpassword.hash)) {
1508 ZERO_STRUCT(pinfo.lmpassword.hash);
1510 E_md4hash(plain_pass, pinfo.ntpassword.hash);
1512 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1513 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
1514 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
1515 } else {
1516 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
1517 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
1520 torture_comment(tctx, "Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment);
1522 torture_assert_ntstatus_ok_goto(tctx,
1523 dcerpc_netr_LogonSamLogonWithFlags_r(b, fn_ctx, &r),
1524 ret, failed,
1525 talloc_asprintf(tctx, "%s: netr_LogonSamLogonWithFlags - %s\n",
1526 __location__, nt_errstr(status)));
1528 if (!r.out.return_authenticator) {
1529 talloc_free(fn_ctx);
1530 torture_fail(tctx, "no authenticator returned");
1533 torture_assert_goto(tctx,
1534 netlogon_creds_client_check(creds, &r.out.return_authenticator->cred),
1535 ret, failed,
1536 "Credential chaining failed\n");
1538 torture_assert_ntstatus_equal(tctx, r.out.result, expected_error,
1539 talloc_asprintf(tctx, "[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n",
1540 account_domain, account_name, nt_errstr(expected_error), nt_errstr(r.out.result)));
1542 ret = true;
1543 failed:
1544 talloc_free(fn_ctx);
1546 return ret;
1549 /* This sets and resets the "minPwdAge" (in order to allow immediate user
1550 * password changes). The behaviour is controlled by the "set" boolean. */
1551 static bool handle_minPwdAge(struct torture_context *torture,
1552 TALLOC_CTX *mem_ctx, bool set)
1554 struct dcerpc_pipe *p;
1555 struct policy_handle connect_handle, domain_handle;
1556 struct samr_Connect c_r;
1557 struct samr_LookupDomain ld_r;
1558 struct samr_OpenDomain od_r;
1559 struct samr_QueryDomainInfo qdi_r;
1560 struct samr_SetDomainInfo sdi_r;
1561 struct samr_Close cl_r;
1562 struct lsa_String domName;
1563 struct dom_sid *domSid = NULL;
1564 union samr_DomainInfo *domInfo = NULL;
1565 static int64_t old_minPwdAge = 0;
1566 NTSTATUS status;
1568 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
1569 if (!NT_STATUS_IS_OK(status)) {
1570 return false;
1573 c_r.in.system_name = 0;
1574 c_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1575 c_r.out.connect_handle = &connect_handle;
1577 torture_assert_ntstatus_ok(torture,
1578 dcerpc_samr_Connect_r(p->binding_handle, mem_ctx, &c_r),
1579 "Connect failed");
1580 torture_assert_ntstatus_ok(torture, c_r.out.result, "Connect failed");
1582 ld_r.in.connect_handle = &connect_handle;
1583 ld_r.in.domain_name = &domName;
1584 ld_r.in.domain_name->string = lpcfg_workgroup(torture->lp_ctx);
1585 ld_r.out.sid = &domSid;
1587 torture_assert_ntstatus_ok(torture,
1588 dcerpc_samr_LookupDomain_r(p->binding_handle, mem_ctx, &ld_r),
1589 "LookupDomain failed");
1590 torture_assert_ntstatus_ok(torture, ld_r.out.result,
1591 "LookupDomain failed");
1593 od_r.in.connect_handle = &connect_handle;
1594 od_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1595 od_r.in.sid = *ld_r.out.sid;
1596 od_r.out.domain_handle = &domain_handle;
1598 torture_assert_ntstatus_ok(torture,
1599 dcerpc_samr_OpenDomain_r(p->binding_handle, mem_ctx, &od_r),
1600 "OpenDomain failed");
1601 torture_assert_ntstatus_ok(torture, od_r.out.result,
1602 "OpenDomain failed");
1604 qdi_r.in.domain_handle = &domain_handle;
1605 qdi_r.in.level = DomainPasswordInformation;
1606 qdi_r.out.info = &domInfo;
1608 torture_assert_ntstatus_ok(torture,
1609 dcerpc_samr_QueryDomainInfo_r(p->binding_handle, mem_ctx, &qdi_r),
1610 "QueryDomainInfo failed");
1611 torture_assert_ntstatus_ok(torture, qdi_r.out.result,
1612 "QueryDomainInfo failed");
1614 if (set) {
1615 old_minPwdAge = domInfo->info1.min_password_age;
1616 domInfo->info1.min_password_age = 0;
1617 } else {
1618 domInfo->info1.min_password_age = old_minPwdAge;
1621 sdi_r.in.domain_handle = &domain_handle;
1622 sdi_r.in.level = DomainPasswordInformation;
1623 sdi_r.in.info = domInfo;
1625 torture_assert_ntstatus_ok(torture,
1626 dcerpc_samr_SetDomainInfo_r(p->binding_handle, mem_ctx, &sdi_r),
1627 "SetDomainInfo failed");
1628 torture_assert_ntstatus_ok(torture, sdi_r.out.result,
1629 "SetDomainInfo failed");
1631 cl_r.in.handle = &connect_handle;
1632 cl_r.out.handle = &connect_handle;
1634 torture_assert_ntstatus_ok(torture,
1635 dcerpc_samr_Close_r(p->binding_handle, mem_ctx, &cl_r),
1636 "Close failed");
1637 torture_assert_ntstatus_ok(torture, cl_r.out.result, "Close failed");
1639 return true;
1642 bool torture_rpc_samlogon(struct torture_context *torture)
1644 NTSTATUS status;
1645 struct dcerpc_pipe *p;
1646 struct dcerpc_binding *b;
1647 struct cli_credentials *machine_credentials;
1648 TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon");
1649 bool ret = true;
1650 struct test_join *join_ctx = NULL;
1651 struct test_join *user_ctx = NULL, *user_ctx_wrong_wks = NULL, *user_ctx_wrong_time = NULL;
1652 const char *old_user_password, *user_password_wrong_wks, *user_password_wrong_time;
1653 char *user_password;
1654 const char *userdomain;
1655 struct samr_SetUserInfo s;
1656 union samr_UserInfo u;
1657 int i;
1658 int ci;
1660 unsigned int credential_flags[] = {
1661 NETLOGON_NEG_AUTH2_FLAGS,
1662 NETLOGON_NEG_ARCFOUR,
1663 NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
1664 NETLOGON_NEG_AUTH2_ADS_FLAGS,
1665 0 /* yes, this is a valid flag, causes the use of DES */
1668 struct netlogon_creds_CredentialState *creds;
1669 struct dcerpc_pipe *tmp_p = NULL;
1671 torture_assert(torture, handle_minPwdAge(torture, mem_ctx, true),
1672 "handle_minPwdAge error!");
1674 /* We only need to join as a workstation here, and in future,
1675 * if we wish to test against trusted domains, we must be a
1676 * workstation here */
1677 join_ctx = torture_join_domain(torture, TEST_MACHINE_NAME, ACB_WSTRUST,
1678 &machine_credentials);
1679 torture_assert(torture, join_ctx, "Failed to join as Workstation\n");
1681 userdomain = torture_setting_string(torture, "userdomain", lpcfg_workgroup(torture->lp_ctx));
1683 user_ctx = torture_create_testuser(torture,
1684 TEST_USER_NAME,
1685 userdomain,
1686 ACB_NORMAL,
1687 &old_user_password);
1688 torture_assert(torture, user_ctx, "Failed to create a test user\n");
1690 user_password = talloc_strdup(torture, old_user_password);
1691 torture_assert(torture, user_password != NULL, "Failed to copy old_user_password\n");
1693 tmp_p = torture_join_samr_pipe(user_ctx);
1694 torture_assert(torture, tmp_p, "torture_join_samr_pipe failed\n");
1695 test_ChangePasswordUser3(tmp_p, torture,
1696 TEST_USER_NAME, 16 /* > 14 */, &user_password,
1697 NULL, 0, false);
1699 user_ctx_wrong_wks = torture_create_testuser(torture,
1700 TEST_USER_NAME_WRONG_WKS,
1701 userdomain,
1702 ACB_NORMAL,
1703 &user_password_wrong_wks);
1704 torture_assert(torture, user_ctx_wrong_wks,
1705 "Failed to create a test user (wrong workstation test)\n");
1707 ZERO_STRUCT(u);
1708 s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_wks);
1709 s.in.info = &u;
1710 s.in.level = 21;
1712 u.info21.fields_present = SAMR_FIELD_WORKSTATIONS;
1713 u.info21.workstations.string = "not" TEST_MACHINE_NAME;
1715 tmp_p = torture_join_samr_pipe(user_ctx_wrong_wks);
1716 status = dcerpc_samr_SetUserInfo_r(tmp_p->binding_handle, mem_ctx, &s);
1717 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
1718 talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status)));
1719 torture_assert_ntstatus_ok_goto(torture, s.out.result, ret, failed,
1720 talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s.out.result)));
1722 user_ctx_wrong_time
1723 = torture_create_testuser(torture, TEST_USER_NAME_WRONG_TIME,
1724 userdomain,
1725 ACB_NORMAL,
1726 &user_password_wrong_time);
1727 torture_assert(torture, user_ctx_wrong_time,
1728 "Failed to create a test user (wrong workstation test)\n");
1730 ZERO_STRUCT(u);
1731 s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_time);
1732 s.in.info = &u;
1733 s.in.level = 21;
1735 u.info21.fields_present = SAMR_FIELD_WORKSTATIONS | SAMR_FIELD_LOGON_HOURS;
1736 u.info21.workstations.string = TEST_MACHINE_NAME;
1737 u.info21.logon_hours.units_per_week = 168;
1738 u.info21.logon_hours.bits = talloc_zero_array(mem_ctx, uint8_t, 168);
1740 tmp_p = torture_join_samr_pipe(user_ctx_wrong_time);
1741 status = dcerpc_samr_SetUserInfo_r(tmp_p->binding_handle, mem_ctx, &s);
1742 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
1743 talloc_asprintf(torture, "SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status)));
1744 torture_assert_ntstatus_ok_goto(torture, s.out.result, ret, failed,
1745 talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s.out.result)));
1747 status = torture_rpc_binding(torture, &b);
1748 if (!NT_STATUS_IS_OK(status)) {
1749 ret = false;
1750 goto failed;
1753 /* We have to use schannel, otherwise the SamLogonEx fails
1754 * with INTERNAL_ERROR */
1756 status = dcerpc_binding_set_flags(b,
1757 DCERPC_SCHANNEL | DCERPC_SIGN |
1758 DCERPC_SCHANNEL_128,
1759 DCERPC_AUTH_OPTIONS);
1760 torture_assert_ntstatus_ok(torture, status, "set flags");
1762 status = dcerpc_pipe_connect_b(mem_ctx, &p, b,
1763 &ndr_table_netlogon,
1764 machine_credentials, torture->ev, torture->lp_ctx);
1766 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
1767 talloc_asprintf(torture, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status)));
1769 creds = cli_credentials_get_netlogon_creds(machine_credentials);
1770 if (creds == NULL) {
1771 ret = false;
1772 goto failed;
1777 struct {
1778 const char *comment;
1779 const char *domain;
1780 const char *username;
1781 const char *password;
1782 bool network_login;
1783 NTSTATUS expected_interactive_error;
1784 NTSTATUS expected_network_error;
1785 uint32_t parameter_control;
1786 bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
1787 } usercreds[] = {
1789 .comment = "domain\\user",
1790 .domain = cli_credentials_get_domain(cmdline_credentials),
1791 .username = cli_credentials_get_username(cmdline_credentials),
1792 .password = cli_credentials_get_password(cmdline_credentials),
1793 .network_login = true,
1794 .expected_interactive_error = NT_STATUS_OK,
1795 .expected_network_error = NT_STATUS_OK
1798 .comment = "realm\\user",
1799 .domain = cli_credentials_get_realm(cmdline_credentials),
1800 .username = cli_credentials_get_username(cmdline_credentials),
1801 .password = cli_credentials_get_password(cmdline_credentials),
1802 .network_login = true,
1803 .expected_interactive_error = NT_STATUS_OK,
1804 .expected_network_error = NT_STATUS_OK
1807 .comment = "user@domain",
1808 .domain = NULL,
1809 .username = talloc_asprintf(mem_ctx,
1810 "%s@%s",
1811 cli_credentials_get_username(cmdline_credentials),
1812 cli_credentials_get_domain(cmdline_credentials)
1814 .password = cli_credentials_get_password(cmdline_credentials),
1815 .network_login = false, /* works for some things, but not NTLMv2. Odd */
1816 .expected_interactive_error = NT_STATUS_OK,
1817 .expected_network_error = NT_STATUS_OK
1820 .comment = "user@realm",
1821 .domain = NULL,
1822 .username = talloc_asprintf(mem_ctx,
1823 "%s@%s",
1824 cli_credentials_get_username(cmdline_credentials),
1825 cli_credentials_get_realm(cmdline_credentials)
1827 .password = cli_credentials_get_password(cmdline_credentials),
1828 .network_login = true,
1829 .expected_interactive_error = NT_STATUS_OK,
1830 .expected_network_error = NT_STATUS_OK
1833 .comment = "machine domain\\user",
1834 .domain = cli_credentials_get_domain(machine_credentials),
1835 .username = cli_credentials_get_username(machine_credentials),
1836 .password = cli_credentials_get_password(machine_credentials),
1837 .network_login = true,
1838 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1839 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1842 .comment = "machine domain\\user",
1843 .domain = cli_credentials_get_domain(machine_credentials),
1844 .username = cli_credentials_get_username(machine_credentials),
1845 .password = cli_credentials_get_password(machine_credentials),
1846 .network_login = true,
1847 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1848 .expected_network_error = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
1851 .comment = "machine realm\\user",
1852 .domain = cli_credentials_get_realm(machine_credentials),
1853 .username = cli_credentials_get_username(machine_credentials),
1854 .password = cli_credentials_get_password(machine_credentials),
1855 .network_login = true,
1856 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1857 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1860 .comment = "machine user@domain",
1861 .domain = NULL,
1862 .username = talloc_asprintf(mem_ctx,
1863 "%s@%s",
1864 cli_credentials_get_username(machine_credentials),
1865 cli_credentials_get_domain(machine_credentials)
1867 .password = cli_credentials_get_password(machine_credentials),
1868 .network_login = false, /* works for some things, but not NTLMv2. Odd */
1869 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1870 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1873 .comment = "machine user@realm",
1874 .domain = NULL,
1875 .username = talloc_asprintf(mem_ctx,
1876 "%s@%s",
1877 cli_credentials_get_username(machine_credentials),
1878 cli_credentials_get_realm(machine_credentials)
1880 .password = cli_credentials_get_password(machine_credentials),
1881 .network_login = true,
1882 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1883 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1886 .comment = "test user (long pw): domain\\user",
1887 .domain = userdomain,
1888 .username = TEST_USER_NAME,
1889 .password = user_password,
1890 .network_login = true,
1891 .expected_interactive_error = NT_STATUS_OK,
1892 .expected_network_error = NT_STATUS_OK
1895 .comment = "test user (long pw): user@realm",
1896 .domain = NULL,
1897 .username = talloc_asprintf(mem_ctx,
1898 "%s@%s",
1899 TEST_USER_NAME,
1900 lpcfg_realm(torture->lp_ctx)),
1901 .password = user_password,
1902 .network_login = true,
1903 .expected_interactive_error = NT_STATUS_OK,
1904 .expected_network_error = NT_STATUS_OK
1907 .comment = "test user (long pw): user@domain",
1908 .domain = NULL,
1909 .username = talloc_asprintf(mem_ctx,
1910 "%s@%s",
1911 TEST_USER_NAME,
1912 userdomain),
1913 .password = user_password,
1914 .network_login = false, /* works for some things, but not NTLMv2. Odd */
1915 .expected_interactive_error = NT_STATUS_OK,
1916 .expected_network_error = NT_STATUS_OK
1918 /* Oddball, can we use the old password ? */
1920 .comment = "test user: user\\domain OLD PASSWORD",
1921 .domain = userdomain,
1922 .username = TEST_USER_NAME,
1923 .password = old_user_password,
1924 .network_login = true,
1925 .expected_interactive_error = NT_STATUS_WRONG_PASSWORD,
1926 .expected_network_error = NT_STATUS_OK,
1927 .old_password = true
1930 .comment = "test user (wrong workstation): domain\\user",
1931 .domain = userdomain,
1932 .username = TEST_USER_NAME_WRONG_WKS,
1933 .password = user_password_wrong_wks,
1934 .network_login = true,
1935 .expected_interactive_error = NT_STATUS_INVALID_WORKSTATION,
1936 .expected_network_error = NT_STATUS_INVALID_WORKSTATION
1940 /* Try all the tests for different username forms */
1941 for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) {
1943 if (!test_InteractiveLogon(p, mem_ctx, torture, creds,
1944 usercreds[ci].comment,
1945 TEST_MACHINE_NAME,
1946 usercreds[ci].domain,
1947 usercreds[ci].username,
1948 usercreds[ci].password,
1949 usercreds[ci].parameter_control,
1950 usercreds[ci].expected_interactive_error)) {
1951 ret = false;
1952 goto failed;
1955 if (usercreds[ci].network_login) {
1956 if (!test_SamLogon(p, mem_ctx, torture, creds,
1957 usercreds[ci].comment,
1958 usercreds[ci].domain,
1959 usercreds[ci].username,
1960 usercreds[ci].password,
1961 usercreds[ci].parameter_control,
1962 usercreds[ci].expected_network_error,
1963 usercreds[ci].old_password,
1964 0)) {
1965 ret = false;
1966 goto failed;
1971 /* Using the first username form, try the different
1972 * credentials flag setups, on only one of the tests (checks
1973 * session key encryption) */
1975 for (i=0; i < ARRAY_SIZE(credential_flags); i++) {
1976 /* TODO: Somehow we lost setting up the different credential flags here! */
1978 torture_comment(torture,
1979 "Testing with flags: 0x%08x\n",
1980 credential_flags[i]);
1982 if (!test_InteractiveLogon(p, mem_ctx, torture, creds,
1983 usercreds[0].comment,
1984 TEST_MACHINE_NAME,
1985 usercreds[0].domain,
1986 usercreds[0].username,
1987 usercreds[0].password,
1988 usercreds[0].parameter_control,
1989 usercreds[0].expected_interactive_error)) {
1990 ret = false;
1991 goto failed;
1994 if (usercreds[0].network_login) {
1995 if (!test_SamLogon(p, mem_ctx, torture, creds,
1996 usercreds[0].comment,
1997 usercreds[0].domain,
1998 usercreds[0].username,
1999 usercreds[0].password,
2000 usercreds[0].parameter_control,
2001 usercreds[0].expected_network_error,
2002 usercreds[0].old_password,
2003 1)) {
2004 ret = false;
2005 goto failed;
2011 failed:
2012 torture_assert(torture, handle_minPwdAge(torture, mem_ctx, false),
2013 "handle_minPwdAge error!");
2015 talloc_free(mem_ctx);
2017 torture_leave_domain(torture, join_ctx);
2018 torture_leave_domain(torture, user_ctx);
2019 torture_leave_domain(torture, user_ctx_wrong_wks);
2020 torture_leave_domain(torture, user_ctx_wrong_time);
2021 return ret;