1/* 2 Unix SMB/CIFS implementation. 3 4 test suite for netlogon SamLogon operations 5 6 Copyright (C) Andrew Tridgell 2003 7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004 8 Copyright (C) Tim Potter 2003 9 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. 14 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. 19 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/>. 22*/ 23 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 "auth/auth.h" 29#include "../lib/crypto/crypto.h" 30#include "lib/cmdline/popt_common.h" 31#include "torture/rpc/rpc.h" 32#include "auth/gensec/schannel_proto.h" 33#include "auth/gensec/gensec.h" 34#include "libcli/auth/libcli_auth.h" 35#include "param/param.h" 36 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" 41 42enum ntlm_break { 43 BREAK_BOTH, 44 BREAK_NONE, 45 BREAK_LM, 46 BREAK_NT, 47 NO_LM, 48 NO_NT 49}; 50 51struct samlogon_state { 52 TALLOC_CTX *mem_ctx; 53 const char *comment; 54 const char *account_name; 55 const char *account_domain; 56 const char *netbios_name; 57 const char *password; 58 const char *workgroup; 59 struct dcerpc_pipe *p; 60 int function_level; 61 uint32_t parameter_control; 62 struct netr_LogonSamLogon r; 63 struct netr_LogonSamLogonEx r_ex; 64 struct netr_LogonSamLogonWithFlags r_flags; 65 struct netr_Authenticator auth, auth2; 66 struct netlogon_creds_CredentialState *creds; 67 NTSTATUS expected_error; 68 bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */ 69 DATA_BLOB chall; 70 struct smb_iconv_convenience *iconv_convenience; 71}; 72 73/* 74 Authenticate a user with a challenge/response, checking session key 75 and valid authentication types 76*/ 77static 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) 86{ 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 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; 98 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_low = 0; 102 ninfo.identity_info.logon_id_high = 0; 103 ninfo.identity_info.account_name.string = samlogon_state->account_name; 104 ninfo.identity_info.workstation.string = TEST_MACHINE_NAME; 105 106 memcpy(ninfo.challenge, chall->data, 8); 107 108 switch (break_which) { 109 case BREAK_NONE: 110 break; 111 case BREAK_LM: 112 if (lm_response && lm_response->data) { 113 lm_response->data[0]++; 114 } 115 break; 116 case BREAK_NT: 117 if (nt_response && nt_response->data) { 118 nt_response->data[0]++; 119 } 120 break; 121 case BREAK_BOTH: 122 if (lm_response && lm_response->data) { 123 lm_response->data[0]++; 124 } 125 if (nt_response && nt_response->data) { 126 nt_response->data[0]++; 127 } 128 break; 129 case NO_LM: 130 data_blob_free(lm_response); 131 break; 132 case NO_NT: 133 data_blob_free(nt_response); 134 break; 135 } 136 137 if (nt_response) { 138 ninfo.nt.data = nt_response->data; 139 ninfo.nt.length = nt_response->length; 140 } else { 141 ninfo.nt.data = NULL; 142 ninfo.nt.length = 0; 143 } 144 145 if (lm_response) { 146 ninfo.lm.data = lm_response->data; 147 ninfo.lm.length = lm_response->length; 148 } else { 149 ninfo.lm.data = NULL; 150 ninfo.lm.length = 0; 151 } 152 153 switch (samlogon_state->function_level) { 154 case NDR_NETR_LOGONSAMLOGON: 155 ZERO_STRUCT(samlogon_state->auth2); 156 netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth); 157 158 r->out.return_authenticator = NULL; 159 status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r); 160 if (!r->out.return_authenticator || 161 !netlogon_creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) { 162 d_printf("Credential chaining failed\n"); 163 } 164 if (!NT_STATUS_IS_OK(status)) { 165 if (error_string) { 166 *error_string = strdup(nt_errstr(status)); 167 } 168 return status; 169 } 170 171 validation_level = r->in.validation_level; 172 173 netlogon_creds_decrypt_samlogon(samlogon_state->creds, validation_level, r->out.validation); 174 175 switch (validation_level) { 176 case 2: 177 base = &r->out.validation->sam2->base; 178 break; 179 case 3: 180 base = &r->out.validation->sam3->base; 181 break; 182 case 6: 183 base = &r->out.validation->sam6->base; 184 break; 185 } 186 break; 187 case NDR_NETR_LOGONSAMLOGONEX: 188 status = dcerpc_netr_LogonSamLogonEx(samlogon_state->p, samlogon_state->mem_ctx, r_ex); 189 if (!NT_STATUS_IS_OK(status)) { 190 if (error_string) { 191 *error_string = strdup(nt_errstr(status)); 192 } 193 return status; 194 } 195 196 validation_level = r_ex->in.validation_level; 197 198 netlogon_creds_decrypt_samlogon(samlogon_state->creds, validation_level, r_ex->out.validation); 199 200 switch (validation_level) { 201 case 2: 202 base = &r_ex->out.validation->sam2->base; 203 break; 204 case 3: 205 base = &r_ex->out.validation->sam3->base; 206 break; 207 case 6: 208 base = &r_ex->out.validation->sam6->base; 209 break; 210 } 211 break; 212 case NDR_NETR_LOGONSAMLOGONWITHFLAGS: 213 ZERO_STRUCT(samlogon_state->auth2); 214 netlogon_creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth); 215 216 r_flags->out.return_authenticator = NULL; 217 status = dcerpc_netr_LogonSamLogonWithFlags(samlogon_state->p, samlogon_state->mem_ctx, r_flags); 218 if (!r_flags->out.return_authenticator || 219 !netlogon_creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) { 220 d_printf("Credential chaining failed\n"); 221 } 222 if (!NT_STATUS_IS_OK(status)) { 223 if (error_string) { 224 *error_string = strdup(nt_errstr(status)); 225 } 226 return status; 227 } 228 229 validation_level = r_flags->in.validation_level; 230 231 netlogon_creds_decrypt_samlogon(samlogon_state->creds, validation_level, r_flags->out.validation); 232 233 switch (validation_level) { 234 case 2: 235 base = &r_flags->out.validation->sam2->base; 236 break; 237 case 3: 238 base = &r_flags->out.validation->sam3->base; 239 break; 240 case 6: 241 base = &r_flags->out.validation->sam6->base; 242 break; 243 } 244 break; 245 default: 246 /* can't happen */ 247 return NT_STATUS_INVALID_PARAMETER; 248 } 249 250 if (!base) { 251 d_printf("No user info returned from 'successful' SamLogon*() call!\n"); 252 return NT_STATUS_INVALID_PARAMETER; 253 } 254 255 if (user_session_key) { 256 memcpy(user_session_key, base->key.key, 16); 257 } 258 if (lm_key) { 259 memcpy(lm_key, base->LMSessKey.key, 8); 260 } 261 262 return status; 263} 264 265 266/* 267 * Test the normal 'LM and NTLM' combination 268 */ 269 270static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) 271{ 272 bool pass = true; 273 bool lm_good; 274 NTSTATUS nt_status; 275 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24); 276 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24); 277 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16); 278 279 uint8_t lm_key[8]; 280 uint8_t user_session_key[16]; 281 uint8_t lm_hash[16]; 282 uint8_t nt_hash[16]; 283 284 ZERO_STRUCT(lm_key); 285 ZERO_STRUCT(user_session_key); 286 287 lm_good = SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data); 288 if (!lm_good) { 289 ZERO_STRUCT(lm_hash); 290 } else { 291 E_deshash(samlogon_state->password, lm_hash); 292 } 293 294 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data); 295 296 E_md4hash(samlogon_state->password, nt_hash); 297 SMBsesskeygen_ntv1(nt_hash, session_key.data); 298 299 nt_status = check_samlogon(samlogon_state, 300 break_which, 301 samlogon_state->parameter_control, 302 &samlogon_state->chall, 303 &lm_response, 304 &nt_response, 305 lm_key, 306 user_session_key, 307 error_string); 308 309 data_blob_free(&lm_response); 310 311 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) { 312 /* for 'long' passwords, the LM password is invalid */ 313 if (break_which == NO_NT && !lm_good) { 314 return true; 315 } 316 /* for 'old' passwords, we allow the server to be OK or wrong password */ 317 if (samlogon_state->old_password) { 318 return true; 319 } 320 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH)); 321 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) { 322 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT)); 323 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) { 324 SAFE_FREE(*error_string); 325 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status)); 326 return false; 327 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) { 328 return true; 329 } else if (!NT_STATUS_IS_OK(nt_status)) { 330 return false; 331 } 332 333 if (break_which == NO_NT && !lm_good) { 334 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!"); 335 return false; 336 } 337 338 if (memcmp(lm_hash, lm_key, 339 sizeof(lm_key)) != 0) { 340 d_printf("LM Key does not match expectations!\n"); 341 d_printf("lm_key:\n"); 342 dump_data(1, lm_key, 8); 343 d_printf("expected:\n"); 344 dump_data(1, lm_hash, 8); 345 pass = false; 346 } 347 348 switch (break_which) { 349 case NO_NT: 350 { 351 uint8_t lm_key_expected[16]; 352 memcpy(lm_key_expected, lm_hash, 8); 353 memset(lm_key_expected+8, '\0', 8); 354 if (memcmp(lm_key_expected, user_session_key, 355 16) != 0) { 356 *error_string = strdup("NT Session Key does not match expectations (should be first-8 LM hash)!\n"); 357 d_printf("user_session_key:\n"); 358 dump_data(1, user_session_key, sizeof(user_session_key)); 359 d_printf("expected:\n"); 360 dump_data(1, lm_key_expected, sizeof(lm_key_expected)); 361 pass = false; 362 } 363 break; 364 } 365 default: 366 if (memcmp(session_key.data, user_session_key, 367 sizeof(user_session_key)) != 0) { 368 *error_string = strdup("NT Session Key does not match expectations!\n"); 369 d_printf("user_session_key:\n"); 370 dump_data(1, user_session_key, 16); 371 d_printf("expected:\n"); 372 dump_data(1, session_key.data, session_key.length); 373 pass = false; 374 } 375 } 376 return pass; 377} 378 379/* 380 * Test LM authentication, no NT response supplied 381 */ 382 383static bool test_lm(struct samlogon_state *samlogon_state, char **error_string) 384{ 385 386 return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string); 387} 388 389/* 390 * Test the NTLM response only, no LM. 391 */ 392 393static bool test_ntlm(struct samlogon_state *samlogon_state, char **error_string) 394{ 395 return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string); 396} 397 398/* 399 * Test the NTLM response only, but in the LM field. 400 */ 401 402static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string) 403{ 404 bool lm_good; 405 bool pass = true; 406 NTSTATUS nt_status; 407 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24); 408 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16); 409 410 uint8_t lm_key[8]; 411 uint8_t lm_hash[16]; 412 uint8_t user_session_key[16]; 413 uint8_t nt_hash[16]; 414 415 ZERO_STRUCT(lm_key); 416 ZERO_STRUCT(user_session_key); 417 418 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 419 nt_response.data); 420 E_md4hash(samlogon_state->password, nt_hash); 421 SMBsesskeygen_ntv1(nt_hash, 422 session_key.data); 423 424 lm_good = E_deshash(samlogon_state->password, lm_hash); 425 if (!lm_good) { 426 ZERO_STRUCT(lm_hash); 427 } 428 nt_status = check_samlogon(samlogon_state, 429 BREAK_NONE, 430 samlogon_state->parameter_control, 431 &samlogon_state->chall, 432 &nt_response, 433 NULL, 434 lm_key, 435 user_session_key, 436 error_string); 437 438 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) { 439 /* for 'old' passwords, we allow the server to be OK or wrong password */ 440 if (samlogon_state->old_password) { 441 return true; 442 } 443 return false; 444 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) { 445 SAFE_FREE(*error_string); 446 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status)); 447 return false; 448 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) { 449 return true; 450 } else if (!NT_STATUS_IS_OK(nt_status)) { 451 return false; 452 } 453 454 if (lm_good) { 455 if (memcmp(lm_hash, lm_key, 456 sizeof(lm_key)) != 0) { 457 d_printf("LM Key does not match expectations!\n"); 458 d_printf("lm_key:\n"); 459 dump_data(1, lm_key, 8); 460 d_printf("expected:\n"); 461 dump_data(1, lm_hash, 8); 462 pass = false; 463 } 464#if 0 465 } else { 466 if (memcmp(session_key.data, lm_key, 467 sizeof(lm_key)) != 0) { 468 d_printf("LM Key does not match expectations (first 8 session key)!\n"); 469 d_printf("lm_key:\n"); 470 dump_data(1, lm_key, 8); 471 d_printf("expected:\n"); 472 dump_data(1, session_key.data, 8); 473 pass = false; 474 } 475#endif 476 } 477 if (lm_good && memcmp(lm_hash, user_session_key, 8) != 0) { 478 uint8_t lm_key_expected[16]; 479 memcpy(lm_key_expected, lm_hash, 8); 480 memset(lm_key_expected+8, '\0', 8); 481 if (memcmp(lm_key_expected, user_session_key, 482 16) != 0) { 483 d_printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n"); 484 d_printf("user_session_key:\n"); 485 dump_data(1, user_session_key, sizeof(user_session_key)); 486 d_printf("expected:\n"); 487 dump_data(1, lm_key_expected, sizeof(lm_key_expected)); 488 pass = false; 489 } 490 } 491 return pass; 492} 493 494/* 495 * Test the NTLM response only, but in the both the NT and LM fields. 496 */ 497 498static bool test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string) 499{ 500 bool pass = true; 501 bool lm_good; 502 NTSTATUS nt_status; 503 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24); 504 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16); 505 506 uint8_t lm_key[8]; 507 uint8_t lm_hash[16]; 508 uint8_t user_session_key[16]; 509 uint8_t nt_hash[16]; 510 511 ZERO_STRUCT(lm_key); 512 ZERO_STRUCT(user_session_key); 513 514 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 515 nt_response.data); 516 E_md4hash(samlogon_state->password, nt_hash); 517 SMBsesskeygen_ntv1(nt_hash, 518 session_key.data); 519 520 lm_good = E_deshash(samlogon_state->password, lm_hash); 521 if (!lm_good) { 522 ZERO_STRUCT(lm_hash); 523 } 524 525 nt_status = check_samlogon(samlogon_state, 526 BREAK_NONE, 527 samlogon_state->parameter_control, 528 &samlogon_state->chall, 529 NULL, 530 &nt_response, 531 lm_key, 532 user_session_key, 533 error_string); 534 535 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) { 536 /* for 'old' passwords, we allow the server to be OK or wrong password */ 537 if (samlogon_state->old_password) { 538 return true; 539 } 540 return false; 541 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) { 542 SAFE_FREE(*error_string); 543 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status)); 544 return false; 545 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) { 546 return true; 547 } else if (!NT_STATUS_IS_OK(nt_status)) { 548 return false; 549 } 550 551 if (!NT_STATUS_IS_OK(nt_status)) { 552 return false; 553 } 554 555 if (memcmp(lm_hash, lm_key, 556 sizeof(lm_key)) != 0) { 557 d_printf("LM Key does not match expectations!\n"); 558 d_printf("lm_key:\n"); 559 dump_data(1, lm_key, 8); 560 d_printf("expected:\n"); 561 dump_data(1, lm_hash, 8); 562 pass = false; 563 } 564 if (memcmp(session_key.data, user_session_key, 565 sizeof(user_session_key)) != 0) { 566 d_printf("NT Session Key does not match expectations!\n"); 567 d_printf("user_session_key:\n"); 568 dump_data(1, user_session_key, 16); 569 d_printf("expected:\n"); 570 dump_data(1, session_key.data, session_key.length); 571 pass = false; 572 } 573 574 575 return pass; 576} 577 578/* 579 * Test the NTLMv2 and LMv2 responses 580 */ 581 582enum ntlmv2_domain { 583 UPPER_DOMAIN, 584 NO_DOMAIN 585}; 586 587static bool test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, 588 enum ntlm_break break_which, 589 enum ntlmv2_domain ntlmv2_domain, 590 char **error_string) 591{ 592 bool pass = true; 593 NTSTATUS nt_status; 594 DATA_BLOB ntlmv2_response = data_blob(NULL, 0); 595 DATA_BLOB lmv2_response = data_blob(NULL, 0); 596 DATA_BLOB lmv2_session_key = data_blob(NULL, 0); 597 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0); 598 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, TEST_MACHINE_NAME, samlogon_state->workgroup); 599 600 uint8_t lm_session_key[8]; 601 uint8_t user_session_key[16]; 602 603 ZERO_STRUCT(lm_session_key); 604 ZERO_STRUCT(user_session_key); 605 606 switch (ntlmv2_domain) { 607 case UPPER_DOMAIN: 608 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 609 samlogon_state->account_name, samlogon_state->account_domain, 610 samlogon_state->password, &samlogon_state->chall, 611 &names_blob, 612 &lmv2_response, &ntlmv2_response, 613 &lmv2_session_key, &ntlmv2_session_key)) { 614 data_blob_free(&names_blob); 615 return false; 616 } 617 break; 618 case NO_DOMAIN: 619 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 620 samlogon_state->account_name, "", 621 samlogon_state->password, &samlogon_state->chall, 622 &names_blob, 623 &lmv2_response, &ntlmv2_response, 624 &lmv2_session_key, &ntlmv2_session_key)) { 625 data_blob_free(&names_blob); 626 return false; 627 } 628 break; 629 } 630 data_blob_free(&names_blob); 631 632 nt_status = check_samlogon(samlogon_state, 633 break_which, 634 samlogon_state->parameter_control, 635 &samlogon_state->chall, 636 &lmv2_response, 637 &ntlmv2_response, 638 lm_session_key, 639 user_session_key, 640 error_string); 641 642 data_blob_free(&lmv2_response); 643 data_blob_free(&ntlmv2_response); 644 645 646 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) { 647 /* for 'old' passwords, we allow the server to be OK or wrong password */ 648 if (samlogon_state->old_password) { 649 return true; 650 } 651 return break_which == BREAK_BOTH; 652 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) { 653 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT)); 654 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) { 655 SAFE_FREE(*error_string); 656 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status)); 657 return false; 658 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) { 659 return true; 660 } else if (!NT_STATUS_IS_OK(nt_status)) { 661 return false; 662 } 663 664 665 switch (break_which) { 666 case NO_NT: 667 if (memcmp(lmv2_session_key.data, user_session_key, 668 sizeof(user_session_key)) != 0) { 669 d_printf("USER (LMv2) Session Key does not match expectations!\n"); 670 d_printf("user_session_key:\n"); 671 dump_data(1, user_session_key, 16); 672 d_printf("expected:\n"); 673 dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length); 674 pass = false; 675 } 676 if (memcmp(lmv2_session_key.data, lm_session_key, 677 sizeof(lm_session_key)) != 0) { 678 d_printf("LM (LMv2) Session Key does not match expectations!\n"); 679 d_printf("lm_session_key:\n"); 680 dump_data(1, lm_session_key, 8); 681 d_printf("expected:\n"); 682 dump_data(1, lmv2_session_key.data, 8); 683 pass = false; 684 } 685 break; 686 default: 687 if (memcmp(ntlmv2_session_key.data, user_session_key, 688 sizeof(user_session_key)) != 0) { 689 if (memcmp(lmv2_session_key.data, user_session_key, 690 sizeof(user_session_key)) == 0) { 691 d_printf("USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n"); 692 d_printf("user_session_key:\n"); 693 dump_data(1, user_session_key, 16); 694 d_printf("expected:\n"); 695 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length); 696 pass = false; 697 698 } else { 699 d_printf("USER (NTLMv2) Session Key does not match expectations!\n"); 700 d_printf("user_session_key:\n"); 701 dump_data(1, user_session_key, 16); 702 d_printf("expected:\n"); 703 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length); 704 pass = false; 705 } 706 } 707 if (memcmp(ntlmv2_session_key.data, lm_session_key, 708 sizeof(lm_session_key)) != 0) { 709 if (memcmp(lmv2_session_key.data, lm_session_key, 710 sizeof(lm_session_key)) == 0) { 711 d_printf("LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n"); 712 d_printf("user_session_key:\n"); 713 dump_data(1, lm_session_key, 8); 714 d_printf("expected:\n"); 715 dump_data(1, ntlmv2_session_key.data, 8); 716 pass = false; 717 } else { 718 d_printf("LM (NTLMv2) Session Key does not match expectations!\n"); 719 d_printf("lm_session_key:\n"); 720 dump_data(1, lm_session_key, 8); 721 d_printf("expected:\n"); 722 dump_data(1, ntlmv2_session_key.data, 8); 723 pass = false; 724 } 725 } 726 } 727 728 return pass; 729} 730 731/* 732 * Test the NTLM and LMv2 responses 733 */ 734 735static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, 736 enum ntlm_break break_which, 737 enum ntlmv2_domain ntlmv2_domain, 738 char **error_string) 739{ 740 bool pass = true; 741 NTSTATUS nt_status; 742 DATA_BLOB ntlmv2_response = data_blob(NULL, 0); 743 DATA_BLOB lmv2_response = data_blob(NULL, 0); 744 DATA_BLOB lmv2_session_key = data_blob(NULL, 0); 745 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0); 746 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, samlogon_state->netbios_name, samlogon_state->workgroup); 747 748 DATA_BLOB ntlm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24); 749 DATA_BLOB ntlm_session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16); 750 751 bool lm_good; 752 uint8_t lm_hash[16]; 753 uint8_t lm_session_key[8]; 754 uint8_t user_session_key[16]; 755 uint8_t nt_hash[16]; 756 757 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 758 ntlm_response.data); 759 E_md4hash(samlogon_state->password, nt_hash); 760 SMBsesskeygen_ntv1(nt_hash, 761 ntlm_session_key.data); 762 763 lm_good = E_deshash(samlogon_state->password, lm_hash); 764 if (!lm_good) { 765 ZERO_STRUCT(lm_hash); 766 } 767 768 ZERO_STRUCT(lm_session_key); 769 ZERO_STRUCT(user_session_key); 770 771 switch (ntlmv2_domain) { 772 case UPPER_DOMAIN: 773 /* TODO - test with various domain cases, and without domain */ 774 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 775 samlogon_state->account_name, samlogon_state->account_domain, 776 samlogon_state->password, &samlogon_state->chall, 777 &names_blob, 778 &lmv2_response, &ntlmv2_response, 779 &lmv2_session_key, &ntlmv2_session_key)) { 780 data_blob_free(&names_blob); 781 return false; 782 } 783 break; 784 case NO_DOMAIN: 785 /* TODO - test with various domain cases, and without domain */ 786 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 787 samlogon_state->account_name, "", 788 samlogon_state->password, &samlogon_state->chall, 789 &names_blob, 790 &lmv2_response, &ntlmv2_response, 791 &lmv2_session_key, &ntlmv2_session_key)) { 792 data_blob_free(&names_blob); 793 return false; 794 } 795 break; 796 } 797 798 data_blob_free(&names_blob); 799 800 nt_status = check_samlogon(samlogon_state, 801 break_which, 802 samlogon_state->parameter_control, 803 &samlogon_state->chall, 804 &lmv2_response, 805 &ntlm_response, 806 lm_session_key, 807 user_session_key, 808 error_string); 809 810 data_blob_free(&lmv2_response); 811 data_blob_free(&ntlmv2_response); 812 813 814 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) { 815 /* for 'old' passwords, we allow the server to be OK or wrong password */ 816 if (samlogon_state->old_password) { 817 return true; 818 } 819 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH)); 820 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) { 821 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH)); 822 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) { 823 SAFE_FREE(*error_string); 824 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status)); 825 return false; 826 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) { 827 return true; 828 } else if (!NT_STATUS_IS_OK(nt_status)) { 829 return false; 830 } 831 832 switch (break_which) { 833 case NO_NT: 834 if (memcmp(lmv2_session_key.data, user_session_key, 835 sizeof(user_session_key)) != 0) { 836 d_printf("USER (LMv2) Session Key does not match expectations!\n"); 837 d_printf("user_session_key:\n"); 838 dump_data(1, user_session_key, 16); 839 d_printf("expected:\n"); 840 dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length); 841 pass = false; 842 } 843 if (memcmp(lmv2_session_key.data, lm_session_key, 844 sizeof(lm_session_key)) != 0) { 845 d_printf("LM (LMv2) Session Key does not match expectations!\n"); 846 d_printf("lm_session_key:\n"); 847 dump_data(1, lm_session_key, 8); 848 d_printf("expected:\n"); 849 dump_data(1, lmv2_session_key.data, 8); 850 pass = false; 851 } 852 break; 853 case BREAK_LM: 854 if (memcmp(ntlm_session_key.data, user_session_key, 855 sizeof(user_session_key)) != 0) { 856 d_printf("USER (NTLMv2) Session Key does not match expectations!\n"); 857 d_printf("user_session_key:\n"); 858 dump_data(1, user_session_key, 16); 859 d_printf("expected:\n"); 860 dump_data(1, ntlm_session_key.data, ntlm_session_key.length); 861 pass = false; 862 } 863 if (lm_good) { 864 if (memcmp(lm_hash, lm_session_key, 865 sizeof(lm_session_key)) != 0) { 866 d_printf("LM Session Key does not match expectations!\n"); 867 d_printf("lm_session_key:\n"); 868 dump_data(1, lm_session_key, 8); 869 d_printf("expected:\n"); 870 dump_data(1, lm_hash, 8); 871 pass = false; 872 } 873 } else { 874 static const uint8_t zeros[8]; 875 if (memcmp(zeros, lm_session_key, 876 sizeof(lm_session_key)) != 0) { 877 d_printf("LM Session Key does not match expectations (zeros)!\n"); 878 d_printf("lm_session_key:\n"); 879 dump_data(1, lm_session_key, 8); 880 d_printf("expected:\n"); 881 dump_data(1, zeros, 8); 882 pass = false; 883 } 884 } 885 break; 886 default: 887 if (memcmp(ntlm_session_key.data, user_session_key, 888 sizeof(user_session_key)) != 0) { 889 d_printf("USER (NTLMv2) Session Key does not match expectations!\n"); 890 d_printf("user_session_key:\n"); 891 dump_data(1, user_session_key, 16); 892 d_printf("expected:\n"); 893 dump_data(1, ntlm_session_key.data, ntlm_session_key.length); 894 pass = false; 895 } 896 if (memcmp(ntlm_session_key.data, lm_session_key, 897 sizeof(lm_session_key)) != 0) { 898 d_printf("LM (NTLMv2) Session Key does not match expectations!\n"); 899 d_printf("lm_session_key:\n"); 900 dump_data(1, lm_session_key, 8); 901 d_printf("expected:\n"); 902 dump_data(1, ntlm_session_key.data, 8); 903 pass = false; 904 } 905 } 906 907 return pass; 908} 909 910/* 911 * Test the NTLMv2 and LMv2 responses 912 */ 913 914static bool test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 915{ 916 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, UPPER_DOMAIN, error_string); 917} 918 919#if 0 920static bool test_lmv2_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) 921{ 922 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, NO_DOMAIN, error_string); 923} 924#endif 925 926/* 927 * Test the LMv2 response only 928 */ 929 930static bool test_lmv2(struct samlogon_state *samlogon_state, char **error_string) 931{ 932 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, UPPER_DOMAIN, error_string); 933} 934 935static bool test_lmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) 936{ 937 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, NO_DOMAIN, error_string); 938} 939 940/* 941 * Test the NTLMv2 response only 942 */ 943 944static bool test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 945{ 946 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, UPPER_DOMAIN, error_string); 947} 948 949static bool test_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) 950{ 951 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, NO_DOMAIN, error_string); 952} 953 954static bool test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string) 955{ 956 return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string); 957} 958 959static bool test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string) 960{ 961 return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string); 962} 963 964static bool test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string) 965{ 966 return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string); 967} 968 969static bool test_lm_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string) 970{ 971 return test_lm_ntlm_broken(samlogon_state, BREAK_BOTH, error_string); 972} 973static bool test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 974{ 975 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string); 976} 977 978static bool test_ntlmv2_lmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) 979{ 980 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string); 981} 982 983static bool test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 984{ 985 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string); 986} 987 988#if 0 989static bool test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) 990{ 991 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string); 992} 993#endif 994 995static bool test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char **error_string) 996{ 997 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string); 998} 999 1000static bool test_ntlmv2_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) 1001{ 1002 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string); 1003} 1004 1005static bool test_lmv2_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string) 1006{ 1007 return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string); 1008} 1009 1010static bool test_lmv2_ntlm_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) 1011{ 1012 return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string); 1013} 1014 1015static bool test_lmv2_ntlm_break_ntlm(struct samlogon_state *samlogon_state, char **error_string) 1016{ 1017 return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string); 1018} 1019 1020static bool test_lmv2_ntlm_break_ntlm_no_dom(struct samlogon_state *samlogon_state, char **error_string) 1021{ 1022 return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string); 1023} 1024 1025static bool test_lmv2_ntlm_break_lm(struct samlogon_state *samlogon_state, char **error_string) 1026{ 1027 return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string); 1028} 1029 1030static bool test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state *samlogon_state, char **error_string) 1031{ 1032 return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string); 1033} 1034 1035/* 1036 * Test the NTLM2 response (extra challenge in LM feild) 1037 * 1038 * This test is the same as the 'break LM' test, but checks that the 1039 * server implements NTLM2 session security in the right place 1040 * (NETLOGON is the wrong place). 1041 */ 1042 1043static bool test_ntlm2(struct samlogon_state *samlogon_state, char **error_string) 1044{ 1045 bool pass = true; 1046 NTSTATUS nt_status; 1047 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24); 1048 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24); 1049 1050 bool lm_good; 1051 uint8_t lm_key[8]; 1052 uint8_t nt_hash[16]; 1053 uint8_t lm_hash[16]; 1054 uint8_t nt_key[16]; 1055 uint8_t user_session_key[16]; 1056 uint8_t expected_user_session_key[16]; 1057 uint8_t session_nonce_hash[16]; 1058 uint8_t client_chall[8]; 1059 1060 struct MD5Context md5_session_nonce_ctx; 1061 HMACMD5Context hmac_ctx; 1062 1063 ZERO_STRUCT(user_session_key); 1064 ZERO_STRUCT(lm_key); 1065 generate_random_buffer(client_chall, 8); 1066 1067 MD5Init(&md5_session_nonce_ctx); 1068 MD5Update(&md5_session_nonce_ctx, samlogon_state->chall.data, 8); 1069 MD5Update(&md5_session_nonce_ctx, client_chall, 8); 1070 MD5Final(session_nonce_hash, &md5_session_nonce_ctx); 1071 1072 E_md4hash(samlogon_state->password, (uint8_t *)nt_hash); 1073 lm_good = E_deshash(samlogon_state->password, (uint8_t *)lm_hash); 1074 SMBsesskeygen_ntv1((const uint8_t *)nt_hash, 1075 nt_key); 1076 1077 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data); 1078 1079 memcpy(lm_response.data, session_nonce_hash, 8); 1080 memset(lm_response.data + 8, 0, 16); 1081 1082 hmac_md5_init_rfc2104(nt_key, 16, &hmac_ctx); 1083 hmac_md5_update(samlogon_state->chall.data, 8, &hmac_ctx); 1084 hmac_md5_update(client_chall, 8, &hmac_ctx); 1085 hmac_md5_final(expected_user_session_key, &hmac_ctx); 1086 1087 nt_status = check_samlogon(samlogon_state, 1088 BREAK_NONE, 1089 samlogon_state->parameter_control, 1090 &samlogon_state->chall, 1091 &lm_response, 1092 &nt_response, 1093 lm_key, 1094 user_session_key, 1095 error_string); 1096 1097 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) { 1098 /* for 'old' passwords, we allow the server to be OK or wrong password */ 1099 if (samlogon_state->old_password) { 1100 return true; 1101 } 1102 return false; 1103 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) { 1104 SAFE_FREE(*error_string); 1105 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status)); 1106 return false; 1107 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) { 1108 return true; 1109 } else if (!NT_STATUS_IS_OK(nt_status)) { 1110 return false; 1111 } 1112 1113 if (lm_good) { 1114 if (memcmp(lm_hash, lm_key, 1115 sizeof(lm_key)) != 0) { 1116 d_printf("LM Key does not match expectations!\n"); 1117 d_printf("lm_key:\n"); 1118 dump_data(1, lm_key, 8); 1119 d_printf("expected:\n"); 1120 dump_data(1, lm_hash, 8); 1121 pass = false; 1122 } 1123 } else { 1124 static const uint8_t zeros[8]; 1125 if (memcmp(zeros, lm_key, 1126 sizeof(lm_key)) != 0) { 1127 d_printf("LM Session Key does not match expectations (zeros)!\n"); 1128 d_printf("lm_key:\n"); 1129 dump_data(1, lm_key, 8); 1130 d_printf("expected:\n"); 1131 dump_data(1, zeros, 8); 1132 pass = false; 1133 } 1134 } 1135 if (memcmp(nt_key, user_session_key, 16) != 0) { 1136 d_printf("NT Session Key does not match expectations (should be NT Key)!\n"); 1137 d_printf("user_session_key:\n"); 1138 dump_data(1, user_session_key, sizeof(user_session_key)); 1139 d_printf("expected:\n"); 1140 dump_data(1, nt_key, sizeof(nt_key)); 1141 pass = false; 1142 } 1143 return pass; 1144} 1145 1146static bool test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) 1147{ 1148 NTSTATUS nt_status; 1149 DATA_BLOB nt_response = data_blob(NULL, 0); 1150 DATA_BLOB lm_response = data_blob(NULL, 0); 1151 char *password; 1152 char *dospw; 1153 smb_ucs2_t *unicodepw; 1154 1155 uint8_t user_session_key[16]; 1156 uint8_t lm_key[16]; 1157 uint8_t lm_hash[16]; 1158 static const uint8_t zeros[8]; 1159 DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros)); 1160 bool lm_good = E_deshash(samlogon_state->password, lm_hash); 1161 1162 ZERO_STRUCT(user_session_key); 1163 1164 if (!push_ucs2_talloc(samlogon_state->mem_ctx, 1165 &unicodepw, samlogon_state->password, NULL)) { 1166 DEBUG(0, ("push_ucs2_allocate failed!\n")); 1167 exit(1); 1168 } 1169 1170 nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, strlen_m(samlogon_state->password)*2); 1171 1172 password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password); 1173 1174 if (!convert_string_talloc_convenience(samlogon_state->mem_ctx, 1175 samlogon_state->iconv_convenience, 1176 CH_UNIX, CH_DOS, 1177 password, strlen(password)+1, 1178 (void**)&dospw, NULL, false)) { 1179 DEBUG(0, ("convert_string_talloc failed!\n")); 1180 exit(1); 1181 } 1182 1183 lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw)); 1184 1185 nt_status = check_samlogon(samlogon_state, 1186 break_which, 1187 samlogon_state->parameter_control | MSV1_0_CLEARTEXT_PASSWORD_ALLOWED, 1188 &chall, 1189 &lm_response, 1190 &nt_response, 1191 lm_key, 1192 user_session_key, 1193 error_string); 1194 1195 if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) { 1196 /* for 'old' passwords, we allow the server to be OK or wrong password */ 1197 if (samlogon_state->old_password) { 1198 return true; 1199 } 1200 /* for 'long' passwords, the LM password is invalid */ 1201 if (break_which == NO_NT && !lm_good) { 1202 return true; 1203 } 1204 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH)); 1205 } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) { 1206 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT)); 1207 } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) { 1208 SAFE_FREE(*error_string); 1209 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status)); 1210 return false; 1211 } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) { 1212 return true; 1213 } else if (!NT_STATUS_IS_OK(nt_status)) { 1214 return false; 1215 } 1216 1217 if (break_which == NO_NT && !lm_good) { 1218 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!"); 1219 return false; 1220 } 1221 1222 return true; 1223} 1224 1225static bool test_plaintext_none_broken(struct samlogon_state *samlogon_state, 1226 char **error_string) { 1227 return test_plaintext(samlogon_state, BREAK_NONE, error_string); 1228} 1229 1230static bool test_plaintext_lm_broken(struct samlogon_state *samlogon_state, 1231 char **error_string) { 1232 return test_plaintext(samlogon_state, BREAK_LM, error_string); 1233} 1234 1235static bool test_plaintext_nt_broken(struct samlogon_state *samlogon_state, 1236 char **error_string) { 1237 return test_plaintext(samlogon_state, BREAK_NT, error_string); 1238} 1239 1240static bool test_plaintext_nt_only(struct samlogon_state *samlogon_state, 1241 char **error_string) { 1242 return test_plaintext(samlogon_state, NO_LM, error_string); 1243} 1244 1245static bool test_plaintext_lm_only(struct samlogon_state *samlogon_state, 1246 char **error_string) { 1247 return test_plaintext(samlogon_state, NO_NT, error_string); 1248} 1249 1250/* 1251 Tests: 1252 1253 - LM only 1254 - NT and LM 1255 - NT 1256 - NT in LM field 1257 - NT in both fields 1258 - NTLMv2 1259 - NTLMv2 and LMv2 1260 - LMv2 1261 - plaintext tests (in challenge-response fields) 1262 1263 check we get the correct session key in each case 1264 check what values we get for the LM session key 1265 1266*/ 1267 1268static const struct ntlm_tests { 1269 bool (*fn)(struct samlogon_state *, char **); 1270 const char *name; 1271 bool expect_fail; 1272} test_table[] = { 1273 {test_lmv2_ntlmv2, "NTLMv2 and LMv2", false}, 1274#if 0 1275 {test_lmv2_ntlmv2_no_dom, "NTLMv2 and LMv2 (no domain)", false}, 1276#endif 1277 {test_lm, "LM", false}, 1278 {test_lm_ntlm, "LM and NTLM", false}, 1279 {test_lm_ntlm_both_broken, "LM and NTLM, both broken", false}, 1280 {test_ntlm, "NTLM", false}, 1281 {test_ntlm_in_lm, "NTLM in LM", false}, 1282 {test_ntlm_in_both, "NTLM in both", false}, 1283 {test_ntlmv2, "NTLMv2", false}, 1284 {test_ntlmv2_no_dom, "NTLMv2 (no domain)", false}, 1285 {test_lmv2, "LMv2", false}, 1286 {test_lmv2_no_dom, "LMv2 (no domain)", false}, 1287 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", false}, 1288 {test_ntlmv2_lmv2_broken_no_dom, "NTLMv2 and LMv2, LMv2 broken (no domain)", false}, 1289 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", false}, 1290#if 0 1291 {test_ntlmv2_ntlmv2_broken_no_dom, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", false}, 1292#endif 1293 {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", false}, 1294 {test_ntlmv2_both_broken_no_dom, "NTLMv2 and LMv2, both broken (no domain)", false}, 1295 {test_ntlm_lm_broken, "NTLM and LM, LM broken", false}, 1296 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", false}, 1297 {test_ntlm2, "NTLM2 (NTLMv2 session security)", false}, 1298 {test_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", false}, 1299 {test_lmv2_ntlm_both_broken_no_dom, "LMv2 and NTLM, both broken (no domain)", false}, 1300 {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", false}, 1301 {test_lmv2_ntlm_break_ntlm_no_dom, "LMv2 and NTLM, NTLM broken (no domain)", false}, 1302 {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", false}, 1303 {test_lmv2_ntlm_break_lm_no_dom, "LMv2 and NTLM, LMv2 broken (no domain)", false}, 1304 {test_plaintext_none_broken, "Plaintext", false}, 1305 {test_plaintext_lm_broken, "Plaintext LM broken", false}, 1306 {test_plaintext_nt_broken, "Plaintext NT broken", false}, 1307 {test_plaintext_nt_only, "Plaintext NT only", false}, 1308 {test_plaintext_lm_only, "Plaintext LM only", false}, 1309 {NULL, NULL} 1310}; 1311 1312/* 1313 try a netlogon SamLogon 1314*/ 1315static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 1316 struct torture_context *tctx, 1317 struct netlogon_creds_CredentialState *creds, 1318 const char *comment, 1319 const char *account_domain, const char *account_name, 1320 const char *plain_pass, uint32_t parameter_control, 1321 NTSTATUS expected_error, bool old_password, 1322 int n_subtests) 1323{ 1324 TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_SamLogon function-level context"); 1325 int i, v, l, f; 1326 bool ret = true; 1327 int validation_levels[] = {2,3,6}; 1328 int logon_levels[] = { 2, 6 }; 1329 int function_levels[] = { 1330 NDR_NETR_LOGONSAMLOGON, 1331 NDR_NETR_LOGONSAMLOGONEX, 1332 NDR_NETR_LOGONSAMLOGONWITHFLAGS }; 1333 struct samlogon_state samlogon_state; 1334 1335 union netr_LogonLevel logon; 1336 union netr_Validation validation; 1337 uint8_t authoritative = 0; 1338 uint32_t flags = 0; 1339 1340 ZERO_STRUCT(logon); 1341 1342 d_printf("testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n"); 1343 1344 samlogon_state.comment = comment; 1345 samlogon_state.account_name = account_name; 1346 samlogon_state.account_domain = account_domain; 1347 samlogon_state.password = plain_pass; 1348 samlogon_state.workgroup = lp_workgroup(tctx->lp_ctx); 1349 samlogon_state.netbios_name = lp_netbios_name(tctx->lp_ctx); 1350 samlogon_state.p = p; 1351 samlogon_state.creds = creds; 1352 samlogon_state.expected_error = expected_error; 1353 samlogon_state.chall = data_blob_talloc(fn_ctx, NULL, 8); 1354 samlogon_state.parameter_control = parameter_control; 1355 samlogon_state.old_password = old_password; 1356 samlogon_state.iconv_convenience = lp_iconv_convenience(tctx->lp_ctx); 1357 1358 generate_random_buffer(samlogon_state.chall.data, 8); 1359 samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p)); 1360 samlogon_state.r_flags.in.computer_name = TEST_MACHINE_NAME; 1361 samlogon_state.r_flags.in.credential = &samlogon_state.auth; 1362 samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2; 1363 samlogon_state.r_flags.in.flags = &flags; 1364 samlogon_state.r_flags.in.logon = &logon; 1365 samlogon_state.r_flags.out.validation = &validation; 1366 samlogon_state.r_flags.out.authoritative = &authoritative; 1367 samlogon_state.r_flags.out.flags = &flags; 1368 1369 samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p)); 1370 samlogon_state.r_ex.in.computer_name = TEST_MACHINE_NAME; 1371 samlogon_state.r_ex.in.flags = &flags; 1372 samlogon_state.r_ex.in.logon = &logon; 1373 samlogon_state.r_ex.out.validation = &validation; 1374 samlogon_state.r_ex.out.authoritative = &authoritative; 1375 samlogon_state.r_ex.out.flags = &flags; 1376 1377 samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p)); 1378 samlogon_state.r.in.computer_name = TEST_MACHINE_NAME; 1379 samlogon_state.r.in.credential = &samlogon_state.auth; 1380 samlogon_state.r.in.return_authenticator = &samlogon_state.auth2; 1381 samlogon_state.r.in.logon = &logon; 1382 samlogon_state.r.out.validation = &validation; 1383 samlogon_state.r.out.authoritative = &authoritative; 1384 1385 1386 for (f=0;f<ARRAY_SIZE(function_levels);f++) { 1387 for (i=0; test_table[i].fn; i++) { 1388 if (n_subtests && (i > n_subtests)) { 1389 continue; 1390 } 1391 for (v=0;v<ARRAY_SIZE(validation_levels);v++) { 1392 for (l=0;l<ARRAY_SIZE(logon_levels);l++) { 1393 char *error_string = NULL; 1394 TALLOC_CTX *tmp_ctx = talloc_named(fn_ctx, 0, "test_SamLogon inner loop"); 1395 samlogon_state.mem_ctx = tmp_ctx; 1396 samlogon_state.function_level = function_levels[f]; 1397 samlogon_state.r.in.validation_level = validation_levels[v]; 1398 samlogon_state.r.in.logon_level = logon_levels[l]; 1399 samlogon_state.r_ex.in.validation_level = validation_levels[v]; 1400 samlogon_state.r_ex.in.logon_level = logon_levels[l]; 1401 samlogon_state.r_flags.in.validation_level = validation_levels[v]; 1402 samlogon_state.r_flags.in.logon_level = logon_levels[l]; 1403 if (!test_table[i].fn(&samlogon_state, &error_string)) { 1404 d_printf("Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n", 1405 samlogon_state.comment, 1406 samlogon_state.account_domain, 1407 samlogon_state.account_name, 1408 test_table[i].name, validation_levels[v], 1409 logon_levels[l], function_levels[f]); 1410 1411 if (test_table[i].expect_fail) { 1412 d_printf(" failed (expected, test incomplete): %s\n", error_string); 1413 } else { 1414 d_printf(" failed: %s\n", error_string); 1415 ret = false; 1416 } 1417 SAFE_FREE(error_string); 1418 } 1419 talloc_free(tmp_ctx); 1420 } 1421 } 1422 } 1423 } 1424 talloc_free(fn_ctx); 1425 return ret; 1426} 1427 1428/* 1429 test an ADS style interactive domain logon 1430*/ 1431bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 1432 struct netlogon_creds_CredentialState *creds, 1433 const char *comment, 1434 const char *workstation_name, 1435 const char *account_domain, const char *account_name, 1436 const char *plain_pass, uint32_t parameter_control, 1437 NTSTATUS expected_error) 1438{ 1439 NTSTATUS status; 1440 TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context"); 1441 struct netr_LogonSamLogonWithFlags r; 1442 struct netr_Authenticator a, ra; 1443 struct netr_PasswordInfo pinfo; 1444 uint32_t flags = 0; 1445 1446 union netr_LogonLevel logon; 1447 union netr_Validation validation; 1448 uint8_t authoritative = 0; 1449 1450 ZERO_STRUCT(a); 1451 ZERO_STRUCT(r); 1452 ZERO_STRUCT(ra); 1453 1454 ZERO_STRUCT(logon); 1455 ZERO_STRUCT(validation); 1456 1457 netlogon_creds_client_authenticator(creds, &a); 1458 1459 logon.password = &pinfo; 1460 1461 r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p)); 1462 r.in.computer_name = TEST_MACHINE_NAME; 1463 r.in.credential = &a; 1464 r.in.return_authenticator = &ra; 1465 r.in.logon_level = 5; 1466 r.in.logon = &logon; 1467 r.in.validation_level = 6; 1468 r.in.flags = &flags; 1469 r.out.validation = &validation; 1470 r.out.authoritative = &authoritative; 1471 r.out.flags = &flags; 1472 1473 pinfo.identity_info.domain_name.string = account_domain; 1474 pinfo.identity_info.parameter_control = parameter_control; 1475 pinfo.identity_info.logon_id_low = 0; 1476 pinfo.identity_info.logon_id_high = 0; 1477 pinfo.identity_info.account_name.string = account_name; 1478 pinfo.identity_info.workstation.string = workstation_name; 1479 1480 if (!E_deshash(plain_pass, pinfo.lmpassword.hash)) { 1481 ZERO_STRUCT(pinfo.lmpassword.hash); 1482 } 1483 E_md4hash(plain_pass, pinfo.ntpassword.hash); 1484 1485 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { 1486 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16); 1487 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16); 1488 } else { 1489 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword); 1490 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword); 1491 } 1492 1493 d_printf("Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment); 1494 1495 status = dcerpc_netr_LogonSamLogonWithFlags(p, fn_ctx, &r); 1496 if (!r.out.return_authenticator 1497 || !netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { 1498 d_printf("Credential chaining failed\n"); 1499 talloc_free(fn_ctx); 1500 return false; 1501 } 1502 1503 talloc_free(fn_ctx); 1504 1505 if (!NT_STATUS_EQUAL(expected_error, status)) { 1506 d_printf("[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n", 1507 account_domain, account_name, nt_errstr(expected_error), nt_errstr(status)); 1508 return false; 1509 } 1510 1511 return true; 1512} 1513 1514 1515 1516bool torture_rpc_samlogon(struct torture_context *torture) 1517{ 1518 NTSTATUS status; 1519 struct dcerpc_pipe *p; 1520 struct dcerpc_binding *b; 1521 struct cli_credentials *machine_credentials; 1522 TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon"); 1523 bool ret = true; 1524 struct test_join *join_ctx = NULL; 1525 struct test_join *user_ctx = NULL, *user_ctx_wrong_wks = NULL, *user_ctx_wrong_time = NULL; 1526 char *user_password, *user_password_wrong_wks, *user_password_wrong_time; 1527 const char *old_user_password; 1528 char *test_machine_account; 1529 const char *userdomain; 1530 struct samr_SetUserInfo s; 1531 union samr_UserInfo u; 1532 int i; 1533 int ci; 1534 1535 unsigned int credential_flags[] = { 1536 NETLOGON_NEG_AUTH2_FLAGS, 1537 NETLOGON_NEG_ARCFOUR, 1538 NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT, 1539 NETLOGON_NEG_AUTH2_ADS_FLAGS, 1540 0 /* yes, this is a valid flag, causes the use of DES */ 1541 }; 1542 1543 struct netlogon_creds_CredentialState *creds; 1544 1545 test_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME); 1546 /* We only need to join as a workstation here, and in future, 1547 * if we wish to test against trusted domains, we must be a 1548 * workstation here */ 1549 join_ctx = torture_join_domain(torture, TEST_MACHINE_NAME, ACB_WSTRUST, 1550 &machine_credentials); 1551 if (!join_ctx) { 1552 d_printf("Failed to join as Workstation\n"); 1553 return false; 1554 } 1555 1556 userdomain = torture_setting_string(torture, "userdomain", lp_workgroup(torture->lp_ctx)); 1557 1558 user_ctx = torture_create_testuser(torture, 1559 TEST_USER_NAME, 1560 userdomain, 1561 ACB_NORMAL, 1562 (const char **)&user_password); 1563 if (!user_ctx) { 1564 d_printf("Failed to create a test user\n"); 1565 return false; 1566 } 1567 1568 old_user_password = user_password; 1569 1570 test_ChangePasswordUser3(torture_join_samr_pipe(user_ctx), torture, 1571 TEST_USER_NAME, 16 /* > 14 */, &user_password, 1572 NULL, 0, false); 1573 1574 user_ctx_wrong_wks = torture_create_testuser(torture, 1575 TEST_USER_NAME_WRONG_WKS, 1576 userdomain, 1577 ACB_NORMAL, 1578 (const char **)&user_password_wrong_wks); 1579 if (!user_ctx_wrong_wks) { 1580 d_printf("Failed to create a test user (wrong workstation test)\n"); 1581 return false; 1582 } 1583 1584 ZERO_STRUCT(u); 1585 s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_wks); 1586 s.in.info = &u; 1587 s.in.level = 21; 1588 1589 u.info21.fields_present = SAMR_FIELD_WORKSTATIONS; 1590 u.info21.workstations.string = "not" TEST_MACHINE_NAME; 1591 1592 status = dcerpc_samr_SetUserInfo(torture_join_samr_pipe(user_ctx_wrong_wks), mem_ctx, &s); 1593 if (!NT_STATUS_IS_OK(status)) { 1594 printf("SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status)); 1595 ret = false; 1596 goto failed; 1597 } 1598 1599 user_ctx_wrong_time 1600 = torture_create_testuser(torture, TEST_USER_NAME_WRONG_TIME, 1601 userdomain, 1602 ACB_NORMAL, 1603 (const char **)&user_password_wrong_time); 1604 if (!user_ctx_wrong_time) { 1605 d_printf("Failed to create a test user (wrong workstation test)\n"); 1606 return false; 1607 } 1608 1609 ZERO_STRUCT(u); 1610 s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_time); 1611 s.in.info = &u; 1612 s.in.level = 21; 1613 1614 u.info21.fields_present = SAMR_FIELD_WORKSTATIONS | SAMR_FIELD_LOGON_HOURS; 1615 u.info21.workstations.string = TEST_MACHINE_NAME; 1616 u.info21.logon_hours.units_per_week = 168; 1617 u.info21.logon_hours.bits = talloc_zero_array(mem_ctx, uint8_t, 168); 1618 1619 status = dcerpc_samr_SetUserInfo(torture_join_samr_pipe(user_ctx_wrong_time), mem_ctx, &s); 1620 if (!NT_STATUS_IS_OK(status)) { 1621 printf("SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status)); 1622 ret = false; 1623 goto failed; 1624 } 1625 1626 status = torture_rpc_binding(torture, &b); 1627 if (!NT_STATUS_IS_OK(status)) { 1628 ret = false; 1629 goto failed; 1630 } 1631 1632 /* We have to use schannel, otherwise the SamLogonEx fails 1633 * with INTERNAL_ERROR */ 1634 1635 b->flags &= ~DCERPC_AUTH_OPTIONS; 1636 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128; 1637 1638 status = dcerpc_pipe_connect_b(mem_ctx, &p, b, 1639 &ndr_table_netlogon, 1640 machine_credentials, torture->ev, torture->lp_ctx); 1641 1642 if (!NT_STATUS_IS_OK(status)) { 1643 d_printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status)); 1644 ret = false; 1645 goto failed; 1646 } 1647 1648 status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds); 1649 if (!NT_STATUS_IS_OK(status)) { 1650 ret = false; 1651 goto failed; 1652 } 1653 1654 { 1655 1656 struct { 1657 const char *comment; 1658 const char *domain; 1659 const char *username; 1660 const char *password; 1661 bool network_login; 1662 NTSTATUS expected_interactive_error; 1663 NTSTATUS expected_network_error; 1664 uint32_t parameter_control; 1665 bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */ 1666 } usercreds[] = { 1667 { 1668 .comment = "domain\\user", 1669 .domain = cli_credentials_get_domain(cmdline_credentials), 1670 .username = cli_credentials_get_username(cmdline_credentials), 1671 .password = cli_credentials_get_password(cmdline_credentials), 1672 .network_login = true, 1673 .expected_interactive_error = NT_STATUS_OK, 1674 .expected_network_error = NT_STATUS_OK 1675 }, 1676 { 1677 .comment = "realm\\user", 1678 .domain = cli_credentials_get_realm(cmdline_credentials), 1679 .username = cli_credentials_get_username(cmdline_credentials), 1680 .password = cli_credentials_get_password(cmdline_credentials), 1681 .network_login = true, 1682 .expected_interactive_error = NT_STATUS_OK, 1683 .expected_network_error = NT_STATUS_OK 1684 }, 1685 { 1686 .comment = "user@domain", 1687 .domain = NULL, 1688 .username = talloc_asprintf(mem_ctx, 1689 "%s@%s", 1690 cli_credentials_get_username(cmdline_credentials), 1691 cli_credentials_get_domain(cmdline_credentials) 1692 ), 1693 .password = cli_credentials_get_password(cmdline_credentials), 1694 .network_login = false, /* works for some things, but not NTLMv2. Odd */ 1695 .expected_interactive_error = NT_STATUS_OK, 1696 .expected_network_error = NT_STATUS_OK 1697 }, 1698 { 1699 .comment = "user@realm", 1700 .domain = NULL, 1701 .username = talloc_asprintf(mem_ctx, 1702 "%s@%s", 1703 cli_credentials_get_username(cmdline_credentials), 1704 cli_credentials_get_realm(cmdline_credentials) 1705 ), 1706 .password = cli_credentials_get_password(cmdline_credentials), 1707 .network_login = true, 1708 .expected_interactive_error = NT_STATUS_OK, 1709 .expected_network_error = NT_STATUS_OK 1710 }, 1711 { 1712 .comment = "machine domain\\user", 1713 .domain = cli_credentials_get_domain(machine_credentials), 1714 .username = cli_credentials_get_username(machine_credentials), 1715 .password = cli_credentials_get_password(machine_credentials), 1716 .network_login = true, 1717 .expected_interactive_error = NT_STATUS_NO_SUCH_USER, 1718 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT 1719 }, 1720 { 1721 .comment = "machine domain\\user", 1722 .domain = cli_credentials_get_domain(machine_credentials), 1723 .username = cli_credentials_get_username(machine_credentials), 1724 .password = cli_credentials_get_password(machine_credentials), 1725 .network_login = true, 1726 .expected_interactive_error = NT_STATUS_NO_SUCH_USER, 1727 .expected_network_error = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 1728 }, 1729 { 1730 .comment = "machine realm\\user", 1731 .domain = cli_credentials_get_realm(machine_credentials), 1732 .username = cli_credentials_get_username(machine_credentials), 1733 .password = cli_credentials_get_password(machine_credentials), 1734 .network_login = true, 1735 .expected_interactive_error = NT_STATUS_NO_SUCH_USER, 1736 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT 1737 }, 1738 { 1739 .comment = "machine user@domain", 1740 .domain = NULL, 1741 .username = talloc_asprintf(mem_ctx, 1742 "%s@%s", 1743 cli_credentials_get_username(machine_credentials), 1744 cli_credentials_get_domain(machine_credentials) 1745 ), 1746 .password = cli_credentials_get_password(machine_credentials), 1747 .network_login = false, /* works for some things, but not NTLMv2. Odd */ 1748 .expected_interactive_error = NT_STATUS_NO_SUCH_USER, 1749 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT 1750 }, 1751 { 1752 .comment = "machine user@realm", 1753 .domain = NULL, 1754 .username = talloc_asprintf(mem_ctx, 1755 "%s@%s", 1756 cli_credentials_get_username(machine_credentials), 1757 cli_credentials_get_realm(machine_credentials) 1758 ), 1759 .password = cli_credentials_get_password(machine_credentials), 1760 .network_login = true, 1761 .expected_interactive_error = NT_STATUS_NO_SUCH_USER, 1762 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT 1763 }, 1764 { 1765 .comment = "test user (long pw): domain\\user", 1766 .domain = userdomain, 1767 .username = TEST_USER_NAME, 1768 .password = user_password, 1769 .network_login = true, 1770 .expected_interactive_error = NT_STATUS_OK, 1771 .expected_network_error = NT_STATUS_OK 1772 }, 1773 { 1774 .comment = "test user (long pw): user@realm", 1775 .domain = NULL, 1776 .username = talloc_asprintf(mem_ctx, 1777 "%s@%s", 1778 TEST_USER_NAME, 1779 lp_realm(torture->lp_ctx)), 1780 .password = user_password, 1781 .network_login = true, 1782 .expected_interactive_error = NT_STATUS_OK, 1783 .expected_network_error = NT_STATUS_OK 1784 }, 1785 { 1786 .comment = "test user (long pw): user@domain", 1787 .domain = NULL, 1788 .username = talloc_asprintf(mem_ctx, 1789 "%s@%s", 1790 TEST_USER_NAME, 1791 userdomain), 1792 .password = user_password, 1793 .network_login = false, /* works for some things, but not NTLMv2. Odd */ 1794 .expected_interactive_error = NT_STATUS_OK, 1795 .expected_network_error = NT_STATUS_OK 1796 }, 1797 /* Oddball, can we use the old password ? */ 1798 { 1799 .comment = "test user: user\\domain OLD PASSWORD", 1800 .domain = userdomain, 1801 .username = TEST_USER_NAME, 1802 .password = old_user_password, 1803 .network_login = true, 1804 .expected_interactive_error = NT_STATUS_WRONG_PASSWORD, 1805 .expected_network_error = NT_STATUS_OK, 1806 .old_password = true 1807 }, 1808 { 1809 .comment = "test user (wong workstation): domain\\user", 1810 .domain = userdomain, 1811 .username = TEST_USER_NAME_WRONG_WKS, 1812 .password = user_password_wrong_wks, 1813 .network_login = true, 1814 .expected_interactive_error = NT_STATUS_INVALID_WORKSTATION, 1815 .expected_network_error = NT_STATUS_INVALID_WORKSTATION 1816 } 1817 }; 1818 1819 /* Try all the tests for different username forms */ 1820 for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) { 1821 1822 if (!test_InteractiveLogon(p, mem_ctx, creds, 1823 usercreds[ci].comment, 1824 TEST_MACHINE_NAME, 1825 usercreds[ci].domain, 1826 usercreds[ci].username, 1827 usercreds[ci].password, 1828 usercreds[ci].parameter_control, 1829 usercreds[ci].expected_interactive_error)) { 1830 ret = false; 1831 } 1832 1833 if (usercreds[ci].network_login) { 1834 if (!test_SamLogon(p, mem_ctx, torture, creds, 1835 usercreds[ci].comment, 1836 usercreds[ci].domain, 1837 usercreds[ci].username, 1838 usercreds[ci].password, 1839 usercreds[ci].parameter_control, 1840 usercreds[ci].expected_network_error, 1841 usercreds[ci].old_password, 1842 0)) { 1843 ret = false; 1844 } 1845 } 1846 } 1847 1848 /* Using the first username form, try the different 1849 * credentials flag setups, on only one of the tests (checks 1850 * session key encryption) */ 1851 1852 for (i=0; i < ARRAY_SIZE(credential_flags); i++) { 1853 /* TODO: Somehow we lost setting up the different credential flags here! */ 1854 1855 if (!test_InteractiveLogon(p, mem_ctx, creds, 1856 usercreds[0].comment, 1857 TEST_MACHINE_NAME, 1858 usercreds[0].domain, 1859 usercreds[0].username, 1860 usercreds[0].password, 1861 usercreds[0].parameter_control, 1862 usercreds[0].expected_interactive_error)) { 1863 ret = false; 1864 } 1865 1866 if (usercreds[0].network_login) { 1867 if (!test_SamLogon(p, mem_ctx, torture, creds, 1868 usercreds[0].comment, 1869 usercreds[0].domain, 1870 usercreds[0].username, 1871 usercreds[0].password, 1872 usercreds[0].parameter_control, 1873 usercreds[0].expected_network_error, 1874 usercreds[0].old_password, 1875 1)) { 1876 ret = false; 1877 } 1878 } 1879 } 1880 1881 } 1882failed: 1883 talloc_free(mem_ctx); 1884 1885 torture_leave_domain(torture, join_ctx); 1886 torture_leave_domain(torture, user_ctx); 1887 torture_leave_domain(torture, user_ctx_wrong_wks); 1888 torture_leave_domain(torture, user_ctx_wrong_time); 1889 return ret; 1890} 1891