2009-09-15 04:53:21 +04:00
/*
2003-08-13 05:53:07 +04:00
Unix SMB / CIFS implementation .
SMB parameters and setup
Copyright ( C ) Andrew Tridgell 1992 - 1998
Modified by Jeremy Allison 1995.
Copyright ( C ) Jeremy Allison 1995 - 2000.
Copyright ( C ) Luke Kennethc Casson Leighton 1996 - 2000.
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2002 - 2003
2009-09-15 04:53:21 +04:00
2003-08-13 05:53:07 +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
2003-08-13 05:53:07 +04:00
( at your option ) any later version .
2009-09-15 04:53:21 +04:00
2003-08-13 05:53:07 +04:00
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 .
2009-09-15 04:53:21 +04:00
2003-08-13 05:53:07 +04:00
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/>.
2003-08-13 05:53:07 +04:00
*/
# include "includes.h"
2004-11-02 03:24:21 +03:00
# include "system/time.h"
2009-04-06 16:54:44 +04:00
# include "../libcli/auth/msrpc_parse.h"
2008-09-24 17:30:23 +04:00
# include "../lib/crypto/crypto.h"
2009-04-06 16:54:44 +04:00
# include "../libcli/auth/libcli_auth.h"
2016-02-23 21:08:31 +03:00
# include "../librpc/gen_ndr/ndr_ntlmssp.h"
2021-08-19 12:29:04 +03:00
# include "lib/util/bytearray.h"
2003-08-13 05:53:07 +04:00
2019-06-24 14:18:32 +03:00
# include "lib/crypto/gnutls_helpers.h"
2019-05-15 09:02:18 +03:00
# include <gnutls/gnutls.h>
# include <gnutls/crypto.h>
2019-11-08 17:40:01 +03:00
int SMBencrypt_hash ( const uint8_t lm_hash [ 16 ] , const uint8_t * c8 , uint8_t p24 [ 24 ] )
2003-08-13 05:53:07 +04:00
{
2004-06-01 12:30:34 +04:00
uint8_t p21 [ 21 ] ;
2019-11-08 17:40:01 +03:00
int rc ;
2003-08-13 05:53:07 +04:00
memset ( p21 , ' \0 ' , 21 ) ;
2009-03-16 13:19:10 +03:00
memcpy ( p21 , lm_hash , 16 ) ;
2003-08-13 05:53:07 +04:00
2019-11-08 17:40:01 +03:00
rc = SMBOWFencrypt ( p21 , c8 , p24 ) ;
2003-08-13 05:53:07 +04:00
# ifdef DEBUG_PASSWORD
2009-03-16 13:19:10 +03:00
DEBUG ( 100 , ( " SMBencrypt_hash: lm#, challenge, response \n " ) ) ;
2004-11-21 20:47:09 +03:00
dump_data ( 100 , p21 , 16 ) ;
dump_data ( 100 , c8 , 8 ) ;
dump_data ( 100 , p24 , 24 ) ;
2003-08-13 05:53:07 +04:00
# endif
2019-11-08 17:40:01 +03:00
return rc ;
2009-03-16 13:19:10 +03:00
}
2004-05-02 12:45:00 +04:00
2009-03-16 13:19:10 +03:00
/*
This implements the X / Open SMB password encryption
2009-09-15 04:53:21 +04:00
It takes a password ( ' unix ' string ) , a 8 byte " crypt key "
and puts 24 bytes of encrypted password into p24
2009-03-16 13:19:10 +03:00
Returns False if password must have been truncated to create LM hash
*/
bool SMBencrypt ( const char * passwd , const uint8_t * c8 , uint8_t p24 [ 24 ] )
{
bool ret ;
uint8_t lm_hash [ 16 ] ;
2019-11-08 17:40:01 +03:00
int rc ;
2009-03-16 13:19:10 +03:00
2009-09-15 04:53:21 +04:00
ret = E_deshash ( passwd , lm_hash ) ;
2019-11-08 17:40:01 +03:00
rc = SMBencrypt_hash ( lm_hash , c8 , p24 ) ;
if ( rc ! = 0 ) {
ret = false ;
}
2004-05-02 12:45:00 +04:00
return ret ;
2003-08-13 05:53:07 +04:00
}
/**
* Creates the MD4 Hash of the users password in NT UNICODE .
* @ param passwd password in ' unix ' charset .
* @ param p16 return password hashed with md4 , caller allocated 16 byte buffer
*/
2009-09-15 04:53:21 +04:00
2008-04-02 06:53:27 +04:00
bool E_md4hash ( const char * passwd , uint8_t p16 [ 16 ] )
2003-08-13 05:53:07 +04:00
{
2009-03-02 00:24:34 +03:00
size_t len ;
smb_ucs2_t * wpwd ;
bool ret ;
2003-08-13 05:53:07 +04:00
2009-03-02 00:24:34 +03:00
ret = push_ucs2_talloc ( NULL , & wpwd , passwd , & len ) ;
if ( ! ret | | len < 2 ) {
2006-10-23 10:06:35 +04:00
/* We don't want to return fixed data, as most callers
* don ' t check */
2007-01-31 12:25:37 +03:00
mdfour ( p16 , ( const uint8_t * ) passwd , strlen ( passwd ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-10-23 10:06:35 +04:00
}
2009-09-15 04:53:21 +04:00
r2552: Character set conversion and string handling updates.
The intial motivation for this commit was to merge in some of the
bugfixes present in Samba3's chrcnv and string handling code into
Samba4. However, along the way I found a lot of unused functions, and
decided to do a bit more...
The strlen_m code now does not use a fixed buffer, but more work is
needed to finish off other functions in str_util.c. These fixed
length buffers hav caused very nasty, hard to chase down bugs at some
sites.
The strupper_m() function has a strupper_talloc() to replace it (we
need to go around and fix more uses, but it's a start). Use of these
new functions will avoid bugs where the upper or lowercase version of
a string is a different length.
I have removed the push_*_allocate functions, which are replaced by
calls to push_*_talloc. Likewise, pstring and other 'fixed length'
wrappers are removed, where possible.
I have removed the first ('base pointer') argument, used by push_ucs2,
as the Samba4 way of doing things ensures that this is always on an
even boundary anyway. (It was used in only one place, in any case).
(This used to be commit dfecb0150627b500cb026b8a4932fe87902ca392)
2004-09-23 04:51:45 +04:00
len - = 2 ;
2009-03-02 00:24:34 +03:00
mdfour ( p16 , ( const uint8_t * ) wpwd , len ) ;
2004-10-08 12:13:00 +04:00
talloc_free ( wpwd ) ;
2007-10-07 02:28:14 +04:00
return true ;
2003-08-13 05:53:07 +04:00
}
/**
* Creates the DES forward - only Hash of the users password in DOS ASCII charset
* @ param passwd password in ' unix ' charset .
* @ param p16 return password hashed with DES , caller allocated 16 byte buffer
2007-10-07 02:28:14 +04:00
* @ return false if password was > 14 characters , and therefore may be incorrect , otherwise true
2004-05-02 12:45:00 +04:00
* @ note p16 is filled in regardless
2003-08-13 05:53:07 +04:00
*/
2009-09-15 04:53:21 +04:00
2008-04-02 06:53:27 +04:00
bool E_deshash ( const char * passwd , uint8_t p16 [ 16 ] )
2003-08-13 05:53:07 +04:00
{
2011-04-12 05:29:59 +04:00
bool ret ;
2019-11-07 18:16:26 +03:00
int rc ;
2011-04-12 05:29:59 +04:00
uint8_t dospwd [ 14 ] ;
2011-05-11 13:57:10 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2006-06-27 21:55:02 +04:00
2011-04-12 05:29:59 +04:00
size_t converted_size ;
2006-06-27 21:55:02 +04:00
2011-04-12 05:29:59 +04:00
char * tmpbuf ;
2003-08-13 05:53:07 +04:00
2011-04-12 05:29:59 +04:00
ZERO_STRUCT ( dospwd ) ;
2011-05-11 13:57:10 +04:00
tmpbuf = strupper_talloc ( frame , passwd ) ;
2011-04-12 05:29:59 +04:00
if ( tmpbuf = = NULL ) {
/* Too many callers don't check this result, we need to fill in the buffer with something */
2011-05-04 03:42:17 +04:00
strlcpy ( ( char * ) dospwd , passwd ? passwd : " " , sizeof ( dospwd ) ) ;
2011-04-12 05:29:59 +04:00
E_P16 ( dospwd , p16 ) ;
2011-05-11 13:57:10 +04:00
talloc_free ( frame ) ;
2011-04-12 05:29:59 +04:00
return false ;
2004-05-02 12:45:00 +04:00
}
2009-09-15 04:53:21 +04:00
ZERO_STRUCT ( dospwd ) ;
2004-05-02 12:45:00 +04:00
2011-04-12 05:29:59 +04:00
ret = convert_string_error ( CH_UNIX , CH_DOS , tmpbuf , strlen ( tmpbuf ) , dospwd , sizeof ( dospwd ) , & converted_size ) ;
2011-05-11 13:57:10 +04:00
talloc_free ( frame ) ;
2011-04-12 05:29:59 +04:00
/* Only the first 14 chars are considered, password need not
* be null terminated . We do this in the error and success
* case to avoid returning a fixed ' password ' buffer , but
* callers should not use it when E_deshash returns false */
2019-11-07 18:16:26 +03:00
rc = E_P16 ( ( const uint8_t * ) dospwd , p16 ) ;
if ( rc ! = 0 ) {
ret = false ;
}
2011-04-12 05:29:59 +04:00
ZERO_STRUCT ( dospwd ) ;
2004-05-02 12:45:00 +04:00
return ret ;
2003-08-13 05:53:07 +04:00
}
2009-03-16 13:19:10 +03:00
/**
2009-09-15 04:53:21 +04:00
* Creates the MD4 and DES ( LM ) Hash of the users password .
2009-03-16 13:19:10 +03:00
* MD4 is of the NT Unicode , DES is of the DOS UPPERCASE password .
* @ param passwd password in ' unix ' charset .
* @ param nt_p16 return password hashed with md4 , caller allocated 16 byte buffer
* @ param p16 return password hashed with des , caller allocated 16 byte buffer
*/
2009-09-15 04:53:21 +04:00
2009-03-16 13:19:10 +03:00
/* Does both the NT and LM owfs of a user's password */
void nt_lm_owf_gen ( const char * pwd , uint8_t nt_p16 [ 16 ] , uint8_t p16 [ 16 ] )
{
/* Calculate the MD4 hash (NT compatible) of the password */
memset ( nt_p16 , ' \0 ' , 16 ) ;
E_md4hash ( pwd , nt_p16 ) ;
# ifdef DEBUG_PASSWORD
DEBUG ( 100 , ( " nt_lm_owf_gen: pwd, nt# \n " ) ) ;
2009-06-15 17:46:58 +04:00
dump_data ( 120 , ( const uint8_t * ) pwd , strlen ( pwd ) ) ;
2009-03-16 13:19:10 +03:00
dump_data ( 100 , nt_p16 , 16 ) ;
# endif
E_deshash ( pwd , ( uint8_t * ) p16 ) ;
# ifdef DEBUG_PASSWORD
DEBUG ( 100 , ( " nt_lm_owf_gen: pwd, lm# \n " ) ) ;
2009-06-15 17:46:58 +04:00
dump_data ( 120 , ( const uint8_t * ) pwd , strlen ( pwd ) ) ;
2009-03-16 13:19:10 +03:00
dump_data ( 100 , p16 , 16 ) ;
# endif
}
2003-08-13 05:53:07 +04:00
/* Does both the NTLMv2 owfs of a user's password */
2007-10-07 02:28:14 +04:00
bool ntv2_owf_gen ( const uint8_t owf [ 16 ] ,
2004-05-02 12:45:00 +04:00
const char * user_in , const char * domain_in ,
2004-06-01 12:30:34 +04:00
uint8_t kr_buf [ 16 ] )
2003-08-13 05:53:07 +04:00
{
2009-03-02 00:24:34 +03:00
smb_ucs2_t * user ;
2009-09-15 04:53:21 +04:00
smb_ucs2_t * domain ;
2003-08-13 05:53:07 +04:00
size_t user_byte_len ;
size_t domain_byte_len ;
2019-05-15 09:05:11 +03:00
gnutls_hmac_hd_t hmac_hnd = NULL ;
int rc ;
bool ok = false ;
2009-09-15 04:53:21 +04:00
TALLOC_CTX * mem_ctx = talloc_init ( " ntv2_owf_gen for %s \\ %s " , domain_in , user_in ) ;
2008-02-21 16:50:57 +03:00
r2552: Character set conversion and string handling updates.
The intial motivation for this commit was to merge in some of the
bugfixes present in Samba3's chrcnv and string handling code into
Samba4. However, along the way I found a lot of unused functions, and
decided to do a bit more...
The strlen_m code now does not use a fixed buffer, but more work is
needed to finish off other functions in str_util.c. These fixed
length buffers hav caused very nasty, hard to chase down bugs at some
sites.
The strupper_m() function has a strupper_talloc() to replace it (we
need to go around and fix more uses, but it's a start). Use of these
new functions will avoid bugs where the upper or lowercase version of
a string is a different length.
I have removed the push_*_allocate functions, which are replaced by
calls to push_*_talloc. Likewise, pstring and other 'fixed length'
wrappers are removed, where possible.
I have removed the first ('base pointer') argument, used by push_ucs2,
as the Samba4 way of doing things ensures that this is always on an
even boundary anyway. (It was used in only one place, in any case).
(This used to be commit dfecb0150627b500cb026b8a4932fe87902ca392)
2004-09-23 04:51:45 +04:00
if ( ! mem_ctx ) {
2007-10-07 02:28:14 +04:00
return false ;
r2552: Character set conversion and string handling updates.
The intial motivation for this commit was to merge in some of the
bugfixes present in Samba3's chrcnv and string handling code into
Samba4. However, along the way I found a lot of unused functions, and
decided to do a bit more...
The strlen_m code now does not use a fixed buffer, but more work is
needed to finish off other functions in str_util.c. These fixed
length buffers hav caused very nasty, hard to chase down bugs at some
sites.
The strupper_m() function has a strupper_talloc() to replace it (we
need to go around and fix more uses, but it's a start). Use of these
new functions will avoid bugs where the upper or lowercase version of
a string is a different length.
I have removed the push_*_allocate functions, which are replaced by
calls to push_*_talloc. Likewise, pstring and other 'fixed length'
wrappers are removed, where possible.
I have removed the first ('base pointer') argument, used by push_ucs2,
as the Samba4 way of doing things ensures that this is always on an
even boundary anyway. (It was used in only one place, in any case).
(This used to be commit dfecb0150627b500cb026b8a4932fe87902ca392)
2004-09-23 04:51:45 +04:00
}
2003-08-13 05:53:07 +04:00
2005-03-06 11:24:34 +03:00
if ( ! user_in ) {
user_in = " " ;
}
if ( ! domain_in ) {
domain_in = " " ;
}
2004-10-08 12:13:00 +04:00
user_in = strupper_talloc ( mem_ctx , user_in ) ;
if ( user_in = = NULL ) {
talloc_free ( mem_ctx ) ;
2007-10-07 02:28:14 +04:00
return false ;
2004-10-08 12:13:00 +04:00
}
2018-12-04 11:49:17 +03:00
ok = push_ucs2_talloc ( mem_ctx , & user , user_in , & user_byte_len ) ;
if ( ! ok ) {
2009-03-16 13:19:10 +03:00
DEBUG ( 0 , ( " push_uss2_talloc() for user failed) \n " ) ) ;
r2552: Character set conversion and string handling updates.
The intial motivation for this commit was to merge in some of the
bugfixes present in Samba3's chrcnv and string handling code into
Samba4. However, along the way I found a lot of unused functions, and
decided to do a bit more...
The strlen_m code now does not use a fixed buffer, but more work is
needed to finish off other functions in str_util.c. These fixed
length buffers hav caused very nasty, hard to chase down bugs at some
sites.
The strupper_m() function has a strupper_talloc() to replace it (we
need to go around and fix more uses, but it's a start). Use of these
new functions will avoid bugs where the upper or lowercase version of
a string is a different length.
I have removed the push_*_allocate functions, which are replaced by
calls to push_*_talloc. Likewise, pstring and other 'fixed length'
wrappers are removed, where possible.
I have removed the first ('base pointer') argument, used by push_ucs2,
as the Samba4 way of doing things ensures that this is always on an
even boundary anyway. (It was used in only one place, in any case).
(This used to be commit dfecb0150627b500cb026b8a4932fe87902ca392)
2004-09-23 04:51:45 +04:00
talloc_free ( mem_ctx ) ;
2007-10-07 02:28:14 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
2018-12-04 11:49:17 +03:00
ok = push_ucs2_talloc ( mem_ctx , & domain , domain_in , & domain_byte_len ) ;
if ( ! ok ) {
2009-03-16 13:19:10 +03:00
DEBUG ( 0 , ( " push_ucs2_talloc() for domain failed \n " ) ) ;
r2552: Character set conversion and string handling updates.
The intial motivation for this commit was to merge in some of the
bugfixes present in Samba3's chrcnv and string handling code into
Samba4. However, along the way I found a lot of unused functions, and
decided to do a bit more...
The strlen_m code now does not use a fixed buffer, but more work is
needed to finish off other functions in str_util.c. These fixed
length buffers hav caused very nasty, hard to chase down bugs at some
sites.
The strupper_m() function has a strupper_talloc() to replace it (we
need to go around and fix more uses, but it's a start). Use of these
new functions will avoid bugs where the upper or lowercase version of
a string is a different length.
I have removed the push_*_allocate functions, which are replaced by
calls to push_*_talloc. Likewise, pstring and other 'fixed length'
wrappers are removed, where possible.
I have removed the first ('base pointer') argument, used by push_ucs2,
as the Samba4 way of doing things ensures that this is always on an
even boundary anyway. (It was used in only one place, in any case).
(This used to be commit dfecb0150627b500cb026b8a4932fe87902ca392)
2004-09-23 04:51:45 +04:00
talloc_free ( mem_ctx ) ;
2007-10-07 02:28:14 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
SMB_ASSERT ( user_byte_len > = 2 ) ;
SMB_ASSERT ( domain_byte_len > = 2 ) ;
/* We don't want null termination */
user_byte_len = user_byte_len - 2 ;
domain_byte_len = domain_byte_len - 2 ;
2009-09-15 04:53:21 +04:00
2019-05-15 09:05:11 +03:00
rc = gnutls_hmac_init ( & hmac_hnd ,
GNUTLS_MAC_MD5 ,
owf ,
16 ) ;
if ( rc < 0 ) {
ok = false ;
goto out ;
}
rc = gnutls_hmac ( hmac_hnd , user , user_byte_len ) ;
if ( rc < 0 ) {
gnutls_hmac_deinit ( hmac_hnd , NULL ) ;
ok = false ;
goto out ;
}
rc = gnutls_hmac ( hmac_hnd , domain , domain_byte_len ) ;
if ( rc < 0 ) {
gnutls_hmac_deinit ( hmac_hnd , NULL ) ;
ok = false ;
goto out ;
}
gnutls_hmac_deinit ( hmac_hnd , kr_buf ) ;
2003-08-13 05:53:07 +04:00
# ifdef DEBUG_PASSWORD
DEBUG ( 100 , ( " ntv2_owf_gen: user, domain, owfkey, kr \n " ) ) ;
2009-04-23 16:24:16 +04:00
dump_data ( 100 , ( uint8_t * ) user , user_byte_len ) ;
dump_data ( 100 , ( uint8_t * ) domain , domain_byte_len ) ;
2003-08-13 05:53:07 +04:00
dump_data ( 100 , owf , 16 ) ;
dump_data ( 100 , kr_buf , 16 ) ;
# endif
2019-05-15 09:05:11 +03:00
ok = true ;
out :
r2552: Character set conversion and string handling updates.
The intial motivation for this commit was to merge in some of the
bugfixes present in Samba3's chrcnv and string handling code into
Samba4. However, along the way I found a lot of unused functions, and
decided to do a bit more...
The strlen_m code now does not use a fixed buffer, but more work is
needed to finish off other functions in str_util.c. These fixed
length buffers hav caused very nasty, hard to chase down bugs at some
sites.
The strupper_m() function has a strupper_talloc() to replace it (we
need to go around and fix more uses, but it's a start). Use of these
new functions will avoid bugs where the upper or lowercase version of
a string is a different length.
I have removed the push_*_allocate functions, which are replaced by
calls to push_*_talloc. Likewise, pstring and other 'fixed length'
wrappers are removed, where possible.
I have removed the first ('base pointer') argument, used by push_ucs2,
as the Samba4 way of doing things ensures that this is always on an
even boundary anyway. (It was used in only one place, in any case).
(This used to be commit dfecb0150627b500cb026b8a4932fe87902ca392)
2004-09-23 04:51:45 +04:00
talloc_free ( mem_ctx ) ;
2019-05-15 09:05:11 +03:00
return ok ;
2003-08-13 05:53:07 +04:00
}
/* Does the des encryption from the NT or LM MD4 hash. */
2019-11-08 17:40:01 +03:00
int SMBOWFencrypt ( const uint8_t passwd [ 16 ] , const uint8_t * c8 , uint8_t p24 [ 24 ] )
2003-08-13 05:53:07 +04:00
{
2004-06-01 12:30:34 +04:00
uint8_t p21 [ 21 ] ;
2003-08-13 05:53:07 +04:00
ZERO_STRUCT ( p21 ) ;
2009-09-15 04:53:21 +04:00
memcpy ( p21 , passwd , 16 ) ;
2019-11-08 17:40:01 +03:00
return E_P24 ( p21 , c8 , p24 ) ;
2003-08-13 05:53:07 +04:00
}
2009-03-16 13:19:10 +03:00
/* Does the des encryption. */
2009-09-15 04:53:21 +04:00
2019-11-08 17:40:01 +03:00
int SMBNTencrypt_hash ( const uint8_t nt_hash [ 16 ] , const uint8_t * c8 , uint8_t * p24 )
2003-08-13 05:53:07 +04:00
{
2004-06-01 12:30:34 +04:00
uint8_t p21 [ 21 ] ;
2019-11-08 17:40:01 +03:00
int rc ;
2009-09-15 04:53:21 +04:00
2003-08-13 05:53:07 +04:00
memset ( p21 , ' \0 ' , 21 ) ;
2009-03-16 13:19:10 +03:00
memcpy ( p21 , nt_hash , 16 ) ;
2019-11-08 17:40:01 +03:00
rc = SMBOWFencrypt ( p21 , c8 , p24 ) ;
2003-08-13 05:53:07 +04:00
# ifdef DEBUG_PASSWORD
DEBUG ( 100 , ( " SMBNTencrypt: nt#, challenge, response \n " ) ) ;
2004-11-21 20:47:09 +03:00
dump_data ( 100 , p21 , 16 ) ;
dump_data ( 100 , c8 , 8 ) ;
dump_data ( 100 , p24 , 24 ) ;
2003-08-13 05:53:07 +04:00
# endif
2019-11-08 17:40:01 +03:00
return rc ;
2003-08-13 05:53:07 +04:00
}
2009-03-16 13:19:10 +03:00
/* Does the NT MD4 hash then des encryption. Plaintext version of the above. */
2019-11-08 17:40:01 +03:00
int SMBNTencrypt ( const char * passwd , const uint8_t * c8 , uint8_t * p24 )
2009-03-16 13:19:10 +03:00
{
uint8_t nt_hash [ 16 ] ;
2009-09-15 04:53:21 +04:00
E_md4hash ( passwd , nt_hash ) ;
2019-11-08 17:40:01 +03:00
return SMBNTencrypt_hash ( nt_hash , c8 , p24 ) ;
2009-03-16 13:19:10 +03:00
}
2003-11-26 04:16:41 +03:00
/* Does the md5 encryption from the Key Response for NTLMv2. */
2019-11-13 14:48:18 +03:00
NTSTATUS SMBOWFencrypt_ntv2 ( const uint8_t kr [ 16 ] ,
const DATA_BLOB * srv_chal ,
const DATA_BLOB * smbcli_chal ,
uint8_t resp_buf [ 16 ] )
2003-08-13 05:53:07 +04:00
{
2019-05-15 09:05:38 +03:00
gnutls_hmac_hd_t hmac_hnd = NULL ;
2019-11-13 14:48:18 +03:00
NTSTATUS status ;
2019-05-15 09:05:38 +03:00
int rc ;
rc = gnutls_hmac_init ( & hmac_hnd ,
GNUTLS_MAC_MD5 ,
kr ,
16 ) ;
if ( rc < 0 ) {
2019-11-13 14:48:18 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_HMAC_NOT_SUPPORTED ) ;
2019-05-15 09:05:38 +03:00
}
rc = gnutls_hmac ( hmac_hnd , srv_chal - > data , srv_chal - > length ) ;
if ( rc < 0 ) {
2019-11-13 14:48:18 +03:00
status = gnutls_error_to_ntstatus ( rc , NT_STATUS_HMAC_NOT_SUPPORTED ) ;
goto out ;
2019-05-15 09:05:38 +03:00
}
rc = gnutls_hmac ( hmac_hnd , smbcli_chal - > data , smbcli_chal - > length ) ;
if ( rc < 0 ) {
2019-11-13 14:48:18 +03:00
status = gnutls_error_to_ntstatus ( rc , NT_STATUS_HMAC_NOT_SUPPORTED ) ;
goto out ;
2019-05-15 09:05:38 +03:00
}
2003-08-13 05:53:07 +04:00
2024-06-03 13:56:02 +03:00
status = NT_STATUS_OK ;
out :
gnutls_hmac_deinit ( hmac_hnd , resp_buf ) ;
2003-08-13 05:53:07 +04:00
# ifdef DEBUG_PASSWORD
2024-06-03 13:56:02 +03:00
DEBUG ( 100 , ( " SMBOWFencrypt_ntv2: srv_chal, smbcli_chal, resp_buf: %s \n " ,
nt_errstr ( status ) ) ) ;
2003-11-26 04:16:41 +03:00
dump_data ( 100 , srv_chal - > data , srv_chal - > length ) ;
2004-08-04 17:23:35 +04:00
dump_data ( 100 , smbcli_chal - > data , smbcli_chal - > length ) ;
2003-08-13 05:53:07 +04:00
dump_data ( 100 , resp_buf , 16 ) ;
# endif
2019-11-13 14:48:18 +03:00
return status ;
2003-08-13 05:53:07 +04:00
}
2019-11-13 14:40:02 +03:00
NTSTATUS SMBsesskeygen_ntv2 ( const uint8_t kr [ 16 ] ,
const uint8_t * nt_resp ,
uint8_t sess_key [ 16 ] )
2003-08-13 05:53:07 +04:00
{
2019-11-13 14:40:02 +03:00
int rc ;
2003-11-26 04:16:41 +03:00
/* a very nice, 128 bit, variable session key */
2019-11-13 14:40:02 +03:00
rc = gnutls_hmac_fast ( GNUTLS_MAC_MD5 ,
kr ,
16 ,
nt_resp ,
16 ,
sess_key ) ;
if ( rc ! = 0 ) {
2023-11-23 09:40:41 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_HMAC_NOT_SUPPORTED ) ;
2019-11-13 14:40:02 +03:00
}
2003-08-13 05:53:07 +04:00
# ifdef DEBUG_PASSWORD
DEBUG ( 100 , ( " SMBsesskeygen_ntv2: \n " ) ) ;
dump_data ( 100 , sess_key , 16 ) ;
# endif
2019-11-13 14:40:02 +03:00
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
}
2004-06-01 12:30:34 +04:00
void SMBsesskeygen_ntv1 ( const uint8_t kr [ 16 ] , uint8_t sess_key [ 16 ] )
2003-08-13 05:53:07 +04:00
{
2009-09-15 04:53:21 +04:00
/* yes, this session key does not change - yes, this
2003-11-26 04:16:41 +03:00
is a problem - but it is 128 bits */
2009-09-15 04:53:21 +04:00
2004-05-29 12:11:46 +04:00
mdfour ( ( uint8_t * ) sess_key , kr , 16 ) ;
2003-08-13 05:53:07 +04:00
# ifdef DEBUG_PASSWORD
DEBUG ( 100 , ( " SMBsesskeygen_ntv1: \n " ) ) ;
dump_data ( 100 , sess_key , 16 ) ;
# endif
}
2019-11-07 15:39:20 +03:00
NTSTATUS SMBsesskeygen_lm_sess_key ( const uint8_t lm_hash [ 16 ] ,
2009-09-15 04:53:21 +04:00
const uint8_t lm_resp [ 24 ] , /* only uses 8 */
2004-05-25 21:50:17 +04:00
uint8_t sess_key [ 16 ] )
2003-11-26 04:16:41 +03:00
{
/* Calculate the LM session key (effective length 40 bits,
but changes with each session ) */
2004-06-01 12:30:34 +04:00
uint8_t p24 [ 24 ] ;
2006-02-12 15:04:41 +03:00
uint8_t partial_lm_hash [ 14 ] ;
2019-11-07 15:39:20 +03:00
int rc ;
2009-09-15 04:53:21 +04:00
memcpy ( partial_lm_hash , lm_hash , 8 ) ;
2006-02-12 15:04:41 +03:00
memset ( partial_lm_hash + 8 , 0xbd , 6 ) ;
2003-11-26 04:16:41 +03:00
2019-11-07 15:39:20 +03:00
rc = des_crypt56_gnutls ( p24 , lm_resp , partial_lm_hash , SAMBA_GNUTLS_ENCRYPT ) ;
if ( rc < 0 ) {
return gnutls_error_to_ntstatus ( rc , NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ) ;
}
rc = des_crypt56_gnutls ( p24 + 8 , lm_resp , partial_lm_hash + 7 , SAMBA_GNUTLS_ENCRYPT ) ;
if ( rc < 0 ) {
return gnutls_error_to_ntstatus ( rc , NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ) ;
}
2004-05-02 12:45:00 +04:00
memcpy ( sess_key , p24 , 16 ) ;
# ifdef DEBUG_PASSWORD
2004-05-02 16:42:01 +04:00
DEBUG ( 100 , ( " SMBsesskeygen_lm_sess_key: \n " ) ) ;
2004-05-02 12:45:00 +04:00
dump_data ( 100 , sess_key , 16 ) ;
# endif
2019-11-07 15:39:20 +03:00
return NT_STATUS_OK ;
2004-05-02 12:45:00 +04:00
}
2009-09-15 04:53:21 +04:00
DATA_BLOB NTLMv2_generate_names_blob ( TALLOC_CTX * mem_ctx ,
const char * hostname ,
2003-11-26 04:16:41 +03:00
const char * domain )
{
2004-05-25 18:06:28 +04:00
DATA_BLOB names_blob = data_blob_talloc ( mem_ctx , NULL , 0 ) ;
2009-09-15 04:53:21 +04:00
2011-03-29 00:26:27 +04:00
/* Deliberately ignore return here.. */
2011-04-07 16:01:50 +04:00
if ( hostname ! = NULL ) {
( void ) msrpc_gen ( mem_ctx , & names_blob ,
" aaa " ,
MsvAvNbDomainName , domain ,
MsvAvNbComputerName , hostname ,
MsvAvEOL , " " ) ;
} else {
( void ) msrpc_gen ( mem_ctx , & names_blob ,
" aa " ,
MsvAvNbDomainName , domain ,
MsvAvEOL , " " ) ;
}
2003-11-26 04:16:41 +03:00
return names_blob ;
}
2015-11-20 11:31:35 +03:00
static DATA_BLOB NTLMv2_generate_client_data ( TALLOC_CTX * mem_ctx ,
NTTIME nttime ,
const DATA_BLOB * names_blob )
2003-11-26 04:16:41 +03:00
{
2004-06-01 12:30:34 +04:00
uint8_t client_chal [ 8 ] ;
2003-11-26 04:16:41 +03:00
DATA_BLOB response = data_blob ( NULL , 0 ) ;
2004-12-04 16:56:25 +03:00
uint8_t long_date [ 8 ] ;
2003-11-26 04:16:41 +03:00
2004-07-14 16:14:07 +04:00
generate_random_buffer ( client_chal , sizeof ( client_chal ) ) ;
2003-11-26 04:16:41 +03:00
2004-05-25 17:57:39 +04:00
push_nttime ( long_date , 0 , nttime ) ;
2003-11-26 04:16:41 +03:00
/* See http://www.ubiqx.org/cifs/SMB.html#SMB.8.5 */
2011-03-29 00:26:27 +04:00
/* Deliberately ignore return here.. */
( void ) msrpc_gen ( mem_ctx , & response , " ddbbdb " ,
2004-06-28 10:46:27 +04:00
0x00000101 , /* Header */
0 , /* 'Reserved' */
long_date , 8 , /* Timestamp */
client_chal , 8 , /* client challenge */
0 , /* Unknown */
names_blob - > data , names_blob - > length ) ; /* End of name list */
2003-11-26 04:16:41 +03:00
return response ;
}
2009-09-15 04:53:21 +04:00
static DATA_BLOB NTLMv2_generate_response ( TALLOC_CTX * out_mem_ctx ,
2005-06-19 17:26:32 +04:00
const uint8_t ntlm_v2_hash [ 16 ] ,
2003-11-26 04:16:41 +03:00
const DATA_BLOB * server_chal ,
2015-11-20 11:31:35 +03:00
NTTIME nttime ,
2003-11-26 04:16:41 +03:00
const DATA_BLOB * names_blob )
2003-08-13 05:53:07 +04:00
{
2004-06-01 12:30:34 +04:00
uint8_t ntlmv2_response [ 16 ] ;
2003-08-13 05:53:07 +04:00
DATA_BLOB ntlmv2_client_data ;
DATA_BLOB final_response ;
2019-11-13 14:52:44 +03:00
NTSTATUS status ;
2009-09-15 04:53:21 +04:00
TALLOC_CTX * mem_ctx = talloc_named ( out_mem_ctx , 0 ,
2005-06-19 17:26:32 +04:00
" NTLMv2_generate_response internal context " ) ;
2004-05-25 18:06:28 +04:00
if ( ! mem_ctx ) {
return data_blob ( NULL , 0 ) ;
}
2009-09-15 04:53:21 +04:00
2003-08-13 05:53:07 +04:00
/* NTLMv2 */
2003-11-26 04:16:41 +03:00
/* generate some data to pass into the response function - including
the hostname and domain name of the server */
2015-11-20 11:31:35 +03:00
ntlmv2_client_data = NTLMv2_generate_client_data ( mem_ctx , nttime , names_blob ) ;
2003-08-13 05:53:07 +04:00
/* Given that data, and the challenge from the server, generate a response */
2019-11-13 14:52:44 +03:00
status = SMBOWFencrypt_ntv2 ( ntlm_v2_hash ,
server_chal ,
& ntlmv2_client_data ,
ntlmv2_response ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( mem_ctx ) ;
return data_blob ( NULL , 0 ) ;
}
2009-09-15 04:53:21 +04:00
2005-10-04 16:04:10 +04:00
final_response = data_blob_talloc ( out_mem_ctx , NULL , sizeof ( ntlmv2_response ) + ntlmv2_client_data . length ) ;
2003-11-26 04:16:41 +03:00
2003-08-13 05:53:07 +04:00
memcpy ( final_response . data , ntlmv2_response , sizeof ( ntlmv2_response ) ) ;
2003-11-26 04:16:41 +03:00
2009-09-15 04:53:21 +04:00
memcpy ( final_response . data + sizeof ( ntlmv2_response ) ,
2003-11-26 04:16:41 +03:00
ntlmv2_client_data . data , ntlmv2_client_data . length ) ;
2005-01-27 10:08:20 +03:00
talloc_free ( mem_ctx ) ;
2003-08-13 05:53:07 +04:00
return final_response ;
}
2009-09-15 04:53:21 +04:00
static DATA_BLOB LMv2_generate_response ( TALLOC_CTX * mem_ctx ,
2005-06-19 17:26:32 +04:00
const uint8_t ntlm_v2_hash [ 16 ] ,
2003-11-26 04:16:41 +03:00
const DATA_BLOB * server_chal )
{
2004-06-01 12:30:34 +04:00
uint8_t lmv2_response [ 16 ] ;
2005-10-04 16:04:10 +04:00
DATA_BLOB lmv2_client_data = data_blob_talloc ( mem_ctx , NULL , 8 ) ;
DATA_BLOB final_response = data_blob_talloc ( mem_ctx , NULL , 24 ) ;
2019-11-13 14:52:44 +03:00
NTSTATUS status ;
2009-09-15 04:53:21 +04:00
2003-11-26 04:16:41 +03:00
/* LMv2 */
/* client-supplied random data */
2009-09-15 04:53:21 +04:00
generate_random_buffer ( lmv2_client_data . data , lmv2_client_data . length ) ;
2003-11-26 04:16:41 +03:00
/* Given that data, and the challenge from the server, generate a response */
2019-11-13 14:52:44 +03:00
status = SMBOWFencrypt_ntv2 ( ntlm_v2_hash ,
server_chal ,
& lmv2_client_data ,
lmv2_response ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
data_blob_free ( & lmv2_client_data ) ;
return data_blob ( NULL , 0 ) ;
}
2003-11-26 04:16:41 +03:00
memcpy ( final_response . data , lmv2_response , sizeof ( lmv2_response ) ) ;
2009-09-15 04:53:21 +04:00
/* after the first 16 bytes is the random data we generated above,
2003-11-26 04:16:41 +03:00
so the server can verify us with it */
2009-09-15 04:53:21 +04:00
memcpy ( final_response . data + sizeof ( lmv2_response ) ,
2003-11-26 04:16:41 +03:00
lmv2_client_data . data , lmv2_client_data . length ) ;
data_blob_free ( & lmv2_client_data ) ;
return final_response ;
}
2009-09-15 04:53:21 +04:00
bool SMBNTLMv2encrypt_hash ( TALLOC_CTX * mem_ctx ,
2005-06-19 17:26:32 +04:00
const char * user , const char * domain , const uint8_t nt_hash [ 16 ] ,
2009-09-15 04:53:21 +04:00
const DATA_BLOB * server_chal ,
2015-11-20 11:31:35 +03:00
const NTTIME * server_timestamp ,
2004-11-12 02:24:30 +03:00
const DATA_BLOB * names_blob ,
2009-09-15 04:53:21 +04:00
DATA_BLOB * lm_response , DATA_BLOB * nt_response ,
DATA_BLOB * lm_session_key , DATA_BLOB * user_session_key )
2003-08-13 05:53:07 +04:00
{
2004-06-01 12:30:34 +04:00
uint8_t ntlm_v2_hash [ 16 ] ;
2019-11-13 14:45:04 +03:00
NTSTATUS status ;
2003-08-13 05:53:07 +04:00
/* We don't use the NT# directly. Instead we use it mashed up with
the username and domain .
This prevents username swapping during the auth exchange
*/
2012-08-24 03:02:09 +04:00
if ( ! ntv2_owf_gen ( nt_hash , user , domain , ntlm_v2_hash ) ) {
2007-10-07 02:28:14 +04:00
return false ;
2003-08-13 05:53:07 +04:00
}
2009-09-15 04:53:21 +04:00
2003-11-26 04:16:41 +03:00
if ( nt_response ) {
2015-11-20 11:31:35 +03:00
const NTTIME * nttime = server_timestamp ;
NTTIME _now = 0 ;
if ( nttime = = NULL ) {
struct timeval tv_now = timeval_current ( ) ;
_now = timeval_to_nttime ( & tv_now ) ;
nttime = & _now ;
}
2009-09-15 04:53:21 +04:00
* nt_response = NTLMv2_generate_response ( mem_ctx ,
2015-11-20 11:31:35 +03:00
ntlm_v2_hash ,
server_chal ,
* nttime ,
2009-09-15 04:53:21 +04:00
names_blob ) ;
2004-05-02 12:45:00 +04:00
if ( user_session_key ) {
2005-10-04 16:04:10 +04:00
* user_session_key = data_blob_talloc ( mem_ctx , NULL , 16 ) ;
2009-09-15 04:53:21 +04:00
2003-11-26 04:16:41 +03:00
/* The NTLMv2 calculations also provide a session key, for signing etc later */
/* use only the first 16 bytes of nt_response for session key */
2019-11-13 14:45:04 +03:00
status = SMBsesskeygen_ntv2 ( ntlm_v2_hash ,
nt_response - > data ,
user_session_key - > data ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return false ;
}
2003-11-26 04:16:41 +03:00
}
}
2009-09-15 04:53:21 +04:00
2003-08-13 05:53:07 +04:00
/* LMv2 */
2009-09-15 04:53:21 +04:00
2003-11-26 04:16:41 +03:00
if ( lm_response ) {
2015-11-20 11:31:35 +03:00
if ( server_timestamp ! = NULL ) {
* lm_response = data_blob_talloc_zero ( mem_ctx , 24 ) ;
} else {
* lm_response = LMv2_generate_response ( mem_ctx ,
ntlm_v2_hash ,
server_chal ) ;
}
2004-11-10 13:58:15 +03:00
if ( lm_session_key ) {
2005-10-04 16:04:10 +04:00
* lm_session_key = data_blob_talloc ( mem_ctx , NULL , 16 ) ;
2009-09-15 04:53:21 +04:00
2004-11-10 13:58:15 +03:00
/* The NTLMv2 calculations also provide a session key, for signing etc later */
/* use only the first 16 bytes of lm_response for session key */
2019-11-13 14:45:04 +03:00
status = SMBsesskeygen_ntv2 ( ntlm_v2_hash ,
lm_response - > data ,
lm_session_key - > data ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return false ;
}
2004-11-10 13:58:15 +03:00
}
2003-11-26 04:16:41 +03:00
}
2009-09-15 04:53:21 +04:00
2007-10-07 02:28:14 +04:00
return true ;
2003-08-13 05:53:07 +04:00
}
2009-09-15 04:53:21 +04:00
bool SMBNTLMv2encrypt ( TALLOC_CTX * mem_ctx ,
const char * user , const char * domain ,
const char * password ,
const DATA_BLOB * server_chal ,
2004-11-12 02:24:30 +03:00
const DATA_BLOB * names_blob ,
2009-09-15 04:53:21 +04:00
DATA_BLOB * lm_response , DATA_BLOB * nt_response ,
DATA_BLOB * lm_session_key , DATA_BLOB * user_session_key )
2004-11-12 02:24:30 +03:00
{
uint8_t nt_hash [ 16 ] ;
E_md4hash ( password , nt_hash ) ;
2009-09-15 04:53:21 +04:00
return SMBNTLMv2encrypt_hash ( mem_ctx ,
2015-11-20 11:31:35 +03:00
user , domain , nt_hash ,
server_chal , NULL , names_blob ,
2004-11-12 02:24:30 +03:00
lm_response , nt_response , lm_session_key , user_session_key ) ;
}
2016-02-23 21:08:31 +03:00
NTSTATUS NTLMv2_RESPONSE_verify_netlogon_creds ( const char * account_name ,
const char * account_domain ,
const DATA_BLOB response ,
const struct netlogon_creds_CredentialState * creds ,
const char * workgroup )
{
TALLOC_CTX * frame = NULL ;
/* RespType + HiRespType */
static const char * magic = " \x01 \x01 " ;
int cmp ;
struct NTLMv2_RESPONSE v2_resp ;
enum ndr_err_code err ;
const struct AV_PAIR * av_nb_cn = NULL ;
const struct AV_PAIR * av_nb_dn = NULL ;
if ( response . length < 48 ) {
/*
* NTLMv2_RESPONSE has at least 48 bytes .
*/
return NT_STATUS_OK ;
}
cmp = memcmp ( response . data + 16 , magic , 2 ) ;
if ( cmp ! = 0 ) {
/*
* It doesn ' t look like a valid NTLMv2_RESPONSE
*/
return NT_STATUS_OK ;
}
2021-12-15 19:25:06 +03:00
if ( response . length = = 95 ) {
/*
* ndr_pull_NTLMv2_RESPONSE ( ) fails on this strange blob ,
* because the AvPairs content is not valid
* as AvLen of the first pair is 33032 ( 0x8108 ) .
*
* I saw a single machine sending the following 3 times
* in a row , but I ' m not sure if everything is static .
*
* Note this is NTLMv2_CLIENT_CHALLENGE only , not
* the full NTLMv2_RESPONSE ( which has Response of 16 bytes
* before the NTLMv2_CLIENT_CHALLENGE ) .
*
* Note this code only prevents
* ndr_pull_error ( Buffer Size Error ) : Pull bytes 39016
* debug message for a known case , the actual
* bug is also handled below in a generic way to
* map NT_STATUS_BUFFER_TOO_SMALL to NT_STATUS_OK .
*
* See https : //bugzilla.samba.org/show_bug.cgi?id=14932
*/
static const char * netapp_magic =
" \x01 \x01 \x00 \x00 \x00 \x00 \x00 \x00 "
" \x3f \x3f \x3f \x3f \x3f \x3f \x3f \x3f "
" \xb8 \x82 \x3a \xf1 \xb3 \xdd \x08 \x15 "
" \x00 \x00 \x00 \x00 \x11 \xa2 \x08 \x81 "
" \x50 \x38 \x22 \x78 \x2b \x94 \x47 \xfe "
" \x54 \x94 \x7b \xff \x17 \x27 \x5a \xb4 "
" \xf4 \x18 \xba \xdc \x2c \x38 \xfd \x5b "
" \xfb \x0e \xc1 \x85 \x1e \xcc \x92 \xbb "
" \x9b \xb1 \xc4 \xd5 \x53 \x14 \xff \x8c "
" \x76 \x49 \xf5 \x45 \x90 \x19 \xa2 " ;
/*
* First we check the initial bytes
* and the 0x3F timestamp .
*/
cmp = memcmp ( response . data + 16 ,
netapp_magic ,
16 ) ;
if ( cmp = = 0 ) {
/*
* Then check everything after the
* client challenge
*/
cmp = memcmp ( response . data + 40 ,
netapp_magic + 24 ,
response . length - 40 ) ;
if ( cmp = = 0 ) {
DBG_DEBUG ( " Invalid NETAPP NTLMv2_RESPONSE "
" for user[%s \\ %s] against "
" SEC_CHAN(%u)[%s/%s] "
" in workgroup[%s] \n " ,
account_domain ,
account_name ,
creds - > secure_channel_type ,
creds - > computer_name ,
creds - > account_name ,
workgroup ) ;
return NT_STATUS_OK ;
}
}
}
2016-02-23 21:08:31 +03:00
frame = talloc_stackframe ( ) ;
err = ndr_pull_struct_blob ( & response , frame , & v2_resp ,
( ndr_pull_flags_fn_t ) ndr_pull_NTLMv2_RESPONSE ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
NTSTATUS status ;
status = ndr_map_error2ntstatus ( err ) ;
2021-12-15 19:25:06 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_BUFFER_TOO_SMALL ) ) {
/*
* We are supposed to ignore invalid buffers ,
* see https : //bugzilla.samba.org/show_bug.cgi?id=14932
*/
status = NT_STATUS_OK ;
}
DEBUG ( 2 , ( " %s: Failed to parse NTLMv2_RESPONSE length=%u "
" for user[%s \\ %s] against SEC_CHAN(%u)[%s/%s] "
" in workgroup[%s] - %s %s %s \n " ,
__func__ ,
( unsigned ) response . length ,
account_domain ,
account_name ,
creds - > secure_channel_type ,
creds - > computer_name ,
creds - > account_name ,
workgroup ,
ndr_map_error2string ( err ) ,
NT_STATUS_IS_OK ( status ) ? " (ignoring) => " : " => " ,
nt_errstr ( status ) ) ) ;
2016-02-23 21:08:31 +03:00
dump_data ( 2 , response . data , response . length ) ;
TALLOC_FREE ( frame ) ;
return status ;
}
if ( DEBUGLVL ( 10 ) ) {
NDR_PRINT_DEBUG ( NTLMv2_RESPONSE , & v2_resp ) ;
}
/*
* Make sure the netbios computer name in the
* NTLMv2_RESPONSE matches the computer name
* in the secure channel credentials for workstation
* trusts .
*
* And the netbios domain name matches our
* workgroup .
*
* This prevents workstations from requesting
* the session key of NTLMSSP sessions of clients
* to other hosts .
*/
if ( creds - > secure_channel_type = = SEC_CHAN_WKSTA ) {
av_nb_cn = ndr_ntlmssp_find_av ( & v2_resp . Challenge . AvPairs ,
MsvAvNbComputerName ) ;
av_nb_dn = ndr_ntlmssp_find_av ( & v2_resp . Challenge . AvPairs ,
MsvAvNbDomainName ) ;
}
if ( av_nb_cn ! = NULL ) {
const char * v = NULL ;
char * a = NULL ;
size_t len ;
v = av_nb_cn - > Value . AvNbComputerName ;
a = talloc_strdup ( frame , creds - > account_name ) ;
if ( a = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
len = strlen ( a ) ;
if ( len > 0 & & a [ len - 1 ] = = ' $ ' ) {
a [ len - 1 ] = ' \0 ' ;
}
cmp = strcasecmp_m ( a , v ) ;
if ( cmp ! = 0 ) {
DEBUG ( 2 , ( " %s: NTLMv2_RESPONSE with "
" NbComputerName[%s] rejected "
" for user[%s \\ %s] "
" against SEC_CHAN_WKSTA[%s/%s] "
" in workgroup[%s] \n " ,
__func__ , v ,
account_domain ,
account_name ,
creds - > computer_name ,
creds - > account_name ,
workgroup ) ) ;
TALLOC_FREE ( frame ) ;
return NT_STATUS_LOGON_FAILURE ;
}
}
if ( av_nb_dn ! = NULL ) {
const char * v = NULL ;
v = av_nb_dn - > Value . AvNbDomainName ;
cmp = strcasecmp_m ( workgroup , v ) ;
if ( cmp ! = 0 ) {
DEBUG ( 2 , ( " %s: NTLMv2_RESPONSE with "
" NbDomainName[%s] rejected "
" for user[%s \\ %s] "
" against SEC_CHAN_WKSTA[%s/%s] "
" in workgroup[%s] \n " ,
__func__ , v ,
account_domain ,
account_name ,
creds - > computer_name ,
creds - > account_name ,
workgroup ) ) ;
TALLOC_FREE ( frame ) ;
return NT_STATUS_LOGON_FAILURE ;
}
}
TALLOC_FREE ( frame ) ;
return NT_STATUS_OK ;
}
2022-07-22 15:26:43 +03:00
enum encode_order {
ENCODE_ORDER_PASSWORD_FIRST ,
ENCODE_ORDER_PASSWORD_LAST ,
} ;
# define PASSWORD_BUFFER_LEN 512
static ssize_t _encode_pwd_buffer_from_str ( uint8_t buf [ PASSWORD_BUFFER_LEN ] ,
const char * password ,
int string_flags ,
enum encode_order order )
{
ssize_t new_pw_len ;
size_t pw_pos = 0 ;
size_t random_pos = 0 ;
size_t random_len = 0 ;
/* The incoming buffer can be any alignment. */
string_flags | = STR_NOALIGN ;
new_pw_len = push_string ( buf ,
password ,
PASSWORD_BUFFER_LEN ,
string_flags ) ;
if ( new_pw_len < 0 ) {
BURN_DATA_SIZE ( buf , PASSWORD_BUFFER_LEN ) ;
return - 1 ;
}
if ( new_pw_len = = PASSWORD_BUFFER_LEN ) {
return new_pw_len ;
}
switch ( order ) {
case ENCODE_ORDER_PASSWORD_FIRST :
pw_pos = 0 ;
random_pos = new_pw_len ;
random_len = PASSWORD_BUFFER_LEN - random_pos ;
break ;
case ENCODE_ORDER_PASSWORD_LAST :
pw_pos = PASSWORD_BUFFER_LEN - new_pw_len ;
random_pos = 0 ;
random_len = pw_pos ;
memmove ( buf + pw_pos , buf , new_pw_len ) ;
break ;
}
generate_random_buffer ( buf + random_pos , random_len ) ;
return new_pw_len ;
}
2003-08-13 05:53:07 +04:00
/***********************************************************
2004-04-21 09:01:31 +04:00
encode a password buffer with a unicode password . The buffer
is filled with random data to make it harder to attack .
2003-08-13 05:53:07 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-07 02:28:14 +04:00
bool encode_pw_buffer ( uint8_t buffer [ 516 ] , const char * password , int string_flags )
2003-08-13 05:53:07 +04:00
{
2022-07-22 15:26:43 +03:00
ssize_t pw_len ;
2003-08-13 05:53:07 +04:00
2022-07-22 15:26:43 +03:00
pw_len = _encode_pwd_buffer_from_str ( buffer ,
password ,
string_flags ,
ENCODE_ORDER_PASSWORD_LAST ) ;
if ( pw_len < 0 | | pw_len > PASSWORD_BUFFER_LEN ) {
2011-03-27 21:41:34 +04:00
return false ;
}
2009-09-15 04:53:21 +04:00
2022-07-22 15:26:43 +03:00
PUSH_LE_U32 ( buffer , PASSWORD_BUFFER_LEN , pw_len ) ;
2004-04-21 09:01:31 +04:00
2007-10-07 02:28:14 +04:00
return true ;
2003-08-13 05:53:07 +04:00
}
2004-04-22 10:18:40 +04:00
2003-08-13 05:53:07 +04:00
/***********************************************************
decode a password buffer
* new_pw_len is the length in bytes of the possibly mulitbyte
returned password including termination .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-16 13:19:10 +03:00
bool decode_pw_buffer ( TALLOC_CTX * ctx ,
uint8_t in_buffer [ 516 ] ,
char * * pp_new_pwrd ,
size_t * new_pw_len ,
charset_t string_charset )
2003-08-13 05:53:07 +04:00
{
2022-07-25 11:14:12 +03:00
DATA_BLOB new_password ;
2003-08-13 05:53:07 +04:00
int byte_len = 0 ;
2022-07-25 11:14:12 +03:00
bool ok ;
2003-08-13 05:53:07 +04:00
2009-03-16 13:19:10 +03:00
* pp_new_pwrd = NULL ;
* new_pw_len = 0 ;
2006-09-28 03:24:36 +04:00
2022-07-25 11:14:12 +03:00
ok = extract_pw_from_buffer ( ctx , in_buffer , & new_password ) ;
if ( ! ok ) {
return false ;
}
2003-08-13 05:53:07 +04:00
/*
Warning ! ! ! : This function is called from some rpc call .
2004-05-02 12:45:00 +04:00
The password IN the buffer may be a UNICODE string .
2003-08-13 05:53:07 +04:00
The password IN new_pwrd is an ASCII string
If you reuse that code somewhere else check first .
*/
2009-03-16 13:19:10 +03:00
/* decode into the return buffer. */
2022-07-25 11:14:12 +03:00
ok = convert_string_talloc ( ctx ,
string_charset ,
CH_UNIX ,
new_password . data ,
new_password . length ,
2023-08-09 07:52:31 +03:00
pp_new_pwrd ,
2022-07-25 11:14:12 +03:00
new_pw_len ) ;
data_blob_free ( & new_password ) ;
if ( ! ok ) {
DBG_ERR ( " Failed to convert incoming password \n " ) ;
2008-09-23 04:50:43 +04:00
return false ;
}
2022-08-02 05:35:50 +03:00
talloc_keep_secret ( * pp_new_pwrd ) ;
2008-09-23 04:50:43 +04:00
2003-08-13 05:53:07 +04:00
# ifdef DEBUG_PASSWORD
DEBUG ( 100 , ( " decode_pw_buffer: new_pwrd: " ) ) ;
2009-03-16 13:19:10 +03:00
dump_data ( 100 , ( uint8_t * ) * pp_new_pwrd , * new_pw_len ) ;
DEBUG ( 100 , ( " multibyte len:%lu \n " , ( unsigned long int ) * new_pw_len ) ) ;
2003-08-13 05:53:07 +04:00
DEBUG ( 100 , ( " original char len:%d \n " , byte_len / 2 ) ) ;
# endif
2009-03-16 13:19:10 +03:00
2007-10-07 02:28:14 +04:00
return true ;
2003-08-13 05:53:07 +04:00
}
2008-10-16 05:48:16 +04:00
2021-08-19 12:29:04 +03:00
# define MAX_PASSWORD_LEN 256
/*
* [ MS - SAMR ] 2.2 .6 .32 This creates the buffer to be sent . It is of type
* SAMPR_USER_PASSWORD_AES .
*/
bool encode_pwd_buffer514_from_str ( uint8_t buffer [ 514 ] ,
const char * password ,
uint32_t string_flags )
{
ssize_t pw_len ;
pw_len = _encode_pwd_buffer_from_str ( buffer + 2 ,
password ,
string_flags ,
ENCODE_ORDER_PASSWORD_FIRST ) ;
if ( pw_len < 0 ) {
return false ;
}
PUSH_LE_U16 ( buffer , 0 , pw_len ) ;
return true ;
}
2021-08-20 10:45:27 +03:00
bool extract_pwd_blob_from_buffer514 ( TALLOC_CTX * mem_ctx ,
const uint8_t in_buffer [ 514 ] ,
DATA_BLOB * new_password )
{
# ifdef DEBUG_PASSWORD
DEBUG ( 100 , ( " in_buffer: " ) ) ;
dump_data ( 100 , in_buffer , 514 ) ;
# endif
new_password - > length = PULL_LE_U16 ( in_buffer , 0 ) ;
if ( new_password - > length = = 0 | | new_password - > length > 512 ) {
return false ;
}
new_password - > data =
talloc_memdup ( mem_ctx , in_buffer + 2 , new_password - > length ) ;
if ( new_password - > data = = NULL ) {
return false ;
}
talloc_keep_secret ( new_password - > data ) ;
# ifdef DEBUG_PASSWORD
DEBUG ( 100 , ( " new_pwd_len: %zu \n " , new_password - > length ) ) ;
DEBUG ( 100 , ( " new_pwd: " ) ) ;
dump_data ( 100 , new_password - > data , new_password - > length ) ;
# endif
return true ;
}
2021-08-23 16:03:19 +03:00
bool decode_pwd_string_from_buffer514 ( TALLOC_CTX * mem_ctx ,
const uint8_t in_buffer [ 514 ] ,
charset_t string_charset ,
DATA_BLOB * decoded_password )
{
DATA_BLOB new_password = {
. length = 0 ,
} ;
bool ok ;
ok = extract_pwd_blob_from_buffer514 ( mem_ctx , in_buffer , & new_password ) ;
if ( ! ok ) {
return false ;
}
ok = convert_string_talloc ( mem_ctx ,
string_charset ,
CH_UNIX ,
new_password . data ,
new_password . length ,
2023-08-09 07:52:31 +03:00
& decoded_password - > data ,
2021-08-23 16:03:19 +03:00
& decoded_password - > length ) ;
data_blob_free ( & new_password ) ;
if ( ! ok ) {
return false ;
}
2022-08-02 05:35:50 +03:00
talloc_keep_secret ( decoded_password - > data ) ;
2021-08-23 16:03:19 +03:00
return true ;
}
2019-07-09 14:01:10 +03:00
/***********************************************************
Encode an arc4 password change buffer .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS encode_rc4_passwd_buffer ( const char * passwd ,
const DATA_BLOB * session_key ,
struct samr_CryptPasswordEx * out_crypt_pwd )
{
uint8_t _confounder [ 16 ] = { 0 } ;
DATA_BLOB confounder = data_blob_const ( _confounder , 16 ) ;
DATA_BLOB pw_data = data_blob_const ( out_crypt_pwd - > data , 516 ) ;
bool ok ;
int rc ;
ok = encode_pw_buffer ( pw_data . data , passwd , STR_UNICODE ) ;
if ( ! ok ) {
return NT_STATUS_INVALID_PARAMETER ;
}
generate_random_buffer ( confounder . data , confounder . length ) ;
rc = samba_gnutls_arcfour_confounded_md5 ( & confounder ,
session_key ,
& pw_data ,
SAMBA_GNUTLS_ENCRYPT ) ;
if ( rc < 0 ) {
ZERO_ARRAY ( _confounder ) ;
data_blob_clear ( & pw_data ) ;
return gnutls_error_to_ntstatus ( rc , NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ) ;
}
/*
* The packet format is the 516 byte RC4 encrypted
2024-07-16 04:32:05 +03:00
* password followed by the 16 byte confounder
2019-07-09 14:01:10 +03:00
* The confounder is a salt to prevent pre - computed hash attacks on the
* database .
*/
memcpy ( & out_crypt_pwd - > data [ 516 ] , confounder . data , confounder . length ) ;
ZERO_ARRAY ( _confounder ) ;
return NT_STATUS_OK ;
}
2009-03-16 13:19:10 +03:00
/***********************************************************
Decode an arc4 encrypted password change buffer .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-07-09 13:53:31 +03:00
NTSTATUS decode_rc4_passwd_buffer ( const DATA_BLOB * psession_key ,
struct samr_CryptPasswordEx * inout_crypt_pwd )
2009-03-16 13:19:10 +03:00
{
/* Confounder is last 16 bytes. */
2019-07-09 13:53:31 +03:00
DATA_BLOB confounder = data_blob_const ( & inout_crypt_pwd - > data [ 516 ] , 16 ) ;
DATA_BLOB pw_data = data_blob_const ( & inout_crypt_pwd - > data , 516 ) ;
2019-07-05 11:09:32 +03:00
int rc ;
2009-03-16 13:19:10 +03:00
2019-07-05 11:09:32 +03:00
rc = samba_gnutls_arcfour_confounded_md5 ( & confounder ,
psession_key ,
& pw_data ,
SAMBA_GNUTLS_DECRYPT ) ;
2019-05-15 09:02:59 +03:00
if ( rc < 0 ) {
2019-07-05 11:09:32 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ) ;
2019-05-15 09:02:59 +03:00
}
2019-07-05 11:09:32 +03:00
return NT_STATUS_OK ;
2009-03-16 13:19:10 +03:00
}
2008-10-17 06:00:24 +04:00
/***********************************************************
encode a password buffer with an already unicode password . The
rest of the buffer is filled with random data to make it harder to attack .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2022-07-25 11:29:01 +03:00
static bool create_pw_buffer_from_blob ( uint8_t buffer [ 512 ] ,
const DATA_BLOB * in_password ,
enum encode_order order )
2008-10-17 06:00:24 +04:00
{
2022-07-25 11:29:01 +03:00
size_t pwd_pos = 0 ;
size_t random_pos = 0 ;
size_t random_len = 0 ;
if ( in_password - > length > 512 ) {
2008-10-17 06:00:24 +04:00
return false ;
}
2022-07-25 11:29:01 +03:00
switch ( order ) {
case ENCODE_ORDER_PASSWORD_FIRST :
pwd_pos = 0 ;
random_pos = in_password - > length ;
break ;
case ENCODE_ORDER_PASSWORD_LAST :
pwd_pos = PASSWORD_BUFFER_LEN - in_password - > length ;
random_pos = 0 ;
break ;
}
random_len = PASSWORD_BUFFER_LEN - in_password - > length ;
memcpy ( buffer + pwd_pos , in_password - > data , in_password - > length ) ;
generate_random_buffer ( buffer + random_pos , random_len ) ;
return true ;
}
bool set_pw_in_buffer ( uint8_t buffer [ 516 ] , const DATA_BLOB * password )
{
bool ok ;
2008-10-17 06:00:24 +04:00
2022-07-25 11:29:01 +03:00
ok = create_pw_buffer_from_blob ( buffer ,
password ,
ENCODE_ORDER_PASSWORD_LAST ) ;
if ( ! ok ) {
return false ;
}
2008-10-17 06:00:24 +04:00
2009-09-15 04:53:21 +04:00
/*
2008-10-17 06:00:24 +04:00
* The length of the new password is in the last 4 bytes of
* the data buffer .
*/
2022-07-25 11:29:01 +03:00
PUSH_LE_U32 ( buffer , PASSWORD_BUFFER_LEN , password - > length ) ;
2008-10-17 06:00:24 +04:00
return true ;
}
2008-10-16 05:48:16 +04:00
/***********************************************************
decode a password buffer
* new_pw_size is the length in bytes of the extracted unicode password
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-09-15 04:53:21 +04:00
bool extract_pw_from_buffer ( TALLOC_CTX * mem_ctx ,
2008-10-16 05:48:16 +04:00
uint8_t in_buffer [ 516 ] , DATA_BLOB * new_pass )
{
int byte_len = 0 ;
/* The length of the new password is in the last 4 bytes of the data buffer. */
byte_len = IVAL ( in_buffer , 512 ) ;
# ifdef DEBUG_PASSWORD
dump_data ( 100 , in_buffer , 516 ) ;
# endif
/* Password cannot be longer than the size of the password buffer */
if ( ( byte_len < 0 ) | | ( byte_len > 512 ) ) {
return false ;
}
* new_pass = data_blob_talloc ( mem_ctx , & in_buffer [ 512 - byte_len ] , byte_len ) ;
2008-12-19 00:18:57 +03:00
if ( ! new_pass - > data ) {
2008-10-16 05:48:16 +04:00
return false ;
}
2022-07-25 09:42:39 +03:00
talloc_keep_secret ( new_pass - > data ) ;
2008-10-16 05:48:16 +04:00
return true ;
}
2009-03-16 13:19:10 +03:00
/* encode a wkssvc_PasswordBuffer:
*
* similar to samr_CryptPasswordEx . Different : 8 byte confounder ( instead of
* 16 byte ) , confounder in front of the 516 byte buffer ( instead of after that
* buffer ) , calling MD5Update ( ) first with session_key and then with confounder
* ( vice versa in samr ) - Guenther */
2019-05-29 16:50:45 +03:00
WERROR encode_wkssvc_join_password_buffer ( TALLOC_CTX * mem_ctx ,
const char * pwd ,
DATA_BLOB * session_key ,
2019-07-08 19:03:00 +03:00
struct wkssvc_PasswordBuffer * * out_pwd_buf )
2009-03-16 13:19:10 +03:00
{
2019-07-08 19:03:00 +03:00
struct wkssvc_PasswordBuffer * pwd_buf = NULL ;
uint8_t _confounder [ 8 ] = { 0 } ;
DATA_BLOB confounder = data_blob_const ( _confounder , 8 ) ;
uint8_t pwbuf [ 516 ] = { 0 } ;
DATA_BLOB encrypt_pwbuf = data_blob_const ( pwbuf , 516 ) ;
2019-05-15 09:03:31 +03:00
int rc ;
2009-03-16 13:19:10 +03:00
2019-07-08 19:03:00 +03:00
pwd_buf = talloc_zero ( mem_ctx , struct wkssvc_PasswordBuffer ) ;
if ( pwd_buf = = NULL ) {
2019-05-29 16:50:45 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2009-03-16 13:19:10 +03:00
}
2019-07-08 19:03:00 +03:00
encode_pw_buffer ( pwbuf , pwd , STR_UNICODE ) ;
2009-03-16 13:19:10 +03:00
2019-07-08 19:03:00 +03:00
generate_random_buffer ( _confounder , sizeof ( _confounder ) ) ;
2009-03-16 13:19:10 +03:00
2019-07-08 19:03:00 +03:00
rc = samba_gnutls_arcfour_confounded_md5 ( session_key ,
& confounder ,
& encrypt_pwbuf ,
SAMBA_GNUTLS_ENCRYPT ) ;
2019-05-15 09:03:31 +03:00
if ( rc < 0 ) {
2019-07-08 19:03:00 +03:00
ZERO_ARRAY ( _confounder ) ;
TALLOC_FREE ( pwd_buf ) ;
return gnutls_error_to_werror ( rc , WERR_CONTENT_BLOCKED ) ;
2019-05-15 09:03:31 +03:00
}
2009-03-16 13:19:10 +03:00
2019-07-08 19:03:00 +03:00
memcpy ( & pwd_buf - > data [ 0 ] , confounder . data , confounder . length ) ;
ZERO_ARRAY ( _confounder ) ;
memcpy ( & pwd_buf - > data [ 8 ] , encrypt_pwbuf . data , encrypt_pwbuf . length ) ;
ZERO_ARRAY ( pwbuf ) ;
2009-03-16 13:19:10 +03:00
2019-07-08 19:03:00 +03:00
* out_pwd_buf = pwd_buf ;
2019-05-15 09:03:31 +03:00
2019-07-08 19:03:00 +03:00
return WERR_OK ;
2009-03-16 13:19:10 +03:00
}
WERROR decode_wkssvc_join_password_buffer ( TALLOC_CTX * mem_ctx ,
struct wkssvc_PasswordBuffer * pwd_buf ,
DATA_BLOB * session_key ,
char * * pwd )
{
Fix gcc11 compiler issue "-Werror=maybe-uninitialized"
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14699
../../source4/dsdb/common/util_links.c: In function ‘ndr_guid_compare’:
../../source4/dsdb/common/util_links.c:38:29: error: ‘v1_data’ may be used uninitialized [-Werror=maybe-uninitialized]
38 | struct ldb_val v1 = data_blob_const(v1_data, sizeof(v1_data));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/dsdb/common/util_links.c:22:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/dsdb/common/util_links.c:37:17: note: ‘v1_data’ declared here
37 | uint8_t v1_data[16];
| ^~~~~~~
cc1: all warnings being treated as errors
[1729/3991] Compiling source3/smbd/smbXsrv_open.c
../../libcli/auth/smbencrypt.c: In function ‘decode_wkssvc_join_password_buffer’:
../../libcli/auth/smbencrypt.c:1045:32: error: ‘_confounder’ may be used uninitialized [-Werror=maybe-uninitialized]
1045 | DATA_BLOB confounder = data_blob_const(_confounder, 8);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../libcli/auth/smbencrypt.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../libcli/auth/smbencrypt.c:1044:17: note: ‘_confounder’ declared here
1044 | uint8_t _confounder[8];
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
[2624/3991] Compiling source4/torture/rpc/samr.c
../../source3/rpc_client/cli_samr.c: In function ‘dcerpc_samr_chgpasswd_user2’:
../../source3/rpc_client/cli_samr.c:158:33: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
158 | DATA_BLOB session_key = data_blob_const(old_nt_hash, 16);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source3/../lib/util/samba_util.h:48,
from ../../source3/include/includes.h:256,
from ../../source3/rpc_client/cli_samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source3/rpc_client/cli_samr.c:152:17: note: ‘old_nt_hash’ declared here
152 | uint8_t old_nt_hash[16];
| ^~~~~~~~~~~
../../source3/rpc_client/cli_samr.c: In function ‘dcerpc_samr_chgpasswd_user3’:
../../source3/rpc_client/cli_samr.c:365:33: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
365 | DATA_BLOB session_key = data_blob_const(old_nt_hash, 16);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source3/../lib/util/samba_util.h:48,
from ../../source3/include/includes.h:256,
from ../../source3/rpc_client/cli_samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source3/rpc_client/cli_samr.c:358:17: note: ‘old_nt_hash’ declared here
358 | uint8_t old_nt_hash[16];
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
[3399/3991] Compiling source3/rpcclient/cmd_spotlight.c
../../source3/smbd/smbXsrv_open.c: In function ‘smbXsrv_open_set_replay_cache’:
../../source3/smbd/smbXsrv_open.c:936:26: error: ‘data’ may be used uninitialized [-Werror=maybe-uninitialized]
936 | DATA_BLOB blob = data_blob_const(data, ARRAY_SIZE(data));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source3/../lib/util/samba_util.h:48,
from ../../source3/include/includes.h:256,
from ../../source3/smbd/smbXsrv_open.c:21:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source3/smbd/smbXsrv_open.c:935:17: note: ‘data’ declared here
935 | uint8_t data[SMBXSRV_OPEN_REPLAY_CACHE_FIXED_SIZE];
| ^~~~
cc1: all warnings being treated as errors
../../source3/rpcclient/cmd_spotlight.c: In function ‘cmd_mdssvc_fetch_properties’:
../../source3/rpcclient/cmd_spotlight.c:60:18: error: ‘share_path’ may be used uninitialized [-Werror=maybe-uninitialized]
60 | status = dcerpc_mdssvc_open(b, mem_ctx,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
61 | &device_id,
| ~~~~~~~~~~~
62 | &unkn1,
| ~~~~~~~
63 | &unkn2,
| ~~~~~~~
64 | argv[2],
| ~~~~~~~~
65 | argv[1],
| ~~~~~~~~
66 | share_path,
| ~~~~~~~~~~~
67 | &share_handle);
| ~~~~~~~~~~~~~~
In file included from ../../source3/rpcclient/cmd_spotlight.c:24:
source3/../librpc/gen_ndr/ndr_mdssvc_c.h:26:10: note: by argument 8 of type ‘const char *’ to ‘dcerpc_mdssvc_open’ declared here
26 | NTSTATUS dcerpc_mdssvc_open(struct dcerpc_binding_handle *h,
| ^~~~~~~~~~~~~~~~~~
../../source3/rpcclient/cmd_spotlight.c:40:14: note: ‘share_path’ declared here
40 | char share_path[1025];
| ^~~~~~~~~~
cc1: all warnings being treated as errors
../../source4/torture/rpc/samr.c: In function ‘test_ChangePasswordUser2’:
../../source4/torture/rpc/samr.c:2266:19: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
2266 | = data_blob_const(old_nt_hash, sizeof(old_nt_hash));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/torture/rpc/samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/torture/rpc/samr.c:2263:17: note: ‘old_nt_hash’ declared here
2263 | uint8_t old_nt_hash[16], new_nt_hash[16];
| ^~~~~~~~~~~
../../source4/torture/rpc/samr.c: In function ‘test_ChangePasswordUser2_ntstatus’:
../../source4/torture/rpc/samr.c:2371:19: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
2371 | = data_blob_const(old_nt_hash, sizeof(old_nt_hash));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/torture/rpc/samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/torture/rpc/samr.c:2368:17: note: ‘old_nt_hash’ declared here
2368 | uint8_t old_nt_hash[16], new_nt_hash[16];
| ^~~~~~~~~~~
../../source4/torture/rpc/samr.c: In function ‘test_ChangePasswordUser3’:
../../source4/torture/rpc/samr.c:2478:38: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
2478 | DATA_BLOB old_nt_hash_blob = data_blob_const(old_nt_hash, 16);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/torture/rpc/samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/torture/rpc/samr.c:2473:17: note: ‘old_nt_hash’ declared here
2473 | uint8_t old_nt_hash[16], new_nt_hash[16];
| ^~~~~~~~~~~
../../source4/torture/rpc/samr.c: In function ‘test_ChangePasswordRandomBytes’:
../../source4/torture/rpc/samr.c:2794:19: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
2794 | = data_blob_const(old_nt_hash,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
2795 | sizeof(old_nt_hash));
| ~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/torture/rpc/samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/torture/rpc/samr.c:2792:17: note: ‘old_nt_hash’ declared here
2792 | uint8_t old_nt_hash[16], new_nt_hash[16];
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
Guenther
Signed-off-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2021-05-03 22:27:43 +03:00
uint8_t _confounder [ 8 ] = { 0 } ;
2019-07-08 19:21:18 +03:00
DATA_BLOB confounder = data_blob_const ( _confounder , 8 ) ;
uint8_t pwbuf [ 516 ] = { 0 } ;
DATA_BLOB decrypt_pwbuf = data_blob_const ( pwbuf , 516 ) ;
2019-05-15 09:04:08 +03:00
bool ok ;
int rc ;
2009-03-16 13:19:10 +03:00
2019-07-08 19:21:18 +03:00
if ( pwd_buf = = NULL ) {
2015-03-26 13:00:10 +03:00
return WERR_INVALID_PASSWORD ;
2009-03-16 13:19:10 +03:00
}
2019-07-08 19:21:18 +03:00
* pwd = NULL ;
2009-03-16 13:19:10 +03:00
if ( session_key - > length ! = 16 ) {
DEBUG ( 10 , ( " invalid session key \n " ) ) ;
2015-03-26 13:00:10 +03:00
return WERR_INVALID_PASSWORD ;
2009-03-16 13:19:10 +03:00
}
2019-07-08 19:21:18 +03:00
confounder = data_blob_const ( & pwd_buf - > data [ 0 ] , 8 ) ;
memcpy ( & pwbuf , & pwd_buf - > data [ 8 ] , 516 ) ;
2009-03-16 13:19:10 +03:00
2019-07-08 19:21:18 +03:00
rc = samba_gnutls_arcfour_confounded_md5 ( session_key ,
& confounder ,
& decrypt_pwbuf ,
SAMBA_GNUTLS_ENCRYPT ) ;
2019-05-15 09:04:08 +03:00
if ( rc < 0 ) {
2019-07-08 19:21:18 +03:00
ZERO_ARRAY ( _confounder ) ;
TALLOC_FREE ( pwd_buf ) ;
return gnutls_error_to_werror ( rc , WERR_CONTENT_BLOCKED ) ;
2019-05-15 09:04:08 +03:00
}
2009-03-16 13:19:10 +03:00
2019-07-08 19:21:18 +03:00
ok = decode_pw_buffer ( mem_ctx ,
decrypt_pwbuf . data ,
pwd ,
& decrypt_pwbuf . length ,
CH_UTF16 ) ;
ZERO_ARRAY ( pwbuf ) ;
2009-03-16 13:19:10 +03:00
2019-05-15 09:04:08 +03:00
if ( ! ok ) {
2019-07-08 19:21:18 +03:00
return WERR_INVALID_PASSWORD ;
2019-05-15 09:04:08 +03:00
}
2019-07-08 19:21:18 +03:00
return WERR_OK ;
2009-03-16 13:19:10 +03:00
}