ctdb-scripts: Support storing statd-callout state in cluster filesystem
[samba4-gss.git] / source4 / torture / rpc / samlogon.c
blob57768aeb41138b263a68f58613cef20de58d8dad
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/cmdline/cmdline.h"
29 #include "torture/rpc/torture_rpc.h"
30 #include "auth/gensec/gensec.h"
31 #include "libcli/auth/libcli_auth.h"
32 #include "param/param.h"
34 #include <gnutls/gnutls.h>
35 #include <gnutls/crypto.h>
37 #define TEST_MACHINE_NAME "samlogontest"
38 #define TEST_USER_NAME "samlogontestuser"
39 #define TEST_USER_NAME_WRONG_WKS "samlogontest2"
40 #define TEST_USER_NAME_WRONG_TIME "samlogontest3"
42 enum ntlm_break {
43 BREAK_BOTH,
44 BREAK_NONE,
45 BREAK_LM,
46 BREAK_NT,
47 NO_LM,
48 NO_NT
51 struct samlogon_state {
52 TALLOC_CTX *mem_ctx;
53 struct torture_context *tctx;
54 const char *comment;
55 const char *account_name;
56 const char *account_domain;
57 const char *netbios_name;
58 const char *password;
59 const char *workgroup;
60 struct dcerpc_pipe *p;
61 int function_level;
62 uint32_t parameter_control;
63 struct netr_LogonSamLogon r;
64 struct netr_LogonSamLogonEx r_ex;
65 struct netr_LogonSamLogonWithFlags r_flags;
66 struct netr_Authenticator auth, auth2;
67 struct netlogon_creds_CredentialState *creds;
68 NTSTATUS expected_error;
69 bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
70 DATA_BLOB chall;
74 Authenticate a user with a challenge/response, checking session key
75 and valid authentication types
77 static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
78 enum ntlm_break break_which,
79 uint32_t parameter_control,
80 DATA_BLOB *chall,
81 DATA_BLOB *lm_response,
82 DATA_BLOB *nt_response,
83 uint8_t lm_key[8],
84 uint8_t user_session_key[16],
85 char **error_string)
87 NTSTATUS status;
88 struct netr_LogonSamLogon *r = &samlogon_state->r;
89 struct netr_LogonSamLogonEx *r_ex = &samlogon_state->r_ex;
90 struct netr_LogonSamLogonWithFlags *r_flags = &samlogon_state->r_flags;
91 struct netr_NetworkInfo ninfo;
92 struct netr_SamBaseInfo *base = NULL;
93 uint16_t validation_level = 0;
94 enum dcerpc_AuthType auth_type;
95 enum dcerpc_AuthLevel auth_level;
97 dcerpc_binding_handle_auth_info(samlogon_state->p->binding_handle,
98 &auth_type,
99 &auth_level);
101 samlogon_state->r.in.logon->network = &ninfo;
102 samlogon_state->r_ex.in.logon->network = &ninfo;
103 samlogon_state->r_flags.in.logon->network = &ninfo;
105 ninfo.identity_info.domain_name.string = samlogon_state->account_domain;
106 ninfo.identity_info.parameter_control = parameter_control;
107 ninfo.identity_info.logon_id = 0;
108 ninfo.identity_info.account_name.string = samlogon_state->account_name;
109 ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
111 memcpy(ninfo.challenge, chall->data, 8);
113 switch (break_which) {
114 case BREAK_NONE:
115 break;
116 case BREAK_LM:
117 if (lm_response && lm_response->data) {
118 lm_response->data[0]++;
120 break;
121 case BREAK_NT:
122 if (nt_response && nt_response->data) {
123 nt_response->data[0]++;
125 break;
126 case BREAK_BOTH:
127 if (lm_response && lm_response->data) {
128 lm_response->data[0]++;
130 if (nt_response && nt_response->data) {
131 nt_response->data[0]++;
133 break;
134 case NO_LM:
135 data_blob_free(lm_response);
136 break;
137 case NO_NT:
138 data_blob_free(nt_response);
139 break;
142 if (nt_response) {
143 ninfo.nt.data = nt_response->data;
144 ninfo.nt.length = nt_response->length;
145 } else {
146 ninfo.nt.data = NULL;
147 ninfo.nt.length = 0;
150 if (lm_response) {
151 ninfo.lm.data = lm_response->data;
152 ninfo.lm.length = lm_response->length;
153 } else {
154 ninfo.lm.data = NULL;
155 ninfo.lm.length = 0;
158 switch (samlogon_state->function_level) {
159 case NDR_NETR_LOGONSAMLOGON:
160 ZERO_STRUCT(samlogon_state->auth2);
161 netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
163 r->out.return_authenticator = NULL;
164 status = dcerpc_netr_LogonSamLogon_r(samlogon_state->p->binding_handle,
165 samlogon_state->mem_ctx, r);
166 if (!NT_STATUS_IS_OK(status)) {
167 if (error_string) {
168 *error_string = strdup(nt_errstr(status));
170 return status;
172 if (!r->out.return_authenticator ||
173 !netlogon_creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) {
174 torture_comment(samlogon_state->tctx, "Credential chaining failed\n");
176 if (!NT_STATUS_IS_OK(r->out.result)) {
177 if (error_string) {
178 *error_string = strdup(nt_errstr(r->out.result));
180 return r->out.result;
183 validation_level = r->in.validation_level;
185 status = netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds,
186 validation_level,
187 r->out.validation,
188 auth_type,
189 auth_level);
190 if (!NT_STATUS_IS_OK(status)) {
191 if (error_string) {
192 *error_string = strdup(nt_errstr(status));
194 return status;
197 switch (validation_level) {
198 case 2:
199 base = &r->out.validation->sam2->base;
200 break;
201 case 3:
202 base = &r->out.validation->sam3->base;
203 break;
204 case 6:
205 base = &r->out.validation->sam6->base;
206 break;
208 break;
209 case NDR_NETR_LOGONSAMLOGONEX:
210 status = dcerpc_netr_LogonSamLogonEx_r(samlogon_state->p->binding_handle,
211 samlogon_state->mem_ctx, r_ex);
212 if (!NT_STATUS_IS_OK(status)) {
213 if (error_string) {
214 *error_string = strdup(nt_errstr(status));
216 return status;
218 if (!NT_STATUS_IS_OK(r_ex->out.result)) {
219 if (error_string) {
220 *error_string = strdup(nt_errstr(r_ex->out.result));
222 return r_ex->out.result;
225 validation_level = r_ex->in.validation_level;
227 status = netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds,
228 validation_level,
229 r_ex->out.validation,
230 auth_type,
231 auth_level);
232 if (!NT_STATUS_IS_OK(status)) {
233 if (error_string) {
234 *error_string = strdup(nt_errstr(status));
236 return status;
239 switch (validation_level) {
240 case 2:
241 base = &r_ex->out.validation->sam2->base;
242 break;
243 case 3:
244 base = &r_ex->out.validation->sam3->base;
245 break;
246 case 6:
247 base = &r_ex->out.validation->sam6->base;
248 break;
250 break;
251 case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
252 ZERO_STRUCT(samlogon_state->auth2);
253 netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
255 r_flags->out.return_authenticator = NULL;
256 status = dcerpc_netr_LogonSamLogonWithFlags_r(samlogon_state->p->binding_handle,
257 samlogon_state->mem_ctx, r_flags);
258 if (!NT_STATUS_IS_OK(status)) {
259 if (error_string) {
260 *error_string = strdup(nt_errstr(status));
262 return status;
264 if (!r_flags->out.return_authenticator ||
265 !netlogon_creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) {
266 torture_comment(samlogon_state->tctx, "Credential chaining failed\n");
268 if (!NT_STATUS_IS_OK(r_flags->out.result)) {
269 if (error_string) {
270 *error_string = strdup(nt_errstr(r_flags->out.result));
272 return r_flags->out.result;
275 validation_level = r_flags->in.validation_level;
277 status = netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds,
278 validation_level,
279 r_flags->out.validation,
280 auth_type,
281 auth_level);
282 if (!NT_STATUS_IS_OK(status)) {
283 if (error_string) {
284 *error_string = strdup(nt_errstr(status));
286 return status;
289 switch (validation_level) {
290 case 2:
291 base = &r_flags->out.validation->sam2->base;
292 break;
293 case 3:
294 base = &r_flags->out.validation->sam3->base;
295 break;
296 case 6:
297 base = &r_flags->out.validation->sam6->base;
298 break;
300 break;
301 default:
302 /* can't happen */
303 return NT_STATUS_INVALID_PARAMETER;
306 if (!base) {
307 torture_comment(samlogon_state->tctx, "No user info returned from 'successful' SamLogon*() call!\n");
308 return NT_STATUS_INVALID_PARAMETER;
311 if (user_session_key) {
312 memcpy(user_session_key, base->key.key, 16);
314 if (lm_key) {
315 memcpy(lm_key, base->LMSessKey.key, 8);
318 return status;
323 * Test the normal 'LM and NTLM' combination
326 static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
328 bool pass = true;
329 bool lm_good;
330 NTSTATUS nt_status;
331 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
332 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
333 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
335 uint8_t lm_key[8];
336 uint8_t user_session_key[16];
337 uint8_t lm_hash[16];
338 uint8_t nt_hash[16];
340 ZERO_STRUCT(lm_key);
341 ZERO_STRUCT(user_session_key);
343 lm_good = SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
344 if (!lm_good) {
345 ZERO_STRUCT(lm_hash);
346 } else {
347 E_deshash(samlogon_state->password, lm_hash);
350 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
352 E_md4hash(samlogon_state->password, nt_hash);
353 SMBsesskeygen_ntv1(nt_hash, session_key.data);
355 nt_status = check_samlogon(samlogon_state,
356 break_which,
357 samlogon_state->parameter_control,
358 &samlogon_state->chall,
359 &lm_response,
360 &nt_response,
361 lm_key,
362 user_session_key,
363 error_string);
365 data_blob_free(&lm_response);
367 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
368 /* for 'long' passwords, the LM password is invalid */
369 if (break_which == NO_NT && !lm_good) {
370 return true;
372 /* for modern servers, the LM password is invalid */
373 if (break_which == NO_NT
374 && !torture_setting_bool(samlogon_state->tctx, "samba3", false)) {
375 return true;
378 /* for 'old' passwords, we allow the server to be OK or wrong password */
379 if (samlogon_state->old_password) {
380 return true;
382 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
383 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
384 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
385 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
386 int ret;
388 SAFE_FREE(*error_string);
389 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
390 if (ret == -1) {
391 *error_string = NULL;
393 return false;
394 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
395 return true;
396 } else if (!NT_STATUS_IS_OK(nt_status)) {
397 return false;
400 if (break_which == NO_NT && !lm_good) {
401 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
402 return false;
405 /* for modern servers, the LM password is invalid */
406 if (break_which == NO_NT
407 && !torture_setting_bool(samlogon_state->tctx, "samba3", false)) {
408 *error_string = strdup("LM password is OK but should have failed against a modern server");
409 return false;
412 if (!all_zero(lm_key, sizeof(lm_key)) != 0) {
413 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
414 torture_comment(samlogon_state->tctx, "lm_key:\n");
415 dump_data(1, lm_key, 8);
416 torture_comment(samlogon_state->tctx, "expected (all zeros):\n");
417 pass = false;
420 switch (break_which) {
421 case NO_NT:
423 uint8_t lm_key_expected[16];
424 memcpy(lm_key_expected, session_key.data, 8);
425 memset(lm_key_expected+8, '\0', 8);
426 if (memcmp(lm_key_expected, user_session_key,
427 16) != 0) {
428 *error_string = strdup("NT Session Key does not match expectations (should be first-8 session key)!\n");
429 torture_comment(samlogon_state->tctx, "user_session_key:\n");
430 dump_data(1, user_session_key, sizeof(user_session_key));
431 torture_comment(samlogon_state->tctx, "expected:\n");
432 dump_data(1, lm_key_expected, sizeof(lm_key_expected));
433 pass = false;
435 break;
437 default:
438 if (memcmp(session_key.data, user_session_key,
439 sizeof(user_session_key)) != 0) {
440 *error_string = strdup("NT Session Key does not match expectations!\n");
441 torture_comment(samlogon_state->tctx, "user_session_key:\n");
442 dump_data(1, user_session_key, 16);
443 torture_comment(samlogon_state->tctx, "expected:\n");
444 dump_data(1, session_key.data, session_key.length);
445 pass = false;
448 return pass;
452 * Test LM authentication, no NT response supplied
455 static bool test_lm(struct samlogon_state *samlogon_state, char **error_string)
458 return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
462 * Test the NTLM response only, no LM.
465 static bool test_ntlm(struct samlogon_state *samlogon_state, char **error_string)
467 return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
471 * Test the NTLM response only, but in the LM field.
474 static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string)
476 bool lm_good;
477 bool pass = true;
478 NTSTATUS nt_status;
479 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
480 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
482 uint8_t lm_key[8];
483 uint8_t lm_hash[16];
484 uint8_t user_session_key[16];
485 uint8_t nt_hash[16];
487 ZERO_STRUCT(lm_key);
488 ZERO_STRUCT(user_session_key);
490 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
491 nt_response.data);
492 E_md4hash(samlogon_state->password, nt_hash);
493 SMBsesskeygen_ntv1(nt_hash,
494 session_key.data);
496 lm_good = E_deshash(samlogon_state->password, lm_hash);
497 if (!lm_good) {
498 ZERO_STRUCT(lm_hash);
500 nt_status = check_samlogon(samlogon_state,
501 BREAK_NONE,
502 samlogon_state->parameter_control,
503 &samlogon_state->chall,
504 &nt_response,
505 NULL,
506 lm_key,
507 user_session_key,
508 error_string);
510 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
511 /* for 'old' passwords, we allow the server to be OK or wrong password */
512 if (samlogon_state->old_password) {
513 return true;
515 return false;
516 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
517 int ret;
519 SAFE_FREE(*error_string);
520 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
521 if (ret == -1) {
522 *error_string = NULL;
524 return false;
525 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
526 return true;
527 } else if (!NT_STATUS_IS_OK(nt_status)) {
528 return false;
531 if (torture_setting_bool(samlogon_state->tctx, "samba4", false)) {
532 if (!all_zero(lm_key, sizeof(lm_key)) != 0) {
533 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
534 torture_comment(samlogon_state->tctx, "lm_key:\n");
535 dump_data(1, lm_key, 8);
536 torture_comment(samlogon_state->tctx, "expected (all zeros):\n");
537 pass = false;
541 if (!all_zero(user_session_key, sizeof(user_session_key)) != 0) {
542 torture_comment(samlogon_state->tctx, "NT Key does not match expectations!\n");
543 torture_comment(samlogon_state->tctx, "user_session_key:\n");
544 dump_data(1, user_session_key, sizeof(user_session_key));
545 torture_comment(samlogon_state->tctx, "expected (all zeros):\n");
546 pass = false;
548 } else {
549 if (lm_good) {
550 if (memcmp(lm_hash, lm_key,
551 sizeof(lm_key)) != 0) {
552 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
553 torture_comment(samlogon_state->tctx, "lm_key:\n");
554 dump_data(1, lm_key, 8);
555 torture_comment(samlogon_state->tctx, "expected:\n");
556 dump_data(1, lm_hash, 8);
557 pass = false;
559 #if 0
560 } else {
561 if (memcmp(session_key.data, lm_key,
562 sizeof(lm_key)) != 0) {
563 torture_comment(samlogon_state->tctx, "LM Key does not match expectations (first 8 session key)!\n");
564 torture_comment(samlogon_state->tctx, "lm_key:\n");
565 dump_data(1, lm_key, 8);
566 torture_comment(samlogon_state->tctx, "expected:\n");
567 dump_data(1, session_key.data, 8);
568 pass = false;
570 #endif
572 if (lm_good && memcmp(lm_hash, user_session_key, 8) != 0) {
573 uint8_t lm_key_expected[16];
574 memcpy(lm_key_expected, lm_hash, 8);
575 memset(lm_key_expected+8, '\0', 8);
576 if (memcmp(lm_key_expected, user_session_key,
577 16) != 0) {
578 torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations (should be first-8 LM hash)!\n");
579 torture_comment(samlogon_state->tctx, "user_session_key:\n");
580 dump_data(1, user_session_key, sizeof(user_session_key));
581 torture_comment(samlogon_state->tctx, "expected:\n");
582 dump_data(1, lm_key_expected, sizeof(lm_key_expected));
583 pass = false;
587 return pass;
591 * Test the NTLM response only, but in the both the NT and LM fields.
594 static bool test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string)
596 bool pass = true;
597 bool lm_good;
598 NTSTATUS nt_status;
599 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
600 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
602 uint8_t lm_key[8];
603 uint8_t lm_hash[16];
604 uint8_t user_session_key[16];
605 uint8_t nt_hash[16];
607 ZERO_STRUCT(lm_key);
608 ZERO_STRUCT(user_session_key);
610 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
611 nt_response.data);
612 E_md4hash(samlogon_state->password, nt_hash);
613 SMBsesskeygen_ntv1(nt_hash,
614 session_key.data);
616 lm_good = E_deshash(samlogon_state->password, lm_hash);
617 if (!lm_good) {
618 ZERO_STRUCT(lm_hash);
621 nt_status = check_samlogon(samlogon_state,
622 BREAK_NONE,
623 samlogon_state->parameter_control,
624 &samlogon_state->chall,
625 NULL,
626 &nt_response,
627 lm_key,
628 user_session_key,
629 error_string);
631 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
632 /* for 'old' passwords, we allow the server to be OK or wrong password */
633 if (samlogon_state->old_password) {
634 return true;
636 return false;
637 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
638 int ret;
640 SAFE_FREE(*error_string);
641 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
642 if (ret == -1) {
643 *error_string = NULL;
645 return false;
646 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
647 return true;
648 } else if (!NT_STATUS_IS_OK(nt_status)) {
649 return false;
652 if (!NT_STATUS_IS_OK(nt_status)) {
653 return false;
656 if (!all_zero(lm_key,
657 sizeof(lm_key)) != 0) {
658 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
659 torture_comment(samlogon_state->tctx, "lm_key:\n");
660 dump_data(1, lm_key, 8);
661 torture_comment(samlogon_state->tctx, "expected (all zero)\n");
662 pass = false;
664 if (memcmp(session_key.data, user_session_key,
665 sizeof(user_session_key)) != 0) {
666 torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations!\n");
667 torture_comment(samlogon_state->tctx, "user_session_key:\n");
668 dump_data(1, user_session_key, 16);
669 torture_comment(samlogon_state->tctx, "expected:\n");
670 dump_data(1, session_key.data, session_key.length);
671 pass = false;
675 return pass;
679 * Test the NTLMv2 and LMv2 responses
682 enum ntlmv2_domain {
683 UPPER_DOMAIN,
684 NO_DOMAIN
687 static bool test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state,
688 enum ntlm_break break_which,
689 enum ntlmv2_domain ntlmv2_domain,
690 char **error_string)
692 bool pass = true;
693 NTSTATUS nt_status;
694 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
695 DATA_BLOB lmv2_response = data_blob(NULL, 0);
696 DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
697 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
698 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, TEST_MACHINE_NAME, samlogon_state->workgroup);
700 uint8_t lm_session_key[8];
701 uint8_t user_session_key[16];
703 ZERO_STRUCT(lm_session_key);
704 ZERO_STRUCT(user_session_key);
706 switch (ntlmv2_domain) {
707 case UPPER_DOMAIN:
708 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
709 samlogon_state->account_name, samlogon_state->account_domain,
710 samlogon_state->password, &samlogon_state->chall,
711 &names_blob,
712 &lmv2_response, &ntlmv2_response,
713 &lmv2_session_key, &ntlmv2_session_key)) {
714 data_blob_free(&names_blob);
715 return false;
717 break;
718 case NO_DOMAIN:
719 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
720 samlogon_state->account_name, "",
721 samlogon_state->password, &samlogon_state->chall,
722 &names_blob,
723 &lmv2_response, &ntlmv2_response,
724 &lmv2_session_key, &ntlmv2_session_key)) {
725 data_blob_free(&names_blob);
726 return false;
728 break;
730 data_blob_free(&names_blob);
732 nt_status = check_samlogon(samlogon_state,
733 break_which,
734 samlogon_state->parameter_control,
735 &samlogon_state->chall,
736 &lmv2_response,
737 &ntlmv2_response,
738 lm_session_key,
739 user_session_key,
740 error_string);
742 data_blob_free(&lmv2_response);
743 data_blob_free(&ntlmv2_response);
746 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
747 /* for 'old' passwords, we allow the server to be OK or wrong password */
748 if (samlogon_state->old_password) {
749 return true;
751 return break_which == BREAK_BOTH;
752 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
753 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
754 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
755 int ret;
757 SAFE_FREE(*error_string);
758 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
759 if (ret == -1) {
760 *error_string = NULL;
762 return false;
763 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
764 return true;
765 } else if (!NT_STATUS_IS_OK(nt_status)) {
766 return false;
770 switch (break_which) {
771 case NO_NT:
772 if (memcmp(lmv2_session_key.data, user_session_key,
773 sizeof(user_session_key)) != 0) {
774 torture_comment(samlogon_state->tctx, "USER (LMv2) Session Key does not match expectations!\n");
775 torture_comment(samlogon_state->tctx, "user_session_key:\n");
776 dump_data(1, user_session_key, 16);
777 torture_comment(samlogon_state->tctx, "expected:\n");
778 dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
779 pass = false;
781 if (memcmp(lmv2_session_key.data, lm_session_key,
782 sizeof(lm_session_key)) != 0) {
783 torture_comment(samlogon_state->tctx, "LM (LMv2) Session Key does not match expectations!\n");
784 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
785 dump_data(1, lm_session_key, 8);
786 torture_comment(samlogon_state->tctx, "expected:\n");
787 dump_data(1, lmv2_session_key.data, 8);
788 pass = false;
790 break;
791 default:
792 if (memcmp(ntlmv2_session_key.data, user_session_key,
793 sizeof(user_session_key)) != 0) {
794 if (memcmp(lmv2_session_key.data, user_session_key,
795 sizeof(user_session_key)) == 0) {
796 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key expected, got LMv2 session key instead:\n");
797 torture_comment(samlogon_state->tctx, "user_session_key:\n");
798 dump_data(1, user_session_key, 16);
799 torture_comment(samlogon_state->tctx, "expected:\n");
800 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
801 pass = false;
803 } else {
804 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n");
805 torture_comment(samlogon_state->tctx, "user_session_key:\n");
806 dump_data(1, user_session_key, 16);
807 torture_comment(samlogon_state->tctx, "expected:\n");
808 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
809 pass = false;
812 if (memcmp(ntlmv2_session_key.data, lm_session_key,
813 sizeof(lm_session_key)) != 0) {
814 if (memcmp(lmv2_session_key.data, lm_session_key,
815 sizeof(lm_session_key)) == 0) {
816 torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key expected, got LMv2 session key instead:\n");
817 torture_comment(samlogon_state->tctx, "user_session_key:\n");
818 dump_data(1, lm_session_key, 8);
819 torture_comment(samlogon_state->tctx, "expected:\n");
820 dump_data(1, ntlmv2_session_key.data, 8);
821 pass = false;
822 } else {
823 torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key does not match expectations!\n");
824 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
825 dump_data(1, lm_session_key, 8);
826 torture_comment(samlogon_state->tctx, "expected:\n");
827 dump_data(1, ntlmv2_session_key.data, 8);
828 pass = false;
833 return pass;
837 * Test the NTLM and LMv2 responses
840 static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state,
841 enum ntlm_break break_which,
842 enum ntlmv2_domain ntlmv2_domain,
843 char **error_string)
845 bool pass = true;
846 NTSTATUS nt_status;
847 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
848 DATA_BLOB lmv2_response = data_blob(NULL, 0);
849 DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
850 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
851 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, samlogon_state->netbios_name, samlogon_state->workgroup);
853 DATA_BLOB ntlm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
854 DATA_BLOB ntlm_session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
856 bool lm_good;
857 uint8_t lm_hash[16];
858 uint8_t lm_session_key[8];
859 uint8_t user_session_key[16];
860 uint8_t nt_hash[16];
862 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
863 ntlm_response.data);
864 E_md4hash(samlogon_state->password, nt_hash);
865 SMBsesskeygen_ntv1(nt_hash,
866 ntlm_session_key.data);
868 lm_good = E_deshash(samlogon_state->password, lm_hash);
869 if (!lm_good) {
870 ZERO_STRUCT(lm_hash);
873 ZERO_STRUCT(lm_session_key);
874 ZERO_STRUCT(user_session_key);
876 switch (ntlmv2_domain) {
877 case UPPER_DOMAIN:
878 /* TODO - test with various domain cases, and without domain */
879 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
880 samlogon_state->account_name, samlogon_state->account_domain,
881 samlogon_state->password, &samlogon_state->chall,
882 &names_blob,
883 &lmv2_response, &ntlmv2_response,
884 &lmv2_session_key, &ntlmv2_session_key)) {
885 data_blob_free(&names_blob);
886 return false;
888 break;
889 case NO_DOMAIN:
890 /* TODO - test with various domain cases, and without domain */
891 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
892 samlogon_state->account_name, "",
893 samlogon_state->password, &samlogon_state->chall,
894 &names_blob,
895 &lmv2_response, &ntlmv2_response,
896 &lmv2_session_key, &ntlmv2_session_key)) {
897 data_blob_free(&names_blob);
898 return false;
900 break;
903 data_blob_free(&names_blob);
905 nt_status = check_samlogon(samlogon_state,
906 break_which,
907 samlogon_state->parameter_control,
908 &samlogon_state->chall,
909 &lmv2_response,
910 &ntlm_response,
911 lm_session_key,
912 user_session_key,
913 error_string);
915 data_blob_free(&lmv2_response);
916 data_blob_free(&ntlmv2_response);
919 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
920 /* for 'old' passwords, we allow the server to be OK or wrong password */
921 if (samlogon_state->old_password) {
922 return true;
924 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
925 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
926 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
927 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
928 int ret;
930 SAFE_FREE(*error_string);
931 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
932 if (ret == -1) {
933 *error_string = NULL;
935 return false;
936 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
937 return true;
938 } else if (!NT_STATUS_IS_OK(nt_status)) {
939 return false;
942 switch (break_which) {
943 case NO_NT:
944 if (memcmp(lmv2_session_key.data, user_session_key,
945 sizeof(user_session_key)) != 0) {
946 torture_comment(samlogon_state->tctx, "USER (LMv2) Session Key does not match expectations!\n");
947 torture_comment(samlogon_state->tctx, "user_session_key:\n");
948 dump_data(1, user_session_key, 16);
949 torture_comment(samlogon_state->tctx, "expected:\n");
950 dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
951 pass = false;
953 if (memcmp(lmv2_session_key.data, lm_session_key,
954 sizeof(lm_session_key)) != 0) {
955 torture_comment(samlogon_state->tctx, "LM (LMv2) Session Key does not match expectations!\n");
956 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
957 dump_data(1, lm_session_key, 8);
958 torture_comment(samlogon_state->tctx, "expected:\n");
959 dump_data(1, lmv2_session_key.data, 8);
960 pass = false;
962 break;
963 case BREAK_LM:
964 if (memcmp(ntlm_session_key.data, user_session_key,
965 sizeof(user_session_key)) != 0) {
966 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n");
967 torture_comment(samlogon_state->tctx, "user_session_key:\n");
968 dump_data(1, user_session_key, 16);
969 torture_comment(samlogon_state->tctx, "expected:\n");
970 dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
971 pass = false;
973 if (!all_zero(lm_session_key,
974 sizeof(lm_session_key))) {
975 torture_comment(samlogon_state->tctx, "LM Session Key does not match expectations (zeros)!\n");
976 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
977 dump_data(1, lm_session_key, 8);
978 pass = false;
980 break;
981 default:
982 if (memcmp(ntlm_session_key.data, user_session_key,
983 sizeof(user_session_key)) != 0) {
984 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n");
985 torture_comment(samlogon_state->tctx, "user_session_key:\n");
986 dump_data(1, user_session_key, 16);
987 torture_comment(samlogon_state->tctx, "expected:\n");
988 dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
989 pass = false;
991 if (memcmp(ntlm_session_key.data, lm_session_key,
992 sizeof(lm_session_key)) != 0) {
993 torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key does not match expectations!\n");
994 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
995 dump_data(1, lm_session_key, 8);
996 torture_comment(samlogon_state->tctx, "expected:\n");
997 dump_data(1, ntlm_session_key.data, 8);
998 pass = false;
1002 return pass;
1006 * Test the NTLMv2 and LMv2 responses
1009 static bool test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
1011 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, UPPER_DOMAIN, error_string);
1014 #if 0
1015 static bool test_lmv2_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1017 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, NO_DOMAIN, error_string);
1019 #endif
1022 * Test the LMv2 response only
1025 static bool test_lmv2(struct samlogon_state *samlogon_state, char **error_string)
1027 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, UPPER_DOMAIN, error_string);
1030 static bool test_lmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1032 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, NO_DOMAIN, error_string);
1036 * Test the NTLMv2 response only
1039 static bool test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
1041 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, UPPER_DOMAIN, error_string);
1044 static bool test_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1046 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, NO_DOMAIN, error_string);
1049 static bool test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string)
1051 return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
1054 static bool test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string)
1056 return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
1059 static bool test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string)
1061 return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
1064 static bool test_lm_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string)
1066 return test_lm_ntlm_broken(samlogon_state, BREAK_BOTH, error_string);
1068 static bool test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
1070 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
1073 static bool test_ntlmv2_lmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1075 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
1078 static bool test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
1080 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
1083 #if 0
1084 static bool test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1086 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
1088 #endif
1090 static bool test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char **error_string)
1092 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
1095 static bool test_ntlmv2_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1097 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
1100 static bool test_lmv2_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string)
1102 return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
1105 static bool test_lmv2_ntlm_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1107 return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
1110 static bool test_lmv2_ntlm_break_ntlm(struct samlogon_state *samlogon_state, char **error_string)
1112 return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
1115 static bool test_lmv2_ntlm_break_ntlm_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1117 return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
1120 static bool test_lmv2_ntlm_break_lm(struct samlogon_state *samlogon_state, char **error_string)
1122 return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
1125 static bool test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1127 return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
1131 * Test the NTLM2 response (extra challenge in LM field)
1133 * This test is the same as the 'break LM' test, but checks that the
1134 * server implements NTLM2 session security in the right place
1135 * (NETLOGON is the wrong place).
1138 static bool test_ntlm2(struct samlogon_state *samlogon_state, char **error_string)
1140 bool pass = true;
1141 NTSTATUS nt_status;
1142 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1143 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1145 uint8_t lm_key[8];
1146 uint8_t nt_hash[16];
1147 uint8_t lm_hash[16];
1148 uint8_t nt_key[16];
1149 uint8_t user_session_key[16];
1150 uint8_t expected_user_session_key[16];
1151 uint8_t session_nonce_hash[16];
1152 uint8_t client_chall[8];
1154 gnutls_hmac_hd_t hmac_hnd;
1155 gnutls_hash_hd_t hash_hnd;
1157 ZERO_STRUCT(user_session_key);
1158 ZERO_STRUCT(lm_key);
1159 generate_random_buffer(client_chall, 8);
1161 gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
1162 gnutls_hash(hash_hnd, samlogon_state->chall.data, 8);
1163 gnutls_hash(hash_hnd, client_chall, 8);
1164 gnutls_hash_deinit(hash_hnd, session_nonce_hash);
1166 E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
1167 E_deshash(samlogon_state->password, (uint8_t *)lm_hash);
1168 SMBsesskeygen_ntv1((const uint8_t *)nt_hash,
1169 nt_key);
1171 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
1173 memcpy(lm_response.data, session_nonce_hash, 8);
1174 memset(lm_response.data + 8, 0, 16);
1176 gnutls_hmac_init(&hmac_hnd,
1177 GNUTLS_MAC_MD5,
1178 nt_key,
1179 16);
1180 gnutls_hmac(hmac_hnd, samlogon_state->chall.data, 8);
1181 gnutls_hmac(hmac_hnd, client_chall, 8);
1182 gnutls_hmac_deinit(hmac_hnd, expected_user_session_key);
1184 nt_status = check_samlogon(samlogon_state,
1185 BREAK_NONE,
1186 samlogon_state->parameter_control,
1187 &samlogon_state->chall,
1188 &lm_response,
1189 &nt_response,
1190 lm_key,
1191 user_session_key,
1192 error_string);
1194 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1195 /* for 'old' passwords, we allow the server to be OK or wrong password */
1196 if (samlogon_state->old_password) {
1197 return true;
1199 return false;
1200 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1201 int ret;
1203 SAFE_FREE(*error_string);
1204 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1205 if (ret == -1) {
1206 *error_string = NULL;
1208 return false;
1209 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1210 return true;
1211 } else if (!NT_STATUS_IS_OK(nt_status)) {
1212 return false;
1215 if (!all_zero(lm_key, sizeof(lm_key))) {
1216 torture_comment(samlogon_state->tctx, "LM Session Key does not match expectations (zeros)!\n");
1217 torture_comment(samlogon_state->tctx, "lm_key:\n");
1218 dump_data(1, lm_key, 8);
1219 pass = false;
1221 if (memcmp(nt_key, user_session_key, 16) != 0) {
1222 torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations (should be NT Key)!\n");
1223 torture_comment(samlogon_state->tctx, "user_session_key:\n");
1224 dump_data(1, user_session_key, sizeof(user_session_key));
1225 torture_comment(samlogon_state->tctx, "expected:\n");
1226 dump_data(1, nt_key, sizeof(nt_key));
1227 pass = false;
1229 return pass;
1232 static bool test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
1234 NTSTATUS nt_status;
1235 DATA_BLOB nt_response = data_blob(NULL, 0);
1236 DATA_BLOB lm_response = data_blob(NULL, 0);
1237 char *password;
1238 char *dospw;
1239 smb_ucs2_t *unicodepw;
1240 size_t converted_size = 0;
1241 uint8_t user_session_key[16];
1242 uint8_t lm_key[16];
1243 uint8_t lm_hash[16];
1244 DATA_BLOB chall = data_blob_talloc_zero(samlogon_state->mem_ctx, 8);
1245 bool lm_good = E_deshash(samlogon_state->password, lm_hash);
1247 ZERO_STRUCT(user_session_key);
1249 if (!push_ucs2_talloc(samlogon_state->mem_ctx,
1250 &unicodepw, samlogon_state->password, &converted_size)) {
1251 DEBUG(0, ("push_ucs2_allocate failed!\n"));
1252 exit(1);
1255 nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, strlen_m(samlogon_state->password)*2);
1257 password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password);
1259 if (!convert_string_talloc(samlogon_state->mem_ctx,
1260 CH_UNIX, CH_DOS,
1261 password, strlen(password)+1,
1262 (void**)&dospw, &converted_size)) {
1263 DEBUG(0, ("convert_string_talloc failed!\n"));
1264 exit(1);
1267 lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
1269 nt_status = check_samlogon(samlogon_state,
1270 break_which,
1271 samlogon_state->parameter_control | MSV1_0_CLEARTEXT_PASSWORD_ALLOWED,
1272 &chall,
1273 &lm_response,
1274 &nt_response,
1275 lm_key,
1276 user_session_key,
1277 error_string);
1279 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1280 /* for 'old' passwords, we allow the server to be OK or wrong password */
1281 if (samlogon_state->old_password) {
1282 return true;
1284 /* for 'long' passwords, the LM password is invalid */
1285 if (break_which == NO_NT && !lm_good) {
1286 return true;
1288 /* for modern servers, the LM password is invalid */
1289 if (break_which == NO_NT
1290 && !torture_setting_bool(samlogon_state->tctx, "samba3", false)) {
1291 return true;
1294 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
1295 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
1296 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
1297 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1298 int ret;
1300 SAFE_FREE(*error_string);
1301 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1302 if (ret == -1) {
1303 *error_string = NULL;
1305 return false;
1306 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1307 return true;
1308 } else if (!NT_STATUS_IS_OK(nt_status)) {
1309 return false;
1312 if (break_which == NO_NT && !lm_good) {
1313 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
1314 return false;
1317 /* for modern servers, the LM password is invalid */
1318 if (break_which == NO_NT
1319 && !torture_setting_bool(samlogon_state->tctx, "samba3", false)) {
1320 *error_string = strdup("LM password is OK but should have failed against a modern server");
1321 return false;
1324 return true;
1327 static bool test_plaintext_none_broken(struct samlogon_state *samlogon_state,
1328 char **error_string) {
1329 return test_plaintext(samlogon_state, BREAK_NONE, error_string);
1332 static bool test_plaintext_lm_broken(struct samlogon_state *samlogon_state,
1333 char **error_string) {
1334 return test_plaintext(samlogon_state, BREAK_LM, error_string);
1337 static bool test_plaintext_nt_broken(struct samlogon_state *samlogon_state,
1338 char **error_string) {
1339 return test_plaintext(samlogon_state, BREAK_NT, error_string);
1342 static bool test_plaintext_nt_only(struct samlogon_state *samlogon_state,
1343 char **error_string) {
1344 return test_plaintext(samlogon_state, NO_LM, error_string);
1347 static bool test_plaintext_lm_only(struct samlogon_state *samlogon_state,
1348 char **error_string) {
1349 return test_plaintext(samlogon_state, NO_NT, error_string);
1353 Tests:
1355 - LM only
1356 - NT and LM
1357 - NT
1358 - NT in LM field
1359 - NT in both fields
1360 - NTLMv2
1361 - NTLMv2 and LMv2
1362 - LMv2
1363 - plaintext tests (in challenge-response fields)
1365 check we get the correct session key in each case
1366 check what values we get for the LM session key
1370 static const struct ntlm_tests {
1371 bool (*fn)(struct samlogon_state *, char **);
1372 const char *name;
1373 bool expect_fail;
1374 } test_table[] = {
1375 {test_lmv2_ntlmv2, "NTLMv2 and LMv2", false},
1376 #if 0
1377 {test_lmv2_ntlmv2_no_dom, "NTLMv2 and LMv2 (no domain)", false},
1378 #endif
1379 {test_lm, "LM", false},
1380 {test_lm_ntlm, "LM and NTLM", false},
1381 {test_lm_ntlm_both_broken, "LM and NTLM, both broken", false},
1382 {test_ntlm, "NTLM", false},
1383 {test_ntlm_in_lm, "NTLM in LM", false},
1384 {test_ntlm_in_both, "NTLM in both", false},
1385 {test_ntlmv2, "NTLMv2", false},
1386 {test_ntlmv2_no_dom, "NTLMv2 (no domain)", false},
1387 {test_lmv2, "LMv2", false},
1388 {test_lmv2_no_dom, "LMv2 (no domain)", false},
1389 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", false},
1390 {test_ntlmv2_lmv2_broken_no_dom, "NTLMv2 and LMv2, LMv2 broken (no domain)", false},
1391 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", false},
1392 #if 0
1393 {test_ntlmv2_ntlmv2_broken_no_dom, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", false},
1394 #endif
1395 {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", false},
1396 {test_ntlmv2_both_broken_no_dom, "NTLMv2 and LMv2, both broken (no domain)", false},
1397 {test_ntlm_lm_broken, "NTLM and LM, LM broken", false},
1398 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", false},
1399 {test_ntlm2, "NTLM2 (NTLMv2 session security)", false},
1400 {test_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", false},
1401 {test_lmv2_ntlm_both_broken_no_dom, "LMv2 and NTLM, both broken (no domain)", false},
1402 {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", false},
1403 {test_lmv2_ntlm_break_ntlm_no_dom, "LMv2 and NTLM, NTLM broken (no domain)", false},
1404 {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", false},
1405 {test_lmv2_ntlm_break_lm_no_dom, "LMv2 and NTLM, LMv2 broken (no domain)", false},
1406 {test_plaintext_none_broken, "Plaintext", false},
1407 {test_plaintext_lm_broken, "Plaintext LM broken", false},
1408 {test_plaintext_nt_broken, "Plaintext NT broken", false},
1409 {test_plaintext_nt_only, "Plaintext NT only", false},
1410 {test_plaintext_lm_only, "Plaintext LM only", false},
1411 { .name = NULL, }
1415 try a netlogon SamLogon
1417 static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1418 struct torture_context *tctx,
1419 struct netlogon_creds_CredentialState *creds,
1420 const char *comment,
1421 const char *account_domain, const char *account_name,
1422 const char *plain_pass, uint32_t parameter_control,
1423 NTSTATUS expected_error, bool old_password,
1424 int n_subtests)
1426 TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_SamLogon function-level context");
1427 int i, v, l, f;
1428 bool ret = true;
1429 int validation_levels[] = {2,3,6};
1430 int logon_levels[] = { NetlogonNetworkInformation, NetlogonNetworkTransitiveInformation };
1431 int function_levels[] = {
1432 NDR_NETR_LOGONSAMLOGON,
1433 NDR_NETR_LOGONSAMLOGONEX,
1434 NDR_NETR_LOGONSAMLOGONWITHFLAGS };
1435 struct samlogon_state samlogon_state;
1437 union netr_LogonLevel logon;
1438 union netr_Validation validation;
1439 uint8_t authoritative = 1;
1440 uint32_t flags = 0;
1442 ZERO_STRUCT(logon);
1444 torture_comment(tctx, "Testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1446 samlogon_state.comment = comment;
1447 samlogon_state.account_name = account_name;
1448 samlogon_state.account_domain = account_domain;
1449 samlogon_state.password = plain_pass;
1450 samlogon_state.workgroup = lpcfg_workgroup(tctx->lp_ctx);
1451 samlogon_state.netbios_name = lpcfg_netbios_name(tctx->lp_ctx);
1452 samlogon_state.p = p;
1453 samlogon_state.creds = creds;
1454 samlogon_state.expected_error = expected_error;
1455 samlogon_state.chall = data_blob_talloc(fn_ctx, NULL, 8);
1456 samlogon_state.parameter_control = parameter_control;
1457 samlogon_state.old_password = old_password;
1458 samlogon_state.tctx = tctx;
1460 generate_random_buffer(samlogon_state.chall.data, 8);
1461 samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1462 samlogon_state.r_flags.in.computer_name = TEST_MACHINE_NAME;
1463 samlogon_state.r_flags.in.credential = &samlogon_state.auth;
1464 samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2;
1465 samlogon_state.r_flags.in.flags = &flags;
1466 samlogon_state.r_flags.in.logon = &logon;
1467 samlogon_state.r_flags.out.validation = &validation;
1468 samlogon_state.r_flags.out.authoritative = &authoritative;
1469 samlogon_state.r_flags.out.flags = &flags;
1471 samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1472 samlogon_state.r_ex.in.computer_name = TEST_MACHINE_NAME;
1473 samlogon_state.r_ex.in.flags = &flags;
1474 samlogon_state.r_ex.in.logon = &logon;
1475 samlogon_state.r_ex.out.validation = &validation;
1476 samlogon_state.r_ex.out.authoritative = &authoritative;
1477 samlogon_state.r_ex.out.flags = &flags;
1479 samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1480 samlogon_state.r.in.computer_name = TEST_MACHINE_NAME;
1481 samlogon_state.r.in.credential = &samlogon_state.auth;
1482 samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
1483 samlogon_state.r.in.logon = &logon;
1484 samlogon_state.r.out.validation = &validation;
1485 samlogon_state.r.out.authoritative = &authoritative;
1488 for (f=0;f<ARRAY_SIZE(function_levels);f++) {
1489 for (i=0; test_table[i].fn; i++) {
1490 if (n_subtests && (i > n_subtests)) {
1491 continue;
1493 for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
1494 for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
1495 char *error_string = NULL;
1496 TALLOC_CTX *tmp_ctx = talloc_named(fn_ctx, 0, "test_SamLogon inner loop");
1497 samlogon_state.mem_ctx = tmp_ctx;
1498 samlogon_state.function_level = function_levels[f];
1499 samlogon_state.r.in.validation_level = validation_levels[v];
1500 samlogon_state.r.in.logon_level = logon_levels[l];
1501 samlogon_state.r_ex.in.validation_level = validation_levels[v];
1502 samlogon_state.r_ex.in.logon_level = logon_levels[l];
1503 samlogon_state.r_flags.in.validation_level = validation_levels[v];
1504 samlogon_state.r_flags.in.logon_level = logon_levels[l];
1505 if (!test_table[i].fn(&samlogon_state, &error_string)) {
1506 torture_comment(tctx, "Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
1507 samlogon_state.comment,
1508 samlogon_state.account_domain,
1509 samlogon_state.account_name,
1510 test_table[i].name, validation_levels[v],
1511 logon_levels[l], function_levels[f]);
1513 if (test_table[i].expect_fail) {
1514 torture_comment(tctx, " failed (expected, test incomplete): %s\n", error_string);
1515 } else {
1516 torture_comment(tctx, " failed: %s\n", error_string);
1517 ret = false;
1519 SAFE_FREE(error_string);
1521 talloc_free(tmp_ctx);
1526 talloc_free(fn_ctx);
1527 return ret;
1531 test an ADS style interactive domain logon
1533 bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1534 struct torture_context *tctx,
1535 struct netlogon_creds_CredentialState *creds,
1536 const char *comment,
1537 const char *workstation_name,
1538 const char *account_domain, const char *account_name,
1539 const char *plain_pass, uint32_t parameter_control,
1540 NTSTATUS expected_error)
1542 NTSTATUS status;
1543 TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context");
1544 bool ret = true;
1545 struct netr_LogonSamLogonWithFlags r;
1546 struct netr_Authenticator a, ra;
1547 struct netr_PasswordInfo pinfo;
1548 uint32_t flags = 0;
1550 union netr_LogonLevel logon;
1551 union netr_Validation validation;
1552 uint8_t authoritative = 1;
1553 struct dcerpc_binding_handle *b = p->binding_handle;
1554 enum dcerpc_AuthType auth_type;
1555 enum dcerpc_AuthLevel auth_level;
1557 dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level);
1559 ZERO_STRUCT(a);
1560 ZERO_STRUCT(r);
1561 ZERO_STRUCT(ra);
1563 ZERO_STRUCT(logon);
1564 ZERO_STRUCT(validation);
1566 netlogon_creds_client_authenticator(creds, &a);
1568 logon.password = &pinfo;
1570 r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1571 r.in.computer_name = TEST_MACHINE_NAME;
1572 r.in.credential = &a;
1573 r.in.return_authenticator = &ra;
1574 r.in.logon_level = NetlogonInteractiveTransitiveInformation;
1575 r.in.logon = &logon;
1576 r.in.validation_level = 6;
1577 r.in.flags = &flags;
1578 r.out.validation = &validation;
1579 r.out.authoritative = &authoritative;
1580 r.out.flags = &flags;
1582 pinfo.identity_info.domain_name.string = account_domain;
1583 pinfo.identity_info.parameter_control = parameter_control;
1584 pinfo.identity_info.logon_id = 0;
1585 pinfo.identity_info.account_name.string = account_name;
1586 pinfo.identity_info.workstation.string = workstation_name;
1588 if (!E_deshash(plain_pass, pinfo.lmpassword.hash)) {
1589 ZERO_STRUCT(pinfo.lmpassword.hash);
1591 E_md4hash(plain_pass, pinfo.ntpassword.hash);
1593 status = netlogon_creds_encrypt_samlogon_logon(creds,
1594 r.in.logon_level,
1595 r.in.logon,
1596 auth_type,
1597 auth_level);
1598 torture_assert_ntstatus_ok_goto(tctx,
1599 status,
1600 ret, failed,
1601 "netlogon_creds_encrypt_samlogon_logon");
1603 torture_comment(tctx, "Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment);
1605 status = dcerpc_netr_LogonSamLogonWithFlags_r(b, fn_ctx, &r);
1606 torture_assert_ntstatus_ok_goto(tctx,
1607 status,
1608 ret, failed,
1609 talloc_asprintf(tctx, "%s: netr_LogonSamLogonWithFlags - %s\n",
1610 __location__, nt_errstr(status)));
1612 if (!r.out.return_authenticator) {
1613 talloc_free(fn_ctx);
1614 torture_fail(tctx, "no authenticator returned");
1617 torture_assert_goto(tctx,
1618 netlogon_creds_client_check(creds, &r.out.return_authenticator->cred),
1619 ret, failed,
1620 "Credential chaining failed\n");
1622 torture_assert_ntstatus_equal(tctx, r.out.result, expected_error,
1623 talloc_asprintf(tctx, "[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n",
1624 account_domain, account_name, nt_errstr(expected_error), nt_errstr(r.out.result)));
1626 ret = true;
1627 failed:
1628 talloc_free(fn_ctx);
1630 return ret;
1633 /* This sets and resets the "minPwdAge" (in order to allow immediate user
1634 * password changes). The behaviour is controlled by the "set" boolean. */
1635 static bool handle_minPwdAge(struct torture_context *torture,
1636 TALLOC_CTX *mem_ctx, bool set)
1638 struct dcerpc_pipe *p;
1639 struct policy_handle connect_handle, domain_handle;
1640 struct samr_Connect c_r;
1641 struct samr_LookupDomain ld_r;
1642 struct samr_OpenDomain od_r;
1643 struct samr_QueryDomainInfo qdi_r;
1644 struct samr_SetDomainInfo sdi_r;
1645 struct samr_Close cl_r;
1646 struct lsa_String domName;
1647 struct dom_sid *domSid = NULL;
1648 union samr_DomainInfo *domInfo = NULL;
1649 static int64_t old_minPwdAge = 0;
1650 NTSTATUS status;
1652 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
1653 if (!NT_STATUS_IS_OK(status)) {
1654 return false;
1657 c_r.in.system_name = 0;
1658 c_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1659 c_r.out.connect_handle = &connect_handle;
1661 torture_assert_ntstatus_ok(torture,
1662 dcerpc_samr_Connect_r(p->binding_handle, mem_ctx, &c_r),
1663 "Connect failed");
1664 torture_assert_ntstatus_ok(torture, c_r.out.result, "Connect failed");
1666 ld_r.in.connect_handle = &connect_handle;
1667 ld_r.in.domain_name = &domName;
1668 ld_r.in.domain_name->string = lpcfg_workgroup(torture->lp_ctx);
1669 ld_r.out.sid = &domSid;
1671 torture_assert_ntstatus_ok(torture,
1672 dcerpc_samr_LookupDomain_r(p->binding_handle, mem_ctx, &ld_r),
1673 "LookupDomain failed");
1674 torture_assert_ntstatus_ok(torture, ld_r.out.result,
1675 "LookupDomain failed");
1677 od_r.in.connect_handle = &connect_handle;
1678 od_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1679 od_r.in.sid = *ld_r.out.sid;
1680 od_r.out.domain_handle = &domain_handle;
1682 torture_assert_ntstatus_ok(torture,
1683 dcerpc_samr_OpenDomain_r(p->binding_handle, mem_ctx, &od_r),
1684 "OpenDomain failed");
1685 torture_assert_ntstatus_ok(torture, od_r.out.result,
1686 "OpenDomain failed");
1688 qdi_r.in.domain_handle = &domain_handle;
1689 qdi_r.in.level = DomainPasswordInformation;
1690 qdi_r.out.info = &domInfo;
1692 torture_assert_ntstatus_ok(torture,
1693 dcerpc_samr_QueryDomainInfo_r(p->binding_handle, mem_ctx, &qdi_r),
1694 "QueryDomainInfo failed");
1695 torture_assert_ntstatus_ok(torture, qdi_r.out.result,
1696 "QueryDomainInfo failed");
1698 if (set) {
1699 old_minPwdAge = domInfo->info1.min_password_age;
1700 domInfo->info1.min_password_age = 0;
1701 } else {
1702 domInfo->info1.min_password_age = old_minPwdAge;
1705 sdi_r.in.domain_handle = &domain_handle;
1706 sdi_r.in.level = DomainPasswordInformation;
1707 sdi_r.in.info = domInfo;
1709 torture_assert_ntstatus_ok(torture,
1710 dcerpc_samr_SetDomainInfo_r(p->binding_handle, mem_ctx, &sdi_r),
1711 "SetDomainInfo failed");
1712 torture_assert_ntstatus_ok(torture, sdi_r.out.result,
1713 "SetDomainInfo failed");
1715 cl_r.in.handle = &connect_handle;
1716 cl_r.out.handle = &connect_handle;
1718 torture_assert_ntstatus_ok(torture,
1719 dcerpc_samr_Close_r(p->binding_handle, mem_ctx, &cl_r),
1720 "Close failed");
1721 torture_assert_ntstatus_ok(torture, cl_r.out.result, "Close failed");
1723 return true;
1726 bool torture_rpc_samlogon(struct torture_context *torture)
1728 NTSTATUS status;
1729 struct dcerpc_pipe *p;
1730 struct dcerpc_binding *b;
1731 struct cli_credentials *machine_credentials;
1732 TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon");
1733 bool ret = true;
1734 struct test_join *join_ctx = NULL;
1735 struct test_join *user_ctx = NULL, *user_ctx_wrong_wks = NULL, *user_ctx_wrong_time = NULL;
1736 const char *old_user_password, *user_password_wrong_wks, *user_password_wrong_time;
1737 char *user_password;
1738 const char *userdomain;
1739 struct samr_SetUserInfo s;
1740 union samr_UserInfo u;
1741 int i;
1742 int ci;
1744 unsigned int credential_flags[] = {
1745 NETLOGON_NEG_AUTH2_FLAGS,
1746 NETLOGON_NEG_ARCFOUR,
1747 NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
1748 NETLOGON_NEG_AUTH2_ADS_FLAGS,
1749 0 /* yes, this is a valid flag, causes the use of DES */
1752 struct netlogon_creds_CredentialState *creds;
1753 struct dcerpc_pipe *tmp_p = NULL;
1755 torture_assert(torture, handle_minPwdAge(torture, mem_ctx, true),
1756 "handle_minPwdAge error!");
1758 /* We only need to join as a workstation here, and in future,
1759 * if we wish to test against trusted domains, we must be a
1760 * workstation here */
1761 join_ctx = torture_join_domain(torture, TEST_MACHINE_NAME, ACB_WSTRUST,
1762 &machine_credentials);
1763 torture_assert(torture, join_ctx, "Failed to join as Workstation\n");
1765 userdomain = torture_setting_string(torture, "userdomain", lpcfg_workgroup(torture->lp_ctx));
1767 user_ctx = torture_create_testuser(torture,
1768 TEST_USER_NAME,
1769 userdomain,
1770 ACB_NORMAL,
1771 &old_user_password);
1772 torture_assert(torture, user_ctx, "Failed to create a test user\n");
1774 user_password = talloc_strdup(torture, old_user_password);
1775 torture_assert(torture, user_password != NULL, "Failed to copy old_user_password\n");
1777 tmp_p = torture_join_samr_pipe(user_ctx);
1778 torture_assert(torture, tmp_p, "torture_join_samr_pipe failed\n");
1779 test_ChangePasswordUser3(tmp_p, torture,
1780 TEST_USER_NAME, 16 /* > 14 */, &user_password,
1781 NULL, 0, false);
1783 user_ctx_wrong_wks = torture_create_testuser(torture,
1784 TEST_USER_NAME_WRONG_WKS,
1785 userdomain,
1786 ACB_NORMAL,
1787 &user_password_wrong_wks);
1788 torture_assert(torture, user_ctx_wrong_wks,
1789 "Failed to create a test user (wrong workstation test)\n");
1791 ZERO_STRUCT(u);
1792 s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_wks);
1793 s.in.info = &u;
1794 s.in.level = 21;
1796 u.info21.fields_present = SAMR_FIELD_WORKSTATIONS;
1797 u.info21.workstations.string = "not" TEST_MACHINE_NAME;
1799 tmp_p = torture_join_samr_pipe(user_ctx_wrong_wks);
1800 status = dcerpc_samr_SetUserInfo_r(tmp_p->binding_handle, mem_ctx, &s);
1801 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
1802 talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status)));
1803 torture_assert_ntstatus_ok_goto(torture, s.out.result, ret, failed,
1804 talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s.out.result)));
1806 user_ctx_wrong_time
1807 = torture_create_testuser(torture, TEST_USER_NAME_WRONG_TIME,
1808 userdomain,
1809 ACB_NORMAL,
1810 &user_password_wrong_time);
1811 torture_assert(torture, user_ctx_wrong_time,
1812 "Failed to create a test user (wrong workstation test)\n");
1814 ZERO_STRUCT(u);
1815 s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_time);
1816 s.in.info = &u;
1817 s.in.level = 21;
1819 u.info21.fields_present = SAMR_FIELD_WORKSTATIONS | SAMR_FIELD_LOGON_HOURS;
1820 u.info21.workstations.string = TEST_MACHINE_NAME;
1821 u.info21.logon_hours.units_per_week = 168;
1822 u.info21.logon_hours.bits = talloc_zero_array(mem_ctx, uint8_t, 168);
1824 tmp_p = torture_join_samr_pipe(user_ctx_wrong_time);
1825 status = dcerpc_samr_SetUserInfo_r(tmp_p->binding_handle, mem_ctx, &s);
1826 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
1827 talloc_asprintf(torture, "SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status)));
1828 torture_assert_ntstatus_ok_goto(torture, s.out.result, ret, failed,
1829 talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s.out.result)));
1832 torture_assert_ntstatus_ok_goto(torture,
1833 torture_rpc_binding(torture, &b),
1834 ret,
1835 failed,
1836 "Obtaining binding");
1838 /* We have to use schannel, otherwise the SamLogonEx fails
1839 * with INTERNAL_ERROR */
1841 status = dcerpc_binding_set_flags(b,
1842 DCERPC_SCHANNEL |
1843 DCERPC_SIGN | DCERPC_SEAL |
1844 DCERPC_SCHANNEL_128,
1845 DCERPC_AUTH_OPTIONS);
1846 torture_assert_ntstatus_ok(torture, status, "set flags");
1848 status = dcerpc_pipe_connect_b(mem_ctx, &p, b,
1849 &ndr_table_netlogon,
1850 machine_credentials, torture->ev, torture->lp_ctx);
1852 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
1853 talloc_asprintf(torture, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status)));
1855 torture_assert_not_null_goto(torture,
1856 creds = cli_credentials_get_netlogon_creds(machine_credentials),
1857 ret,
1858 failed,
1859 "obtaining credentials");
1863 struct {
1864 const char *comment;
1865 const char *domain;
1866 const char *username;
1867 const char *password;
1868 bool network_login;
1869 NTSTATUS expected_interactive_error;
1870 NTSTATUS expected_network_error;
1871 uint32_t parameter_control;
1872 bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
1873 } usercreds[] = {
1875 .comment = "domain\\user",
1876 .domain = cli_credentials_get_domain(
1877 samba_cmdline_get_creds()),
1878 .username = cli_credentials_get_username(
1879 samba_cmdline_get_creds()),
1880 .password = cli_credentials_get_password(
1881 samba_cmdline_get_creds()),
1882 .network_login = true,
1883 .expected_interactive_error = NT_STATUS_OK,
1884 .expected_network_error = NT_STATUS_OK,
1885 .parameter_control = 0,
1888 .comment = "realm\\user",
1889 .domain = cli_credentials_get_realm(
1890 samba_cmdline_get_creds()),
1891 .username = cli_credentials_get_username(
1892 samba_cmdline_get_creds()),
1893 .password = cli_credentials_get_password(
1894 samba_cmdline_get_creds()),
1895 .network_login = true,
1896 .expected_interactive_error = NT_STATUS_OK,
1897 .expected_network_error = NT_STATUS_OK,
1898 .parameter_control = 0,
1901 .comment = "user@domain",
1902 .domain = NULL,
1903 .username = talloc_asprintf(mem_ctx,
1904 "%s@%s",
1905 cli_credentials_get_username(
1906 samba_cmdline_get_creds()),
1907 cli_credentials_get_domain(
1908 samba_cmdline_get_creds())
1910 .password = cli_credentials_get_password(
1911 samba_cmdline_get_creds()),
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,
1915 .parameter_control = 0,
1918 .comment = "user@realm",
1919 .domain = NULL,
1920 .username = talloc_asprintf(mem_ctx,
1921 "%s@%s",
1922 cli_credentials_get_username(
1923 samba_cmdline_get_creds()),
1924 cli_credentials_get_realm(
1925 samba_cmdline_get_creds())
1927 .password = cli_credentials_get_password(
1928 samba_cmdline_get_creds()),
1929 .network_login = true,
1930 .expected_interactive_error = NT_STATUS_OK,
1931 .expected_network_error = NT_STATUS_OK,
1932 .parameter_control = 0,
1935 .comment = "machine domain\\user",
1936 .domain = cli_credentials_get_domain(machine_credentials),
1937 .username = cli_credentials_get_username(machine_credentials),
1938 .password = cli_credentials_get_password(machine_credentials),
1939 .network_login = true,
1940 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1941 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1944 .comment = "machine domain\\user",
1945 .domain = cli_credentials_get_domain(machine_credentials),
1946 .username = cli_credentials_get_username(machine_credentials),
1947 .password = cli_credentials_get_password(machine_credentials),
1948 .network_login = true,
1949 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1950 .expected_network_error = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT,
1951 .parameter_control = 0,
1954 .comment = "machine realm\\user",
1955 .domain = cli_credentials_get_realm(machine_credentials),
1956 .username = cli_credentials_get_username(machine_credentials),
1957 .password = cli_credentials_get_password(machine_credentials),
1958 .network_login = true,
1959 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1960 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1963 .comment = "machine user@domain",
1964 .domain = NULL,
1965 .username = talloc_asprintf(mem_ctx,
1966 "%s@%s",
1967 cli_credentials_get_username(machine_credentials),
1968 cli_credentials_get_domain(machine_credentials)
1970 .password = cli_credentials_get_password(machine_credentials),
1971 .network_login = false, /* works for some things, but not NTLMv2. Odd */
1972 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1973 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1976 .comment = "machine user@realm",
1977 .domain = NULL,
1978 .username = talloc_asprintf(mem_ctx,
1979 "%s@%s",
1980 cli_credentials_get_username(machine_credentials),
1981 cli_credentials_get_realm(machine_credentials)
1983 .password = cli_credentials_get_password(machine_credentials),
1984 .network_login = true,
1985 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1986 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1989 .comment = "test user (long pw): domain\\user",
1990 .domain = userdomain,
1991 .username = TEST_USER_NAME,
1992 .password = user_password,
1993 .network_login = true,
1994 .expected_interactive_error = NT_STATUS_OK,
1995 .expected_network_error = NT_STATUS_OK,
1996 .parameter_control = 0,
1999 .comment = "test user (long pw): user@realm",
2000 .domain = NULL,
2001 .username = talloc_asprintf(mem_ctx,
2002 "%s@%s",
2003 TEST_USER_NAME,
2004 lpcfg_realm(torture->lp_ctx)),
2005 .password = user_password,
2006 .network_login = true,
2007 .expected_interactive_error = NT_STATUS_OK,
2008 .expected_network_error = NT_STATUS_OK,
2009 .parameter_control = 0,
2012 .comment = "test user (long pw): user@domain",
2013 .domain = NULL,
2014 .username = talloc_asprintf(mem_ctx,
2015 "%s@%s",
2016 TEST_USER_NAME,
2017 userdomain),
2018 .password = user_password,
2019 .network_login = false, /* works for some things, but not NTLMv2. Odd */
2020 .expected_interactive_error = NT_STATUS_OK,
2021 .expected_network_error = NT_STATUS_OK,
2022 .parameter_control = 0,
2024 /* Oddball, can we use the old password ? */
2026 .comment = "test user: user\\domain OLD PASSWORD",
2027 .domain = userdomain,
2028 .username = TEST_USER_NAME,
2029 .password = old_user_password,
2030 .network_login = true,
2031 .expected_interactive_error = NT_STATUS_WRONG_PASSWORD,
2032 .expected_network_error = NT_STATUS_OK,
2033 .old_password = true
2036 .comment = "test user (wrong workstation): domain\\user",
2037 .domain = userdomain,
2038 .username = TEST_USER_NAME_WRONG_WKS,
2039 .password = user_password_wrong_wks,
2040 .network_login = true,
2041 .expected_interactive_error = NT_STATUS_INVALID_WORKSTATION,
2042 .expected_network_error = NT_STATUS_INVALID_WORKSTATION,
2043 .parameter_control = 0,
2047 /* Try all the tests for different username forms */
2048 for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) {
2050 torture_assert_goto(torture,
2051 test_InteractiveLogon(p, mem_ctx, torture, creds,
2052 usercreds[ci].comment,
2053 TEST_MACHINE_NAME,
2054 usercreds[ci].domain,
2055 usercreds[ci].username,
2056 usercreds[ci].password,
2057 usercreds[ci].parameter_control,
2058 usercreds[ci].expected_interactive_error),
2059 ret,
2060 failed,
2061 talloc_asprintf(mem_ctx, "InteractiveLogon: %s",
2062 usercreds[ci].comment));
2064 if (usercreds[ci].network_login) {
2065 torture_assert_goto(torture,
2066 test_SamLogon(p, mem_ctx, torture, creds,
2067 usercreds[ci].comment,
2068 usercreds[ci].domain,
2069 usercreds[ci].username,
2070 usercreds[ci].password,
2071 usercreds[ci].parameter_control,
2072 usercreds[ci].expected_network_error,
2073 usercreds[ci].old_password,
2075 ret,
2076 failed,
2077 talloc_asprintf(mem_ctx, "SamLogon: %s",
2078 usercreds[ci].comment));
2082 /* Using the first username form, try the different
2083 * credentials flag setups, on only one of the tests (checks
2084 * session key encryption) */
2086 for (i=0; i < ARRAY_SIZE(credential_flags); i++) {
2087 /* TODO: Somehow we lost setting up the different credential flags here! */
2089 torture_comment(torture,
2090 "Testing with flags: 0x%08x\n",
2091 credential_flags[i]);
2093 torture_assert_goto(torture,
2094 test_InteractiveLogon(p, mem_ctx, torture, creds,
2095 usercreds[0].comment,
2096 TEST_MACHINE_NAME,
2097 usercreds[0].domain,
2098 usercreds[0].username,
2099 usercreds[0].password,
2100 usercreds[0].parameter_control,
2101 usercreds[0].expected_interactive_error),
2102 ret,
2103 failed,
2104 talloc_asprintf(mem_ctx,
2105 "Testing InteractiveLogon with flags: 0x%08x\n",
2106 credential_flags[i]));
2108 if (usercreds[0].network_login) {
2109 torture_assert_goto(torture,
2110 test_SamLogon(p, mem_ctx, torture, creds,
2111 usercreds[0].comment,
2112 usercreds[0].domain,
2113 usercreds[0].username,
2114 usercreds[0].password,
2115 usercreds[0].parameter_control,
2116 usercreds[0].expected_network_error,
2117 usercreds[0].old_password,
2119 ret,
2120 failed,
2121 talloc_asprintf(mem_ctx,
2122 "Testing SamLogon with flags: 0x%08x\n",
2123 credential_flags[i]));
2128 failed:
2129 torture_assert(torture, handle_minPwdAge(torture, mem_ctx, false),
2130 "handle_minPwdAge error!");
2132 talloc_free(mem_ctx);
2134 torture_leave_domain(torture, join_ctx);
2135 torture_leave_domain(torture, user_ctx);
2136 torture_leave_domain(torture, user_ctx_wrong_wks);
2137 torture_leave_domain(torture, user_ctx_wrong_time);
2138 return ret;