関数 | |
static BOOL | smb_pwd_check_ntlmv1 (const DATA_BLOB *nt_response, const uchar *part_passwd, const DATA_BLOB *sec_blob, DATA_BLOB *user_sess_key) |
static BOOL | smb_pwd_check_ntlmv2 (const DATA_BLOB *ntv2_response, const uchar *part_passwd, const DATA_BLOB *sec_blob, const char *user, const char *domain, BOOL upper_case_domain, DATA_BLOB *user_sess_key) |
NTSTATUS | ntlm_password_check (TALLOC_CTX *mem_ctx, const DATA_BLOB *challenge, const DATA_BLOB *lm_response, const DATA_BLOB *nt_response, const DATA_BLOB *lm_interactive_pwd, const DATA_BLOB *nt_interactive_pwd, const char *username, const char *client_username, const char *client_domain, const uint8 *lm_pw, const uint8 *nt_pw, DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) |
Check a challenge-response password against the value of the NT or LM password hash. |
static BOOL smb_pwd_check_ntlmv1 | ( | const DATA_BLOB * | nt_response, | |
const uchar * | part_passwd, | |||
const DATA_BLOB * | sec_blob, | |||
DATA_BLOB * | user_sess_key | |||
) | [static] |
ntlm_check.c の 33 行で定義されています。
参照先 data_blob_::data・data_blob()・dump_data()・data_blob_::length・SMBOWFencrypt()・SMBsesskeygen_ntv1().
00037 { 00038 /* Finish the encryption of part_passwd. */ 00039 uchar p24[24]; 00040 00041 if (part_passwd == NULL) { 00042 DEBUG(10,("No password set - DISALLOWING access\n")); 00043 /* No password set - always false ! */ 00044 return False; 00045 } 00046 00047 if (sec_blob->length != 8) { 00048 DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challenge size (%lu)\n", 00049 (unsigned long)sec_blob->length)); 00050 return False; 00051 } 00052 00053 if (nt_response->length != 24) { 00054 DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%lu)\n", 00055 (unsigned long)nt_response->length)); 00056 return False; 00057 } 00058 00059 SMBOWFencrypt(part_passwd, sec_blob->data, p24); 00060 if (user_sess_key != NULL) { 00061 *user_sess_key = data_blob(NULL, 16); 00062 SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key->data); 00063 } 00064 00065 00066 #ifdef DEBUG_PASSWORD 00067 DEBUG(100,("Part password (P16) was |\n")); 00068 dump_data(100, (const char *)part_passwd, 16); 00069 DEBUGADD(100,("Password from client was |\n")); 00070 dump_data(100, (const char *)nt_response->data, nt_response->length); 00071 DEBUGADD(100,("Given challenge was |\n")); 00072 dump_data(100, (const char *)sec_blob->data, sec_blob->length); 00073 DEBUGADD(100,("Value from encryption was |\n")); 00074 dump_data(100, (const char *)p24, 24); 00075 #endif 00076 return (memcmp(p24, nt_response->data, 24) == 0); 00077 }
static BOOL smb_pwd_check_ntlmv2 | ( | const DATA_BLOB * | ntv2_response, | |
const uchar * | part_passwd, | |||
const DATA_BLOB * | sec_blob, | |||
const char * | user, | |||
const char * | domain, | |||
BOOL | upper_case_domain, | |||
DATA_BLOB * | user_sess_key | |||
) | [static] |
ntlm_check.c の 84 行で定義されています。
参照先 data_blob_::data・data_blob()・data_blob_clear_free()・dump_data()・data_blob_::length・ntv2_owf_gen()・SMBOWFencrypt_ntv2()・SMBsesskeygen_ntv2().
00090 { 00091 /* Finish the encryption of part_passwd. */ 00092 uchar kr[16]; 00093 uchar value_from_encryption[16]; 00094 uchar client_response[16]; 00095 DATA_BLOB client_key_data; 00096 BOOL res; 00097 00098 if (part_passwd == NULL) { 00099 DEBUG(10,("No password set - DISALLOWING access\n")); 00100 /* No password set - always False */ 00101 return False; 00102 } 00103 00104 if (sec_blob->length != 8) { 00105 DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect challenge size (%lu)\n", 00106 (unsigned long)sec_blob->length)); 00107 return False; 00108 } 00109 00110 if (ntv2_response->length < 24) { 00111 /* We MUST have more than 16 bytes, or the stuff below will go 00112 crazy. No known implementation sends less than the 24 bytes 00113 for LMv2, let alone NTLMv2. */ 00114 DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%lu)\n", 00115 (unsigned long)ntv2_response->length)); 00116 return False; 00117 } 00118 00119 client_key_data = data_blob(ntv2_response->data+16, ntv2_response->length-16); 00120 /* 00121 todo: should we be checking this for anything? We can't for LMv2, 00122 but for NTLMv2 it is meant to contain the current time etc. 00123 */ 00124 00125 memcpy(client_response, ntv2_response->data, sizeof(client_response)); 00126 00127 if (!ntv2_owf_gen(part_passwd, user, domain, upper_case_domain, kr)) { 00128 return False; 00129 } 00130 00131 SMBOWFencrypt_ntv2(kr, sec_blob, &client_key_data, value_from_encryption); 00132 if (user_sess_key != NULL) { 00133 *user_sess_key = data_blob(NULL, 16); 00134 SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key->data); 00135 } 00136 00137 #if DEBUG_PASSWORD 00138 DEBUG(100,("Part password (P16) was |\n")); 00139 dump_data(100, (const char *)part_passwd, 16); 00140 DEBUGADD(100,("Password from client was |\n")); 00141 dump_data(100, (const char *)ntv2_response->data, ntv2_response->length); 00142 DEBUGADD(100,("Variable data from client was |\n")); 00143 dump_data(100, (const char *)client_key_data.data, client_key_data.length); 00144 DEBUGADD(100,("Given challenge was |\n")); 00145 dump_data(100, (const char *)sec_blob->data, sec_blob->length); 00146 DEBUGADD(100,("Value from encryption was |\n")); 00147 dump_data(100, (const char *)value_from_encryption, 16); 00148 #endif 00149 data_blob_clear_free(&client_key_data); 00150 res = (memcmp(value_from_encryption, client_response, 16) == 0); 00151 if ((!res) && (user_sess_key != NULL)) 00152 data_blob_clear_free(user_sess_key); 00153 return res; 00154 }
NTSTATUS ntlm_password_check | ( | TALLOC_CTX * | mem_ctx, | |
const DATA_BLOB * | challenge, | |||
const DATA_BLOB * | lm_response, | |||
const DATA_BLOB * | nt_response, | |||
const DATA_BLOB * | lm_interactive_pwd, | |||
const DATA_BLOB * | nt_interactive_pwd, | |||
const char * | username, | |||
const char * | client_username, | |||
const char * | client_domain, | |||
const uint8 * | lm_pw, | |||
const uint8 * | nt_pw, | |||
DATA_BLOB * | user_sess_key, | |||
DATA_BLOB * | lm_sess_key | |||
) |
Check a challenge-response password against the value of the NT or LM password hash.
mem_ctx | talloc context | |
challenge | 8-byte challenge. If all zero, forces plaintext comparison | |
nt_response | 'unicode' NT response to the challenge, or unicode password | |
lm_response | ASCII or LANMAN response to the challenge, or password in DOS code page | |
username | internal Samba username, for log messages | |
client_username | username the client used | |
client_domain | domain name the client used (may be mapped) | |
nt_pw | MD4 unicode password from our passdb or similar | |
lm_pw | LANMAN ASCII password from our passdb or similar | |
user_sess_key | User session key | |
lm_sess_key | LM session key (first 8 bytes of the LM hash) |
ntlm_check.c の 173 行で定義されています。
参照先 data_blob_::data・data_blob()・E_P16()・data_blob_::length・mdfour()・smb_pwd_check_ntlmv1()・smb_pwd_check_ntlmv2()・SMBsesskeygen_ntv1().
参照元 local_pw_check()・sam_password_ok().
00185 { 00186 static const unsigned char zeros[8] = { 0, }; 00187 if (nt_pw == NULL) { 00188 DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n", 00189 username)); 00190 } 00191 00192 if (nt_interactive_pwd && nt_interactive_pwd->length && nt_pw) { 00193 if (nt_interactive_pwd->length != 16) { 00194 DEBUG(3,("ntlm_password_check: Interactive logon: Invalid NT password length (%d) supplied for user %s\n", (int)nt_interactive_pwd->length, 00195 username)); 00196 return NT_STATUS_WRONG_PASSWORD; 00197 } 00198 00199 if (memcmp(nt_interactive_pwd->data, nt_pw, 16) == 0) { 00200 if (user_sess_key) { 00201 *user_sess_key = data_blob(NULL, 16); 00202 SMBsesskeygen_ntv1(nt_pw, NULL, user_sess_key->data); 00203 } 00204 return NT_STATUS_OK; 00205 } else { 00206 DEBUG(3,("ntlm_password_check: Interactive logon: NT password check failed for user %s\n", 00207 username)); 00208 return NT_STATUS_WRONG_PASSWORD; 00209 } 00210 00211 } else if (lm_interactive_pwd && lm_interactive_pwd->length && lm_pw) { 00212 if (lm_interactive_pwd->length != 16) { 00213 DEBUG(3,("ntlm_password_check: Interactive logon: Invalid LANMAN password length (%d) supplied for user %s\n", (int)lm_interactive_pwd->length, 00214 username)); 00215 return NT_STATUS_WRONG_PASSWORD; 00216 } 00217 00218 if (!lp_lanman_auth()) { 00219 DEBUG(3,("ntlm_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled!\n", 00220 username)); 00221 return NT_STATUS_WRONG_PASSWORD; 00222 } 00223 00224 if (memcmp(lm_interactive_pwd->data, lm_pw, 16) == 0) { 00225 return NT_STATUS_OK; 00226 } else { 00227 DEBUG(3,("ntlm_password_check: Interactive logon: LANMAN password check failed for user %s\n", 00228 username)); 00229 return NT_STATUS_WRONG_PASSWORD; 00230 } 00231 } 00232 00233 /* Check for cleartext netlogon. Used by Exchange 5.5. */ 00234 if (challenge->length == sizeof(zeros) && 00235 (memcmp(challenge->data, zeros, challenge->length) == 0 )) { 00236 00237 DEBUG(4,("ntlm_password_check: checking plaintext passwords for user %s\n", 00238 username)); 00239 if (nt_pw && nt_response->length) { 00240 unsigned char pwhash[16]; 00241 mdfour(pwhash, nt_response->data, nt_response->length); 00242 if (memcmp(pwhash, nt_pw, sizeof(pwhash)) == 0) { 00243 return NT_STATUS_OK; 00244 } else { 00245 DEBUG(3,("ntlm_password_check: NT (Unicode) plaintext password check failed for user %s\n", 00246 username)); 00247 return NT_STATUS_WRONG_PASSWORD; 00248 } 00249 00250 } else if (!lp_lanman_auth()) { 00251 DEBUG(3,("ntlm_password_check: (plaintext password check) LANMAN passwords NOT PERMITTED for user %s\n", 00252 username)); 00253 00254 } else if (lm_pw && lm_response->length) { 00255 uchar dospwd[14]; 00256 uchar p16[16]; 00257 ZERO_STRUCT(dospwd); 00258 00259 memcpy(dospwd, lm_response->data, MIN(lm_response->length, sizeof(dospwd))); 00260 /* Only the fisrt 14 chars are considered, password need not be null terminated. */ 00261 00262 /* we *might* need to upper-case the string here */ 00263 E_P16((const unsigned char *)dospwd, p16); 00264 00265 if (memcmp(p16, lm_pw, sizeof(p16)) == 0) { 00266 return NT_STATUS_OK; 00267 } else { 00268 DEBUG(3,("ntlm_password_check: LANMAN (ASCII) plaintext password check failed for user %s\n", 00269 username)); 00270 return NT_STATUS_WRONG_PASSWORD; 00271 } 00272 } else { 00273 DEBUG(3, ("Plaintext authentication for user %s attempted, but neither NT nor LM passwords available\n", username)); 00274 return NT_STATUS_WRONG_PASSWORD; 00275 } 00276 } 00277 00278 if (nt_response->length != 0 && nt_response->length < 24) { 00279 DEBUG(2,("ntlm_password_check: invalid NT password length (%lu) for user %s\n", 00280 (unsigned long)nt_response->length, username)); 00281 } 00282 00283 if (nt_response->length >= 24 && nt_pw) { 00284 if (nt_response->length > 24) { 00285 /* We have the NT MD4 hash challenge available - see if we can 00286 use it 00287 */ 00288 DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n", client_domain)); 00289 if (smb_pwd_check_ntlmv2( nt_response, 00290 nt_pw, challenge, 00291 client_username, 00292 client_domain, 00293 False, 00294 user_sess_key)) { 00295 return NT_STATUS_OK; 00296 } 00297 00298 DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", client_domain)); 00299 if (smb_pwd_check_ntlmv2( nt_response, 00300 nt_pw, challenge, 00301 client_username, 00302 client_domain, 00303 True, 00304 user_sess_key)) { 00305 return NT_STATUS_OK; 00306 } 00307 00308 DEBUG(4,("ntlm_password_check: Checking NTLMv2 password without a domain\n")); 00309 if (smb_pwd_check_ntlmv2( nt_response, 00310 nt_pw, challenge, 00311 client_username, 00312 "", 00313 False, 00314 user_sess_key)) { 00315 return NT_STATUS_OK; 00316 } else { 00317 DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n")); 00318 return NT_STATUS_WRONG_PASSWORD; 00319 } 00320 } 00321 00322 if (lp_ntlm_auth()) { 00323 /* We have the NT MD4 hash challenge available - see if we can 00324 use it (ie. does it exist in the smbpasswd file). 00325 */ 00326 DEBUG(4,("ntlm_password_check: Checking NT MD4 password\n")); 00327 if (smb_pwd_check_ntlmv1(nt_response, 00328 nt_pw, challenge, 00329 user_sess_key)) { 00330 /* The LM session key for this response is not very secure, 00331 so use it only if we otherwise allow LM authentication */ 00332 00333 if (lp_lanman_auth() && lm_pw) { 00334 uint8 first_8_lm_hash[16]; 00335 memcpy(first_8_lm_hash, lm_pw, 8); 00336 memset(first_8_lm_hash + 8, '\0', 8); 00337 if (lm_sess_key) { 00338 *lm_sess_key = data_blob(first_8_lm_hash, 16); 00339 } 00340 } 00341 return NT_STATUS_OK; 00342 } else { 00343 DEBUG(3,("ntlm_password_check: NT MD4 password check failed for user %s\n", 00344 username)); 00345 return NT_STATUS_WRONG_PASSWORD; 00346 } 00347 } else { 00348 DEBUG(2,("ntlm_password_check: NTLMv1 passwords NOT PERMITTED for user %s\n", 00349 username)); 00350 /* no return, becouse we might pick up LMv2 in the LM field */ 00351 } 00352 } 00353 00354 if (lm_response->length == 0) { 00355 DEBUG(3,("ntlm_password_check: NEITHER LanMan nor NT password supplied for user %s\n", 00356 username)); 00357 return NT_STATUS_WRONG_PASSWORD; 00358 } 00359 00360 if (lm_response->length < 24) { 00361 DEBUG(2,("ntlm_password_check: invalid LanMan password length (%lu) for user %s\n", 00362 (unsigned long)nt_response->length, username)); 00363 return NT_STATUS_WRONG_PASSWORD; 00364 } 00365 00366 if (!lp_lanman_auth()) { 00367 DEBUG(3,("ntlm_password_check: Lanman passwords NOT PERMITTED for user %s\n", 00368 username)); 00369 } else if (!lm_pw) { 00370 DEBUG(3,("ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied)\n", 00371 username)); 00372 } else { 00373 DEBUG(4,("ntlm_password_check: Checking LM password\n")); 00374 if (smb_pwd_check_ntlmv1(lm_response, 00375 lm_pw, challenge, 00376 NULL)) { 00377 uint8 first_8_lm_hash[16]; 00378 memcpy(first_8_lm_hash, lm_pw, 8); 00379 memset(first_8_lm_hash + 8, '\0', 8); 00380 if (user_sess_key) { 00381 *user_sess_key = data_blob(first_8_lm_hash, 16); 00382 } 00383 00384 if (lm_sess_key) { 00385 *lm_sess_key = data_blob(first_8_lm_hash, 16); 00386 } 00387 return NT_STATUS_OK; 00388 } 00389 } 00390 00391 if (!nt_pw) { 00392 DEBUG(4,("ntlm_password_check: LM password check failed for user, no NT password %s\n",username)); 00393 return NT_STATUS_WRONG_PASSWORD; 00394 } 00395 00396 /* This is for 'LMv2' authentication. almost NTLMv2 but limited to 24 bytes. 00397 - related to Win9X, legacy NAS pass-though authentication 00398 */ 00399 DEBUG(4,("ntlm_password_check: Checking LMv2 password with domain %s\n", client_domain)); 00400 if (smb_pwd_check_ntlmv2( lm_response, 00401 nt_pw, challenge, 00402 client_username, 00403 client_domain, 00404 False, 00405 NULL)) { 00406 return NT_STATUS_OK; 00407 } 00408 00409 DEBUG(4,("ntlm_password_check: Checking LMv2 password with upper-cased version of domain %s\n", client_domain)); 00410 if (smb_pwd_check_ntlmv2( lm_response, 00411 nt_pw, challenge, 00412 client_username, 00413 client_domain, 00414 True, 00415 NULL)) { 00416 return NT_STATUS_OK; 00417 } 00418 00419 DEBUG(4,("ntlm_password_check: Checking LMv2 password without a domain\n")); 00420 if (smb_pwd_check_ntlmv2( lm_response, 00421 nt_pw, challenge, 00422 client_username, 00423 "", 00424 False, 00425 NULL)) { 00426 return NT_STATUS_OK; 00427 } 00428 00429 /* Apparently NT accepts NT responses in the LM field 00430 - I think this is related to Win9X pass-though authentication 00431 */ 00432 DEBUG(4,("ntlm_password_check: Checking NT MD4 password in LM field\n")); 00433 if (lp_ntlm_auth()) { 00434 if (smb_pwd_check_ntlmv1(lm_response, 00435 nt_pw, challenge, 00436 NULL)) { 00437 /* The session key for this response is still very odd. 00438 It not very secure, so use it only if we otherwise 00439 allow LM authentication */ 00440 00441 if (lp_lanman_auth() && lm_pw) { 00442 uint8 first_8_lm_hash[16]; 00443 memcpy(first_8_lm_hash, lm_pw, 8); 00444 memset(first_8_lm_hash + 8, '\0', 8); 00445 if (user_sess_key) { 00446 *user_sess_key = data_blob(first_8_lm_hash, 16); 00447 } 00448 00449 if (lm_sess_key) { 00450 *lm_sess_key = data_blob(first_8_lm_hash, 16); 00451 } 00452 } 00453 return NT_STATUS_OK; 00454 } 00455 DEBUG(3,("ntlm_password_check: LM password, NT MD4 password in LM field and LMv2 failed for user %s\n",username)); 00456 } else { 00457 DEBUG(3,("ntlm_password_check: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted\n",username)); 00458 } 00459 return NT_STATUS_WRONG_PASSWORD; 00460 }