00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "includes.h"
00026 #include "utils/ntlm_auth.h"
00027
00028 #undef DBGC_CLASS
00029 #define DBGC_CLASS DBGC_WINBIND
00030
00031 enum ntlm_break {
00032 BREAK_NONE,
00033 BREAK_LM,
00034 BREAK_NT,
00035 NO_LM,
00036 NO_NT
00037 };
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 static BOOL test_lm_ntlm_broken(enum ntlm_break break_which)
00049 {
00050 BOOL pass = True;
00051 NTSTATUS nt_status;
00052 uint32 flags = 0;
00053 DATA_BLOB lm_response = data_blob(NULL, 24);
00054 DATA_BLOB nt_response = data_blob(NULL, 24);
00055 DATA_BLOB session_key = data_blob(NULL, 16);
00056
00057 uchar lm_key[8];
00058 uchar user_session_key[16];
00059 uchar lm_hash[16];
00060 uchar nt_hash[16];
00061 DATA_BLOB chall = get_challenge();
00062 char *error_string;
00063
00064 ZERO_STRUCT(lm_key);
00065 ZERO_STRUCT(user_session_key);
00066
00067 flags |= WBFLAG_PAM_LMKEY;
00068 flags |= WBFLAG_PAM_USER_SESSION_KEY;
00069
00070 SMBencrypt(opt_password,chall.data,lm_response.data);
00071 E_deshash(opt_password, lm_hash);
00072
00073 SMBNTencrypt(opt_password,chall.data,nt_response.data);
00074
00075 E_md4hash(opt_password, nt_hash);
00076 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
00077
00078 switch (break_which) {
00079 case BREAK_NONE:
00080 break;
00081 case BREAK_LM:
00082 lm_response.data[0]++;
00083 break;
00084 case BREAK_NT:
00085 nt_response.data[0]++;
00086 break;
00087 case NO_LM:
00088 data_blob_free(&lm_response);
00089 break;
00090 case NO_NT:
00091 data_blob_free(&nt_response);
00092 break;
00093 }
00094
00095 nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
00096 opt_workstation,
00097 &chall,
00098 &lm_response,
00099 &nt_response,
00100 flags,
00101 lm_key,
00102 user_session_key,
00103 &error_string, NULL);
00104
00105 data_blob_free(&lm_response);
00106
00107 if (!NT_STATUS_IS_OK(nt_status)) {
00108 d_printf("%s (0x%x)\n",
00109 error_string,
00110 NT_STATUS_V(nt_status));
00111 SAFE_FREE(error_string);
00112 return break_which == BREAK_NT;
00113 }
00114
00115 if (memcmp(lm_hash, lm_key,
00116 sizeof(lm_key)) != 0) {
00117 DEBUG(1, ("LM Key does not match expectations!\n"));
00118 DEBUG(1, ("lm_key:\n"));
00119 dump_data(1, (const char *)lm_key, 8);
00120 DEBUG(1, ("expected:\n"));
00121 dump_data(1, (const char *)lm_hash, 8);
00122 pass = False;
00123 }
00124
00125 if (break_which == NO_NT) {
00126 if (memcmp(lm_hash, user_session_key,
00127 8) != 0) {
00128 DEBUG(1, ("NT Session Key does not match expectations (should be LM hash)!\n"));
00129 DEBUG(1, ("user_session_key:\n"));
00130 dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
00131 DEBUG(1, ("expected:\n"));
00132 dump_data(1, (const char *)lm_hash, sizeof(lm_hash));
00133 pass = False;
00134 }
00135 } else {
00136 if (memcmp(session_key.data, user_session_key,
00137 sizeof(user_session_key)) != 0) {
00138 DEBUG(1, ("NT Session Key does not match expectations!\n"));
00139 DEBUG(1, ("user_session_key:\n"));
00140 dump_data(1, (const char *)user_session_key, 16);
00141 DEBUG(1, ("expected:\n"));
00142 dump_data(1, (const char *)session_key.data, session_key.length);
00143 pass = False;
00144 }
00145 }
00146 return pass;
00147 }
00148
00149
00150
00151
00152
00153 static BOOL test_lm(void)
00154 {
00155
00156 return test_lm_ntlm_broken(NO_NT);
00157 }
00158
00159
00160
00161
00162
00163 static BOOL test_ntlm(void)
00164 {
00165 return test_lm_ntlm_broken(NO_LM);
00166 }
00167
00168
00169
00170
00171
00172 static BOOL test_ntlm_in_lm(void)
00173 {
00174 BOOL pass = True;
00175 NTSTATUS nt_status;
00176 uint32 flags = 0;
00177 DATA_BLOB nt_response = data_blob(NULL, 24);
00178
00179 uchar lm_key[8];
00180 uchar lm_hash[16];
00181 uchar user_session_key[16];
00182 DATA_BLOB chall = get_challenge();
00183 char *error_string;
00184
00185 ZERO_STRUCT(user_session_key);
00186
00187 flags |= WBFLAG_PAM_LMKEY;
00188 flags |= WBFLAG_PAM_USER_SESSION_KEY;
00189
00190 SMBNTencrypt(opt_password,chall.data,nt_response.data);
00191
00192 E_deshash(opt_password, lm_hash);
00193
00194 nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
00195 opt_workstation,
00196 &chall,
00197 &nt_response,
00198 NULL,
00199 flags,
00200 lm_key,
00201 user_session_key,
00202 &error_string, NULL);
00203
00204 data_blob_free(&nt_response);
00205
00206 if (!NT_STATUS_IS_OK(nt_status)) {
00207 d_printf("%s (0x%x)\n",
00208 error_string,
00209 NT_STATUS_V(nt_status));
00210 SAFE_FREE(error_string);
00211 return False;
00212 }
00213
00214 if (memcmp(lm_hash, lm_key,
00215 sizeof(lm_key)) != 0) {
00216 DEBUG(1, ("LM Key does not match expectations!\n"));
00217 DEBUG(1, ("lm_key:\n"));
00218 dump_data(1, (const char *)lm_key, 8);
00219 DEBUG(1, ("expected:\n"));
00220 dump_data(1, (const char *)lm_hash, 8);
00221 pass = False;
00222 }
00223 if (memcmp(lm_hash, user_session_key, 8) != 0) {
00224 DEBUG(1, ("Session Key (first 8 lm hash) does not match expectations!\n"));
00225 DEBUG(1, ("user_session_key:\n"));
00226 dump_data(1, (const char *)user_session_key, 16);
00227 DEBUG(1, ("expected:\n"));
00228 dump_data(1, (const char *)lm_hash, 8);
00229 pass = False;
00230 }
00231 return pass;
00232 }
00233
00234
00235
00236
00237
00238 static BOOL test_ntlm_in_both(void)
00239 {
00240 BOOL pass = True;
00241 NTSTATUS nt_status;
00242 uint32 flags = 0;
00243 DATA_BLOB nt_response = data_blob(NULL, 24);
00244 DATA_BLOB session_key = data_blob(NULL, 16);
00245
00246 char lm_key[8];
00247 char lm_hash[16];
00248 char user_session_key[16];
00249 char nt_hash[16];
00250 DATA_BLOB chall = get_challenge();
00251 char *error_string;
00252
00253 ZERO_STRUCT(lm_key);
00254 ZERO_STRUCT(user_session_key);
00255
00256 flags |= WBFLAG_PAM_LMKEY;
00257 flags |= WBFLAG_PAM_USER_SESSION_KEY;
00258
00259 SMBNTencrypt(opt_password,chall.data,nt_response.data);
00260 E_md4hash(opt_password, (unsigned char *)nt_hash);
00261 SMBsesskeygen_ntv1((const unsigned char *)nt_hash, NULL, session_key.data);
00262
00263 E_deshash(opt_password, (unsigned char *)lm_hash);
00264
00265 nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
00266 opt_workstation,
00267 &chall,
00268 &nt_response,
00269 &nt_response,
00270 flags,
00271 (unsigned char *)lm_key,
00272 (unsigned char *)user_session_key,
00273 &error_string, NULL);
00274
00275 data_blob_free(&nt_response);
00276
00277 if (!NT_STATUS_IS_OK(nt_status)) {
00278 d_printf("%s (0x%x)\n",
00279 error_string,
00280 NT_STATUS_V(nt_status));
00281 SAFE_FREE(error_string);
00282 return False;
00283 }
00284
00285 if (memcmp(lm_hash, lm_key,
00286 sizeof(lm_key)) != 0) {
00287 DEBUG(1, ("LM Key does not match expectations!\n"));
00288 DEBUG(1, ("lm_key:\n"));
00289 dump_data(1, lm_key, 8);
00290 DEBUG(1, ("expected:\n"));
00291 dump_data(1, lm_hash, 8);
00292 pass = False;
00293 }
00294 if (memcmp(session_key.data, user_session_key,
00295 sizeof(user_session_key)) != 0) {
00296 DEBUG(1, ("NT Session Key does not match expectations!\n"));
00297 DEBUG(1, ("user_session_key:\n"));
00298 dump_data(1, user_session_key, 16);
00299 DEBUG(1, ("expected:\n"));
00300 dump_data(1, (const char *)session_key.data, session_key.length);
00301 pass = False;
00302 }
00303
00304
00305 return pass;
00306 }
00307
00308
00309
00310
00311
00312 static BOOL test_lmv2_ntlmv2_broken(enum ntlm_break break_which)
00313 {
00314 BOOL pass = True;
00315 NTSTATUS nt_status;
00316 uint32 flags = 0;
00317 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
00318 DATA_BLOB lmv2_response = data_blob(NULL, 0);
00319 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
00320 DATA_BLOB names_blob = NTLMv2_generate_names_blob(get_winbind_netbios_name(), get_winbind_domain());
00321
00322 uchar user_session_key[16];
00323 DATA_BLOB chall = get_challenge();
00324 char *error_string;
00325
00326 ZERO_STRUCT(user_session_key);
00327
00328 flags |= WBFLAG_PAM_USER_SESSION_KEY;
00329
00330 if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall,
00331 &names_blob,
00332 &lmv2_response, &ntlmv2_response,
00333 &ntlmv2_session_key)) {
00334 data_blob_free(&names_blob);
00335 return False;
00336 }
00337 data_blob_free(&names_blob);
00338
00339 switch (break_which) {
00340 case BREAK_NONE:
00341 break;
00342 case BREAK_LM:
00343 lmv2_response.data[0]++;
00344 break;
00345 case BREAK_NT:
00346 ntlmv2_response.data[0]++;
00347 break;
00348 case NO_LM:
00349 data_blob_free(&lmv2_response);
00350 break;
00351 case NO_NT:
00352 data_blob_free(&ntlmv2_response);
00353 break;
00354 }
00355
00356 nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
00357 opt_workstation,
00358 &chall,
00359 &lmv2_response,
00360 &ntlmv2_response,
00361 flags,
00362 NULL,
00363 user_session_key,
00364 &error_string, NULL);
00365
00366 data_blob_free(&lmv2_response);
00367 data_blob_free(&ntlmv2_response);
00368
00369 if (!NT_STATUS_IS_OK(nt_status)) {
00370 d_printf("%s (0x%x)\n",
00371 error_string,
00372 NT_STATUS_V(nt_status));
00373 SAFE_FREE(error_string);
00374 return break_which == BREAK_NT;
00375 }
00376
00377 if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key,
00378 sizeof(user_session_key)) != 0) {
00379 DEBUG(1, ("USER (NTLMv2) Session Key does not match expectations!\n"));
00380 DEBUG(1, ("user_session_key:\n"));
00381 dump_data(1, (const char *)user_session_key, 16);
00382 DEBUG(1, ("expected:\n"));
00383 dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length);
00384 pass = False;
00385 }
00386 return pass;
00387 }
00388
00389
00390
00391
00392
00393 static BOOL test_lmv2_ntlmv2(void)
00394 {
00395 return test_lmv2_ntlmv2_broken(BREAK_NONE);
00396 }
00397
00398
00399
00400
00401
00402 static BOOL test_lmv2(void)
00403 {
00404 return test_lmv2_ntlmv2_broken(NO_NT);
00405 }
00406
00407
00408
00409
00410
00411 static BOOL test_ntlmv2(void)
00412 {
00413 return test_lmv2_ntlmv2_broken(NO_LM);
00414 }
00415
00416 static BOOL test_lm_ntlm(void)
00417 {
00418 return test_lm_ntlm_broken(BREAK_NONE);
00419 }
00420
00421 static BOOL test_ntlm_lm_broken(void)
00422 {
00423 return test_lm_ntlm_broken(BREAK_LM);
00424 }
00425
00426 static BOOL test_ntlm_ntlm_broken(void)
00427 {
00428 return test_lm_ntlm_broken(BREAK_NT);
00429 }
00430
00431 static BOOL test_ntlmv2_lmv2_broken(void)
00432 {
00433 return test_lmv2_ntlmv2_broken(BREAK_LM);
00434 }
00435
00436 static BOOL test_ntlmv2_ntlmv2_broken(void)
00437 {
00438 return test_lmv2_ntlmv2_broken(BREAK_NT);
00439 }
00440
00441 static BOOL test_plaintext(enum ntlm_break break_which)
00442 {
00443 NTSTATUS nt_status;
00444 uint32 flags = 0;
00445 DATA_BLOB nt_response = data_blob(NULL, 0);
00446 DATA_BLOB lm_response = data_blob(NULL, 0);
00447 char *password;
00448 smb_ucs2_t *nt_response_ucs2;
00449
00450 uchar user_session_key[16];
00451 uchar lm_key[16];
00452 static const uchar zeros[8] = { 0, };
00453 DATA_BLOB chall = data_blob(zeros, sizeof(zeros));
00454 char *error_string;
00455
00456 ZERO_STRUCT(user_session_key);
00457
00458 flags |= WBFLAG_PAM_LMKEY;
00459 flags |= WBFLAG_PAM_USER_SESSION_KEY;
00460
00461 if ((push_ucs2_allocate(&nt_response_ucs2, opt_password)) == -1) {
00462 DEBUG(0, ("push_ucs2_allocate failed!\n"));
00463 exit(1);
00464 }
00465
00466 nt_response.data = (unsigned char *)nt_response_ucs2;
00467 nt_response.length = strlen_w(nt_response_ucs2)*sizeof(smb_ucs2_t);
00468
00469 if ((password = strdup_upper(opt_password)) == NULL) {
00470 DEBUG(0, ("strdup_upper failed!\n"));
00471 exit(1);
00472 }
00473
00474 if ((convert_string_allocate(NULL, CH_UNIX,
00475 CH_DOS, password,
00476 strlen(password)+1,
00477 &lm_response.data,True)) == -1) {
00478 DEBUG(0, ("convert_string_allocate failed!\n"));
00479 exit(1);
00480 }
00481
00482 SAFE_FREE(password);
00483
00484 lm_response.length = strlen((const char *)lm_response.data);
00485
00486 switch (break_which) {
00487 case BREAK_NONE:
00488 break;
00489 case BREAK_LM:
00490 lm_response.data[0]++;
00491 break;
00492 case BREAK_NT:
00493 nt_response.data[0]++;
00494 break;
00495 case NO_LM:
00496 SAFE_FREE(lm_response.data);
00497 lm_response.length = 0;
00498 break;
00499 case NO_NT:
00500 SAFE_FREE(nt_response.data);
00501 nt_response.length = 0;
00502 break;
00503 }
00504
00505 nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
00506 opt_workstation,
00507 &chall,
00508 &lm_response,
00509 &nt_response,
00510 flags,
00511 lm_key,
00512 user_session_key,
00513 &error_string, NULL);
00514
00515 SAFE_FREE(nt_response.data);
00516 SAFE_FREE(lm_response.data);
00517 data_blob_free(&chall);
00518
00519 if (!NT_STATUS_IS_OK(nt_status)) {
00520 d_printf("%s (0x%x)\n",
00521 error_string,
00522 NT_STATUS_V(nt_status));
00523 SAFE_FREE(error_string);
00524 return break_which == BREAK_NT;
00525 }
00526
00527 return break_which != BREAK_NT;
00528 }
00529
00530 static BOOL test_plaintext_none_broken(void) {
00531 return test_plaintext(BREAK_NONE);
00532 }
00533
00534 static BOOL test_plaintext_lm_broken(void) {
00535 return test_plaintext(BREAK_LM);
00536 }
00537
00538 static BOOL test_plaintext_nt_broken(void) {
00539 return test_plaintext(BREAK_NT);
00540 }
00541
00542 static BOOL test_plaintext_nt_only(void) {
00543 return test_plaintext(NO_LM);
00544 }
00545
00546 static BOOL test_plaintext_lm_only(void) {
00547 return test_plaintext(NO_NT);
00548 }
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 static const struct ntlm_tests {
00569 BOOL (*fn)(void);
00570 const char *name;
00571 } test_table[] = {
00572 {test_lm, "LM"},
00573 {test_lm_ntlm, "LM and NTLM"},
00574 {test_ntlm, "NTLM"},
00575 {test_ntlm_in_lm, "NTLM in LM"},
00576 {test_ntlm_in_both, "NTLM in both"},
00577 {test_ntlmv2, "NTLMv2"},
00578 {test_lmv2_ntlmv2, "NTLMv2 and LMv2"},
00579 {test_lmv2, "LMv2"},
00580 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken"},
00581 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken"},
00582 {test_ntlm_lm_broken, "NTLM and LM, LM broken"},
00583 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken"},
00584 {test_plaintext_none_broken, "Plaintext"},
00585 {test_plaintext_lm_broken, "Plaintext LM broken"},
00586 {test_plaintext_nt_broken, "Plaintext NT broken"},
00587 {test_plaintext_nt_only, "Plaintext NT only"},
00588 {test_plaintext_lm_only, "Plaintext LM only"},
00589 {NULL, NULL}
00590 };
00591
00592 BOOL diagnose_ntlm_auth(void)
00593 {
00594 unsigned int i;
00595 BOOL pass = True;
00596
00597 for (i=0; test_table[i].fn; i++) {
00598 if (!test_table[i].fn()) {
00599 DEBUG(1, ("Test %s failed!\n", test_table[i].name));
00600 pass = False;
00601 }
00602 }
00603
00604 return pass;
00605 }
00606