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
the Free Software Foundation ; either version 2 of the License , or
( 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
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2004-11-02 09:14:15 +03:00
# include "lib/crypto/crypto.h"
2004-05-02 12:45:00 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_AUTH
/****************************************************************************
Core of smb password checking routine .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-10-08 12:05:11 +04:00
static BOOL smb_pwd_check_ntlmv1 ( TALLOC_CTX * mem_ctx ,
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 ! */
return False ;
}
if ( sec_blob - > length ! = 8 ) {
DEBUG ( 0 , ( " smb_pwd_check_ntlmv1: incorrect challenge size (%lu) \n " ,
( unsigned long ) sec_blob - > length ) ) ;
return False ;
}
if ( nt_response - > length ! = 24 ) {
DEBUG ( 0 , ( " smb_pwd_check_ntlmv1: incorrect password length (%lu) \n " ,
( unsigned long ) nt_response - > length ) ) ;
return False ;
}
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 ) ;
}
return True ;
}
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-10-08 12:05:11 +04:00
static BOOL smb_pwd_check_ntlmv2 ( TALLOC_CTX * mem_ctx ,
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 ,
BOOL upper_case_domain , /* should the domain be transformed into upper case? */
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 " ) ) ;
/* No password set - always False */
return False ;
}
if ( sec_blob - > length ! = 8 ) {
DEBUG ( 0 , ( " smb_pwd_check_ntlmv2: incorrect challenge size (%lu) \n " ,
( unsigned long ) sec_blob - > length ) ) ;
return False ;
}
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 ) ) ;
return False ;
}
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 ) ) {
return False ;
}
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 ) ;
}
return True ;
}
return False ;
}
/****************************************************************************
Core of smb password checking routine . ( NTLMv2 , LMv2 )
Note : The same code works with both NTLMv2 and LMv2 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL smb_sess_key_ntlmv2 ( TALLOC_CTX * mem_ctx ,
const DATA_BLOB * ntv2_response ,
const uint8_t * part_passwd ,
const DATA_BLOB * sec_blob ,
const char * user , const char * domain ,
BOOL upper_case_domain , /* should the domain be transformed into upper case? */
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 " ) ) ;
/* No password set - always False */
return False ;
}
if ( sec_blob - > length ! = 8 ) {
DEBUG ( 0 , ( " smb_sess_key_ntlmv2: incorrect challenge size (%lu) \n " ,
( unsigned long ) sec_blob - > length ) ) ;
return False ;
}
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 ) ) ;
return False ;
}
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 ) ) {
return False ;
}
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 ) ;
return True ;
2004-05-02 12:45:00 +04:00
}
/**
* 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 nt_pw MD4 unicode password from our passdb or similar
* @ param lm_pw LANMAN ASCII 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 ,
const DATA_BLOB * challenge ,
const DATA_BLOB * lm_response ,
const DATA_BLOB * nt_response ,
2004-06-05 08:32:50 +04:00
const DATA_BLOB * lm_interactive_password ,
const DATA_BLOB * nt_interactive_password ,
2004-05-02 12:45:00 +04:00
const char * username ,
const char * client_username ,
const char * client_domain ,
2004-05-25 21:50:17 +04:00
const uint8_t * lm_pw , const uint8_t * nt_pw ,
2004-05-02 12:45:00 +04:00
DATA_BLOB * user_sess_key ,
DATA_BLOB * lm_sess_key )
{
2004-05-29 12:11:46 +04:00
static const uint8_t zeros [ 8 ] ;
2005-01-06 15:13:31 +03:00
DATA_BLOB tmp_sess_key ;
2004-05-02 12:45:00 +04:00
if ( nt_pw = = NULL ) {
DEBUG ( 3 , ( " ntlm_password_check: NO NT password stored for user %s. \n " ,
username ) ) ;
}
2004-11-07 15:40:07 +03:00
if ( lm_sess_key ) {
* lm_sess_key = data_blob ( NULL , 0 ) ;
}
if ( user_sess_key ) {
* user_sess_key = data_blob ( NULL , 0 ) ;
}
2004-06-05 08:32:50 +04:00
if ( nt_interactive_password & & nt_interactive_password - > length & & nt_pw ) {
if ( nt_interactive_password - > length ! = 16 ) {
DEBUG ( 3 , ( " ntlm_password_check: Interactive logon: Invalid NT password length (%d) supplied for user %s \n " , ( int ) nt_interactive_password - > length ,
2004-05-02 12:45:00 +04:00
username ) ) ;
return NT_STATUS_WRONG_PASSWORD ;
}
2004-06-05 08:32:50 +04:00
if ( memcmp ( nt_interactive_password - > data , nt_pw , 16 ) = = 0 ) {
2004-05-02 12:45:00 +04:00
if ( user_sess_key ) {
2004-10-08 12:05:11 +04:00
* user_sess_key = data_blob_talloc ( mem_ctx , NULL , 16 ) ;
2004-05-09 16:42:18 +04:00
SMBsesskeygen_ntv1 ( nt_pw , user_sess_key - > data ) ;
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 ;
}
2004-06-05 08:32:50 +04:00
} else if ( lm_interactive_password & & lm_interactive_password - > length & & lm_pw ) {
if ( lm_interactive_password - > length ! = 16 ) {
DEBUG ( 3 , ( " ntlm_password_check: Interactive logon: Invalid LANMAN password length (%d) supplied for user %s \n " , ( int ) lm_interactive_password - > length ,
2004-05-02 12:45:00 +04:00
username ) ) ;
return NT_STATUS_WRONG_PASSWORD ;
}
if ( ! lp_lanman_auth ( ) ) {
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 ;
}
2004-06-05 08:32:50 +04:00
if ( memcmp ( lm_interactive_password - > data , lm_pw , 16 ) = = 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 ;
}
}
/* Check for cleartext netlogon. Used by Exchange 5.5. */
if ( challenge - > length = = sizeof ( zeros ) & &
( memcmp ( challenge - > data , zeros , challenge - > length ) = = 0 ) ) {
DEBUG ( 4 , ( " ntlm_password_check: checking plaintext passwords for user %s \n " ,
username ) ) ;
if ( nt_pw & & nt_response - > length ) {
2004-05-29 12:11:46 +04:00
uint8_t pwhash [ 16 ] ;
2004-05-02 12:45:00 +04:00
mdfour ( pwhash , nt_response - > data , nt_response - > length ) ;
if ( memcmp ( pwhash , nt_pw , sizeof ( pwhash ) ) = = 0 ) {
return NT_STATUS_OK ;
} else {
DEBUG ( 3 , ( " ntlm_password_check: NT (Unicode) plaintext password check failed for user %s \n " ,
username ) ) ;
return NT_STATUS_WRONG_PASSWORD ;
}
} else if ( ! lp_lanman_auth ( ) ) {
DEBUG ( 3 , ( " ntlm_password_check: (plaintext password check) LANMAN passwords NOT PERMITTED for user %s \n " ,
username ) ) ;
} else if ( lm_pw & & lm_response - > length ) {
2004-06-01 12:30:34 +04:00
uint8_t dospwd [ 14 ] ;
uint8_t p16 [ 16 ] ;
2004-05-02 12:45:00 +04:00
ZERO_STRUCT ( dospwd ) ;
memcpy ( dospwd , lm_response - > data , MIN ( lm_response - > length , sizeof ( dospwd ) ) ) ;
/* Only the fisrt 14 chars are considered, password need not be null terminated. */
/* we *might* need to upper-case the string here */
2004-05-29 12:11:46 +04:00
E_P16 ( ( const uint8_t * ) dospwd , p16 ) ;
2004-05-02 12:45:00 +04:00
if ( memcmp ( p16 , lm_pw , sizeof ( p16 ) ) = = 0 ) {
return NT_STATUS_OK ;
} else {
DEBUG ( 3 , ( " ntlm_password_check: LANMAN (ASCII) plaintext password check failed for user %s \n " ,
username ) ) ;
return NT_STATUS_WRONG_PASSWORD ;
}
} else {
DEBUG ( 3 , ( " Plaintext authentication for user %s attempted, but neither NT nor LM passwords available \n " , username ) ) ;
return NT_STATUS_WRONG_PASSWORD ;
}
}
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-01-03 09:23:02 +03:00
if ( nt_response - > length > 24 & & nt_pw ) {
/* 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 ,
nt_pw , challenge ,
client_username ,
client_domain ,
False ,
user_sess_key ) ) {
if ( lm_sess_key ) {
* lm_sess_key = * user_sess_key ;
2005-01-06 15:13:31 +03:00
if ( user_sess_key - > length ) {
lm_sess_key - > length = 8 ;
}
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 ,
nt_pw , challenge ,
client_username ,
client_domain ,
True ,
user_sess_key ) ) {
if ( lm_sess_key ) {
* lm_sess_key = * user_sess_key ;
2005-01-06 15:13:31 +03:00
if ( user_sess_key - > length ) {
lm_sess_key - > length = 8 ;
}
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 ,
nt_pw , challenge ,
client_username ,
" " ,
False ,
user_sess_key ) ) {
if ( lm_sess_key ) {
* lm_sess_key = * user_sess_key ;
2005-01-06 15:13:31 +03:00
if ( user_sess_key - > length ) {
lm_sess_key - > length = 8 ;
}
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-01-03 09:23:02 +03:00
} else if ( nt_response - > length = = 24 & & nt_pw ) {
2004-05-02 12:45:00 +04:00
if ( lp_ntlm_auth ( ) ) {
/* 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 ,
2004-05-02 12:45:00 +04:00
nt_pw , challenge ,
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
2004-05-02 12:45:00 +04:00
if ( lp_lanman_auth ( ) & & lm_pw ) {
2004-10-08 12:05:11 +04:00
* lm_sess_key = data_blob_talloc ( mem_ctx , lm_pw , 8 ) ;
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 ;
}
if ( ! lp_lanman_auth ( ) ) {
DEBUG ( 3 , ( " ntlm_password_check: Lanman passwords NOT PERMITTED for user %s \n " ,
username ) ) ;
} else if ( ! lm_pw ) {
DEBUG ( 3 , ( " ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied) \n " ,
username ) ) ;
} 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 ,
2004-05-02 12:45:00 +04:00
lm_pw , challenge ,
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 */
if ( lp_lanman_auth ( ) & & lm_pw ) {
uint8_t first_8_lm_hash [ 16 ] ;
memcpy ( first_8_lm_hash , lm_pw , 8 ) ;
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 ) ;
* lm_sess_key = data_blob_talloc ( mem_ctx , lm_pw , 8 ) ;
2004-06-08 02:17:51 +04:00
}
2004-05-02 12:45:00 +04:00
return NT_STATUS_OK ;
}
}
if ( ! nt_pw ) {
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 ,
nt_pw , challenge ,
client_username ,
client_domain ,
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 ,
nt_pw , challenge ,
client_username ,
client_domain ,
False ,
user_sess_key ) ;
} else if ( user_sess_key ) {
/* Otherwise, use the LMv2 session key */
* user_sess_key = tmp_sess_key ;
}
if ( user_sess_key & & lm_sess_key ) {
2005-01-03 09:23:02 +03:00
* lm_sess_key = * user_sess_key ;
2005-01-06 15:13:31 +03:00
if ( user_sess_key - > length ) {
lm_sess_key - > length = 8 ;
}
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 ,
nt_pw , challenge ,
client_username ,
client_domain ,
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 ,
nt_pw , challenge ,
client_username ,
client_domain ,
True ,
user_sess_key ) ;
} else if ( user_sess_key ) {
/* Otherwise, use the LMv2 session key */
* user_sess_key = tmp_sess_key ;
}
if ( user_sess_key & & lm_sess_key ) {
2005-01-03 09:23:02 +03:00
* lm_sess_key = * user_sess_key ;
2005-01-06 15:13:31 +03:00
if ( user_sess_key - > length ) {
lm_sess_key - > length = 8 ;
}
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 ,
nt_pw , challenge ,
client_username ,
" " ,
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 ,
nt_pw , challenge ,
client_username ,
" " ,
False ,
user_sess_key ) ;
} else if ( user_sess_key ) {
/* Otherwise, use the LMv2 session key */
* user_sess_key = tmp_sess_key ;
}
if ( user_sess_key & & lm_sess_key ) {
2005-01-03 09:23:02 +03:00
* lm_sess_key = * user_sess_key ;
2005-01-06 15:13:31 +03:00
if ( user_sess_key - > length ) {
lm_sess_key - > length = 8 ;
}
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 " ) ) ;
if ( lp_ntlm_auth ( ) ) {
2004-10-08 12:05:11 +04:00
if ( smb_pwd_check_ntlmv1 ( mem_ctx ,
lm_response ,
2004-05-02 12:45:00 +04:00
nt_pw , challenge ,
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 */
if ( lp_lanman_auth ( ) & & lm_pw ) {
2004-05-25 21:50:17 +04:00
uint8_t first_8_lm_hash [ 16 ] ;
2004-05-02 12:45:00 +04:00
memcpy ( first_8_lm_hash , lm_pw , 8 ) ;
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 ) ;
* lm_sess_key = data_blob_talloc ( mem_ctx , lm_pw , 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 ) ) ;
}
return NT_STATUS_WRONG_PASSWORD ;
}