s4-dsdb:large_ldap: Fix typos in variable names
[Samba.git] / source4 / torture / rpc / samlogon.c
blob00a87baee99d917bb7c9cfdae3814852f669bc7f
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;
95 samlogon_state->r.in.logon->network = &ninfo;
96 samlogon_state->r_ex.in.logon->network = &ninfo;
97 samlogon_state->r_flags.in.logon->network = &ninfo;
99 ninfo.identity_info.domain_name.string = samlogon_state->account_domain;
100 ninfo.identity_info.parameter_control = parameter_control;
101 ninfo.identity_info.logon_id = 0;
102 ninfo.identity_info.account_name.string = samlogon_state->account_name;
103 ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
105 memcpy(ninfo.challenge, chall->data, 8);
107 switch (break_which) {
108 case BREAK_NONE:
109 break;
110 case BREAK_LM:
111 if (lm_response && lm_response->data) {
112 lm_response->data[0]++;
114 break;
115 case BREAK_NT:
116 if (nt_response && nt_response->data) {
117 nt_response->data[0]++;
119 break;
120 case BREAK_BOTH:
121 if (lm_response && lm_response->data) {
122 lm_response->data[0]++;
124 if (nt_response && nt_response->data) {
125 nt_response->data[0]++;
127 break;
128 case NO_LM:
129 data_blob_free(lm_response);
130 break;
131 case NO_NT:
132 data_blob_free(nt_response);
133 break;
136 if (nt_response) {
137 ninfo.nt.data = nt_response->data;
138 ninfo.nt.length = nt_response->length;
139 } else {
140 ninfo.nt.data = NULL;
141 ninfo.nt.length = 0;
144 if (lm_response) {
145 ninfo.lm.data = lm_response->data;
146 ninfo.lm.length = lm_response->length;
147 } else {
148 ninfo.lm.data = NULL;
149 ninfo.lm.length = 0;
152 switch (samlogon_state->function_level) {
153 case NDR_NETR_LOGONSAMLOGON:
154 ZERO_STRUCT(samlogon_state->auth2);
155 netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
157 r->out.return_authenticator = NULL;
158 status = dcerpc_netr_LogonSamLogon_r(samlogon_state->p->binding_handle,
159 samlogon_state->mem_ctx, r);
160 if (!NT_STATUS_IS_OK(status)) {
161 if (error_string) {
162 *error_string = strdup(nt_errstr(status));
164 return status;
166 if (!r->out.return_authenticator ||
167 !netlogon_creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) {
168 torture_comment(samlogon_state->tctx, "Credential chaining failed\n");
170 if (!NT_STATUS_IS_OK(r->out.result)) {
171 if (error_string) {
172 *error_string = strdup(nt_errstr(r->out.result));
174 return r->out.result;
177 validation_level = r->in.validation_level;
179 status = netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds,
180 validation_level,
181 r->out.validation);
182 if (!NT_STATUS_IS_OK(status)) {
183 if (error_string) {
184 *error_string = strdup(nt_errstr(status));
186 return status;
189 switch (validation_level) {
190 case 2:
191 base = &r->out.validation->sam2->base;
192 break;
193 case 3:
194 base = &r->out.validation->sam3->base;
195 break;
196 case 6:
197 base = &r->out.validation->sam6->base;
198 break;
200 break;
201 case NDR_NETR_LOGONSAMLOGONEX:
202 status = dcerpc_netr_LogonSamLogonEx_r(samlogon_state->p->binding_handle,
203 samlogon_state->mem_ctx, r_ex);
204 if (!NT_STATUS_IS_OK(status)) {
205 if (error_string) {
206 *error_string = strdup(nt_errstr(status));
208 return status;
210 if (!NT_STATUS_IS_OK(r_ex->out.result)) {
211 if (error_string) {
212 *error_string = strdup(nt_errstr(r_ex->out.result));
214 return r_ex->out.result;
217 validation_level = r_ex->in.validation_level;
219 status = netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds,
220 validation_level,
221 r_ex->out.validation);
222 if (!NT_STATUS_IS_OK(status)) {
223 if (error_string) {
224 *error_string = strdup(nt_errstr(status));
226 return status;
229 switch (validation_level) {
230 case 2:
231 base = &r_ex->out.validation->sam2->base;
232 break;
233 case 3:
234 base = &r_ex->out.validation->sam3->base;
235 break;
236 case 6:
237 base = &r_ex->out.validation->sam6->base;
238 break;
240 break;
241 case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
242 ZERO_STRUCT(samlogon_state->auth2);
243 netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
245 r_flags->out.return_authenticator = NULL;
246 status = dcerpc_netr_LogonSamLogonWithFlags_r(samlogon_state->p->binding_handle,
247 samlogon_state->mem_ctx, r_flags);
248 if (!NT_STATUS_IS_OK(status)) {
249 if (error_string) {
250 *error_string = strdup(nt_errstr(status));
252 return status;
254 if (!r_flags->out.return_authenticator ||
255 !netlogon_creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) {
256 torture_comment(samlogon_state->tctx, "Credential chaining failed\n");
258 if (!NT_STATUS_IS_OK(r_flags->out.result)) {
259 if (error_string) {
260 *error_string = strdup(nt_errstr(r_flags->out.result));
262 return r_flags->out.result;
265 validation_level = r_flags->in.validation_level;
267 status = netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds,
268 validation_level,
269 r_flags->out.validation);
270 if (!NT_STATUS_IS_OK(status)) {
271 if (error_string) {
272 *error_string = strdup(nt_errstr(status));
274 return status;
277 switch (validation_level) {
278 case 2:
279 base = &r_flags->out.validation->sam2->base;
280 break;
281 case 3:
282 base = &r_flags->out.validation->sam3->base;
283 break;
284 case 6:
285 base = &r_flags->out.validation->sam6->base;
286 break;
288 break;
289 default:
290 /* can't happen */
291 return NT_STATUS_INVALID_PARAMETER;
294 if (!base) {
295 torture_comment(samlogon_state->tctx, "No user info returned from 'successful' SamLogon*() call!\n");
296 return NT_STATUS_INVALID_PARAMETER;
299 if (user_session_key) {
300 memcpy(user_session_key, base->key.key, 16);
302 if (lm_key) {
303 memcpy(lm_key, base->LMSessKey.key, 8);
306 return status;
311 * Test the normal 'LM and NTLM' combination
314 static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
316 bool pass = true;
317 bool lm_good;
318 NTSTATUS nt_status;
319 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
320 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
321 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
323 uint8_t lm_key[8];
324 uint8_t user_session_key[16];
325 uint8_t lm_hash[16];
326 uint8_t nt_hash[16];
328 ZERO_STRUCT(lm_key);
329 ZERO_STRUCT(user_session_key);
331 lm_good = SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
332 if (!lm_good) {
333 ZERO_STRUCT(lm_hash);
334 } else {
335 E_deshash(samlogon_state->password, lm_hash);
338 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
340 E_md4hash(samlogon_state->password, nt_hash);
341 SMBsesskeygen_ntv1(nt_hash, session_key.data);
343 nt_status = check_samlogon(samlogon_state,
344 break_which,
345 samlogon_state->parameter_control,
346 &samlogon_state->chall,
347 &lm_response,
348 &nt_response,
349 lm_key,
350 user_session_key,
351 error_string);
353 data_blob_free(&lm_response);
355 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
356 /* for 'long' passwords, the LM password is invalid */
357 if (break_which == NO_NT && !lm_good) {
358 return true;
360 /* for modern servers, the LM password is invalid */
361 if (break_which == NO_NT
362 && !torture_setting_bool(samlogon_state->tctx, "samba3", false)) {
363 return true;
366 /* for 'old' passwords, we allow the server to be OK or wrong password */
367 if (samlogon_state->old_password) {
368 return true;
370 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
371 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
372 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
373 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
374 int ret;
376 SAFE_FREE(*error_string);
377 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
378 if (ret == -1) {
379 *error_string = NULL;
381 return false;
382 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
383 return true;
384 } else if (!NT_STATUS_IS_OK(nt_status)) {
385 return false;
388 if (break_which == NO_NT && !lm_good) {
389 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
390 return false;
393 /* for modern servers, the LM password is invalid */
394 if (break_which == NO_NT
395 && !torture_setting_bool(samlogon_state->tctx, "samba3", false)) {
396 *error_string = strdup("LM password is OK but should have failed against a modern server");
397 return false;
400 if (!all_zero(lm_key, sizeof(lm_key)) != 0) {
401 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
402 torture_comment(samlogon_state->tctx, "lm_key:\n");
403 dump_data(1, lm_key, 8);
404 torture_comment(samlogon_state->tctx, "expected (all zeros):\n");
405 pass = false;
408 switch (break_which) {
409 case NO_NT:
411 uint8_t lm_key_expected[16];
412 memcpy(lm_key_expected, session_key.data, 8);
413 memset(lm_key_expected+8, '\0', 8);
414 if (memcmp(lm_key_expected, user_session_key,
415 16) != 0) {
416 *error_string = strdup("NT Session Key does not match expectations (should be first-8 session key)!\n");
417 torture_comment(samlogon_state->tctx, "user_session_key:\n");
418 dump_data(1, user_session_key, sizeof(user_session_key));
419 torture_comment(samlogon_state->tctx, "expected:\n");
420 dump_data(1, lm_key_expected, sizeof(lm_key_expected));
421 pass = false;
423 break;
425 default:
426 if (memcmp(session_key.data, user_session_key,
427 sizeof(user_session_key)) != 0) {
428 *error_string = strdup("NT Session Key does not match expectations!\n");
429 torture_comment(samlogon_state->tctx, "user_session_key:\n");
430 dump_data(1, user_session_key, 16);
431 torture_comment(samlogon_state->tctx, "expected:\n");
432 dump_data(1, session_key.data, session_key.length);
433 pass = false;
436 return pass;
440 * Test LM authentication, no NT response supplied
443 static bool test_lm(struct samlogon_state *samlogon_state, char **error_string)
446 return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
450 * Test the NTLM response only, no LM.
453 static bool test_ntlm(struct samlogon_state *samlogon_state, char **error_string)
455 return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
459 * Test the NTLM response only, but in the LM field.
462 static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string)
464 bool lm_good;
465 bool pass = true;
466 NTSTATUS nt_status;
467 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
468 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
470 uint8_t lm_key[8];
471 uint8_t lm_hash[16];
472 uint8_t user_session_key[16];
473 uint8_t nt_hash[16];
475 ZERO_STRUCT(lm_key);
476 ZERO_STRUCT(user_session_key);
478 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
479 nt_response.data);
480 E_md4hash(samlogon_state->password, nt_hash);
481 SMBsesskeygen_ntv1(nt_hash,
482 session_key.data);
484 lm_good = E_deshash(samlogon_state->password, lm_hash);
485 if (!lm_good) {
486 ZERO_STRUCT(lm_hash);
488 nt_status = check_samlogon(samlogon_state,
489 BREAK_NONE,
490 samlogon_state->parameter_control,
491 &samlogon_state->chall,
492 &nt_response,
493 NULL,
494 lm_key,
495 user_session_key,
496 error_string);
498 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
499 /* for 'old' passwords, we allow the server to be OK or wrong password */
500 if (samlogon_state->old_password) {
501 return true;
503 return false;
504 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
505 int ret;
507 SAFE_FREE(*error_string);
508 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
509 if (ret == -1) {
510 *error_string = NULL;
512 return false;
513 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
514 return true;
515 } else if (!NT_STATUS_IS_OK(nt_status)) {
516 return false;
519 if (torture_setting_bool(samlogon_state->tctx, "samba4", false)) {
520 if (!all_zero(lm_key, sizeof(lm_key)) != 0) {
521 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
522 torture_comment(samlogon_state->tctx, "lm_key:\n");
523 dump_data(1, lm_key, 8);
524 torture_comment(samlogon_state->tctx, "expected (all zeros):\n");
525 pass = false;
529 if (!all_zero(user_session_key, sizeof(user_session_key)) != 0) {
530 torture_comment(samlogon_state->tctx, "NT Key does not match expectations!\n");
531 torture_comment(samlogon_state->tctx, "user_session_key:\n");
532 dump_data(1, user_session_key, sizeof(user_session_key));
533 torture_comment(samlogon_state->tctx, "expected (all zeros):\n");
534 pass = false;
536 } else {
537 if (lm_good) {
538 if (memcmp(lm_hash, lm_key,
539 sizeof(lm_key)) != 0) {
540 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
541 torture_comment(samlogon_state->tctx, "lm_key:\n");
542 dump_data(1, lm_key, 8);
543 torture_comment(samlogon_state->tctx, "expected:\n");
544 dump_data(1, lm_hash, 8);
545 pass = false;
547 #if 0
548 } else {
549 if (memcmp(session_key.data, lm_key,
550 sizeof(lm_key)) != 0) {
551 torture_comment(samlogon_state->tctx, "LM Key does not match expectations (first 8 session key)!\n");
552 torture_comment(samlogon_state->tctx, "lm_key:\n");
553 dump_data(1, lm_key, 8);
554 torture_comment(samlogon_state->tctx, "expected:\n");
555 dump_data(1, session_key.data, 8);
556 pass = false;
558 #endif
560 if (lm_good && memcmp(lm_hash, user_session_key, 8) != 0) {
561 uint8_t lm_key_expected[16];
562 memcpy(lm_key_expected, lm_hash, 8);
563 memset(lm_key_expected+8, '\0', 8);
564 if (memcmp(lm_key_expected, user_session_key,
565 16) != 0) {
566 torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations (should be first-8 LM hash)!\n");
567 torture_comment(samlogon_state->tctx, "user_session_key:\n");
568 dump_data(1, user_session_key, sizeof(user_session_key));
569 torture_comment(samlogon_state->tctx, "expected:\n");
570 dump_data(1, lm_key_expected, sizeof(lm_key_expected));
571 pass = false;
575 return pass;
579 * Test the NTLM response only, but in the both the NT and LM fields.
582 static bool test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string)
584 bool pass = true;
585 bool lm_good;
586 NTSTATUS nt_status;
587 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
588 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
590 uint8_t lm_key[8];
591 uint8_t lm_hash[16];
592 uint8_t user_session_key[16];
593 uint8_t nt_hash[16];
595 ZERO_STRUCT(lm_key);
596 ZERO_STRUCT(user_session_key);
598 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
599 nt_response.data);
600 E_md4hash(samlogon_state->password, nt_hash);
601 SMBsesskeygen_ntv1(nt_hash,
602 session_key.data);
604 lm_good = E_deshash(samlogon_state->password, lm_hash);
605 if (!lm_good) {
606 ZERO_STRUCT(lm_hash);
609 nt_status = check_samlogon(samlogon_state,
610 BREAK_NONE,
611 samlogon_state->parameter_control,
612 &samlogon_state->chall,
613 NULL,
614 &nt_response,
615 lm_key,
616 user_session_key,
617 error_string);
619 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
620 /* for 'old' passwords, we allow the server to be OK or wrong password */
621 if (samlogon_state->old_password) {
622 return true;
624 return false;
625 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
626 int ret;
628 SAFE_FREE(*error_string);
629 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
630 if (ret == -1) {
631 *error_string = NULL;
633 return false;
634 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
635 return true;
636 } else if (!NT_STATUS_IS_OK(nt_status)) {
637 return false;
640 if (!NT_STATUS_IS_OK(nt_status)) {
641 return false;
644 if (!all_zero(lm_key,
645 sizeof(lm_key)) != 0) {
646 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
647 torture_comment(samlogon_state->tctx, "lm_key:\n");
648 dump_data(1, lm_key, 8);
649 torture_comment(samlogon_state->tctx, "expected (all zero)\n");
650 pass = false;
652 if (memcmp(session_key.data, user_session_key,
653 sizeof(user_session_key)) != 0) {
654 torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations!\n");
655 torture_comment(samlogon_state->tctx, "user_session_key:\n");
656 dump_data(1, user_session_key, 16);
657 torture_comment(samlogon_state->tctx, "expected:\n");
658 dump_data(1, session_key.data, session_key.length);
659 pass = false;
663 return pass;
667 * Test the NTLMv2 and LMv2 responses
670 enum ntlmv2_domain {
671 UPPER_DOMAIN,
672 NO_DOMAIN
675 static bool test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state,
676 enum ntlm_break break_which,
677 enum ntlmv2_domain ntlmv2_domain,
678 char **error_string)
680 bool pass = true;
681 NTSTATUS nt_status;
682 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
683 DATA_BLOB lmv2_response = data_blob(NULL, 0);
684 DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
685 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
686 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, TEST_MACHINE_NAME, samlogon_state->workgroup);
688 uint8_t lm_session_key[8];
689 uint8_t user_session_key[16];
691 ZERO_STRUCT(lm_session_key);
692 ZERO_STRUCT(user_session_key);
694 switch (ntlmv2_domain) {
695 case UPPER_DOMAIN:
696 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
697 samlogon_state->account_name, samlogon_state->account_domain,
698 samlogon_state->password, &samlogon_state->chall,
699 &names_blob,
700 &lmv2_response, &ntlmv2_response,
701 &lmv2_session_key, &ntlmv2_session_key)) {
702 data_blob_free(&names_blob);
703 return false;
705 break;
706 case NO_DOMAIN:
707 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
708 samlogon_state->account_name, "",
709 samlogon_state->password, &samlogon_state->chall,
710 &names_blob,
711 &lmv2_response, &ntlmv2_response,
712 &lmv2_session_key, &ntlmv2_session_key)) {
713 data_blob_free(&names_blob);
714 return false;
716 break;
718 data_blob_free(&names_blob);
720 nt_status = check_samlogon(samlogon_state,
721 break_which,
722 samlogon_state->parameter_control,
723 &samlogon_state->chall,
724 &lmv2_response,
725 &ntlmv2_response,
726 lm_session_key,
727 user_session_key,
728 error_string);
730 data_blob_free(&lmv2_response);
731 data_blob_free(&ntlmv2_response);
734 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
735 /* for 'old' passwords, we allow the server to be OK or wrong password */
736 if (samlogon_state->old_password) {
737 return true;
739 return break_which == BREAK_BOTH;
740 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
741 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
742 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
743 int ret;
745 SAFE_FREE(*error_string);
746 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
747 if (ret == -1) {
748 *error_string = NULL;
750 return false;
751 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
752 return true;
753 } else if (!NT_STATUS_IS_OK(nt_status)) {
754 return false;
758 switch (break_which) {
759 case NO_NT:
760 if (memcmp(lmv2_session_key.data, user_session_key,
761 sizeof(user_session_key)) != 0) {
762 torture_comment(samlogon_state->tctx, "USER (LMv2) Session Key does not match expectations!\n");
763 torture_comment(samlogon_state->tctx, "user_session_key:\n");
764 dump_data(1, user_session_key, 16);
765 torture_comment(samlogon_state->tctx, "expected:\n");
766 dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
767 pass = false;
769 if (memcmp(lmv2_session_key.data, lm_session_key,
770 sizeof(lm_session_key)) != 0) {
771 torture_comment(samlogon_state->tctx, "LM (LMv2) Session Key does not match expectations!\n");
772 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
773 dump_data(1, lm_session_key, 8);
774 torture_comment(samlogon_state->tctx, "expected:\n");
775 dump_data(1, lmv2_session_key.data, 8);
776 pass = false;
778 break;
779 default:
780 if (memcmp(ntlmv2_session_key.data, user_session_key,
781 sizeof(user_session_key)) != 0) {
782 if (memcmp(lmv2_session_key.data, user_session_key,
783 sizeof(user_session_key)) == 0) {
784 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
785 torture_comment(samlogon_state->tctx, "user_session_key:\n");
786 dump_data(1, user_session_key, 16);
787 torture_comment(samlogon_state->tctx, "expected:\n");
788 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
789 pass = false;
791 } else {
792 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n");
793 torture_comment(samlogon_state->tctx, "user_session_key:\n");
794 dump_data(1, user_session_key, 16);
795 torture_comment(samlogon_state->tctx, "expected:\n");
796 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
797 pass = false;
800 if (memcmp(ntlmv2_session_key.data, lm_session_key,
801 sizeof(lm_session_key)) != 0) {
802 if (memcmp(lmv2_session_key.data, lm_session_key,
803 sizeof(lm_session_key)) == 0) {
804 torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
805 torture_comment(samlogon_state->tctx, "user_session_key:\n");
806 dump_data(1, lm_session_key, 8);
807 torture_comment(samlogon_state->tctx, "expected:\n");
808 dump_data(1, ntlmv2_session_key.data, 8);
809 pass = false;
810 } else {
811 torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key does not match expectations!\n");
812 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
813 dump_data(1, lm_session_key, 8);
814 torture_comment(samlogon_state->tctx, "expected:\n");
815 dump_data(1, ntlmv2_session_key.data, 8);
816 pass = false;
821 return pass;
825 * Test the NTLM and LMv2 responses
828 static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state,
829 enum ntlm_break break_which,
830 enum ntlmv2_domain ntlmv2_domain,
831 char **error_string)
833 bool pass = true;
834 NTSTATUS nt_status;
835 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
836 DATA_BLOB lmv2_response = data_blob(NULL, 0);
837 DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
838 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
839 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, samlogon_state->netbios_name, samlogon_state->workgroup);
841 DATA_BLOB ntlm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
842 DATA_BLOB ntlm_session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
844 bool lm_good;
845 uint8_t lm_hash[16];
846 uint8_t lm_session_key[8];
847 uint8_t user_session_key[16];
848 uint8_t nt_hash[16];
850 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
851 ntlm_response.data);
852 E_md4hash(samlogon_state->password, nt_hash);
853 SMBsesskeygen_ntv1(nt_hash,
854 ntlm_session_key.data);
856 lm_good = E_deshash(samlogon_state->password, lm_hash);
857 if (!lm_good) {
858 ZERO_STRUCT(lm_hash);
861 ZERO_STRUCT(lm_session_key);
862 ZERO_STRUCT(user_session_key);
864 switch (ntlmv2_domain) {
865 case UPPER_DOMAIN:
866 /* TODO - test with various domain cases, and without domain */
867 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
868 samlogon_state->account_name, samlogon_state->account_domain,
869 samlogon_state->password, &samlogon_state->chall,
870 &names_blob,
871 &lmv2_response, &ntlmv2_response,
872 &lmv2_session_key, &ntlmv2_session_key)) {
873 data_blob_free(&names_blob);
874 return false;
876 break;
877 case NO_DOMAIN:
878 /* TODO - test with various domain cases, and without domain */
879 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
880 samlogon_state->account_name, "",
881 samlogon_state->password, &samlogon_state->chall,
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;
891 data_blob_free(&names_blob);
893 nt_status = check_samlogon(samlogon_state,
894 break_which,
895 samlogon_state->parameter_control,
896 &samlogon_state->chall,
897 &lmv2_response,
898 &ntlm_response,
899 lm_session_key,
900 user_session_key,
901 error_string);
903 data_blob_free(&lmv2_response);
904 data_blob_free(&ntlmv2_response);
907 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
908 /* for 'old' passwords, we allow the server to be OK or wrong password */
909 if (samlogon_state->old_password) {
910 return true;
912 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
913 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
914 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
915 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
916 int ret;
918 SAFE_FREE(*error_string);
919 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
920 if (ret == -1) {
921 *error_string = NULL;
923 return false;
924 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
925 return true;
926 } else if (!NT_STATUS_IS_OK(nt_status)) {
927 return false;
930 switch (break_which) {
931 case NO_NT:
932 if (memcmp(lmv2_session_key.data, user_session_key,
933 sizeof(user_session_key)) != 0) {
934 torture_comment(samlogon_state->tctx, "USER (LMv2) Session Key does not match expectations!\n");
935 torture_comment(samlogon_state->tctx, "user_session_key:\n");
936 dump_data(1, user_session_key, 16);
937 torture_comment(samlogon_state->tctx, "expected:\n");
938 dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
939 pass = false;
941 if (memcmp(lmv2_session_key.data, lm_session_key,
942 sizeof(lm_session_key)) != 0) {
943 torture_comment(samlogon_state->tctx, "LM (LMv2) Session Key does not match expectations!\n");
944 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
945 dump_data(1, lm_session_key, 8);
946 torture_comment(samlogon_state->tctx, "expected:\n");
947 dump_data(1, lmv2_session_key.data, 8);
948 pass = false;
950 break;
951 case BREAK_LM:
952 if (memcmp(ntlm_session_key.data, user_session_key,
953 sizeof(user_session_key)) != 0) {
954 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n");
955 torture_comment(samlogon_state->tctx, "user_session_key:\n");
956 dump_data(1, user_session_key, 16);
957 torture_comment(samlogon_state->tctx, "expected:\n");
958 dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
959 pass = false;
961 if (!all_zero(lm_session_key,
962 sizeof(lm_session_key))) {
963 torture_comment(samlogon_state->tctx, "LM Session Key does not match expectations (zeros)!\n");
964 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
965 dump_data(1, lm_session_key, 8);
966 pass = false;
968 break;
969 default:
970 if (memcmp(ntlm_session_key.data, user_session_key,
971 sizeof(user_session_key)) != 0) {
972 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n");
973 torture_comment(samlogon_state->tctx, "user_session_key:\n");
974 dump_data(1, user_session_key, 16);
975 torture_comment(samlogon_state->tctx, "expected:\n");
976 dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
977 pass = false;
979 if (memcmp(ntlm_session_key.data, lm_session_key,
980 sizeof(lm_session_key)) != 0) {
981 torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key does not match expectations!\n");
982 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
983 dump_data(1, lm_session_key, 8);
984 torture_comment(samlogon_state->tctx, "expected:\n");
985 dump_data(1, ntlm_session_key.data, 8);
986 pass = false;
990 return pass;
994 * Test the NTLMv2 and LMv2 responses
997 static bool test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
999 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, UPPER_DOMAIN, error_string);
1002 #if 0
1003 static bool test_lmv2_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1005 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, NO_DOMAIN, error_string);
1007 #endif
1010 * Test the LMv2 response only
1013 static bool test_lmv2(struct samlogon_state *samlogon_state, char **error_string)
1015 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, UPPER_DOMAIN, error_string);
1018 static bool test_lmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1020 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, NO_DOMAIN, error_string);
1024 * Test the NTLMv2 response only
1027 static bool test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
1029 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, UPPER_DOMAIN, error_string);
1032 static bool test_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1034 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, NO_DOMAIN, error_string);
1037 static bool test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string)
1039 return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
1042 static bool test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string)
1044 return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
1047 static bool test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string)
1049 return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
1052 static bool test_lm_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string)
1054 return test_lm_ntlm_broken(samlogon_state, BREAK_BOTH, error_string);
1056 static bool test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
1058 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
1061 static bool test_ntlmv2_lmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1063 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
1066 static bool test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
1068 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
1071 #if 0
1072 static bool test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1074 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
1076 #endif
1078 static bool test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char **error_string)
1080 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
1083 static bool test_ntlmv2_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1085 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
1088 static bool test_lmv2_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string)
1090 return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
1093 static bool test_lmv2_ntlm_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1095 return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
1098 static bool test_lmv2_ntlm_break_ntlm(struct samlogon_state *samlogon_state, char **error_string)
1100 return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
1103 static bool test_lmv2_ntlm_break_ntlm_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1105 return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
1108 static bool test_lmv2_ntlm_break_lm(struct samlogon_state *samlogon_state, char **error_string)
1110 return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
1113 static bool test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1115 return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
1119 * Test the NTLM2 response (extra challenge in LM feild)
1121 * This test is the same as the 'break LM' test, but checks that the
1122 * server implements NTLM2 session security in the right place
1123 * (NETLOGON is the wrong place).
1126 static bool test_ntlm2(struct samlogon_state *samlogon_state, char **error_string)
1128 bool pass = true;
1129 NTSTATUS nt_status;
1130 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1131 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1133 uint8_t lm_key[8];
1134 uint8_t nt_hash[16];
1135 uint8_t lm_hash[16];
1136 uint8_t nt_key[16];
1137 uint8_t user_session_key[16];
1138 uint8_t expected_user_session_key[16];
1139 uint8_t session_nonce_hash[16];
1140 uint8_t client_chall[8];
1142 gnutls_hmac_hd_t hmac_hnd;
1143 gnutls_hash_hd_t hash_hnd;
1145 ZERO_STRUCT(user_session_key);
1146 ZERO_STRUCT(lm_key);
1147 generate_random_buffer(client_chall, 8);
1149 gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
1150 gnutls_hash(hash_hnd, samlogon_state->chall.data, 8);
1151 gnutls_hash(hash_hnd, client_chall, 8);
1152 gnutls_hash_deinit(hash_hnd, session_nonce_hash);
1154 E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
1155 E_deshash(samlogon_state->password, (uint8_t *)lm_hash);
1156 SMBsesskeygen_ntv1((const uint8_t *)nt_hash,
1157 nt_key);
1159 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
1161 memcpy(lm_response.data, session_nonce_hash, 8);
1162 memset(lm_response.data + 8, 0, 16);
1164 gnutls_hmac_init(&hmac_hnd,
1165 GNUTLS_MAC_MD5,
1166 nt_key,
1167 16);
1168 gnutls_hmac(hmac_hnd, samlogon_state->chall.data, 8);
1169 gnutls_hmac(hmac_hnd, client_chall, 8);
1170 gnutls_hmac_deinit(hmac_hnd, expected_user_session_key);
1172 nt_status = check_samlogon(samlogon_state,
1173 BREAK_NONE,
1174 samlogon_state->parameter_control,
1175 &samlogon_state->chall,
1176 &lm_response,
1177 &nt_response,
1178 lm_key,
1179 user_session_key,
1180 error_string);
1182 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1183 /* for 'old' passwords, we allow the server to be OK or wrong password */
1184 if (samlogon_state->old_password) {
1185 return true;
1187 return false;
1188 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1189 int ret;
1191 SAFE_FREE(*error_string);
1192 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1193 if (ret == -1) {
1194 *error_string = NULL;
1196 return false;
1197 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1198 return true;
1199 } else if (!NT_STATUS_IS_OK(nt_status)) {
1200 return false;
1203 if (!all_zero(lm_key, sizeof(lm_key))) {
1204 torture_comment(samlogon_state->tctx, "LM Session Key does not match expectations (zeros)!\n");
1205 torture_comment(samlogon_state->tctx, "lm_key:\n");
1206 dump_data(1, lm_key, 8);
1207 pass = false;
1209 if (memcmp(nt_key, user_session_key, 16) != 0) {
1210 torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations (should be NT Key)!\n");
1211 torture_comment(samlogon_state->tctx, "user_session_key:\n");
1212 dump_data(1, user_session_key, sizeof(user_session_key));
1213 torture_comment(samlogon_state->tctx, "expected:\n");
1214 dump_data(1, nt_key, sizeof(nt_key));
1215 pass = false;
1217 return pass;
1220 static bool test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
1222 NTSTATUS nt_status;
1223 DATA_BLOB nt_response = data_blob(NULL, 0);
1224 DATA_BLOB lm_response = data_blob(NULL, 0);
1225 char *password;
1226 char *dospw;
1227 smb_ucs2_t *unicodepw;
1228 size_t converted_size = 0;
1229 uint8_t user_session_key[16];
1230 uint8_t lm_key[16];
1231 uint8_t lm_hash[16];
1232 DATA_BLOB chall = data_blob_talloc_zero(samlogon_state->mem_ctx, 8);
1233 bool lm_good = E_deshash(samlogon_state->password, lm_hash);
1235 ZERO_STRUCT(user_session_key);
1237 if (!push_ucs2_talloc(samlogon_state->mem_ctx,
1238 &unicodepw, samlogon_state->password, &converted_size)) {
1239 DEBUG(0, ("push_ucs2_allocate failed!\n"));
1240 exit(1);
1243 nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, strlen_m(samlogon_state->password)*2);
1245 password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password);
1247 if (!convert_string_talloc(samlogon_state->mem_ctx,
1248 CH_UNIX, CH_DOS,
1249 password, strlen(password)+1,
1250 (void**)&dospw, &converted_size)) {
1251 DEBUG(0, ("convert_string_talloc failed!\n"));
1252 exit(1);
1255 lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
1257 nt_status = check_samlogon(samlogon_state,
1258 break_which,
1259 samlogon_state->parameter_control | MSV1_0_CLEARTEXT_PASSWORD_ALLOWED,
1260 &chall,
1261 &lm_response,
1262 &nt_response,
1263 lm_key,
1264 user_session_key,
1265 error_string);
1267 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1268 /* for 'old' passwords, we allow the server to be OK or wrong password */
1269 if (samlogon_state->old_password) {
1270 return true;
1272 /* for 'long' passwords, the LM password is invalid */
1273 if (break_which == NO_NT && !lm_good) {
1274 return true;
1276 /* for modern servers, the LM password is invalid */
1277 if (break_which == NO_NT
1278 && !torture_setting_bool(samlogon_state->tctx, "samba3", false)) {
1279 return true;
1282 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
1283 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
1284 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
1285 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1286 int ret;
1288 SAFE_FREE(*error_string);
1289 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1290 if (ret == -1) {
1291 *error_string = NULL;
1293 return false;
1294 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1295 return true;
1296 } else if (!NT_STATUS_IS_OK(nt_status)) {
1297 return false;
1300 if (break_which == NO_NT && !lm_good) {
1301 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
1302 return false;
1305 /* for modern servers, the LM password is invalid */
1306 if (break_which == NO_NT
1307 && !torture_setting_bool(samlogon_state->tctx, "samba3", false)) {
1308 *error_string = strdup("LM password is OK but should have failed against a modern server");
1309 return false;
1312 return true;
1315 static bool test_plaintext_none_broken(struct samlogon_state *samlogon_state,
1316 char **error_string) {
1317 return test_plaintext(samlogon_state, BREAK_NONE, error_string);
1320 static bool test_plaintext_lm_broken(struct samlogon_state *samlogon_state,
1321 char **error_string) {
1322 return test_plaintext(samlogon_state, BREAK_LM, error_string);
1325 static bool test_plaintext_nt_broken(struct samlogon_state *samlogon_state,
1326 char **error_string) {
1327 return test_plaintext(samlogon_state, BREAK_NT, error_string);
1330 static bool test_plaintext_nt_only(struct samlogon_state *samlogon_state,
1331 char **error_string) {
1332 return test_plaintext(samlogon_state, NO_LM, error_string);
1335 static bool test_plaintext_lm_only(struct samlogon_state *samlogon_state,
1336 char **error_string) {
1337 return test_plaintext(samlogon_state, NO_NT, error_string);
1341 Tests:
1343 - LM only
1344 - NT and LM
1345 - NT
1346 - NT in LM field
1347 - NT in both fields
1348 - NTLMv2
1349 - NTLMv2 and LMv2
1350 - LMv2
1351 - plaintext tests (in challenge-response fields)
1353 check we get the correct session key in each case
1354 check what values we get for the LM session key
1358 static const struct ntlm_tests {
1359 bool (*fn)(struct samlogon_state *, char **);
1360 const char *name;
1361 bool expect_fail;
1362 } test_table[] = {
1363 {test_lmv2_ntlmv2, "NTLMv2 and LMv2", false},
1364 #if 0
1365 {test_lmv2_ntlmv2_no_dom, "NTLMv2 and LMv2 (no domain)", false},
1366 #endif
1367 {test_lm, "LM", false},
1368 {test_lm_ntlm, "LM and NTLM", false},
1369 {test_lm_ntlm_both_broken, "LM and NTLM, both broken", false},
1370 {test_ntlm, "NTLM", false},
1371 {test_ntlm_in_lm, "NTLM in LM", false},
1372 {test_ntlm_in_both, "NTLM in both", false},
1373 {test_ntlmv2, "NTLMv2", false},
1374 {test_ntlmv2_no_dom, "NTLMv2 (no domain)", false},
1375 {test_lmv2, "LMv2", false},
1376 {test_lmv2_no_dom, "LMv2 (no domain)", false},
1377 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", false},
1378 {test_ntlmv2_lmv2_broken_no_dom, "NTLMv2 and LMv2, LMv2 broken (no domain)", false},
1379 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", false},
1380 #if 0
1381 {test_ntlmv2_ntlmv2_broken_no_dom, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", false},
1382 #endif
1383 {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", false},
1384 {test_ntlmv2_both_broken_no_dom, "NTLMv2 and LMv2, both broken (no domain)", false},
1385 {test_ntlm_lm_broken, "NTLM and LM, LM broken", false},
1386 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", false},
1387 {test_ntlm2, "NTLM2 (NTLMv2 session security)", false},
1388 {test_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", false},
1389 {test_lmv2_ntlm_both_broken_no_dom, "LMv2 and NTLM, both broken (no domain)", false},
1390 {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", false},
1391 {test_lmv2_ntlm_break_ntlm_no_dom, "LMv2 and NTLM, NTLM broken (no domain)", false},
1392 {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", false},
1393 {test_lmv2_ntlm_break_lm_no_dom, "LMv2 and NTLM, LMv2 broken (no domain)", false},
1394 {test_plaintext_none_broken, "Plaintext", false},
1395 {test_plaintext_lm_broken, "Plaintext LM broken", false},
1396 {test_plaintext_nt_broken, "Plaintext NT broken", false},
1397 {test_plaintext_nt_only, "Plaintext NT only", false},
1398 {test_plaintext_lm_only, "Plaintext LM only", false},
1399 { .name = NULL, }
1403 try a netlogon SamLogon
1405 static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1406 struct torture_context *tctx,
1407 struct netlogon_creds_CredentialState *creds,
1408 const char *comment,
1409 const char *account_domain, const char *account_name,
1410 const char *plain_pass, uint32_t parameter_control,
1411 NTSTATUS expected_error, bool old_password,
1412 int n_subtests)
1414 TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_SamLogon function-level context");
1415 int i, v, l, f;
1416 bool ret = true;
1417 int validation_levels[] = {2,3,6};
1418 int logon_levels[] = { NetlogonNetworkInformation, NetlogonNetworkTransitiveInformation };
1419 int function_levels[] = {
1420 NDR_NETR_LOGONSAMLOGON,
1421 NDR_NETR_LOGONSAMLOGONEX,
1422 NDR_NETR_LOGONSAMLOGONWITHFLAGS };
1423 struct samlogon_state samlogon_state;
1425 union netr_LogonLevel logon;
1426 union netr_Validation validation;
1427 uint8_t authoritative = 1;
1428 uint32_t flags = 0;
1430 ZERO_STRUCT(logon);
1432 torture_comment(tctx, "Testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1434 samlogon_state.comment = comment;
1435 samlogon_state.account_name = account_name;
1436 samlogon_state.account_domain = account_domain;
1437 samlogon_state.password = plain_pass;
1438 samlogon_state.workgroup = lpcfg_workgroup(tctx->lp_ctx);
1439 samlogon_state.netbios_name = lpcfg_netbios_name(tctx->lp_ctx);
1440 samlogon_state.p = p;
1441 samlogon_state.creds = creds;
1442 samlogon_state.expected_error = expected_error;
1443 samlogon_state.chall = data_blob_talloc(fn_ctx, NULL, 8);
1444 samlogon_state.parameter_control = parameter_control;
1445 samlogon_state.old_password = old_password;
1446 samlogon_state.tctx = tctx;
1448 generate_random_buffer(samlogon_state.chall.data, 8);
1449 samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1450 samlogon_state.r_flags.in.computer_name = TEST_MACHINE_NAME;
1451 samlogon_state.r_flags.in.credential = &samlogon_state.auth;
1452 samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2;
1453 samlogon_state.r_flags.in.flags = &flags;
1454 samlogon_state.r_flags.in.logon = &logon;
1455 samlogon_state.r_flags.out.validation = &validation;
1456 samlogon_state.r_flags.out.authoritative = &authoritative;
1457 samlogon_state.r_flags.out.flags = &flags;
1459 samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1460 samlogon_state.r_ex.in.computer_name = TEST_MACHINE_NAME;
1461 samlogon_state.r_ex.in.flags = &flags;
1462 samlogon_state.r_ex.in.logon = &logon;
1463 samlogon_state.r_ex.out.validation = &validation;
1464 samlogon_state.r_ex.out.authoritative = &authoritative;
1465 samlogon_state.r_ex.out.flags = &flags;
1467 samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1468 samlogon_state.r.in.computer_name = TEST_MACHINE_NAME;
1469 samlogon_state.r.in.credential = &samlogon_state.auth;
1470 samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
1471 samlogon_state.r.in.logon = &logon;
1472 samlogon_state.r.out.validation = &validation;
1473 samlogon_state.r.out.authoritative = &authoritative;
1476 for (f=0;f<ARRAY_SIZE(function_levels);f++) {
1477 for (i=0; test_table[i].fn; i++) {
1478 if (n_subtests && (i > n_subtests)) {
1479 continue;
1481 for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
1482 for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
1483 char *error_string = NULL;
1484 TALLOC_CTX *tmp_ctx = talloc_named(fn_ctx, 0, "test_SamLogon inner loop");
1485 samlogon_state.mem_ctx = tmp_ctx;
1486 samlogon_state.function_level = function_levels[f];
1487 samlogon_state.r.in.validation_level = validation_levels[v];
1488 samlogon_state.r.in.logon_level = logon_levels[l];
1489 samlogon_state.r_ex.in.validation_level = validation_levels[v];
1490 samlogon_state.r_ex.in.logon_level = logon_levels[l];
1491 samlogon_state.r_flags.in.validation_level = validation_levels[v];
1492 samlogon_state.r_flags.in.logon_level = logon_levels[l];
1493 if (!test_table[i].fn(&samlogon_state, &error_string)) {
1494 torture_comment(tctx, "Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
1495 samlogon_state.comment,
1496 samlogon_state.account_domain,
1497 samlogon_state.account_name,
1498 test_table[i].name, validation_levels[v],
1499 logon_levels[l], function_levels[f]);
1501 if (test_table[i].expect_fail) {
1502 torture_comment(tctx, " failed (expected, test incomplete): %s\n", error_string);
1503 } else {
1504 torture_comment(tctx, " failed: %s\n", error_string);
1505 ret = false;
1507 SAFE_FREE(error_string);
1509 talloc_free(tmp_ctx);
1514 talloc_free(fn_ctx);
1515 return ret;
1519 test an ADS style interactive domain logon
1521 bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1522 struct torture_context *tctx,
1523 struct netlogon_creds_CredentialState *creds,
1524 const char *comment,
1525 const char *workstation_name,
1526 const char *account_domain, const char *account_name,
1527 const char *plain_pass, uint32_t parameter_control,
1528 NTSTATUS expected_error)
1530 NTSTATUS status;
1531 TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context");
1532 bool ret = true;
1533 struct netr_LogonSamLogonWithFlags r;
1534 struct netr_Authenticator a, ra;
1535 struct netr_PasswordInfo pinfo;
1536 uint32_t flags = 0;
1538 union netr_LogonLevel logon;
1539 union netr_Validation validation;
1540 uint8_t authoritative = 1;
1541 struct dcerpc_binding_handle *b = p->binding_handle;
1543 ZERO_STRUCT(a);
1544 ZERO_STRUCT(r);
1545 ZERO_STRUCT(ra);
1547 ZERO_STRUCT(logon);
1548 ZERO_STRUCT(validation);
1550 netlogon_creds_client_authenticator(creds, &a);
1552 logon.password = &pinfo;
1554 r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1555 r.in.computer_name = TEST_MACHINE_NAME;
1556 r.in.credential = &a;
1557 r.in.return_authenticator = &ra;
1558 r.in.logon_level = NetlogonInteractiveTransitiveInformation;
1559 r.in.logon = &logon;
1560 r.in.validation_level = 6;
1561 r.in.flags = &flags;
1562 r.out.validation = &validation;
1563 r.out.authoritative = &authoritative;
1564 r.out.flags = &flags;
1566 pinfo.identity_info.domain_name.string = account_domain;
1567 pinfo.identity_info.parameter_control = parameter_control;
1568 pinfo.identity_info.logon_id = 0;
1569 pinfo.identity_info.account_name.string = account_name;
1570 pinfo.identity_info.workstation.string = workstation_name;
1572 if (!E_deshash(plain_pass, pinfo.lmpassword.hash)) {
1573 ZERO_STRUCT(pinfo.lmpassword.hash);
1575 E_md4hash(plain_pass, pinfo.ntpassword.hash);
1577 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1578 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
1579 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
1580 } else {
1581 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
1582 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
1585 torture_comment(tctx, "Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment);
1587 status = dcerpc_netr_LogonSamLogonWithFlags_r(b, fn_ctx, &r);
1588 torture_assert_ntstatus_ok_goto(tctx,
1589 status,
1590 ret, failed,
1591 talloc_asprintf(tctx, "%s: netr_LogonSamLogonWithFlags - %s\n",
1592 __location__, nt_errstr(status)));
1594 if (!r.out.return_authenticator) {
1595 talloc_free(fn_ctx);
1596 torture_fail(tctx, "no authenticator returned");
1599 torture_assert_goto(tctx,
1600 netlogon_creds_client_check(creds, &r.out.return_authenticator->cred),
1601 ret, failed,
1602 "Credential chaining failed\n");
1604 torture_assert_ntstatus_equal(tctx, r.out.result, expected_error,
1605 talloc_asprintf(tctx, "[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n",
1606 account_domain, account_name, nt_errstr(expected_error), nt_errstr(r.out.result)));
1608 ret = true;
1609 failed:
1610 talloc_free(fn_ctx);
1612 return ret;
1615 /* This sets and resets the "minPwdAge" (in order to allow immediate user
1616 * password changes). The behaviour is controlled by the "set" boolean. */
1617 static bool handle_minPwdAge(struct torture_context *torture,
1618 TALLOC_CTX *mem_ctx, bool set)
1620 struct dcerpc_pipe *p;
1621 struct policy_handle connect_handle, domain_handle;
1622 struct samr_Connect c_r;
1623 struct samr_LookupDomain ld_r;
1624 struct samr_OpenDomain od_r;
1625 struct samr_QueryDomainInfo qdi_r;
1626 struct samr_SetDomainInfo sdi_r;
1627 struct samr_Close cl_r;
1628 struct lsa_String domName;
1629 struct dom_sid *domSid = NULL;
1630 union samr_DomainInfo *domInfo = NULL;
1631 static int64_t old_minPwdAge = 0;
1632 NTSTATUS status;
1634 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
1635 if (!NT_STATUS_IS_OK(status)) {
1636 return false;
1639 c_r.in.system_name = 0;
1640 c_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1641 c_r.out.connect_handle = &connect_handle;
1643 torture_assert_ntstatus_ok(torture,
1644 dcerpc_samr_Connect_r(p->binding_handle, mem_ctx, &c_r),
1645 "Connect failed");
1646 torture_assert_ntstatus_ok(torture, c_r.out.result, "Connect failed");
1648 ld_r.in.connect_handle = &connect_handle;
1649 ld_r.in.domain_name = &domName;
1650 ld_r.in.domain_name->string = lpcfg_workgroup(torture->lp_ctx);
1651 ld_r.out.sid = &domSid;
1653 torture_assert_ntstatus_ok(torture,
1654 dcerpc_samr_LookupDomain_r(p->binding_handle, mem_ctx, &ld_r),
1655 "LookupDomain failed");
1656 torture_assert_ntstatus_ok(torture, ld_r.out.result,
1657 "LookupDomain failed");
1659 od_r.in.connect_handle = &connect_handle;
1660 od_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1661 od_r.in.sid = *ld_r.out.sid;
1662 od_r.out.domain_handle = &domain_handle;
1664 torture_assert_ntstatus_ok(torture,
1665 dcerpc_samr_OpenDomain_r(p->binding_handle, mem_ctx, &od_r),
1666 "OpenDomain failed");
1667 torture_assert_ntstatus_ok(torture, od_r.out.result,
1668 "OpenDomain failed");
1670 qdi_r.in.domain_handle = &domain_handle;
1671 qdi_r.in.level = DomainPasswordInformation;
1672 qdi_r.out.info = &domInfo;
1674 torture_assert_ntstatus_ok(torture,
1675 dcerpc_samr_QueryDomainInfo_r(p->binding_handle, mem_ctx, &qdi_r),
1676 "QueryDomainInfo failed");
1677 torture_assert_ntstatus_ok(torture, qdi_r.out.result,
1678 "QueryDomainInfo failed");
1680 if (set) {
1681 old_minPwdAge = domInfo->info1.min_password_age;
1682 domInfo->info1.min_password_age = 0;
1683 } else {
1684 domInfo->info1.min_password_age = old_minPwdAge;
1687 sdi_r.in.domain_handle = &domain_handle;
1688 sdi_r.in.level = DomainPasswordInformation;
1689 sdi_r.in.info = domInfo;
1691 torture_assert_ntstatus_ok(torture,
1692 dcerpc_samr_SetDomainInfo_r(p->binding_handle, mem_ctx, &sdi_r),
1693 "SetDomainInfo failed");
1694 torture_assert_ntstatus_ok(torture, sdi_r.out.result,
1695 "SetDomainInfo failed");
1697 cl_r.in.handle = &connect_handle;
1698 cl_r.out.handle = &connect_handle;
1700 torture_assert_ntstatus_ok(torture,
1701 dcerpc_samr_Close_r(p->binding_handle, mem_ctx, &cl_r),
1702 "Close failed");
1703 torture_assert_ntstatus_ok(torture, cl_r.out.result, "Close failed");
1705 return true;
1708 bool torture_rpc_samlogon(struct torture_context *torture)
1710 NTSTATUS status;
1711 struct dcerpc_pipe *p;
1712 struct dcerpc_binding *b;
1713 struct cli_credentials *machine_credentials;
1714 TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon");
1715 bool ret = true;
1716 struct test_join *join_ctx = NULL;
1717 struct test_join *user_ctx = NULL, *user_ctx_wrong_wks = NULL, *user_ctx_wrong_time = NULL;
1718 const char *old_user_password, *user_password_wrong_wks, *user_password_wrong_time;
1719 char *user_password;
1720 const char *userdomain;
1721 struct samr_SetUserInfo s;
1722 union samr_UserInfo u;
1723 int i;
1724 int ci;
1726 unsigned int credential_flags[] = {
1727 NETLOGON_NEG_AUTH2_FLAGS,
1728 NETLOGON_NEG_ARCFOUR,
1729 NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
1730 NETLOGON_NEG_AUTH2_ADS_FLAGS,
1731 0 /* yes, this is a valid flag, causes the use of DES */
1734 struct netlogon_creds_CredentialState *creds;
1735 struct dcerpc_pipe *tmp_p = NULL;
1737 torture_assert(torture, handle_minPwdAge(torture, mem_ctx, true),
1738 "handle_minPwdAge error!");
1740 /* We only need to join as a workstation here, and in future,
1741 * if we wish to test against trusted domains, we must be a
1742 * workstation here */
1743 join_ctx = torture_join_domain(torture, TEST_MACHINE_NAME, ACB_WSTRUST,
1744 &machine_credentials);
1745 torture_assert(torture, join_ctx, "Failed to join as Workstation\n");
1747 userdomain = torture_setting_string(torture, "userdomain", lpcfg_workgroup(torture->lp_ctx));
1749 user_ctx = torture_create_testuser(torture,
1750 TEST_USER_NAME,
1751 userdomain,
1752 ACB_NORMAL,
1753 &old_user_password);
1754 torture_assert(torture, user_ctx, "Failed to create a test user\n");
1756 user_password = talloc_strdup(torture, old_user_password);
1757 torture_assert(torture, user_password != NULL, "Failed to copy old_user_password\n");
1759 tmp_p = torture_join_samr_pipe(user_ctx);
1760 torture_assert(torture, tmp_p, "torture_join_samr_pipe failed\n");
1761 test_ChangePasswordUser3(tmp_p, torture,
1762 TEST_USER_NAME, 16 /* > 14 */, &user_password,
1763 NULL, 0, false);
1765 user_ctx_wrong_wks = torture_create_testuser(torture,
1766 TEST_USER_NAME_WRONG_WKS,
1767 userdomain,
1768 ACB_NORMAL,
1769 &user_password_wrong_wks);
1770 torture_assert(torture, user_ctx_wrong_wks,
1771 "Failed to create a test user (wrong workstation test)\n");
1773 ZERO_STRUCT(u);
1774 s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_wks);
1775 s.in.info = &u;
1776 s.in.level = 21;
1778 u.info21.fields_present = SAMR_FIELD_WORKSTATIONS;
1779 u.info21.workstations.string = "not" TEST_MACHINE_NAME;
1781 tmp_p = torture_join_samr_pipe(user_ctx_wrong_wks);
1782 status = dcerpc_samr_SetUserInfo_r(tmp_p->binding_handle, mem_ctx, &s);
1783 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
1784 talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status)));
1785 torture_assert_ntstatus_ok_goto(torture, s.out.result, ret, failed,
1786 talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s.out.result)));
1788 user_ctx_wrong_time
1789 = torture_create_testuser(torture, TEST_USER_NAME_WRONG_TIME,
1790 userdomain,
1791 ACB_NORMAL,
1792 &user_password_wrong_time);
1793 torture_assert(torture, user_ctx_wrong_time,
1794 "Failed to create a test user (wrong workstation test)\n");
1796 ZERO_STRUCT(u);
1797 s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_time);
1798 s.in.info = &u;
1799 s.in.level = 21;
1801 u.info21.fields_present = SAMR_FIELD_WORKSTATIONS | SAMR_FIELD_LOGON_HOURS;
1802 u.info21.workstations.string = TEST_MACHINE_NAME;
1803 u.info21.logon_hours.units_per_week = 168;
1804 u.info21.logon_hours.bits = talloc_zero_array(mem_ctx, uint8_t, 168);
1806 tmp_p = torture_join_samr_pipe(user_ctx_wrong_time);
1807 status = dcerpc_samr_SetUserInfo_r(tmp_p->binding_handle, mem_ctx, &s);
1808 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
1809 talloc_asprintf(torture, "SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status)));
1810 torture_assert_ntstatus_ok_goto(torture, s.out.result, ret, failed,
1811 talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s.out.result)));
1814 torture_assert_ntstatus_ok_goto(torture,
1815 torture_rpc_binding(torture, &b),
1816 ret,
1817 failed,
1818 "Obtaining binding");
1820 /* We have to use schannel, otherwise the SamLogonEx fails
1821 * with INTERNAL_ERROR */
1823 status = dcerpc_binding_set_flags(b,
1824 DCERPC_SCHANNEL |
1825 DCERPC_SIGN | DCERPC_SEAL |
1826 DCERPC_SCHANNEL_128,
1827 DCERPC_AUTH_OPTIONS);
1828 torture_assert_ntstatus_ok(torture, status, "set flags");
1830 status = dcerpc_pipe_connect_b(mem_ctx, &p, b,
1831 &ndr_table_netlogon,
1832 machine_credentials, torture->ev, torture->lp_ctx);
1834 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
1835 talloc_asprintf(torture, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status)));
1837 torture_assert_not_null_goto(torture,
1838 creds = cli_credentials_get_netlogon_creds(machine_credentials),
1839 ret,
1840 failed,
1841 "obtaining credentails");
1845 struct {
1846 const char *comment;
1847 const char *domain;
1848 const char *username;
1849 const char *password;
1850 bool network_login;
1851 NTSTATUS expected_interactive_error;
1852 NTSTATUS expected_network_error;
1853 uint32_t parameter_control;
1854 bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
1855 } usercreds[] = {
1857 .comment = "domain\\user",
1858 .domain = cli_credentials_get_domain(
1859 samba_cmdline_get_creds()),
1860 .username = cli_credentials_get_username(
1861 samba_cmdline_get_creds()),
1862 .password = cli_credentials_get_password(
1863 samba_cmdline_get_creds()),
1864 .network_login = true,
1865 .expected_interactive_error = NT_STATUS_OK,
1866 .expected_network_error = NT_STATUS_OK,
1867 .parameter_control = 0,
1870 .comment = "realm\\user",
1871 .domain = cli_credentials_get_realm(
1872 samba_cmdline_get_creds()),
1873 .username = cli_credentials_get_username(
1874 samba_cmdline_get_creds()),
1875 .password = cli_credentials_get_password(
1876 samba_cmdline_get_creds()),
1877 .network_login = true,
1878 .expected_interactive_error = NT_STATUS_OK,
1879 .expected_network_error = NT_STATUS_OK,
1880 .parameter_control = 0,
1883 .comment = "user@domain",
1884 .domain = NULL,
1885 .username = talloc_asprintf(mem_ctx,
1886 "%s@%s",
1887 cli_credentials_get_username(
1888 samba_cmdline_get_creds()),
1889 cli_credentials_get_domain(
1890 samba_cmdline_get_creds())
1892 .password = cli_credentials_get_password(
1893 samba_cmdline_get_creds()),
1894 .network_login = false, /* works for some things, but not NTLMv2. Odd */
1895 .expected_interactive_error = NT_STATUS_OK,
1896 .expected_network_error = NT_STATUS_OK,
1897 .parameter_control = 0,
1900 .comment = "user@realm",
1901 .domain = NULL,
1902 .username = talloc_asprintf(mem_ctx,
1903 "%s@%s",
1904 cli_credentials_get_username(
1905 samba_cmdline_get_creds()),
1906 cli_credentials_get_realm(
1907 samba_cmdline_get_creds())
1909 .password = cli_credentials_get_password(
1910 samba_cmdline_get_creds()),
1911 .network_login = true,
1912 .expected_interactive_error = NT_STATUS_OK,
1913 .expected_network_error = NT_STATUS_OK,
1914 .parameter_control = 0,
1917 .comment = "machine domain\\user",
1918 .domain = cli_credentials_get_domain(machine_credentials),
1919 .username = cli_credentials_get_username(machine_credentials),
1920 .password = cli_credentials_get_password(machine_credentials),
1921 .network_login = true,
1922 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1923 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1926 .comment = "machine domain\\user",
1927 .domain = cli_credentials_get_domain(machine_credentials),
1928 .username = cli_credentials_get_username(machine_credentials),
1929 .password = cli_credentials_get_password(machine_credentials),
1930 .network_login = true,
1931 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1932 .expected_network_error = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT,
1933 .parameter_control = 0,
1936 .comment = "machine realm\\user",
1937 .domain = cli_credentials_get_realm(machine_credentials),
1938 .username = cli_credentials_get_username(machine_credentials),
1939 .password = cli_credentials_get_password(machine_credentials),
1940 .network_login = true,
1941 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1942 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1945 .comment = "machine user@domain",
1946 .domain = NULL,
1947 .username = talloc_asprintf(mem_ctx,
1948 "%s@%s",
1949 cli_credentials_get_username(machine_credentials),
1950 cli_credentials_get_domain(machine_credentials)
1952 .password = cli_credentials_get_password(machine_credentials),
1953 .network_login = false, /* works for some things, but not NTLMv2. Odd */
1954 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1955 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1958 .comment = "machine user@realm",
1959 .domain = NULL,
1960 .username = talloc_asprintf(mem_ctx,
1961 "%s@%s",
1962 cli_credentials_get_username(machine_credentials),
1963 cli_credentials_get_realm(machine_credentials)
1965 .password = cli_credentials_get_password(machine_credentials),
1966 .network_login = true,
1967 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1968 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1971 .comment = "test user (long pw): domain\\user",
1972 .domain = userdomain,
1973 .username = TEST_USER_NAME,
1974 .password = user_password,
1975 .network_login = true,
1976 .expected_interactive_error = NT_STATUS_OK,
1977 .expected_network_error = NT_STATUS_OK,
1978 .parameter_control = 0,
1981 .comment = "test user (long pw): user@realm",
1982 .domain = NULL,
1983 .username = talloc_asprintf(mem_ctx,
1984 "%s@%s",
1985 TEST_USER_NAME,
1986 lpcfg_realm(torture->lp_ctx)),
1987 .password = user_password,
1988 .network_login = true,
1989 .expected_interactive_error = NT_STATUS_OK,
1990 .expected_network_error = NT_STATUS_OK,
1991 .parameter_control = 0,
1994 .comment = "test user (long pw): user@domain",
1995 .domain = NULL,
1996 .username = talloc_asprintf(mem_ctx,
1997 "%s@%s",
1998 TEST_USER_NAME,
1999 userdomain),
2000 .password = user_password,
2001 .network_login = false, /* works for some things, but not NTLMv2. Odd */
2002 .expected_interactive_error = NT_STATUS_OK,
2003 .expected_network_error = NT_STATUS_OK,
2004 .parameter_control = 0,
2006 /* Oddball, can we use the old password ? */
2008 .comment = "test user: user\\domain OLD PASSWORD",
2009 .domain = userdomain,
2010 .username = TEST_USER_NAME,
2011 .password = old_user_password,
2012 .network_login = true,
2013 .expected_interactive_error = NT_STATUS_WRONG_PASSWORD,
2014 .expected_network_error = NT_STATUS_OK,
2015 .old_password = true
2018 .comment = "test user (wrong workstation): domain\\user",
2019 .domain = userdomain,
2020 .username = TEST_USER_NAME_WRONG_WKS,
2021 .password = user_password_wrong_wks,
2022 .network_login = true,
2023 .expected_interactive_error = NT_STATUS_INVALID_WORKSTATION,
2024 .expected_network_error = NT_STATUS_INVALID_WORKSTATION,
2025 .parameter_control = 0,
2029 /* Try all the tests for different username forms */
2030 for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) {
2032 torture_assert_goto(torture,
2033 test_InteractiveLogon(p, mem_ctx, torture, creds,
2034 usercreds[ci].comment,
2035 TEST_MACHINE_NAME,
2036 usercreds[ci].domain,
2037 usercreds[ci].username,
2038 usercreds[ci].password,
2039 usercreds[ci].parameter_control,
2040 usercreds[ci].expected_interactive_error),
2041 ret,
2042 failed,
2043 talloc_asprintf(mem_ctx, "InteractiveLogon: %s",
2044 usercreds[ci].comment));
2046 if (usercreds[ci].network_login) {
2047 torture_assert_goto(torture,
2048 test_SamLogon(p, mem_ctx, torture, creds,
2049 usercreds[ci].comment,
2050 usercreds[ci].domain,
2051 usercreds[ci].username,
2052 usercreds[ci].password,
2053 usercreds[ci].parameter_control,
2054 usercreds[ci].expected_network_error,
2055 usercreds[ci].old_password,
2057 ret,
2058 failed,
2059 talloc_asprintf(mem_ctx, "SamLogon: %s",
2060 usercreds[ci].comment));
2064 /* Using the first username form, try the different
2065 * credentials flag setups, on only one of the tests (checks
2066 * session key encryption) */
2068 for (i=0; i < ARRAY_SIZE(credential_flags); i++) {
2069 /* TODO: Somehow we lost setting up the different credential flags here! */
2071 torture_comment(torture,
2072 "Testing with flags: 0x%08x\n",
2073 credential_flags[i]);
2075 torture_assert_goto(torture,
2076 test_InteractiveLogon(p, mem_ctx, torture, creds,
2077 usercreds[0].comment,
2078 TEST_MACHINE_NAME,
2079 usercreds[0].domain,
2080 usercreds[0].username,
2081 usercreds[0].password,
2082 usercreds[0].parameter_control,
2083 usercreds[0].expected_interactive_error),
2084 ret,
2085 failed,
2086 talloc_asprintf(mem_ctx,
2087 "Testing InteractiveLogon with flags: 0x%08x\n",
2088 credential_flags[i]));
2090 if (usercreds[0].network_login) {
2091 torture_assert_goto(torture,
2092 test_SamLogon(p, mem_ctx, torture, creds,
2093 usercreds[0].comment,
2094 usercreds[0].domain,
2095 usercreds[0].username,
2096 usercreds[0].password,
2097 usercreds[0].parameter_control,
2098 usercreds[0].expected_network_error,
2099 usercreds[0].old_password,
2101 ret,
2102 failed,
2103 talloc_asprintf(mem_ctx,
2104 "Testing SamLogon with flags: 0x%08x\n",
2105 credential_flags[i]));
2110 failed:
2111 torture_assert(torture, handle_minPwdAge(torture, mem_ctx, false),
2112 "handle_minPwdAge error!");
2114 talloc_free(mem_ctx);
2116 torture_leave_domain(torture, join_ctx);
2117 torture_leave_domain(torture, user_ctx);
2118 torture_leave_domain(torture, user_ctx_wrong_wks);
2119 torture_leave_domain(torture, user_ctx_wrong_time);
2120 return ret;