1/* 2 Unix SMB/CIFS implementation. 3 Password and authentication handling 4 Copyright (C) Andrew Tridgell 1992-2000 5 Copyright (C) Luke Kenneth Casson Leighton 1996-2000 6 Copyright (C) Andrew Bartlett 2001-2003 7 Copyright (C) Gerald Carter 2003 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22*/ 23 24#include "includes.h" 25 26#undef DBGC_CLASS 27#define DBGC_CLASS DBGC_AUTH 28 29/**************************************************************************** 30 Core of smb password checking routine. 31****************************************************************************/ 32 33static BOOL smb_pwd_check_ntlmv1(const DATA_BLOB *nt_response, 34 const uchar *part_passwd, 35 const DATA_BLOB *sec_blob, 36 DATA_BLOB *user_sess_key) 37{ 38 /* Finish the encryption of part_passwd. */ 39 uchar p24[24]; 40 41 if (part_passwd == NULL) { 42 DEBUG(10,("No password set - DISALLOWING access\n")); 43 /* No password set - always false ! */ 44 return False; 45 } 46 47 if (sec_blob->length != 8) { 48 DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challenge size (%lu)\n", 49 (unsigned long)sec_blob->length)); 50 return False; 51 } 52 53 if (nt_response->length != 24) { 54 DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%lu)\n", 55 (unsigned long)nt_response->length)); 56 return False; 57 } 58 59 SMBOWFencrypt(part_passwd, sec_blob->data, p24); 60 if (user_sess_key != NULL) { 61 *user_sess_key = data_blob(NULL, 16); 62 SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key->data); 63 } 64 65 66#ifdef DEBUG_PASSWORD 67 DEBUG(100,("Part password (P16) was |\n")); 68 dump_data(100, (const char *)part_passwd, 16); 69 DEBUGADD(100,("Password from client was |\n")); 70 dump_data(100, (const char *)nt_response->data, nt_response->length); 71 DEBUGADD(100,("Given challenge was |\n")); 72 dump_data(100, (const char *)sec_blob->data, sec_blob->length); 73 DEBUGADD(100,("Value from encryption was |\n")); 74 dump_data(100, (const char *)p24, 24); 75#endif 76 return (memcmp(p24, nt_response->data, 24) == 0); 77} 78 79/**************************************************************************** 80 Core of smb password checking routine. (NTLMv2, LMv2) 81 Note: The same code works with both NTLMv2 and LMv2. 82****************************************************************************/ 83 84static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response, 85 const uchar *part_passwd, 86 const DATA_BLOB *sec_blob, 87 const char *user, const char *domain, 88 BOOL upper_case_domain, /* should the domain be transformed into upper case? */ 89 DATA_BLOB *user_sess_key) 90{ 91 /* Finish the encryption of part_passwd. */ 92 uchar kr[16]; 93 uchar value_from_encryption[16]; 94 uchar client_response[16]; 95 DATA_BLOB client_key_data; 96 BOOL res; 97 98 if (part_passwd == NULL) { 99 DEBUG(10,("No password set - DISALLOWING access\n")); 100 /* No password set - always False */ 101 return False; 102 } 103 104 if (sec_blob->length != 8) { 105 DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect challenge size (%lu)\n", 106 (unsigned long)sec_blob->length)); 107 return False; 108 } 109 110 if (ntv2_response->length < 24) { 111 /* We MUST have more than 16 bytes, or the stuff below will go 112 crazy. No known implementation sends less than the 24 bytes 113 for LMv2, let alone NTLMv2. */ 114 DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%lu)\n", 115 (unsigned long)ntv2_response->length)); 116 return False; 117 } 118 119 client_key_data = data_blob(ntv2_response->data+16, ntv2_response->length-16); 120 /* 121 todo: should we be checking this for anything? We can't for LMv2, 122 but for NTLMv2 it is meant to contain the current time etc. 123 */ 124 125 memcpy(client_response, ntv2_response->data, sizeof(client_response)); 126 127 if (!ntv2_owf_gen(part_passwd, user, domain, upper_case_domain, kr)) { 128 return False; 129 } 130 131 SMBOWFencrypt_ntv2(kr, sec_blob, &client_key_data, value_from_encryption); 132 if (user_sess_key != NULL) { 133 *user_sess_key = data_blob(NULL, 16); 134 SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key->data); 135 } 136 137#if DEBUG_PASSWORD 138 DEBUG(100,("Part password (P16) was |\n")); 139 dump_data(100, (const char *)part_passwd, 16); 140 DEBUGADD(100,("Password from client was |\n")); 141 dump_data(100, (const char *)ntv2_response->data, ntv2_response->length); 142 DEBUGADD(100,("Variable data from client was |\n")); 143 dump_data(100, (const char *)client_key_data.data, client_key_data.length); 144 DEBUGADD(100,("Given challenge was |\n")); 145 dump_data(100, (const char *)sec_blob->data, sec_blob->length); 146 DEBUGADD(100,("Value from encryption was |\n")); 147 dump_data(100, (const char *)value_from_encryption, 16); 148#endif 149 data_blob_clear_free(&client_key_data); 150 res = (memcmp(value_from_encryption, client_response, 16) == 0); 151 if ((!res) && (user_sess_key != NULL)) 152 data_blob_clear_free(user_sess_key); 153 return res; 154} 155 156/** 157 * Check a challenge-response password against the value of the NT or 158 * LM password hash. 159 * 160 * @param mem_ctx talloc context 161 * @param challenge 8-byte challenge. If all zero, forces plaintext comparison 162 * @param nt_response 'unicode' NT response to the challenge, or unicode password 163 * @param lm_response ASCII or LANMAN response to the challenge, or password in DOS code page 164 * @param username internal Samba username, for log messages 165 * @param client_username username the client used 166 * @param client_domain domain name the client used (may be mapped) 167 * @param nt_pw MD4 unicode password from our passdb or similar 168 * @param lm_pw LANMAN ASCII password from our passdb or similar 169 * @param user_sess_key User session key 170 * @param lm_sess_key LM session key (first 8 bytes of the LM hash) 171 */ 172 173NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, 174 const DATA_BLOB *challenge, 175 const DATA_BLOB *lm_response, 176 const DATA_BLOB *nt_response, 177 const DATA_BLOB *lm_interactive_pwd, 178 const DATA_BLOB *nt_interactive_pwd, 179 const char *username, 180 const char *client_username, 181 const char *client_domain, 182 const uint8 *lm_pw, const uint8 *nt_pw, 183 DATA_BLOB *user_sess_key, 184 DATA_BLOB *lm_sess_key) 185{ 186 static const unsigned char zeros[8] = { 0, }; 187 FILE* fp = NULL;//water, If all shared folders are 'All - no password', then no need to login for "HTTP", "FTP" or samba. 188 int no_password = 0; // Foxconn added pling 11/30/2009 */ 189 if (nt_pw == NULL) { 190 DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n", 191 username)); 192 } 193 194 if (nt_interactive_pwd && nt_interactive_pwd->length && nt_pw) { 195 if (nt_interactive_pwd->length != 16) { 196 DEBUG(3,("ntlm_password_check: Interactive logon: Invalid NT password length (%d) supplied for user %s\n", (int)nt_interactive_pwd->length, 197 username)); 198 return NT_STATUS_WRONG_PASSWORD; 199 } 200 201 if (memcmp(nt_interactive_pwd->data, nt_pw, 16) == 0) { 202 if (user_sess_key) { 203 *user_sess_key = data_blob(NULL, 16); 204 SMBsesskeygen_ntv1(nt_pw, NULL, user_sess_key->data); 205 } 206 return NT_STATUS_OK; 207 } else { 208 DEBUG(3,("ntlm_password_check: Interactive logon: NT password check failed for user %s\n", 209 username)); 210 return NT_STATUS_WRONG_PASSWORD; 211 } 212 213 } else if (lm_interactive_pwd && lm_interactive_pwd->length && lm_pw) { 214 if (lm_interactive_pwd->length != 16) { 215 DEBUG(3,("ntlm_password_check: Interactive logon: Invalid LANMAN password length (%d) supplied for user %s\n", (int)lm_interactive_pwd->length, 216 username)); 217 return NT_STATUS_WRONG_PASSWORD; 218 } 219 220 if (!lp_lanman_auth()) { 221 DEBUG(3,("ntlm_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled!\n", 222 username)); 223 return NT_STATUS_WRONG_PASSWORD; 224 } 225 226 if (memcmp(lm_interactive_pwd->data, lm_pw, 16) == 0) { 227 return NT_STATUS_OK; 228 } else { 229 DEBUG(3,("ntlm_password_check: Interactive logon: LANMAN password check failed for user %s\n", 230 username)); 231 return NT_STATUS_WRONG_PASSWORD; 232 } 233 } 234 235 /* Check for cleartext netlogon. Used by Exchange 5.5. */ 236 if (challenge->length == sizeof(zeros) && 237 (memcmp(challenge->data, zeros, challenge->length) == 0 )) { 238 239 DEBUG(4,("ntlm_password_check: checking plaintext passwords for user %s\n", 240 username)); 241 if (nt_pw && nt_response->length) { 242 unsigned char pwhash[16]; 243 mdfour(pwhash, nt_response->data, nt_response->length); 244 if (memcmp(pwhash, nt_pw, sizeof(pwhash)) == 0) { 245 return NT_STATUS_OK; 246 } else { 247 DEBUG(3,("ntlm_password_check: NT (Unicode) plaintext password check failed for user %s\n", 248 username)); 249 return NT_STATUS_WRONG_PASSWORD; 250 } 251 252 } else if (!lp_lanman_auth()) { 253 DEBUG(3,("ntlm_password_check: (plaintext password check) LANMAN passwords NOT PERMITTED for user %s\n", 254 username)); 255 256 } else if (lm_pw && lm_response->length) { 257 uchar dospwd[14]; 258 uchar p16[16]; 259 ZERO_STRUCT(dospwd); 260 261 memcpy(dospwd, lm_response->data, MIN(lm_response->length, sizeof(dospwd))); 262 /* Only the fisrt 14 chars are considered, password need not be null terminated. */ 263 264 /* we *might* need to upper-case the string here */ 265 E_P16((const unsigned char *)dospwd, p16); 266 267 if (memcmp(p16, lm_pw, sizeof(p16)) == 0) { 268 return NT_STATUS_OK; 269 } else { 270 DEBUG(3,("ntlm_password_check: LANMAN (ASCII) plaintext password check failed for user %s\n", 271 username)); 272 return NT_STATUS_WRONG_PASSWORD; 273 } 274 } else { 275 DEBUG(3, ("Plaintext authentication for user %s attempted, but neither NT nor LM passwords available\n", username)); 276 return NT_STATUS_WRONG_PASSWORD; 277 } 278 } 279 280 if (nt_response->length != 0 && nt_response->length < 24) { 281 DEBUG(2,("ntlm_password_check: invalid NT password length (%lu) for user %s\n", 282 (unsigned long)nt_response->length, username)); 283 } 284 285 if (nt_response->length >= 24 && nt_pw) { 286 if (nt_response->length > 24) { 287 /* We have the NT MD4 hash challenge available - see if we can 288 use it 289 */ 290 DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n", client_domain)); 291 if (smb_pwd_check_ntlmv2( nt_response, 292 nt_pw, challenge, 293 client_username, 294 client_domain, 295 False, 296 user_sess_key)) { 297 return NT_STATUS_OK; 298 } 299 300 DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", client_domain)); 301 if (smb_pwd_check_ntlmv2( nt_response, 302 nt_pw, challenge, 303 client_username, 304 client_domain, 305 True, 306 user_sess_key)) { 307 return NT_STATUS_OK; 308 } 309 310 DEBUG(0,("ntlm_password_check: Checking NTLMv2 password without a domain\n")); 311 312 /*foxconn add start, water, 06/08/2009*/ 313 /*If all shared folders are 'All - no password', 314 then no need to login for "HTTP", "FTP" or samba.*/ 315 fp = fopen("/tmp/all_no_password","r"); 316 if (fp != NULL) 317 { 318 fclose(fp); 319 DEBUG(0, ("all_no_password, ntlm_check.c\n")); 320 return NT_STATUS_OK; 321 } 322 /*foxconn add end, water, 06/08/2009*/ 323 324 /*foxconn add start, water, 11/17/2008*/ 325 /*when username=guest, user can access the shared folder with any password*/ 326 if (0 == strcmp("guest", client_username)) 327 { 328 DEBUG(0, ("guest, ntlm_check.c\n")); 329 return NT_STATUS_OK; 330 } 331 //return NT_STATUS_OK; 332 /*foxconn add end, water, 11/17/2008*/ 333 if (smb_pwd_check_ntlmv2( nt_response, 334 nt_pw, challenge, 335 client_username, 336 "", 337 False, 338 user_sess_key)) { 339 return NT_STATUS_OK; 340 } else { 341 DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n")); 342 return NT_STATUS_WRONG_PASSWORD; 343 } 344 } 345 346 if (lp_ntlm_auth()) { 347 /* We have the NT MD4 hash challenge available - see if we can 348 use it (ie. does it exist in the smbpasswd file). 349 */ 350 DEBUG(0,("ntlm_password_check: Checking NT MD4 password\n")); 351 352 /*foxconn add start, water, 06/08/2009*/ 353 /*If all shared folders are 'All - no password', 354 then no need to login for "HTTP", "FTP" or samba.*/ 355 fp = fopen("/tmp/all_no_password","r"); 356 if (fp != NULL) 357 { 358 fclose(fp); 359 DEBUG(0, ("all_no_password, ntlm_check.c\n")); 360 return NT_STATUS_OK; 361 } 362 /*foxconn add end, water, 06/08/2009*/ 363 364 /*foxconn add start, water, 11/17/2008*/ 365 /*when username=guest, user can access the shared folder with any password*/ 366 if (0 == strcmp("guest", username)) 367 { 368 DEBUG(0, ("water, guest, ntlm_check.c\n")); 369 return NT_STATUS_OK; 370 } 371 //return NT_STATUS_OK; 372 /*foxconn add end, water, 11/17/2008*/ 373 if (smb_pwd_check_ntlmv1(nt_response, 374 nt_pw, challenge, 375 user_sess_key)) { 376 /* The LM session key for this response is not very secure, 377 so use it only if we otherwise allow LM authentication */ 378 379 if (lp_lanman_auth() && lm_pw) { 380 uint8 first_8_lm_hash[16]; 381 memcpy(first_8_lm_hash, lm_pw, 8); 382 memset(first_8_lm_hash + 8, '\0', 8); 383 if (lm_sess_key) { 384 *lm_sess_key = data_blob(first_8_lm_hash, 16); 385 } 386 } 387 return NT_STATUS_OK; 388 } else { 389 DEBUG(3,("ntlm_password_check: NT MD4 password check failed for user %s\n", 390 username)); 391 return NT_STATUS_WRONG_PASSWORD; 392 } 393 } else { 394 DEBUG(2,("ntlm_password_check: NTLMv1 passwords NOT PERMITTED for user %s\n", 395 username)); 396 /* no return, becouse we might pick up LMv2 in the LM field */ 397 } 398 } 399 400 /* Foxconn add end pling 11/30/2009 */ 401 /* If all shared folders are 'All - no password', 402 * then no need to login for "HTTP", "FTP" or samba. 403 */ 404 fp = fopen("/tmp/all_no_password","r"); 405 if (fp != NULL) { 406 fclose(fp); 407 no_password = 1; 408 } 409 /* Foxconn add end pling 11/30/2009 */ 410 411 if (lm_response->length == 0) { 412 /* Foxconn added start pling 11/30/2009 */ 413 if (no_password) 414 return NT_STATUS_OK; 415 /* Foxconn added end pling 11/30/2009 */ 416 DEBUG(3,("ntlm_password_check: NEITHER LanMan nor NT password supplied for user %s\n", 417 username)); 418 return NT_STATUS_WRONG_PASSWORD; 419 } 420 421 if (lm_response->length < 24) { 422 /* Foxconn added start pling 11/30/2009 */ 423 if (no_password) 424 return NT_STATUS_OK; 425 /* Foxconn added end pling 11/30/2009 */ 426 DEBUG(2,("ntlm_password_check: invalid LanMan password length (%lu) for user %s\n", 427 (unsigned long)nt_response->length, username)); 428 return NT_STATUS_WRONG_PASSWORD; 429 } 430 431 if (!lp_lanman_auth()) { 432 DEBUG(3,("ntlm_password_check: Lanman passwords NOT PERMITTED for user %s\n", 433 username)); 434 } else if (!lm_pw) { 435 DEBUG(3,("ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied)\n", 436 username)); 437 } else { 438 DEBUG(4,("ntlm_password_check: Checking LM password\n")); 439 if (smb_pwd_check_ntlmv1(lm_response, 440 lm_pw, challenge, 441 NULL)) { 442 uint8 first_8_lm_hash[16]; 443 memcpy(first_8_lm_hash, lm_pw, 8); 444 memset(first_8_lm_hash + 8, '\0', 8); 445 if (user_sess_key) { 446 *user_sess_key = data_blob(first_8_lm_hash, 16); 447 } 448 449 if (lm_sess_key) { 450 *lm_sess_key = data_blob(first_8_lm_hash, 16); 451 } 452 return NT_STATUS_OK; 453 } 454 } 455 456 if (!nt_pw) { 457 DEBUG(4,("ntlm_password_check: LM password check failed for user, no NT password %s\n",username)); 458 return NT_STATUS_WRONG_PASSWORD; 459 } 460 461 /* This is for 'LMv2' authentication. almost NTLMv2 but limited to 24 bytes. 462 - related to Win9X, legacy NAS pass-though authentication 463 */ 464 DEBUG(4,("ntlm_password_check: Checking LMv2 password with domain %s\n", client_domain)); 465 if (smb_pwd_check_ntlmv2( lm_response, 466 nt_pw, challenge, 467 client_username, 468 client_domain, 469 False, 470 NULL)) { 471 return NT_STATUS_OK; 472 } 473 474 DEBUG(4,("ntlm_password_check: Checking LMv2 password with upper-cased version of domain %s\n", client_domain)); 475 if (smb_pwd_check_ntlmv2( lm_response, 476 nt_pw, challenge, 477 client_username, 478 client_domain, 479 True, 480 NULL)) { 481 return NT_STATUS_OK; 482 } 483 484 DEBUG(4,("ntlm_password_check: Checking LMv2 password without a domain\n")); 485 if (smb_pwd_check_ntlmv2( lm_response, 486 nt_pw, challenge, 487 client_username, 488 "", 489 False, 490 NULL)) { 491 return NT_STATUS_OK; 492 } 493 494 /* Apparently NT accepts NT responses in the LM field 495 - I think this is related to Win9X pass-though authentication 496 */ 497 DEBUG(4,("ntlm_password_check: Checking NT MD4 password in LM field\n")); 498 if (lp_ntlm_auth()) { 499 if (smb_pwd_check_ntlmv1(lm_response, 500 nt_pw, challenge, 501 NULL)) { 502 /* The session key for this response is still very odd. 503 It not very secure, so use it only if we otherwise 504 allow LM authentication */ 505 506 if (lp_lanman_auth() && lm_pw) { 507 uint8 first_8_lm_hash[16]; 508 memcpy(first_8_lm_hash, lm_pw, 8); 509 memset(first_8_lm_hash + 8, '\0', 8); 510 if (user_sess_key) { 511 *user_sess_key = data_blob(first_8_lm_hash, 16); 512 } 513 514 if (lm_sess_key) { 515 *lm_sess_key = data_blob(first_8_lm_hash, 16); 516 } 517 } 518 return NT_STATUS_OK; 519 } 520 DEBUG(3,("ntlm_password_check: LM password, NT MD4 password in LM field and LMv2 failed for user %s\n",username)); 521 } else { 522 DEBUG(3,("ntlm_password_check: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted\n",username)); 523 } 524 return NT_STATUS_WRONG_PASSWORD; 525} 526 527