2004-05-02 12:45:00 +04:00
/*
Unix SMB / CIFS implementation .
Password and authentication handling
2004-05-14 03:16:33 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2001 - 2004
Copyright ( C ) Gerald Carter 2003
Copyright ( C ) Luke Kenneth Casson Leighton 1996 - 2000
2004-05-02 12:45:00 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-05-02 12:45:00 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-05-02 12:45:00 +04:00
*/
# include "includes.h"
2008-09-24 17:30:23 +04:00
# include "../lib/crypto/crypto.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/netlogon.h"
2006-03-14 18:03:25 +03:00
# include "libcli/auth/libcli_auth.h"
2004-05-02 12:45:00 +04:00
/****************************************************************************
Core of smb password checking routine .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-07 02:16:19 +04:00
static bool smb_pwd_check_ntlmv1 ( TALLOC_CTX * mem_ctx ,
2004-10-08 12:05:11 +04:00
const DATA_BLOB * nt_response ,
2004-06-01 12:30:34 +04:00
const uint8_t * part_passwd ,
2004-05-02 12:45:00 +04:00
const DATA_BLOB * sec_blob ,
DATA_BLOB * user_sess_key )
{
/* Finish the encryption of part_passwd. */
2004-06-01 12:30:34 +04:00
uint8_t p24 [ 24 ] ;
2004-05-02 12:45:00 +04:00
if ( part_passwd = = NULL ) {
DEBUG ( 10 , ( " No password set - DISALLOWING access \n " ) ) ;
/* No password set - always false ! */
2007-10-07 02:16:19 +04:00
return false ;
2004-05-02 12:45:00 +04:00
}
if ( sec_blob - > length ! = 8 ) {
DEBUG ( 0 , ( " smb_pwd_check_ntlmv1: incorrect challenge size (%lu) \n " ,
( unsigned long ) sec_blob - > length ) ) ;
2007-10-07 02:16:19 +04:00
return false ;
2004-05-02 12:45:00 +04:00
}
if ( nt_response - > length ! = 24 ) {
DEBUG ( 0 , ( " smb_pwd_check_ntlmv1: incorrect password length (%lu) \n " ,
( unsigned long ) nt_response - > length ) ) ;
2007-10-07 02:16:19 +04:00
return false ;
2004-05-02 12:45:00 +04:00
}
SMBOWFencrypt ( part_passwd , sec_blob - > data , p24 ) ;
# if DEBUG_PASSWORD
DEBUG ( 100 , ( " Part password (P16) was | \n " ) ) ;
dump_data ( 100 , part_passwd , 16 ) ;
DEBUGADD ( 100 , ( " Password from client was | \n " ) ) ;
dump_data ( 100 , nt_response - > data , nt_response - > length ) ;
DEBUGADD ( 100 , ( " Given challenge was | \n " ) ) ;
dump_data ( 100 , sec_blob - > data , sec_blob - > length ) ;
DEBUGADD ( 100 , ( " Value from encryption was | \n " ) ) ;
dump_data ( 100 , p24 , 24 ) ;
# endif
2005-01-06 15:13:31 +03:00
if ( memcmp ( p24 , nt_response - > data , 24 ) = = 0 ) {
if ( user_sess_key ! = NULL ) {
* user_sess_key = data_blob_talloc ( mem_ctx , NULL , 16 ) ;
SMBsesskeygen_ntv1 ( part_passwd , user_sess_key - > data ) ;
}
2007-10-07 02:16:19 +04:00
return true ;
2005-01-06 15:13:31 +03:00
}
2007-10-07 02:16:19 +04:00
return false ;
2004-05-02 12:45:00 +04:00
}
/****************************************************************************
Core of smb password checking routine . ( NTLMv2 , LMv2 )
Note : The same code works with both NTLMv2 and LMv2 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-07 02:16:19 +04:00
static bool smb_pwd_check_ntlmv2 ( TALLOC_CTX * mem_ctx ,
2004-10-08 12:05:11 +04:00
const DATA_BLOB * ntv2_response ,
2004-06-01 12:30:34 +04:00
const uint8_t * part_passwd ,
2004-05-02 12:45:00 +04:00
const DATA_BLOB * sec_blob ,
const char * user , const char * domain ,
2007-10-07 02:16:19 +04:00
bool upper_case_domain , /* should the domain be transformed into upper case? */
2004-05-02 12:45:00 +04:00
DATA_BLOB * user_sess_key )
{
/* Finish the encryption of part_passwd. */
2004-06-01 12:30:34 +04:00
uint8_t kr [ 16 ] ;
uint8_t value_from_encryption [ 16 ] ;
2004-05-02 12:45:00 +04:00
DATA_BLOB client_key_data ;
if ( part_passwd = = NULL ) {
DEBUG ( 10 , ( " No password set - DISALLOWING access \n " ) ) ;
2007-10-07 02:16:19 +04:00
/* No password set - always false */
return false ;
2004-05-02 12:45:00 +04:00
}
if ( sec_blob - > length ! = 8 ) {
DEBUG ( 0 , ( " smb_pwd_check_ntlmv2: incorrect challenge size (%lu) \n " ,
( unsigned long ) sec_blob - > length ) ) ;
2007-10-07 02:16:19 +04:00
return false ;
2004-05-02 12:45:00 +04:00
}
if ( ntv2_response - > length < 24 ) {
/* We MUST have more than 16 bytes, or the stuff below will go
crazy . No known implementation sends less than the 24 bytes
for LMv2 , let alone NTLMv2 . */
DEBUG ( 0 , ( " smb_pwd_check_ntlmv2: incorrect password length (%lu) \n " ,
( unsigned long ) ntv2_response - > length ) ) ;
2007-10-07 02:16:19 +04:00
return false ;
2004-05-02 12:45:00 +04:00
}
2004-10-08 12:05:11 +04:00
client_key_data = data_blob_talloc ( mem_ctx , ntv2_response - > data + 16 , ntv2_response - > length - 16 ) ;
2004-05-02 12:45:00 +04:00
/*
todo : should we be checking this for anything ? We can ' t for LMv2 ,
but for NTLMv2 it is meant to contain the current time etc .
*/
if ( ! ntv2_owf_gen ( part_passwd , user , domain , upper_case_domain , kr ) ) {
2007-10-07 02:16:19 +04:00
return false ;
2004-05-02 12:45:00 +04:00
}
SMBOWFencrypt_ntv2 ( kr , sec_blob , & client_key_data , value_from_encryption ) ;
# if DEBUG_PASSWORD
DEBUG ( 100 , ( " Part password (P16) was | \n " ) ) ;
dump_data ( 100 , part_passwd , 16 ) ;
DEBUGADD ( 100 , ( " Password from client was | \n " ) ) ;
dump_data ( 100 , ntv2_response - > data , ntv2_response - > length ) ;
DEBUGADD ( 100 , ( " Variable data from client was | \n " ) ) ;
dump_data ( 100 , client_key_data . data , client_key_data . length ) ;
DEBUGADD ( 100 , ( " Given challenge was | \n " ) ) ;
dump_data ( 100 , sec_blob - > data , sec_blob - > length ) ;
DEBUGADD ( 100 , ( " Value from encryption was | \n " ) ) ;
dump_data ( 100 , value_from_encryption , 16 ) ;
# endif
data_blob_clear_free ( & client_key_data ) ;
2005-01-06 15:13:31 +03:00
if ( memcmp ( value_from_encryption , ntv2_response - > data , 16 ) = = 0 ) {
if ( user_sess_key ! = NULL ) {
* user_sess_key = data_blob_talloc ( mem_ctx , NULL , 16 ) ;
SMBsesskeygen_ntv2 ( kr , value_from_encryption , user_sess_key - > data ) ;
}
2007-10-07 02:16:19 +04:00
return true ;
2005-01-06 15:13:31 +03:00
}
2007-10-07 02:16:19 +04:00
return false ;
2005-01-06 15:13:31 +03:00
}
/****************************************************************************
Core of smb password checking routine . ( NTLMv2 , LMv2 )
Note : The same code works with both NTLMv2 and LMv2 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-07 02:16:19 +04:00
static bool smb_sess_key_ntlmv2 ( TALLOC_CTX * mem_ctx ,
2005-01-06 15:13:31 +03:00
const DATA_BLOB * ntv2_response ,
const uint8_t * part_passwd ,
const DATA_BLOB * sec_blob ,
const char * user , const char * domain ,
2007-10-07 02:16:19 +04:00
bool upper_case_domain , /* should the domain be transformed into upper case? */
2005-01-06 15:13:31 +03:00
DATA_BLOB * user_sess_key )
{
/* Finish the encryption of part_passwd. */
uint8_t kr [ 16 ] ;
uint8_t value_from_encryption [ 16 ] ;
DATA_BLOB client_key_data ;
if ( part_passwd = = NULL ) {
DEBUG ( 10 , ( " No password set - DISALLOWING access \n " ) ) ;
2007-10-07 02:16:19 +04:00
/* No password set - always false */
return false ;
2005-01-06 15:13:31 +03:00
}
if ( sec_blob - > length ! = 8 ) {
DEBUG ( 0 , ( " smb_sess_key_ntlmv2: incorrect challenge size (%lu) \n " ,
( unsigned long ) sec_blob - > length ) ) ;
2007-10-07 02:16:19 +04:00
return false ;
2005-01-06 15:13:31 +03:00
}
if ( ntv2_response - > length < 24 ) {
/* We MUST have more than 16 bytes, or the stuff below will go
crazy . No known implementation sends less than the 24 bytes
for LMv2 , let alone NTLMv2 . */
DEBUG ( 0 , ( " smb_sess_key_ntlmv2: incorrect password length (%lu) \n " ,
( unsigned long ) ntv2_response - > length ) ) ;
2007-10-07 02:16:19 +04:00
return false ;
2005-01-06 15:13:31 +03:00
}
client_key_data = data_blob_talloc ( mem_ctx , ntv2_response - > data + 16 , ntv2_response - > length - 16 ) ;
if ( ! ntv2_owf_gen ( part_passwd , user , domain , upper_case_domain , kr ) ) {
2007-10-07 02:16:19 +04:00
return false ;
2005-01-06 15:13:31 +03:00
}
SMBOWFencrypt_ntv2 ( kr , sec_blob , & client_key_data , value_from_encryption ) ;
* user_sess_key = data_blob_talloc ( mem_ctx , NULL , 16 ) ;
SMBsesskeygen_ntv2 ( kr , value_from_encryption , user_sess_key - > data ) ;
2007-10-07 02:16:19 +04:00
return true ;
2004-05-02 12:45:00 +04:00
}
/**
2005-07-22 08:10:07 +04:00
* Compare password hashes against those from the SAM
2004-05-02 12:45:00 +04:00
*
* @ param mem_ctx talloc context
2005-07-22 08:10:07 +04:00
* @ param client_lanman LANMAN password hash , as supplied by the client
* @ param client_nt NT ( MD4 ) password hash , as supplied by the client
2004-05-02 12:45:00 +04:00
* @ param username internal Samba username , for log messages
* @ param client_username username the client used
* @ param client_domain domain name the client used ( may be mapped )
2005-07-22 08:10:07 +04:00
* @ param stored_lanman LANMAN password hash , as stored on the SAM
* @ param stored_nt NT ( MD4 ) password hash , as stored on the SAM
2004-05-02 12:45:00 +04:00
* @ param user_sess_key User session key
* @ param lm_sess_key LM session key ( first 8 bytes of the LM hash )
*/
2005-07-22 08:10:07 +04:00
NTSTATUS hash_password_check ( TALLOC_CTX * mem_ctx ,
2008-11-01 19:55:57 +03:00
bool lanman_auth ,
2005-07-22 08:10:07 +04:00
const struct samr_Password * client_lanman ,
const struct samr_Password * client_nt ,
2004-05-02 12:45:00 +04:00
const char * username ,
2005-07-22 08:10:07 +04:00
const struct samr_Password * stored_lanman ,
2005-08-20 09:59:27 +04:00
const struct samr_Password * stored_nt )
2004-05-02 12:45:00 +04:00
{
2005-07-22 08:10:07 +04:00
if ( stored_nt = = NULL ) {
2004-05-02 12:45:00 +04:00
DEBUG ( 3 , ( " ntlm_password_check: NO NT password stored for user %s. \n " ,
username ) ) ;
}
2005-07-22 08:10:07 +04:00
if ( client_nt & & stored_nt ) {
if ( memcmp ( client_nt - > hash , stored_nt - > hash , sizeof ( stored_nt - > hash ) ) = = 0 ) {
2004-05-02 12:45:00 +04:00
return NT_STATUS_OK ;
} else {
DEBUG ( 3 , ( " ntlm_password_check: Interactive logon: NT password check failed for user %s \n " ,
username ) ) ;
return NT_STATUS_WRONG_PASSWORD ;
}
2005-07-22 08:10:07 +04:00
} else if ( client_lanman & & stored_lanman ) {
2008-11-01 19:55:57 +03:00
if ( ! lanman_auth ) {
2004-05-02 12:45:00 +04:00
DEBUG ( 3 , ( " ntlm_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled! \n " ,
username ) ) ;
return NT_STATUS_WRONG_PASSWORD ;
}
2005-10-28 15:20:48 +04:00
if ( strchr_m ( username , ' @ ' ) ) {
return NT_STATUS_NOT_FOUND ;
}
2004-05-02 12:45:00 +04:00
2005-07-22 08:10:07 +04:00
if ( memcmp ( client_lanman - > hash , stored_lanman - > hash , sizeof ( stored_lanman - > hash ) ) = = 0 ) {
2004-05-02 12:45:00 +04:00
return NT_STATUS_OK ;
} else {
DEBUG ( 3 , ( " ntlm_password_check: Interactive logon: LANMAN password check failed for user %s \n " ,
username ) ) ;
return NT_STATUS_WRONG_PASSWORD ;
}
}
2005-10-28 15:20:48 +04:00
if ( strchr_m ( username , ' @ ' ) ) {
return NT_STATUS_NOT_FOUND ;
}
2005-07-22 08:10:07 +04:00
return NT_STATUS_WRONG_PASSWORD ;
}
/**
* Check a challenge - response password against the value of the NT or
* LM password hash .
*
* @ param mem_ctx talloc context
* @ param challenge 8 - byte challenge . If all zero , forces plaintext comparison
* @ param nt_response ' unicode ' NT response to the challenge , or unicode password
* @ param lm_response ASCII or LANMAN response to the challenge , or password in DOS code page
* @ param username internal Samba username , for log messages
* @ param client_username username the client used
* @ param client_domain domain name the client used ( may be mapped )
* @ param stored_lanman LANMAN ASCII password from our passdb or similar
* @ param stored_nt MD4 unicode password from our passdb or similar
* @ param user_sess_key User session key
* @ param lm_sess_key LM session key ( first 8 bytes of the LM hash )
*/
NTSTATUS ntlm_password_check ( TALLOC_CTX * mem_ctx ,
2008-11-01 19:55:57 +03:00
bool lanman_auth ,
bool ntlm_auth ,
2005-10-28 12:54:37 +04:00
uint32_t logon_parameters ,
2005-07-22 08:10:07 +04:00
const DATA_BLOB * challenge ,
const DATA_BLOB * lm_response ,
const DATA_BLOB * nt_response ,
const char * username ,
const char * client_username ,
const char * client_domain ,
const struct samr_Password * stored_lanman ,
const struct samr_Password * stored_nt ,
DATA_BLOB * user_sess_key ,
DATA_BLOB * lm_sess_key )
{
2007-12-10 06:33:39 +03:00
const static uint8_t zeros [ 8 ] ;
2005-07-22 08:10:07 +04:00
DATA_BLOB tmp_sess_key ;
if ( stored_nt = = NULL ) {
DEBUG ( 3 , ( " ntlm_password_check: NO NT password stored for user %s. \n " ,
username ) ) ;
}
2005-08-20 09:59:27 +04:00
* lm_sess_key = data_blob ( NULL , 0 ) ;
* user_sess_key = data_blob ( NULL , 0 ) ;
2004-05-02 12:45:00 +04:00
/* Check for cleartext netlogon. Used by Exchange 5.5. */
2005-10-28 12:54:37 +04:00
if ( ( logon_parameters & MSV1_0_CLEARTEXT_PASSWORD_ALLOWED )
& & challenge - > length = = sizeof ( zeros )
& & ( memcmp ( challenge - > data , zeros , challenge - > length ) = = 0 ) ) {
2005-08-20 09:59:27 +04:00
struct samr_Password client_nt ;
struct samr_Password client_lm ;
2005-10-29 15:11:05 +04:00
char * unix_pw = NULL ;
2007-10-07 02:16:19 +04:00
bool lm_ok ;
2004-05-02 12:45:00 +04:00
DEBUG ( 4 , ( " ntlm_password_check: checking plaintext passwords for user %s \n " ,
username ) ) ;
2005-08-20 09:59:27 +04:00
mdfour ( client_nt . hash , nt_response - > data , nt_response - > length ) ;
2005-10-29 15:11:05 +04:00
if ( lm_response - > length & &
2008-11-01 19:55:57 +03:00
( convert_string_talloc ( mem_ctx , CH_DOS , CH_UNIX ,
2005-10-29 15:11:05 +04:00
lm_response - > data , lm_response - > length ,
2009-03-01 21:55:46 +03:00
( void * * ) & unix_pw , NULL , false ) ) ) {
2005-10-29 15:11:05 +04:00
if ( E_deshash ( unix_pw , client_lm . hash ) ) {
2007-10-07 02:16:19 +04:00
lm_ok = true ;
2005-10-29 15:11:05 +04:00
} else {
2007-10-07 02:16:19 +04:00
lm_ok = false ;
2005-10-29 15:11:05 +04:00
}
} else {
2007-10-07 02:16:19 +04:00
lm_ok = false ;
2005-10-29 15:11:05 +04:00
}
2005-10-28 15:20:48 +04:00
return hash_password_check ( mem_ctx ,
2008-11-01 19:55:57 +03:00
lanman_auth ,
2005-10-29 15:11:05 +04:00
lm_ok ? & client_lm : NULL ,
2005-10-28 15:20:48 +04:00
nt_response - > length ? & client_nt : NULL ,
2005-08-20 09:59:27 +04:00
username ,
stored_lanman , stored_nt ) ;
2004-05-02 12:45:00 +04:00
}
if ( nt_response - > length ! = 0 & & nt_response - > length < 24 ) {
DEBUG ( 2 , ( " ntlm_password_check: invalid NT password length (%lu) for user %s \n " ,
( unsigned long ) nt_response - > length , username ) ) ;
}
2005-07-22 08:10:07 +04:00
if ( nt_response - > length > 24 & & stored_nt ) {
2005-01-03 09:23:02 +03:00
/* We have the NT MD4 hash challenge available - see if we can
use it
*/
DEBUG ( 4 , ( " ntlm_password_check: Checking NTLMv2 password with domain [%s] \n " , client_domain ) ) ;
if ( smb_pwd_check_ntlmv2 ( mem_ctx ,
nt_response ,
2005-07-22 08:10:07 +04:00
stored_nt - > hash , challenge ,
2005-01-03 09:23:02 +03:00
client_username ,
client_domain ,
2007-10-07 02:16:19 +04:00
false ,
2005-01-03 09:23:02 +03:00
user_sess_key ) ) {
2005-08-20 09:59:27 +04:00
if ( user_sess_key - > length ) {
2009-04-20 12:54:57 +04:00
* lm_sess_key = data_blob_talloc ( mem_ctx , user_sess_key - > data , MIN ( 8 , user_sess_key - > length ) ) ;
2004-05-02 12:45:00 +04:00
}
2005-01-03 09:23:02 +03:00
return NT_STATUS_OK ;
}
DEBUG ( 4 , ( " ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s] \n " , client_domain ) ) ;
if ( smb_pwd_check_ntlmv2 ( mem_ctx ,
nt_response ,
2005-07-22 08:10:07 +04:00
stored_nt - > hash , challenge ,
2005-01-03 09:23:02 +03:00
client_username ,
client_domain ,
2007-10-07 02:16:19 +04:00
true ,
2005-01-03 09:23:02 +03:00
user_sess_key ) ) {
2005-08-20 09:59:27 +04:00
if ( user_sess_key - > length ) {
2009-04-20 12:54:57 +04:00
* lm_sess_key = data_blob_talloc ( mem_ctx , user_sess_key - > data , MIN ( 8 , user_sess_key - > length ) ) ;
2004-05-02 12:45:00 +04:00
}
2005-01-03 09:23:02 +03:00
return NT_STATUS_OK ;
}
DEBUG ( 4 , ( " ntlm_password_check: Checking NTLMv2 password without a domain \n " ) ) ;
if ( smb_pwd_check_ntlmv2 ( mem_ctx ,
nt_response ,
2005-07-22 08:10:07 +04:00
stored_nt - > hash , challenge ,
2005-01-03 09:23:02 +03:00
client_username ,
" " ,
2007-10-07 02:16:19 +04:00
false ,
2005-01-03 09:23:02 +03:00
user_sess_key ) ) {
2005-08-20 09:59:27 +04:00
if ( user_sess_key - > length ) {
2009-04-20 12:54:57 +04:00
* lm_sess_key = data_blob_talloc ( mem_ctx , user_sess_key - > data , MIN ( 8 , user_sess_key - > length ) ) ;
2004-05-02 12:45:00 +04:00
}
2005-01-03 09:23:02 +03:00
return NT_STATUS_OK ;
} else {
DEBUG ( 3 , ( " ntlm_password_check: NTLMv2 password check failed \n " ) ) ;
2004-05-02 12:45:00 +04:00
}
2005-07-22 08:10:07 +04:00
} else if ( nt_response - > length = = 24 & & stored_nt ) {
2008-11-01 19:55:57 +03:00
if ( ntlm_auth ) {
2004-05-02 12:45:00 +04:00
/* We have the NT MD4 hash challenge available - see if we can
use it ( ie . does it exist in the smbpasswd file ) .
*/
DEBUG ( 4 , ( " ntlm_password_check: Checking NT MD4 password \n " ) ) ;
2004-10-08 12:05:11 +04:00
if ( smb_pwd_check_ntlmv1 ( mem_ctx ,
nt_response ,
2005-07-22 08:10:07 +04:00
stored_nt - > hash , challenge ,
2004-05-02 12:45:00 +04:00
user_sess_key ) ) {
/* The LM session key for this response is not very secure,
so use it only if we otherwise allow LM authentication */
2005-01-03 09:23:02 +03:00
2008-11-01 19:55:57 +03:00
if ( lanman_auth & & stored_lanman ) {
2009-04-20 12:54:57 +04:00
* lm_sess_key = data_blob_talloc ( mem_ctx , stored_lanman - > hash , MIN ( 8 , user_sess_key - > length ) ) ;
2004-05-02 12:45:00 +04:00
}
return NT_STATUS_OK ;
} else {
DEBUG ( 3 , ( " ntlm_password_check: NT MD4 password check failed for user %s \n " ,
username ) ) ;
return NT_STATUS_WRONG_PASSWORD ;
}
} else {
DEBUG ( 2 , ( " ntlm_password_check: NTLMv1 passwords NOT PERMITTED for user %s \n " ,
username ) ) ;
/* no return, becouse we might pick up LMv2 in the LM field */
}
}
if ( lm_response - > length = = 0 ) {
DEBUG ( 3 , ( " ntlm_password_check: NEITHER LanMan nor NT password supplied for user %s \n " ,
username ) ) ;
return NT_STATUS_WRONG_PASSWORD ;
}
if ( lm_response - > length < 24 ) {
DEBUG ( 2 , ( " ntlm_password_check: invalid LanMan password length (%lu) for user %s \n " ,
( unsigned long ) nt_response - > length , username ) ) ;
return NT_STATUS_WRONG_PASSWORD ;
}
2008-11-01 19:55:57 +03:00
if ( ! lanman_auth ) {
2004-05-02 12:45:00 +04:00
DEBUG ( 3 , ( " ntlm_password_check: Lanman passwords NOT PERMITTED for user %s \n " ,
username ) ) ;
2005-07-22 08:10:07 +04:00
} else if ( ! stored_lanman ) {
2004-05-02 12:45:00 +04:00
DEBUG ( 3 , ( " ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied) \n " ,
username ) ) ;
2005-10-28 15:20:48 +04:00
} else if ( strchr_m ( username , ' @ ' ) ) {
DEBUG ( 3 , ( " ntlm_password_check: NO LanMan password allowed for username@realm logins (user: %s) \n " ,
username ) ) ;
2004-05-02 12:45:00 +04:00
} else {
DEBUG ( 4 , ( " ntlm_password_check: Checking LM password \n " ) ) ;
2004-10-08 12:05:11 +04:00
if ( smb_pwd_check_ntlmv1 ( mem_ctx ,
lm_response ,
2005-07-22 08:10:07 +04:00
stored_lanman - > hash , challenge ,
2004-05-02 12:45:00 +04:00
NULL ) ) {
2004-06-08 02:17:51 +04:00
/* The session key for this response is still very odd.
It not very secure , so use it only if we otherwise
allow LM authentication */
2008-11-01 19:55:57 +03:00
if ( lanman_auth & & stored_lanman ) {
2004-06-08 02:17:51 +04:00
uint8_t first_8_lm_hash [ 16 ] ;
2005-07-22 08:10:07 +04:00
memcpy ( first_8_lm_hash , stored_lanman - > hash , 8 ) ;
2004-06-08 02:17:51 +04:00
memset ( first_8_lm_hash + 8 , ' \0 ' , 8 ) ;
2004-10-08 12:05:11 +04:00
* user_sess_key = data_blob_talloc ( mem_ctx , first_8_lm_hash , 16 ) ;
2005-07-22 08:10:07 +04:00
* lm_sess_key = data_blob_talloc ( mem_ctx , stored_lanman - > hash , 8 ) ;
2004-06-08 02:17:51 +04:00
}
2004-05-02 12:45:00 +04:00
return NT_STATUS_OK ;
}
}
2005-07-22 08:10:07 +04:00
if ( ! stored_nt ) {
2004-05-02 12:45:00 +04:00
DEBUG ( 4 , ( " ntlm_password_check: LM password check failed for user, no NT password %s \n " , username ) ) ;
return NT_STATUS_WRONG_PASSWORD ;
}
/* This is for 'LMv2' authentication. almost NTLMv2 but limited to 24 bytes.
- related to Win9X , legacy NAS pass - though authentication
*/
DEBUG ( 4 , ( " ntlm_password_check: Checking LMv2 password with domain %s \n " , client_domain ) ) ;
2004-10-08 12:05:11 +04:00
if ( smb_pwd_check_ntlmv2 ( mem_ctx ,
lm_response ,
2005-07-22 08:10:07 +04:00
stored_nt - > hash , challenge ,
2004-10-08 12:05:11 +04:00
client_username ,
client_domain ,
2007-10-07 02:16:19 +04:00
false ,
2005-01-06 15:13:31 +03:00
& tmp_sess_key ) ) {
if ( nt_response - > length > 24 ) {
/* If NTLMv2 authentication has preceeded us
* ( even if it failed ) , then use the session
* key from that . See the RPC - SAMLOGON
* torture test */
smb_sess_key_ntlmv2 ( mem_ctx ,
nt_response ,
2005-07-22 08:10:07 +04:00
stored_nt - > hash , challenge ,
2005-01-06 15:13:31 +03:00
client_username ,
client_domain ,
2007-10-07 02:16:19 +04:00
false ,
2005-01-06 15:13:31 +03:00
user_sess_key ) ;
2005-08-20 09:59:27 +04:00
} else {
2005-01-06 15:13:31 +03:00
/* Otherwise, use the LMv2 session key */
* user_sess_key = tmp_sess_key ;
}
2005-08-20 09:59:27 +04:00
if ( user_sess_key - > length ) {
2009-04-20 12:54:57 +04:00
* lm_sess_key = data_blob_talloc ( mem_ctx , user_sess_key - > data , MIN ( 8 , user_sess_key - > length ) ) ;
2005-01-03 09:23:02 +03:00
}
2004-05-02 12:45:00 +04:00
return NT_STATUS_OK ;
}
DEBUG ( 4 , ( " ntlm_password_check: Checking LMv2 password with upper-cased version of domain %s \n " , client_domain ) ) ;
2004-10-08 12:05:11 +04:00
if ( smb_pwd_check_ntlmv2 ( mem_ctx ,
lm_response ,
2005-07-22 08:10:07 +04:00
stored_nt - > hash , challenge ,
2004-10-08 12:05:11 +04:00
client_username ,
client_domain ,
2007-10-07 02:16:19 +04:00
true ,
2005-01-06 15:13:31 +03:00
& tmp_sess_key ) ) {
if ( nt_response - > length > 24 ) {
/* If NTLMv2 authentication has preceeded us
* ( even if it failed ) , then use the session
* key from that . See the RPC - SAMLOGON
* torture test */
smb_sess_key_ntlmv2 ( mem_ctx ,
nt_response ,
2005-07-22 08:10:07 +04:00
stored_nt - > hash , challenge ,
2005-01-06 15:13:31 +03:00
client_username ,
client_domain ,
2007-10-07 02:16:19 +04:00
true ,
2005-01-06 15:13:31 +03:00
user_sess_key ) ;
2005-08-20 09:59:27 +04:00
} else {
2005-01-06 15:13:31 +03:00
/* Otherwise, use the LMv2 session key */
* user_sess_key = tmp_sess_key ;
}
2005-08-20 09:59:27 +04:00
if ( user_sess_key - > length ) {
2009-04-20 12:54:57 +04:00
* lm_sess_key = data_blob_talloc ( mem_ctx , user_sess_key - > data , MIN ( 8 , user_sess_key - > length ) ) ;
2005-01-03 09:23:02 +03:00
}
2004-05-02 12:45:00 +04:00
return NT_STATUS_OK ;
}
DEBUG ( 4 , ( " ntlm_password_check: Checking LMv2 password without a domain \n " ) ) ;
2004-10-08 12:05:11 +04:00
if ( smb_pwd_check_ntlmv2 ( mem_ctx ,
lm_response ,
2005-07-22 08:10:07 +04:00
stored_nt - > hash , challenge ,
2004-10-08 12:05:11 +04:00
client_username ,
" " ,
2007-10-07 02:16:19 +04:00
false ,
2005-01-06 15:13:31 +03:00
& tmp_sess_key ) ) {
if ( nt_response - > length > 24 ) {
/* If NTLMv2 authentication has preceeded us
* ( even if it failed ) , then use the session
* key from that . See the RPC - SAMLOGON
* torture test */
smb_sess_key_ntlmv2 ( mem_ctx ,
nt_response ,
2005-07-22 08:10:07 +04:00
stored_nt - > hash , challenge ,
2005-01-06 15:13:31 +03:00
client_username ,
" " ,
2007-10-07 02:16:19 +04:00
false ,
2005-01-06 15:13:31 +03:00
user_sess_key ) ;
2005-08-20 09:59:27 +04:00
} else {
2005-01-06 15:13:31 +03:00
/* Otherwise, use the LMv2 session key */
* user_sess_key = tmp_sess_key ;
}
2005-08-20 09:59:27 +04:00
if ( user_sess_key - > length ) {
2009-04-20 12:54:57 +04:00
* lm_sess_key = data_blob_talloc ( mem_ctx , user_sess_key - > data , MIN ( 8 , user_sess_key - > length ) ) ;
2005-01-03 09:23:02 +03:00
}
2004-05-02 12:45:00 +04:00
return NT_STATUS_OK ;
}
/* Apparently NT accepts NT responses in the LM field
- I think this is related to Win9X pass - though authentication
*/
DEBUG ( 4 , ( " ntlm_password_check: Checking NT MD4 password in LM field \n " ) ) ;
2008-11-01 19:55:57 +03:00
if ( ntlm_auth ) {
2004-10-08 12:05:11 +04:00
if ( smb_pwd_check_ntlmv1 ( mem_ctx ,
lm_response ,
2005-07-22 08:10:07 +04:00
stored_nt - > hash , challenge ,
2004-05-02 12:45:00 +04:00
NULL ) ) {
/* The session key for this response is still very odd.
It not very secure , so use it only if we otherwise
allow LM authentication */
2008-11-01 19:55:57 +03:00
if ( lanman_auth & & stored_lanman ) {
2004-05-25 21:50:17 +04:00
uint8_t first_8_lm_hash [ 16 ] ;
2005-07-22 08:10:07 +04:00
memcpy ( first_8_lm_hash , stored_lanman - > hash , 8 ) ;
2004-05-02 12:45:00 +04:00
memset ( first_8_lm_hash + 8 , ' \0 ' , 8 ) ;
2004-10-08 12:05:11 +04:00
* user_sess_key = data_blob_talloc ( mem_ctx , first_8_lm_hash , 16 ) ;
2005-07-22 08:10:07 +04:00
* lm_sess_key = data_blob_talloc ( mem_ctx , stored_lanman - > hash , 8 ) ;
2004-05-02 12:45:00 +04:00
}
return NT_STATUS_OK ;
}
DEBUG ( 3 , ( " ntlm_password_check: LM password, NT MD4 password in LM field and LMv2 failed for user %s \n " , username ) ) ;
} else {
DEBUG ( 3 , ( " ntlm_password_check: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted \n " , username ) ) ;
}
2005-10-28 15:20:48 +04:00
/* Try and match error codes */
if ( strchr_m ( username , ' @ ' ) ) {
return NT_STATUS_NOT_FOUND ;
}
2004-05-02 12:45:00 +04:00
return NT_STATUS_WRONG_PASSWORD ;
}