drsuapi.idl: fix source_dsa spelling
[samba4-gss.git] / source4 / torture / rpc / samlogon.c
blobebf00bc4cf5737a8a8968f72a1202cf97547976b
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 == NULL) {
173 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
174 if (error_string) {
175 *error_string = strdup(nt_errstr(status));
177 return status;
179 status = netlogon_creds_client_verify(samlogon_state->creds,
180 &r->out.return_authenticator->cred,
181 auth_type,
182 auth_level);
183 if (!NT_STATUS_IS_OK(status)) {
184 if (error_string) {
185 *error_string = strdup(nt_errstr(status));
187 return status;
189 if (!NT_STATUS_IS_OK(r->out.result)) {
190 if (error_string) {
191 *error_string = strdup(nt_errstr(r->out.result));
193 return r->out.result;
196 validation_level = r->in.validation_level;
198 status = netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds,
199 validation_level,
200 r->out.validation,
201 auth_type,
202 auth_level);
203 if (!NT_STATUS_IS_OK(status)) {
204 if (error_string) {
205 *error_string = strdup(nt_errstr(status));
207 return status;
210 switch (validation_level) {
211 case 2:
212 base = &r->out.validation->sam2->base;
213 break;
214 case 3:
215 base = &r->out.validation->sam3->base;
216 break;
217 case 6:
218 base = &r->out.validation->sam6->base;
219 break;
221 break;
222 case NDR_NETR_LOGONSAMLOGONEX:
223 status = dcerpc_netr_LogonSamLogonEx_r(samlogon_state->p->binding_handle,
224 samlogon_state->mem_ctx, r_ex);
225 if (!NT_STATUS_IS_OK(status)) {
226 if (error_string) {
227 *error_string = strdup(nt_errstr(status));
229 return status;
231 if (!NT_STATUS_IS_OK(r_ex->out.result)) {
232 if (error_string) {
233 *error_string = strdup(nt_errstr(r_ex->out.result));
235 return r_ex->out.result;
238 validation_level = r_ex->in.validation_level;
240 status = netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds,
241 validation_level,
242 r_ex->out.validation,
243 auth_type,
244 auth_level);
245 if (!NT_STATUS_IS_OK(status)) {
246 if (error_string) {
247 *error_string = strdup(nt_errstr(status));
249 return status;
252 switch (validation_level) {
253 case 2:
254 base = &r_ex->out.validation->sam2->base;
255 break;
256 case 3:
257 base = &r_ex->out.validation->sam3->base;
258 break;
259 case 6:
260 base = &r_ex->out.validation->sam6->base;
261 break;
263 break;
264 case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
265 ZERO_STRUCT(samlogon_state->auth2);
266 netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
268 r_flags->out.return_authenticator = NULL;
269 status = dcerpc_netr_LogonSamLogonWithFlags_r(samlogon_state->p->binding_handle,
270 samlogon_state->mem_ctx, r_flags);
271 if (!NT_STATUS_IS_OK(status)) {
272 if (error_string) {
273 *error_string = strdup(nt_errstr(status));
275 return status;
277 if (r_flags->out.return_authenticator == NULL) {
278 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
279 if (error_string) {
280 *error_string = strdup(nt_errstr(status));
282 return status;
284 status = netlogon_creds_client_verify(samlogon_state->creds,
285 &r_flags->out.return_authenticator->cred,
286 auth_type,
287 auth_level);
288 if (!NT_STATUS_IS_OK(status)) {
289 if (error_string) {
290 *error_string = strdup(nt_errstr(status));
292 return status;
294 if (!NT_STATUS_IS_OK(r_flags->out.result)) {
295 if (error_string) {
296 *error_string = strdup(nt_errstr(r_flags->out.result));
298 return r_flags->out.result;
301 validation_level = r_flags->in.validation_level;
303 status = netlogon_creds_decrypt_samlogon_validation(samlogon_state->creds,
304 validation_level,
305 r_flags->out.validation,
306 auth_type,
307 auth_level);
308 if (!NT_STATUS_IS_OK(status)) {
309 if (error_string) {
310 *error_string = strdup(nt_errstr(status));
312 return status;
315 switch (validation_level) {
316 case 2:
317 base = &r_flags->out.validation->sam2->base;
318 break;
319 case 3:
320 base = &r_flags->out.validation->sam3->base;
321 break;
322 case 6:
323 base = &r_flags->out.validation->sam6->base;
324 break;
326 break;
327 default:
328 /* can't happen */
329 return NT_STATUS_INVALID_PARAMETER;
332 if (!base) {
333 torture_comment(samlogon_state->tctx, "No user info returned from 'successful' SamLogon*() call!\n");
334 return NT_STATUS_INVALID_PARAMETER;
337 if (user_session_key) {
338 memcpy(user_session_key, base->key.key, 16);
340 if (lm_key) {
341 memcpy(lm_key, base->LMSessKey.key, 8);
344 return status;
349 * Test the normal 'LM and NTLM' combination
352 static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
354 bool pass = true;
355 bool lm_good;
356 NTSTATUS nt_status;
357 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
358 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
359 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
361 uint8_t lm_key[8];
362 uint8_t user_session_key[16];
363 uint8_t lm_hash[16];
364 uint8_t nt_hash[16];
366 ZERO_STRUCT(lm_key);
367 ZERO_STRUCT(user_session_key);
369 lm_good = SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
370 if (!lm_good) {
371 ZERO_STRUCT(lm_hash);
372 } else {
373 E_deshash(samlogon_state->password, lm_hash);
376 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
378 E_md4hash(samlogon_state->password, nt_hash);
379 SMBsesskeygen_ntv1(nt_hash, session_key.data);
381 nt_status = check_samlogon(samlogon_state,
382 break_which,
383 samlogon_state->parameter_control,
384 &samlogon_state->chall,
385 &lm_response,
386 &nt_response,
387 lm_key,
388 user_session_key,
389 error_string);
391 data_blob_free(&lm_response);
393 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
394 /* for 'long' passwords, the LM password is invalid */
395 if (break_which == NO_NT && !lm_good) {
396 return true;
398 /* for modern servers, the LM password is invalid */
399 if (break_which == NO_NT
400 && !torture_setting_bool(samlogon_state->tctx, "samba3", false)) {
401 return true;
404 /* for 'old' passwords, we allow the server to be OK or wrong password */
405 if (samlogon_state->old_password) {
406 return true;
408 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
409 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
410 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
411 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
412 int ret;
414 SAFE_FREE(*error_string);
415 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
416 if (ret == -1) {
417 *error_string = NULL;
419 return false;
420 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
421 return true;
422 } else if (!NT_STATUS_IS_OK(nt_status)) {
423 return false;
426 if (break_which == NO_NT && !lm_good) {
427 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
428 return false;
431 /* for modern servers, the LM password is invalid */
432 if (break_which == NO_NT
433 && !torture_setting_bool(samlogon_state->tctx, "samba3", false)) {
434 *error_string = strdup("LM password is OK but should have failed against a modern server");
435 return false;
438 if (!all_zero(lm_key, sizeof(lm_key)) != 0) {
439 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
440 torture_comment(samlogon_state->tctx, "lm_key:\n");
441 dump_data(1, lm_key, 8);
442 torture_comment(samlogon_state->tctx, "expected (all zeros):\n");
443 pass = false;
446 switch (break_which) {
447 case NO_NT:
449 uint8_t lm_key_expected[16];
450 memcpy(lm_key_expected, session_key.data, 8);
451 memset(lm_key_expected+8, '\0', 8);
452 if (memcmp(lm_key_expected, user_session_key,
453 16) != 0) {
454 *error_string = strdup("NT Session Key does not match expectations (should be first-8 session key)!\n");
455 torture_comment(samlogon_state->tctx, "user_session_key:\n");
456 dump_data(1, user_session_key, sizeof(user_session_key));
457 torture_comment(samlogon_state->tctx, "expected:\n");
458 dump_data(1, lm_key_expected, sizeof(lm_key_expected));
459 pass = false;
461 break;
463 default:
464 if (memcmp(session_key.data, user_session_key,
465 sizeof(user_session_key)) != 0) {
466 *error_string = strdup("NT Session Key does not match expectations!\n");
467 torture_comment(samlogon_state->tctx, "user_session_key:\n");
468 dump_data(1, user_session_key, 16);
469 torture_comment(samlogon_state->tctx, "expected:\n");
470 dump_data(1, session_key.data, session_key.length);
471 pass = false;
474 return pass;
478 * Test LM authentication, no NT response supplied
481 static bool test_lm(struct samlogon_state *samlogon_state, char **error_string)
484 return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
488 * Test the NTLM response only, no LM.
491 static bool test_ntlm(struct samlogon_state *samlogon_state, char **error_string)
493 return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
497 * Test the NTLM response only, but in the LM field.
500 static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string)
502 bool lm_good;
503 bool pass = true;
504 NTSTATUS nt_status;
505 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
506 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
508 uint8_t lm_key[8];
509 uint8_t lm_hash[16];
510 uint8_t user_session_key[16];
511 uint8_t nt_hash[16];
513 ZERO_STRUCT(lm_key);
514 ZERO_STRUCT(user_session_key);
516 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
517 nt_response.data);
518 E_md4hash(samlogon_state->password, nt_hash);
519 SMBsesskeygen_ntv1(nt_hash,
520 session_key.data);
522 lm_good = E_deshash(samlogon_state->password, lm_hash);
523 if (!lm_good) {
524 ZERO_STRUCT(lm_hash);
526 nt_status = check_samlogon(samlogon_state,
527 BREAK_NONE,
528 samlogon_state->parameter_control,
529 &samlogon_state->chall,
530 &nt_response,
531 NULL,
532 lm_key,
533 user_session_key,
534 error_string);
536 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
537 /* for 'old' passwords, we allow the server to be OK or wrong password */
538 if (samlogon_state->old_password) {
539 return true;
541 return false;
542 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
543 int ret;
545 SAFE_FREE(*error_string);
546 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
547 if (ret == -1) {
548 *error_string = NULL;
550 return false;
551 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
552 return true;
553 } else if (!NT_STATUS_IS_OK(nt_status)) {
554 return false;
557 if (torture_setting_bool(samlogon_state->tctx, "samba4", false)) {
558 if (!all_zero(lm_key, sizeof(lm_key)) != 0) {
559 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
560 torture_comment(samlogon_state->tctx, "lm_key:\n");
561 dump_data(1, lm_key, 8);
562 torture_comment(samlogon_state->tctx, "expected (all zeros):\n");
563 pass = false;
567 if (!all_zero(user_session_key, sizeof(user_session_key)) != 0) {
568 torture_comment(samlogon_state->tctx, "NT Key does not match expectations!\n");
569 torture_comment(samlogon_state->tctx, "user_session_key:\n");
570 dump_data(1, user_session_key, sizeof(user_session_key));
571 torture_comment(samlogon_state->tctx, "expected (all zeros):\n");
572 pass = false;
574 } else {
575 if (lm_good) {
576 if (memcmp(lm_hash, lm_key,
577 sizeof(lm_key)) != 0) {
578 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
579 torture_comment(samlogon_state->tctx, "lm_key:\n");
580 dump_data(1, lm_key, 8);
581 torture_comment(samlogon_state->tctx, "expected:\n");
582 dump_data(1, lm_hash, 8);
583 pass = false;
585 #if 0
586 } else {
587 if (memcmp(session_key.data, lm_key,
588 sizeof(lm_key)) != 0) {
589 torture_comment(samlogon_state->tctx, "LM Key does not match expectations (first 8 session key)!\n");
590 torture_comment(samlogon_state->tctx, "lm_key:\n");
591 dump_data(1, lm_key, 8);
592 torture_comment(samlogon_state->tctx, "expected:\n");
593 dump_data(1, session_key.data, 8);
594 pass = false;
596 #endif
598 if (lm_good && memcmp(lm_hash, user_session_key, 8) != 0) {
599 uint8_t lm_key_expected[16];
600 memcpy(lm_key_expected, lm_hash, 8);
601 memset(lm_key_expected+8, '\0', 8);
602 if (memcmp(lm_key_expected, user_session_key,
603 16) != 0) {
604 torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations (should be first-8 LM hash)!\n");
605 torture_comment(samlogon_state->tctx, "user_session_key:\n");
606 dump_data(1, user_session_key, sizeof(user_session_key));
607 torture_comment(samlogon_state->tctx, "expected:\n");
608 dump_data(1, lm_key_expected, sizeof(lm_key_expected));
609 pass = false;
613 return pass;
617 * Test the NTLM response only, but in the both the NT and LM fields.
620 static bool test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string)
622 bool pass = true;
623 bool lm_good;
624 NTSTATUS nt_status;
625 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
626 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
628 uint8_t lm_key[8];
629 uint8_t lm_hash[16];
630 uint8_t user_session_key[16];
631 uint8_t nt_hash[16];
633 ZERO_STRUCT(lm_key);
634 ZERO_STRUCT(user_session_key);
636 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
637 nt_response.data);
638 E_md4hash(samlogon_state->password, nt_hash);
639 SMBsesskeygen_ntv1(nt_hash,
640 session_key.data);
642 lm_good = E_deshash(samlogon_state->password, lm_hash);
643 if (!lm_good) {
644 ZERO_STRUCT(lm_hash);
647 nt_status = check_samlogon(samlogon_state,
648 BREAK_NONE,
649 samlogon_state->parameter_control,
650 &samlogon_state->chall,
651 NULL,
652 &nt_response,
653 lm_key,
654 user_session_key,
655 error_string);
657 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
658 /* for 'old' passwords, we allow the server to be OK or wrong password */
659 if (samlogon_state->old_password) {
660 return true;
662 return false;
663 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
664 int ret;
666 SAFE_FREE(*error_string);
667 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
668 if (ret == -1) {
669 *error_string = NULL;
671 return false;
672 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
673 return true;
674 } else if (!NT_STATUS_IS_OK(nt_status)) {
675 return false;
678 if (!NT_STATUS_IS_OK(nt_status)) {
679 return false;
682 if (!all_zero(lm_key,
683 sizeof(lm_key)) != 0) {
684 torture_comment(samlogon_state->tctx, "LM Key does not match expectations!\n");
685 torture_comment(samlogon_state->tctx, "lm_key:\n");
686 dump_data(1, lm_key, 8);
687 torture_comment(samlogon_state->tctx, "expected (all zero)\n");
688 pass = false;
690 if (memcmp(session_key.data, user_session_key,
691 sizeof(user_session_key)) != 0) {
692 torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations!\n");
693 torture_comment(samlogon_state->tctx, "user_session_key:\n");
694 dump_data(1, user_session_key, 16);
695 torture_comment(samlogon_state->tctx, "expected:\n");
696 dump_data(1, session_key.data, session_key.length);
697 pass = false;
701 return pass;
705 * Test the NTLMv2 and LMv2 responses
708 enum ntlmv2_domain {
709 UPPER_DOMAIN,
710 NO_DOMAIN
713 static bool test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state,
714 enum ntlm_break break_which,
715 enum ntlmv2_domain ntlmv2_domain,
716 char **error_string)
718 bool pass = true;
719 NTSTATUS nt_status;
720 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
721 DATA_BLOB lmv2_response = data_blob(NULL, 0);
722 DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
723 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
724 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, TEST_MACHINE_NAME, samlogon_state->workgroup);
726 uint8_t lm_session_key[8];
727 uint8_t user_session_key[16];
729 ZERO_STRUCT(lm_session_key);
730 ZERO_STRUCT(user_session_key);
732 switch (ntlmv2_domain) {
733 case UPPER_DOMAIN:
734 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
735 samlogon_state->account_name, samlogon_state->account_domain,
736 samlogon_state->password, &samlogon_state->chall,
737 &names_blob,
738 &lmv2_response, &ntlmv2_response,
739 &lmv2_session_key, &ntlmv2_session_key)) {
740 data_blob_free(&names_blob);
741 return false;
743 break;
744 case NO_DOMAIN:
745 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
746 samlogon_state->account_name, "",
747 samlogon_state->password, &samlogon_state->chall,
748 &names_blob,
749 &lmv2_response, &ntlmv2_response,
750 &lmv2_session_key, &ntlmv2_session_key)) {
751 data_blob_free(&names_blob);
752 return false;
754 break;
756 data_blob_free(&names_blob);
758 nt_status = check_samlogon(samlogon_state,
759 break_which,
760 samlogon_state->parameter_control,
761 &samlogon_state->chall,
762 &lmv2_response,
763 &ntlmv2_response,
764 lm_session_key,
765 user_session_key,
766 error_string);
768 data_blob_free(&lmv2_response);
769 data_blob_free(&ntlmv2_response);
772 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
773 /* for 'old' passwords, we allow the server to be OK or wrong password */
774 if (samlogon_state->old_password) {
775 return true;
777 return break_which == BREAK_BOTH;
778 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
779 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
780 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
781 int ret;
783 SAFE_FREE(*error_string);
784 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
785 if (ret == -1) {
786 *error_string = NULL;
788 return false;
789 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
790 return true;
791 } else if (!NT_STATUS_IS_OK(nt_status)) {
792 return false;
796 switch (break_which) {
797 case NO_NT:
798 if (memcmp(lmv2_session_key.data, user_session_key,
799 sizeof(user_session_key)) != 0) {
800 torture_comment(samlogon_state->tctx, "USER (LMv2) Session Key does not match expectations!\n");
801 torture_comment(samlogon_state->tctx, "user_session_key:\n");
802 dump_data(1, user_session_key, 16);
803 torture_comment(samlogon_state->tctx, "expected:\n");
804 dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
805 pass = false;
807 if (memcmp(lmv2_session_key.data, lm_session_key,
808 sizeof(lm_session_key)) != 0) {
809 torture_comment(samlogon_state->tctx, "LM (LMv2) Session Key does not match expectations!\n");
810 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
811 dump_data(1, lm_session_key, 8);
812 torture_comment(samlogon_state->tctx, "expected:\n");
813 dump_data(1, lmv2_session_key.data, 8);
814 pass = false;
816 break;
817 default:
818 if (memcmp(ntlmv2_session_key.data, user_session_key,
819 sizeof(user_session_key)) != 0) {
820 if (memcmp(lmv2_session_key.data, user_session_key,
821 sizeof(user_session_key)) == 0) {
822 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key expected, got LMv2 session key instead:\n");
823 torture_comment(samlogon_state->tctx, "user_session_key:\n");
824 dump_data(1, user_session_key, 16);
825 torture_comment(samlogon_state->tctx, "expected:\n");
826 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
827 pass = false;
829 } else {
830 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n");
831 torture_comment(samlogon_state->tctx, "user_session_key:\n");
832 dump_data(1, user_session_key, 16);
833 torture_comment(samlogon_state->tctx, "expected:\n");
834 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
835 pass = false;
838 if (memcmp(ntlmv2_session_key.data, lm_session_key,
839 sizeof(lm_session_key)) != 0) {
840 if (memcmp(lmv2_session_key.data, lm_session_key,
841 sizeof(lm_session_key)) == 0) {
842 torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key expected, got LMv2 session key instead:\n");
843 torture_comment(samlogon_state->tctx, "user_session_key:\n");
844 dump_data(1, lm_session_key, 8);
845 torture_comment(samlogon_state->tctx, "expected:\n");
846 dump_data(1, ntlmv2_session_key.data, 8);
847 pass = false;
848 } else {
849 torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key does not match expectations!\n");
850 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
851 dump_data(1, lm_session_key, 8);
852 torture_comment(samlogon_state->tctx, "expected:\n");
853 dump_data(1, ntlmv2_session_key.data, 8);
854 pass = false;
859 return pass;
863 * Test the NTLM and LMv2 responses
866 static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state,
867 enum ntlm_break break_which,
868 enum ntlmv2_domain ntlmv2_domain,
869 char **error_string)
871 bool pass = true;
872 NTSTATUS nt_status;
873 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
874 DATA_BLOB lmv2_response = data_blob(NULL, 0);
875 DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
876 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
877 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, samlogon_state->netbios_name, samlogon_state->workgroup);
879 DATA_BLOB ntlm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
880 DATA_BLOB ntlm_session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
882 bool lm_good;
883 uint8_t lm_hash[16];
884 uint8_t lm_session_key[8];
885 uint8_t user_session_key[16];
886 uint8_t nt_hash[16];
888 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
889 ntlm_response.data);
890 E_md4hash(samlogon_state->password, nt_hash);
891 SMBsesskeygen_ntv1(nt_hash,
892 ntlm_session_key.data);
894 lm_good = E_deshash(samlogon_state->password, lm_hash);
895 if (!lm_good) {
896 ZERO_STRUCT(lm_hash);
899 ZERO_STRUCT(lm_session_key);
900 ZERO_STRUCT(user_session_key);
902 switch (ntlmv2_domain) {
903 case UPPER_DOMAIN:
904 /* TODO - test with various domain cases, and without domain */
905 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
906 samlogon_state->account_name, samlogon_state->account_domain,
907 samlogon_state->password, &samlogon_state->chall,
908 &names_blob,
909 &lmv2_response, &ntlmv2_response,
910 &lmv2_session_key, &ntlmv2_session_key)) {
911 data_blob_free(&names_blob);
912 return false;
914 break;
915 case NO_DOMAIN:
916 /* TODO - test with various domain cases, and without domain */
917 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx,
918 samlogon_state->account_name, "",
919 samlogon_state->password, &samlogon_state->chall,
920 &names_blob,
921 &lmv2_response, &ntlmv2_response,
922 &lmv2_session_key, &ntlmv2_session_key)) {
923 data_blob_free(&names_blob);
924 return false;
926 break;
929 data_blob_free(&names_blob);
931 nt_status = check_samlogon(samlogon_state,
932 break_which,
933 samlogon_state->parameter_control,
934 &samlogon_state->chall,
935 &lmv2_response,
936 &ntlm_response,
937 lm_session_key,
938 user_session_key,
939 error_string);
941 data_blob_free(&lmv2_response);
942 data_blob_free(&ntlmv2_response);
945 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
946 /* for 'old' passwords, we allow the server to be OK or wrong password */
947 if (samlogon_state->old_password) {
948 return true;
950 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
951 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
952 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
953 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
954 int ret;
956 SAFE_FREE(*error_string);
957 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
958 if (ret == -1) {
959 *error_string = NULL;
961 return false;
962 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
963 return true;
964 } else if (!NT_STATUS_IS_OK(nt_status)) {
965 return false;
968 switch (break_which) {
969 case NO_NT:
970 if (memcmp(lmv2_session_key.data, user_session_key,
971 sizeof(user_session_key)) != 0) {
972 torture_comment(samlogon_state->tctx, "USER (LMv2) Session Key does not match expectations!\n");
973 torture_comment(samlogon_state->tctx, "user_session_key:\n");
974 dump_data(1, user_session_key, 16);
975 torture_comment(samlogon_state->tctx, "expected:\n");
976 dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
977 pass = false;
979 if (memcmp(lmv2_session_key.data, lm_session_key,
980 sizeof(lm_session_key)) != 0) {
981 torture_comment(samlogon_state->tctx, "LM (LMv2) Session Key does not match expectations!\n");
982 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
983 dump_data(1, lm_session_key, 8);
984 torture_comment(samlogon_state->tctx, "expected:\n");
985 dump_data(1, lmv2_session_key.data, 8);
986 pass = false;
988 break;
989 case BREAK_LM:
990 if (memcmp(ntlm_session_key.data, user_session_key,
991 sizeof(user_session_key)) != 0) {
992 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n");
993 torture_comment(samlogon_state->tctx, "user_session_key:\n");
994 dump_data(1, user_session_key, 16);
995 torture_comment(samlogon_state->tctx, "expected:\n");
996 dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
997 pass = false;
999 if (!all_zero(lm_session_key,
1000 sizeof(lm_session_key))) {
1001 torture_comment(samlogon_state->tctx, "LM Session Key does not match expectations (zeros)!\n");
1002 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
1003 dump_data(1, lm_session_key, 8);
1004 pass = false;
1006 break;
1007 default:
1008 if (memcmp(ntlm_session_key.data, user_session_key,
1009 sizeof(user_session_key)) != 0) {
1010 torture_comment(samlogon_state->tctx, "USER (NTLMv2) Session Key does not match expectations!\n");
1011 torture_comment(samlogon_state->tctx, "user_session_key:\n");
1012 dump_data(1, user_session_key, 16);
1013 torture_comment(samlogon_state->tctx, "expected:\n");
1014 dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
1015 pass = false;
1017 if (memcmp(ntlm_session_key.data, lm_session_key,
1018 sizeof(lm_session_key)) != 0) {
1019 torture_comment(samlogon_state->tctx, "LM (NTLMv2) Session Key does not match expectations!\n");
1020 torture_comment(samlogon_state->tctx, "lm_session_key:\n");
1021 dump_data(1, lm_session_key, 8);
1022 torture_comment(samlogon_state->tctx, "expected:\n");
1023 dump_data(1, ntlm_session_key.data, 8);
1024 pass = false;
1028 return pass;
1032 * Test the NTLMv2 and LMv2 responses
1035 static bool test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
1037 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, UPPER_DOMAIN, error_string);
1040 #if 0
1041 static bool test_lmv2_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1043 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, NO_DOMAIN, error_string);
1045 #endif
1048 * Test the LMv2 response only
1051 static bool test_lmv2(struct samlogon_state *samlogon_state, char **error_string)
1053 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, UPPER_DOMAIN, error_string);
1056 static bool test_lmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1058 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, NO_DOMAIN, error_string);
1062 * Test the NTLMv2 response only
1065 static bool test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
1067 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, UPPER_DOMAIN, error_string);
1070 static bool test_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1072 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, NO_DOMAIN, error_string);
1075 static bool test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string)
1077 return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
1080 static bool test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string)
1082 return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
1085 static bool test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string)
1087 return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
1090 static bool test_lm_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string)
1092 return test_lm_ntlm_broken(samlogon_state, BREAK_BOTH, error_string);
1094 static bool test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
1096 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
1099 static bool test_ntlmv2_lmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1101 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
1104 static bool test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
1106 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
1109 #if 0
1110 static bool test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1112 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
1114 #endif
1116 static bool test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char **error_string)
1118 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
1121 static bool test_ntlmv2_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1123 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
1126 static bool test_lmv2_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string)
1128 return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
1131 static bool test_lmv2_ntlm_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1133 return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
1136 static bool test_lmv2_ntlm_break_ntlm(struct samlogon_state *samlogon_state, char **error_string)
1138 return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
1141 static bool test_lmv2_ntlm_break_ntlm_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1143 return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
1146 static bool test_lmv2_ntlm_break_lm(struct samlogon_state *samlogon_state, char **error_string)
1148 return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
1151 static bool test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state *samlogon_state, char **error_string)
1153 return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
1157 * Test the NTLM2 response (extra challenge in LM field)
1159 * This test is the same as the 'break LM' test, but checks that the
1160 * server implements NTLM2 session security in the right place
1161 * (NETLOGON is the wrong place).
1164 static bool test_ntlm2(struct samlogon_state *samlogon_state, char **error_string)
1166 bool pass = true;
1167 NTSTATUS nt_status;
1168 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1169 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1171 uint8_t lm_key[8];
1172 uint8_t nt_hash[16];
1173 uint8_t lm_hash[16];
1174 uint8_t nt_key[16];
1175 uint8_t user_session_key[16];
1176 uint8_t expected_user_session_key[16];
1177 uint8_t session_nonce_hash[16];
1178 uint8_t client_chall[8];
1180 gnutls_hmac_hd_t hmac_hnd;
1181 gnutls_hash_hd_t hash_hnd;
1183 ZERO_STRUCT(user_session_key);
1184 ZERO_STRUCT(lm_key);
1185 generate_random_buffer(client_chall, 8);
1187 gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
1188 gnutls_hash(hash_hnd, samlogon_state->chall.data, 8);
1189 gnutls_hash(hash_hnd, client_chall, 8);
1190 gnutls_hash_deinit(hash_hnd, session_nonce_hash);
1192 E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
1193 E_deshash(samlogon_state->password, (uint8_t *)lm_hash);
1194 SMBsesskeygen_ntv1((const uint8_t *)nt_hash,
1195 nt_key);
1197 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
1199 memcpy(lm_response.data, session_nonce_hash, 8);
1200 memset(lm_response.data + 8, 0, 16);
1202 gnutls_hmac_init(&hmac_hnd,
1203 GNUTLS_MAC_MD5,
1204 nt_key,
1205 16);
1206 gnutls_hmac(hmac_hnd, samlogon_state->chall.data, 8);
1207 gnutls_hmac(hmac_hnd, client_chall, 8);
1208 gnutls_hmac_deinit(hmac_hnd, expected_user_session_key);
1210 nt_status = check_samlogon(samlogon_state,
1211 BREAK_NONE,
1212 samlogon_state->parameter_control,
1213 &samlogon_state->chall,
1214 &lm_response,
1215 &nt_response,
1216 lm_key,
1217 user_session_key,
1218 error_string);
1220 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1221 /* for 'old' passwords, we allow the server to be OK or wrong password */
1222 if (samlogon_state->old_password) {
1223 return true;
1225 return false;
1226 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1227 int ret;
1229 SAFE_FREE(*error_string);
1230 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1231 if (ret == -1) {
1232 *error_string = NULL;
1234 return false;
1235 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1236 return true;
1237 } else if (!NT_STATUS_IS_OK(nt_status)) {
1238 return false;
1241 if (!all_zero(lm_key, sizeof(lm_key))) {
1242 torture_comment(samlogon_state->tctx, "LM Session Key does not match expectations (zeros)!\n");
1243 torture_comment(samlogon_state->tctx, "lm_key:\n");
1244 dump_data(1, lm_key, 8);
1245 pass = false;
1247 if (memcmp(nt_key, user_session_key, 16) != 0) {
1248 torture_comment(samlogon_state->tctx, "NT Session Key does not match expectations (should be NT Key)!\n");
1249 torture_comment(samlogon_state->tctx, "user_session_key:\n");
1250 dump_data(1, user_session_key, sizeof(user_session_key));
1251 torture_comment(samlogon_state->tctx, "expected:\n");
1252 dump_data(1, nt_key, sizeof(nt_key));
1253 pass = false;
1255 return pass;
1258 static bool test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
1260 NTSTATUS nt_status;
1261 DATA_BLOB nt_response = data_blob(NULL, 0);
1262 DATA_BLOB lm_response = data_blob(NULL, 0);
1263 char *password;
1264 char *dospw;
1265 smb_ucs2_t *unicodepw;
1266 size_t converted_size = 0;
1267 uint8_t user_session_key[16];
1268 uint8_t lm_key[16];
1269 uint8_t lm_hash[16];
1270 DATA_BLOB chall = data_blob_talloc_zero(samlogon_state->mem_ctx, 8);
1271 bool lm_good = E_deshash(samlogon_state->password, lm_hash);
1273 ZERO_STRUCT(user_session_key);
1275 if (!push_ucs2_talloc(samlogon_state->mem_ctx,
1276 &unicodepw, samlogon_state->password, &converted_size)) {
1277 DEBUG(0, ("push_ucs2_allocate failed!\n"));
1278 exit(1);
1281 nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, strlen_m(samlogon_state->password)*2);
1283 password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password);
1285 if (!convert_string_talloc(samlogon_state->mem_ctx,
1286 CH_UNIX, CH_DOS,
1287 password, strlen(password)+1,
1288 (void**)&dospw, &converted_size)) {
1289 DEBUG(0, ("convert_string_talloc failed!\n"));
1290 exit(1);
1293 lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
1295 nt_status = check_samlogon(samlogon_state,
1296 break_which,
1297 samlogon_state->parameter_control | MSV1_0_CLEARTEXT_PASSWORD_ALLOWED,
1298 &chall,
1299 &lm_response,
1300 &nt_response,
1301 lm_key,
1302 user_session_key,
1303 error_string);
1305 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1306 /* for 'old' passwords, we allow the server to be OK or wrong password */
1307 if (samlogon_state->old_password) {
1308 return true;
1310 /* for 'long' passwords, the LM password is invalid */
1311 if (break_which == NO_NT && !lm_good) {
1312 return true;
1314 /* for modern servers, the LM password is invalid */
1315 if (break_which == NO_NT
1316 && !torture_setting_bool(samlogon_state->tctx, "samba3", false)) {
1317 return true;
1320 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
1321 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
1322 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
1323 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1324 int ret;
1326 SAFE_FREE(*error_string);
1327 ret = asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1328 if (ret == -1) {
1329 *error_string = NULL;
1331 return false;
1332 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1333 return true;
1334 } else if (!NT_STATUS_IS_OK(nt_status)) {
1335 return false;
1338 if (break_which == NO_NT && !lm_good) {
1339 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
1340 return false;
1343 /* for modern servers, the LM password is invalid */
1344 if (break_which == NO_NT
1345 && !torture_setting_bool(samlogon_state->tctx, "samba3", false)) {
1346 *error_string = strdup("LM password is OK but should have failed against a modern server");
1347 return false;
1350 return true;
1353 static bool test_plaintext_none_broken(struct samlogon_state *samlogon_state,
1354 char **error_string) {
1355 return test_plaintext(samlogon_state, BREAK_NONE, error_string);
1358 static bool test_plaintext_lm_broken(struct samlogon_state *samlogon_state,
1359 char **error_string) {
1360 return test_plaintext(samlogon_state, BREAK_LM, error_string);
1363 static bool test_plaintext_nt_broken(struct samlogon_state *samlogon_state,
1364 char **error_string) {
1365 return test_plaintext(samlogon_state, BREAK_NT, error_string);
1368 static bool test_plaintext_nt_only(struct samlogon_state *samlogon_state,
1369 char **error_string) {
1370 return test_plaintext(samlogon_state, NO_LM, error_string);
1373 static bool test_plaintext_lm_only(struct samlogon_state *samlogon_state,
1374 char **error_string) {
1375 return test_plaintext(samlogon_state, NO_NT, error_string);
1379 Tests:
1381 - LM only
1382 - NT and LM
1383 - NT
1384 - NT in LM field
1385 - NT in both fields
1386 - NTLMv2
1387 - NTLMv2 and LMv2
1388 - LMv2
1389 - plaintext tests (in challenge-response fields)
1391 check we get the correct session key in each case
1392 check what values we get for the LM session key
1396 static const struct ntlm_tests {
1397 bool (*fn)(struct samlogon_state *, char **);
1398 const char *name;
1399 bool expect_fail;
1400 } test_table[] = {
1401 {test_lmv2_ntlmv2, "NTLMv2 and LMv2", false},
1402 #if 0
1403 {test_lmv2_ntlmv2_no_dom, "NTLMv2 and LMv2 (no domain)", false},
1404 #endif
1405 {test_lm, "LM", false},
1406 {test_lm_ntlm, "LM and NTLM", false},
1407 {test_lm_ntlm_both_broken, "LM and NTLM, both broken", false},
1408 {test_ntlm, "NTLM", false},
1409 {test_ntlm_in_lm, "NTLM in LM", false},
1410 {test_ntlm_in_both, "NTLM in both", false},
1411 {test_ntlmv2, "NTLMv2", false},
1412 {test_ntlmv2_no_dom, "NTLMv2 (no domain)", false},
1413 {test_lmv2, "LMv2", false},
1414 {test_lmv2_no_dom, "LMv2 (no domain)", false},
1415 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", false},
1416 {test_ntlmv2_lmv2_broken_no_dom, "NTLMv2 and LMv2, LMv2 broken (no domain)", false},
1417 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", false},
1418 #if 0
1419 {test_ntlmv2_ntlmv2_broken_no_dom, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", false},
1420 #endif
1421 {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", false},
1422 {test_ntlmv2_both_broken_no_dom, "NTLMv2 and LMv2, both broken (no domain)", false},
1423 {test_ntlm_lm_broken, "NTLM and LM, LM broken", false},
1424 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", false},
1425 {test_ntlm2, "NTLM2 (NTLMv2 session security)", false},
1426 {test_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", false},
1427 {test_lmv2_ntlm_both_broken_no_dom, "LMv2 and NTLM, both broken (no domain)", false},
1428 {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", false},
1429 {test_lmv2_ntlm_break_ntlm_no_dom, "LMv2 and NTLM, NTLM broken (no domain)", false},
1430 {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", false},
1431 {test_lmv2_ntlm_break_lm_no_dom, "LMv2 and NTLM, LMv2 broken (no domain)", false},
1432 {test_plaintext_none_broken, "Plaintext", false},
1433 {test_plaintext_lm_broken, "Plaintext LM broken", false},
1434 {test_plaintext_nt_broken, "Plaintext NT broken", false},
1435 {test_plaintext_nt_only, "Plaintext NT only", false},
1436 {test_plaintext_lm_only, "Plaintext LM only", false},
1437 { .name = NULL, }
1441 try a netlogon SamLogon
1443 static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1444 struct torture_context *tctx,
1445 struct netlogon_creds_CredentialState *creds,
1446 const char *comment,
1447 const char *account_domain, const char *account_name,
1448 const char *plain_pass, uint32_t parameter_control,
1449 NTSTATUS expected_error, bool old_password,
1450 int n_subtests)
1452 TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_SamLogon function-level context");
1453 int i, v, l, f;
1454 bool ret = true;
1455 int validation_levels[] = {2,3,6};
1456 int logon_levels[] = { NetlogonNetworkInformation, NetlogonNetworkTransitiveInformation };
1457 int function_levels[] = {
1458 NDR_NETR_LOGONSAMLOGON,
1459 NDR_NETR_LOGONSAMLOGONEX,
1460 NDR_NETR_LOGONSAMLOGONWITHFLAGS };
1461 struct samlogon_state samlogon_state;
1463 union netr_LogonLevel logon;
1464 union netr_Validation validation;
1465 uint8_t authoritative = 1;
1466 uint32_t flags = 0;
1468 ZERO_STRUCT(logon);
1470 torture_comment(tctx, "Testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1472 samlogon_state.comment = comment;
1473 samlogon_state.account_name = account_name;
1474 samlogon_state.account_domain = account_domain;
1475 samlogon_state.password = plain_pass;
1476 samlogon_state.workgroup = lpcfg_workgroup(tctx->lp_ctx);
1477 samlogon_state.netbios_name = lpcfg_netbios_name(tctx->lp_ctx);
1478 samlogon_state.p = p;
1479 samlogon_state.creds = creds;
1480 samlogon_state.expected_error = expected_error;
1481 samlogon_state.chall = data_blob_talloc(fn_ctx, NULL, 8);
1482 samlogon_state.parameter_control = parameter_control;
1483 samlogon_state.old_password = old_password;
1484 samlogon_state.tctx = tctx;
1486 generate_random_buffer(samlogon_state.chall.data, 8);
1487 samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1488 samlogon_state.r_flags.in.computer_name = TEST_MACHINE_NAME;
1489 samlogon_state.r_flags.in.credential = &samlogon_state.auth;
1490 samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2;
1491 samlogon_state.r_flags.in.flags = &flags;
1492 samlogon_state.r_flags.in.logon = &logon;
1493 samlogon_state.r_flags.out.validation = &validation;
1494 samlogon_state.r_flags.out.authoritative = &authoritative;
1495 samlogon_state.r_flags.out.flags = &flags;
1497 samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1498 samlogon_state.r_ex.in.computer_name = TEST_MACHINE_NAME;
1499 samlogon_state.r_ex.in.flags = &flags;
1500 samlogon_state.r_ex.in.logon = &logon;
1501 samlogon_state.r_ex.out.validation = &validation;
1502 samlogon_state.r_ex.out.authoritative = &authoritative;
1503 samlogon_state.r_ex.out.flags = &flags;
1505 samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1506 samlogon_state.r.in.computer_name = TEST_MACHINE_NAME;
1507 samlogon_state.r.in.credential = &samlogon_state.auth;
1508 samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
1509 samlogon_state.r.in.logon = &logon;
1510 samlogon_state.r.out.validation = &validation;
1511 samlogon_state.r.out.authoritative = &authoritative;
1514 for (f=0;f<ARRAY_SIZE(function_levels);f++) {
1515 for (i=0; test_table[i].fn; i++) {
1516 if (n_subtests && (i > n_subtests)) {
1517 continue;
1519 for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
1520 for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
1521 char *error_string = NULL;
1522 TALLOC_CTX *tmp_ctx = talloc_named(fn_ctx, 0, "test_SamLogon inner loop");
1523 samlogon_state.mem_ctx = tmp_ctx;
1524 samlogon_state.function_level = function_levels[f];
1525 samlogon_state.r.in.validation_level = validation_levels[v];
1526 samlogon_state.r.in.logon_level = logon_levels[l];
1527 samlogon_state.r_ex.in.validation_level = validation_levels[v];
1528 samlogon_state.r_ex.in.logon_level = logon_levels[l];
1529 samlogon_state.r_flags.in.validation_level = validation_levels[v];
1530 samlogon_state.r_flags.in.logon_level = logon_levels[l];
1531 if (!test_table[i].fn(&samlogon_state, &error_string)) {
1532 torture_comment(tctx, "Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
1533 samlogon_state.comment,
1534 samlogon_state.account_domain,
1535 samlogon_state.account_name,
1536 test_table[i].name, validation_levels[v],
1537 logon_levels[l], function_levels[f]);
1539 if (test_table[i].expect_fail) {
1540 torture_comment(tctx, " failed (expected, test incomplete): %s\n", error_string);
1541 } else {
1542 torture_comment(tctx, " failed: %s\n", error_string);
1543 ret = false;
1545 SAFE_FREE(error_string);
1547 talloc_free(tmp_ctx);
1552 talloc_free(fn_ctx);
1553 return ret;
1557 test an ADS style interactive domain logon
1559 bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1560 struct torture_context *tctx,
1561 struct netlogon_creds_CredentialState *creds,
1562 const char *comment,
1563 const char *workstation_name,
1564 const char *account_domain, const char *account_name,
1565 const char *plain_pass, uint32_t parameter_control,
1566 NTSTATUS expected_error)
1568 NTSTATUS status;
1569 TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context");
1570 bool ret = true;
1571 struct netr_LogonSamLogonWithFlags r;
1572 struct netr_Authenticator a, ra;
1573 struct netr_PasswordInfo pinfo;
1574 uint32_t flags = 0;
1576 union netr_LogonLevel logon;
1577 union netr_Validation validation;
1578 uint8_t authoritative = 1;
1579 struct dcerpc_binding_handle *b = p->binding_handle;
1580 enum dcerpc_AuthType auth_type;
1581 enum dcerpc_AuthLevel auth_level;
1583 dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level);
1585 ZERO_STRUCT(a);
1586 ZERO_STRUCT(r);
1587 ZERO_STRUCT(ra);
1589 ZERO_STRUCT(logon);
1590 ZERO_STRUCT(validation);
1592 netlogon_creds_client_authenticator(creds, &a);
1594 logon.password = &pinfo;
1596 r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1597 r.in.computer_name = TEST_MACHINE_NAME;
1598 r.in.credential = &a;
1599 r.in.return_authenticator = &ra;
1600 r.in.logon_level = NetlogonInteractiveTransitiveInformation;
1601 r.in.logon = &logon;
1602 r.in.validation_level = 6;
1603 r.in.flags = &flags;
1604 r.out.validation = &validation;
1605 r.out.authoritative = &authoritative;
1606 r.out.flags = &flags;
1608 pinfo.identity_info.domain_name.string = account_domain;
1609 pinfo.identity_info.parameter_control = parameter_control;
1610 pinfo.identity_info.logon_id = 0;
1611 pinfo.identity_info.account_name.string = account_name;
1612 pinfo.identity_info.workstation.string = workstation_name;
1614 if (!E_deshash(plain_pass, pinfo.lmpassword.hash)) {
1615 ZERO_STRUCT(pinfo.lmpassword.hash);
1617 E_md4hash(plain_pass, pinfo.ntpassword.hash);
1619 status = netlogon_creds_encrypt_samlogon_logon(creds,
1620 r.in.logon_level,
1621 r.in.logon,
1622 auth_type,
1623 auth_level);
1624 torture_assert_ntstatus_ok_goto(tctx,
1625 status,
1626 ret, failed,
1627 "netlogon_creds_encrypt_samlogon_logon");
1629 torture_comment(tctx, "Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment);
1631 status = dcerpc_netr_LogonSamLogonWithFlags_r(b, fn_ctx, &r);
1632 torture_assert_ntstatus_ok_goto(tctx,
1633 status,
1634 ret, failed,
1635 talloc_asprintf(tctx, "%s: netr_LogonSamLogonWithFlags - %s\n",
1636 __location__, nt_errstr(status)));
1638 if (!r.out.return_authenticator) {
1639 talloc_free(fn_ctx);
1640 torture_fail(tctx, "no authenticator returned");
1643 status = netlogon_creds_client_verify(creds,
1644 &r.out.return_authenticator->cred,
1645 auth_type,
1646 auth_level);
1647 torture_assert_ntstatus_ok_goto(tctx, status, ret, failed,
1648 "Credential chaining failed\n");
1650 torture_assert_ntstatus_equal(tctx, r.out.result, expected_error,
1651 talloc_asprintf(tctx, "[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n",
1652 account_domain, account_name, nt_errstr(expected_error), nt_errstr(r.out.result)));
1654 ret = true;
1655 failed:
1656 talloc_free(fn_ctx);
1658 return ret;
1661 /* This sets and resets the "minPwdAge" (in order to allow immediate user
1662 * password changes). The behaviour is controlled by the "set" boolean. */
1663 static bool handle_minPwdAge(struct torture_context *torture,
1664 TALLOC_CTX *mem_ctx, bool set)
1666 struct dcerpc_pipe *p;
1667 struct policy_handle connect_handle, domain_handle;
1668 struct samr_Connect c_r;
1669 struct samr_LookupDomain ld_r;
1670 struct samr_OpenDomain od_r;
1671 struct samr_QueryDomainInfo qdi_r;
1672 struct samr_SetDomainInfo sdi_r;
1673 struct samr_Close cl_r;
1674 struct lsa_String domName;
1675 struct dom_sid *domSid = NULL;
1676 union samr_DomainInfo *domInfo = NULL;
1677 static int64_t old_minPwdAge = 0;
1678 NTSTATUS status;
1680 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
1681 if (!NT_STATUS_IS_OK(status)) {
1682 return false;
1685 c_r.in.system_name = 0;
1686 c_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1687 c_r.out.connect_handle = &connect_handle;
1689 torture_assert_ntstatus_ok(torture,
1690 dcerpc_samr_Connect_r(p->binding_handle, mem_ctx, &c_r),
1691 "Connect failed");
1692 torture_assert_ntstatus_ok(torture, c_r.out.result, "Connect failed");
1694 ld_r.in.connect_handle = &connect_handle;
1695 ld_r.in.domain_name = &domName;
1696 ld_r.in.domain_name->string = lpcfg_workgroup(torture->lp_ctx);
1697 ld_r.out.sid = &domSid;
1699 torture_assert_ntstatus_ok(torture,
1700 dcerpc_samr_LookupDomain_r(p->binding_handle, mem_ctx, &ld_r),
1701 "LookupDomain failed");
1702 torture_assert_ntstatus_ok(torture, ld_r.out.result,
1703 "LookupDomain failed");
1705 od_r.in.connect_handle = &connect_handle;
1706 od_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1707 od_r.in.sid = *ld_r.out.sid;
1708 od_r.out.domain_handle = &domain_handle;
1710 torture_assert_ntstatus_ok(torture,
1711 dcerpc_samr_OpenDomain_r(p->binding_handle, mem_ctx, &od_r),
1712 "OpenDomain failed");
1713 torture_assert_ntstatus_ok(torture, od_r.out.result,
1714 "OpenDomain failed");
1716 qdi_r.in.domain_handle = &domain_handle;
1717 qdi_r.in.level = DomainPasswordInformation;
1718 qdi_r.out.info = &domInfo;
1720 torture_assert_ntstatus_ok(torture,
1721 dcerpc_samr_QueryDomainInfo_r(p->binding_handle, mem_ctx, &qdi_r),
1722 "QueryDomainInfo failed");
1723 torture_assert_ntstatus_ok(torture, qdi_r.out.result,
1724 "QueryDomainInfo failed");
1726 if (set) {
1727 old_minPwdAge = domInfo->info1.min_password_age;
1728 domInfo->info1.min_password_age = 0;
1729 } else {
1730 domInfo->info1.min_password_age = old_minPwdAge;
1733 sdi_r.in.domain_handle = &domain_handle;
1734 sdi_r.in.level = DomainPasswordInformation;
1735 sdi_r.in.info = domInfo;
1737 torture_assert_ntstatus_ok(torture,
1738 dcerpc_samr_SetDomainInfo_r(p->binding_handle, mem_ctx, &sdi_r),
1739 "SetDomainInfo failed");
1740 torture_assert_ntstatus_ok(torture, sdi_r.out.result,
1741 "SetDomainInfo failed");
1743 cl_r.in.handle = &connect_handle;
1744 cl_r.out.handle = &connect_handle;
1746 torture_assert_ntstatus_ok(torture,
1747 dcerpc_samr_Close_r(p->binding_handle, mem_ctx, &cl_r),
1748 "Close failed");
1749 torture_assert_ntstatus_ok(torture, cl_r.out.result, "Close failed");
1751 return true;
1754 bool torture_rpc_samlogon(struct torture_context *torture)
1756 NTSTATUS status;
1757 struct dcerpc_pipe *p;
1758 struct dcerpc_binding *b;
1759 struct cli_credentials *machine_credentials;
1760 TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon");
1761 bool ret = true;
1762 struct test_join *join_ctx = NULL;
1763 struct test_join *user_ctx = NULL, *user_ctx_wrong_wks = NULL, *user_ctx_wrong_time = NULL;
1764 const char *old_user_password, *user_password_wrong_wks, *user_password_wrong_time;
1765 char *user_password;
1766 const char *userdomain;
1767 struct samr_SetUserInfo s;
1768 union samr_UserInfo u;
1769 int i;
1770 int ci;
1772 unsigned int credential_flags[] = {
1773 NETLOGON_NEG_AUTH2_FLAGS,
1774 NETLOGON_NEG_ARCFOUR,
1775 NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
1776 NETLOGON_NEG_AUTH2_ADS_FLAGS,
1777 0 /* yes, this is a valid flag, causes the use of DES */
1780 struct netlogon_creds_CredentialState *creds;
1781 struct dcerpc_pipe *tmp_p = NULL;
1783 torture_assert(torture, handle_minPwdAge(torture, mem_ctx, true),
1784 "handle_minPwdAge error!");
1786 /* We only need to join as a workstation here, and in future,
1787 * if we wish to test against trusted domains, we must be a
1788 * workstation here */
1789 join_ctx = torture_join_domain(torture, TEST_MACHINE_NAME, ACB_WSTRUST,
1790 &machine_credentials);
1791 torture_assert(torture, join_ctx, "Failed to join as Workstation\n");
1793 userdomain = torture_setting_string(torture, "userdomain", lpcfg_workgroup(torture->lp_ctx));
1795 user_ctx = torture_create_testuser(torture,
1796 TEST_USER_NAME,
1797 userdomain,
1798 ACB_NORMAL,
1799 &old_user_password);
1800 torture_assert(torture, user_ctx, "Failed to create a test user\n");
1802 user_password = talloc_strdup(torture, old_user_password);
1803 torture_assert(torture, user_password != NULL, "Failed to copy old_user_password\n");
1805 tmp_p = torture_join_samr_pipe(user_ctx);
1806 torture_assert(torture, tmp_p, "torture_join_samr_pipe failed\n");
1807 test_ChangePasswordUser3(tmp_p, torture,
1808 TEST_USER_NAME, 16 /* > 14 */, &user_password,
1809 NULL, 0, false);
1811 user_ctx_wrong_wks = torture_create_testuser(torture,
1812 TEST_USER_NAME_WRONG_WKS,
1813 userdomain,
1814 ACB_NORMAL,
1815 &user_password_wrong_wks);
1816 torture_assert(torture, user_ctx_wrong_wks,
1817 "Failed to create a test user (wrong workstation test)\n");
1819 ZERO_STRUCT(u);
1820 s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_wks);
1821 s.in.info = &u;
1822 s.in.level = 21;
1824 u.info21.fields_present = SAMR_FIELD_WORKSTATIONS;
1825 u.info21.workstations.string = "not" TEST_MACHINE_NAME;
1827 tmp_p = torture_join_samr_pipe(user_ctx_wrong_wks);
1828 status = dcerpc_samr_SetUserInfo_r(tmp_p->binding_handle, mem_ctx, &s);
1829 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
1830 talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status)));
1831 torture_assert_ntstatus_ok_goto(torture, s.out.result, ret, failed,
1832 talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s.out.result)));
1834 user_ctx_wrong_time
1835 = torture_create_testuser(torture, TEST_USER_NAME_WRONG_TIME,
1836 userdomain,
1837 ACB_NORMAL,
1838 &user_password_wrong_time);
1839 torture_assert(torture, user_ctx_wrong_time,
1840 "Failed to create a test user (wrong workstation test)\n");
1842 ZERO_STRUCT(u);
1843 s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_time);
1844 s.in.info = &u;
1845 s.in.level = 21;
1847 u.info21.fields_present = SAMR_FIELD_WORKSTATIONS | SAMR_FIELD_LOGON_HOURS;
1848 u.info21.workstations.string = TEST_MACHINE_NAME;
1849 u.info21.logon_hours.units_per_week = 168;
1850 u.info21.logon_hours.bits = talloc_zero_array(mem_ctx, uint8_t, 168);
1852 tmp_p = torture_join_samr_pipe(user_ctx_wrong_time);
1853 status = dcerpc_samr_SetUserInfo_r(tmp_p->binding_handle, mem_ctx, &s);
1854 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
1855 talloc_asprintf(torture, "SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status)));
1856 torture_assert_ntstatus_ok_goto(torture, s.out.result, ret, failed,
1857 talloc_asprintf(torture, "SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s.out.result)));
1860 torture_assert_ntstatus_ok_goto(torture,
1861 torture_rpc_binding(torture, &b),
1862 ret,
1863 failed,
1864 "Obtaining binding");
1866 /* We have to use schannel, otherwise the SamLogonEx fails
1867 * with INTERNAL_ERROR */
1869 status = dcerpc_binding_set_flags(b,
1870 DCERPC_SCHANNEL |
1871 DCERPC_SIGN | DCERPC_SEAL |
1872 DCERPC_SCHANNEL_128,
1873 DCERPC_AUTH_OPTIONS);
1874 torture_assert_ntstatus_ok(torture, status, "set flags");
1876 status = dcerpc_pipe_connect_b(mem_ctx, &p, b,
1877 &ndr_table_netlogon,
1878 machine_credentials, torture->ev, torture->lp_ctx);
1880 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
1881 talloc_asprintf(torture, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status)));
1883 torture_assert_not_null_goto(torture,
1884 creds = cli_credentials_get_netlogon_creds(machine_credentials),
1885 ret,
1886 failed,
1887 "obtaining credentials");
1891 struct {
1892 const char *comment;
1893 const char *domain;
1894 const char *username;
1895 const char *password;
1896 bool network_login;
1897 NTSTATUS expected_interactive_error;
1898 NTSTATUS expected_network_error;
1899 uint32_t parameter_control;
1900 bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
1901 } usercreds[] = {
1903 .comment = "domain\\user",
1904 .domain = cli_credentials_get_domain(
1905 samba_cmdline_get_creds()),
1906 .username = cli_credentials_get_username(
1907 samba_cmdline_get_creds()),
1908 .password = cli_credentials_get_password(
1909 samba_cmdline_get_creds()),
1910 .network_login = true,
1911 .expected_interactive_error = NT_STATUS_OK,
1912 .expected_network_error = NT_STATUS_OK,
1913 .parameter_control = 0,
1916 .comment = "realm\\user",
1917 .domain = cli_credentials_get_realm(
1918 samba_cmdline_get_creds()),
1919 .username = cli_credentials_get_username(
1920 samba_cmdline_get_creds()),
1921 .password = cli_credentials_get_password(
1922 samba_cmdline_get_creds()),
1923 .network_login = true,
1924 .expected_interactive_error = NT_STATUS_OK,
1925 .expected_network_error = NT_STATUS_OK,
1926 .parameter_control = 0,
1929 .comment = "user@domain",
1930 .domain = NULL,
1931 .username = talloc_asprintf(mem_ctx,
1932 "%s@%s",
1933 cli_credentials_get_username(
1934 samba_cmdline_get_creds()),
1935 cli_credentials_get_domain(
1936 samba_cmdline_get_creds())
1938 .password = cli_credentials_get_password(
1939 samba_cmdline_get_creds()),
1940 .network_login = false, /* works for some things, but not NTLMv2. Odd */
1941 .expected_interactive_error = NT_STATUS_OK,
1942 .expected_network_error = NT_STATUS_OK,
1943 .parameter_control = 0,
1946 .comment = "user@realm",
1947 .domain = NULL,
1948 .username = talloc_asprintf(mem_ctx,
1949 "%s@%s",
1950 cli_credentials_get_username(
1951 samba_cmdline_get_creds()),
1952 cli_credentials_get_realm(
1953 samba_cmdline_get_creds())
1955 .password = cli_credentials_get_password(
1956 samba_cmdline_get_creds()),
1957 .network_login = true,
1958 .expected_interactive_error = NT_STATUS_OK,
1959 .expected_network_error = NT_STATUS_OK,
1960 .parameter_control = 0,
1963 .comment = "machine domain\\user",
1964 .domain = cli_credentials_get_domain(machine_credentials),
1965 .username = cli_credentials_get_username(machine_credentials),
1966 .password = cli_credentials_get_password(machine_credentials),
1967 .network_login = true,
1968 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1969 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1972 .comment = "machine domain\\user",
1973 .domain = cli_credentials_get_domain(machine_credentials),
1974 .username = cli_credentials_get_username(machine_credentials),
1975 .password = cli_credentials_get_password(machine_credentials),
1976 .network_login = true,
1977 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1978 .expected_network_error = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT,
1979 .parameter_control = 0,
1982 .comment = "machine realm\\user",
1983 .domain = cli_credentials_get_realm(machine_credentials),
1984 .username = cli_credentials_get_username(machine_credentials),
1985 .password = cli_credentials_get_password(machine_credentials),
1986 .network_login = true,
1987 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1988 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1991 .comment = "machine user@domain",
1992 .domain = NULL,
1993 .username = talloc_asprintf(mem_ctx,
1994 "%s@%s",
1995 cli_credentials_get_username(machine_credentials),
1996 cli_credentials_get_domain(machine_credentials)
1998 .password = cli_credentials_get_password(machine_credentials),
1999 .network_login = false, /* works for some things, but not NTLMv2. Odd */
2000 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
2001 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
2004 .comment = "machine user@realm",
2005 .domain = NULL,
2006 .username = talloc_asprintf(mem_ctx,
2007 "%s@%s",
2008 cli_credentials_get_username(machine_credentials),
2009 cli_credentials_get_realm(machine_credentials)
2011 .password = cli_credentials_get_password(machine_credentials),
2012 .network_login = true,
2013 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
2014 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
2017 .comment = "test user (long pw): domain\\user",
2018 .domain = userdomain,
2019 .username = TEST_USER_NAME,
2020 .password = user_password,
2021 .network_login = true,
2022 .expected_interactive_error = NT_STATUS_OK,
2023 .expected_network_error = NT_STATUS_OK,
2024 .parameter_control = 0,
2027 .comment = "test user (long pw): user@realm",
2028 .domain = NULL,
2029 .username = talloc_asprintf(mem_ctx,
2030 "%s@%s",
2031 TEST_USER_NAME,
2032 lpcfg_realm(torture->lp_ctx)),
2033 .password = user_password,
2034 .network_login = true,
2035 .expected_interactive_error = NT_STATUS_OK,
2036 .expected_network_error = NT_STATUS_OK,
2037 .parameter_control = 0,
2040 .comment = "test user (long pw): user@domain",
2041 .domain = NULL,
2042 .username = talloc_asprintf(mem_ctx,
2043 "%s@%s",
2044 TEST_USER_NAME,
2045 userdomain),
2046 .password = user_password,
2047 .network_login = false, /* works for some things, but not NTLMv2. Odd */
2048 .expected_interactive_error = NT_STATUS_OK,
2049 .expected_network_error = NT_STATUS_OK,
2050 .parameter_control = 0,
2052 /* Oddball, can we use the old password ? */
2054 .comment = "test user: user\\domain OLD PASSWORD",
2055 .domain = userdomain,
2056 .username = TEST_USER_NAME,
2057 .password = old_user_password,
2058 .network_login = true,
2059 .expected_interactive_error = NT_STATUS_WRONG_PASSWORD,
2060 .expected_network_error = NT_STATUS_OK,
2061 .old_password = true
2064 .comment = "test user (wrong workstation): domain\\user",
2065 .domain = userdomain,
2066 .username = TEST_USER_NAME_WRONG_WKS,
2067 .password = user_password_wrong_wks,
2068 .network_login = true,
2069 .expected_interactive_error = NT_STATUS_INVALID_WORKSTATION,
2070 .expected_network_error = NT_STATUS_INVALID_WORKSTATION,
2071 .parameter_control = 0,
2075 /* Try all the tests for different username forms */
2076 for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) {
2078 torture_assert_goto(torture,
2079 test_InteractiveLogon(p, mem_ctx, torture, creds,
2080 usercreds[ci].comment,
2081 TEST_MACHINE_NAME,
2082 usercreds[ci].domain,
2083 usercreds[ci].username,
2084 usercreds[ci].password,
2085 usercreds[ci].parameter_control,
2086 usercreds[ci].expected_interactive_error),
2087 ret,
2088 failed,
2089 talloc_asprintf(mem_ctx, "InteractiveLogon: %s",
2090 usercreds[ci].comment));
2092 if (usercreds[ci].network_login) {
2093 torture_assert_goto(torture,
2094 test_SamLogon(p, mem_ctx, torture, creds,
2095 usercreds[ci].comment,
2096 usercreds[ci].domain,
2097 usercreds[ci].username,
2098 usercreds[ci].password,
2099 usercreds[ci].parameter_control,
2100 usercreds[ci].expected_network_error,
2101 usercreds[ci].old_password,
2103 ret,
2104 failed,
2105 talloc_asprintf(mem_ctx, "SamLogon: %s",
2106 usercreds[ci].comment));
2110 /* Using the first username form, try the different
2111 * credentials flag setups, on only one of the tests (checks
2112 * session key encryption) */
2114 for (i=0; i < ARRAY_SIZE(credential_flags); i++) {
2115 torture_comment(torture,
2116 "Testing with flags: 0x%08x\n",
2117 credential_flags[i]);
2119 ret = test_SetupCredentials2(p,
2120 torture,
2121 credential_flags[i],
2122 machine_credentials,
2123 SEC_CHAN_WKSTA,
2124 &creds);
2125 torture_assert_goto(torture, ret, ret, failed, "test_SetupCredentials2()\n");
2127 torture_assert_goto(torture,
2128 test_InteractiveLogon(p, mem_ctx, torture, creds,
2129 usercreds[0].comment,
2130 TEST_MACHINE_NAME,
2131 usercreds[0].domain,
2132 usercreds[0].username,
2133 usercreds[0].password,
2134 usercreds[0].parameter_control,
2135 usercreds[0].expected_interactive_error),
2136 ret,
2137 failed,
2138 talloc_asprintf(mem_ctx,
2139 "Testing InteractiveLogon with flags: 0x%08x\n",
2140 credential_flags[i]));
2142 if (usercreds[0].network_login) {
2143 torture_assert_goto(torture,
2144 test_SamLogon(p, mem_ctx, torture, creds,
2145 usercreds[0].comment,
2146 usercreds[0].domain,
2147 usercreds[0].username,
2148 usercreds[0].password,
2149 usercreds[0].parameter_control,
2150 usercreds[0].expected_network_error,
2151 usercreds[0].old_password,
2153 ret,
2154 failed,
2155 talloc_asprintf(mem_ctx,
2156 "Testing SamLogon with flags: 0x%08x\n",
2157 credential_flags[i]));
2161 torture_comment(torture, "Testing with krb5\n");
2163 cli_credentials_set_netlogon_creds(machine_credentials, NULL);
2164 status = dcerpc_binding_set_flags(b,
2165 DCERPC_SCHANNEL |
2166 DCERPC_SIGN | DCERPC_SEAL |
2167 DCERPC_SCHANNEL_KRB5,
2168 DCERPC_AUTH_OPTIONS);
2169 torture_assert_ntstatus_ok(torture, status, "set flags");
2171 status = dcerpc_pipe_connect_b(mem_ctx, &p, b,
2172 &ndr_table_netlogon,
2173 machine_credentials, torture->ev, torture->lp_ctx);
2175 torture_assert_ntstatus_ok_goto(torture, status, ret, failed,
2176 talloc_asprintf(torture, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status)));
2178 torture_assert_not_null_goto(torture,
2179 creds = cli_credentials_get_netlogon_creds(machine_credentials),
2180 ret,
2181 failed,
2182 "obtaining credentials");
2184 torture_assert_goto(torture,
2185 test_InteractiveLogon(p, mem_ctx, torture, creds,
2186 usercreds[0].comment,
2187 TEST_MACHINE_NAME,
2188 usercreds[0].domain,
2189 usercreds[0].username,
2190 usercreds[0].password,
2191 usercreds[0].parameter_control,
2192 usercreds[0].expected_interactive_error),
2193 ret,
2194 failed,
2195 talloc_asprintf(mem_ctx,
2196 "Testing InteractiveLogon with krb5\n"
2199 if (usercreds[0].network_login) {
2200 torture_assert_goto(torture,
2201 test_SamLogon(p, mem_ctx, torture, creds,
2202 usercreds[0].comment,
2203 usercreds[0].domain,
2204 usercreds[0].username,
2205 usercreds[0].password,
2206 usercreds[0].parameter_control,
2207 usercreds[0].expected_network_error,
2208 usercreds[0].old_password,
2210 ret,
2211 failed,
2212 talloc_asprintf(mem_ctx,
2213 "Testing SamLogon with krb5\n"
2217 failed:
2218 torture_assert(torture, handle_minPwdAge(torture, mem_ctx, false),
2219 "handle_minPwdAge error!");
2221 talloc_free(mem_ctx);
2223 torture_leave_domain(torture, join_ctx);
2224 torture_leave_domain(torture, user_ctx);
2225 torture_leave_domain(torture, user_ctx_wrong_wks);
2226 torture_leave_domain(torture, user_ctx_wrong_time);
2227 return ret;