2011-04-29 12:41:27 +10:00
/*
Unix SMB / CIFS implementation .
client file operations
Copyright ( C ) Andrew Tridgell 1994 - 1998
Copyright ( C ) Jeremy Allison 2001 - 2002
Copyright ( C ) James Myers 2003
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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "libcli/smb/smb_common.h"
2011-05-04 21:19:46 +10:00
# include "system/filesys.h"
2019-10-09 09:38:08 +02:00
# include "lib/param/loadparm.h"
2021-07-13 18:00:59 +02:00
# include "lib/param/param.h"
# include "libcli/smb/smb2_negotiate_context.h"
2011-04-29 12:41:27 +10:00
2017-06-19 21:52:54 +02:00
const char * smb_protocol_types_string ( enum protocol_types protocol )
{
switch ( protocol ) {
case PROTOCOL_DEFAULT :
return " DEFAULT " ;
case PROTOCOL_NONE :
return " NONE " ;
case PROTOCOL_CORE :
return " CORE " ;
case PROTOCOL_COREPLUS :
return " COREPLUS " ;
case PROTOCOL_LANMAN1 :
return " LANMAN1 " ;
case PROTOCOL_LANMAN2 :
return " LANMAN2 " ;
case PROTOCOL_NT1 :
return " NT1 " ;
case PROTOCOL_SMB2_02 :
return " SMB2_02 " ;
case PROTOCOL_SMB2_10 :
return " SMB2_10 " ;
case PROTOCOL_SMB3_00 :
return " SMB3_00 " ;
case PROTOCOL_SMB3_02 :
return " SMB3_02 " ;
case PROTOCOL_SMB3_11 :
return " SMB3_11 " ;
}
return " Invalid protocol_types value " ;
}
2011-04-29 12:41:27 +10:00
/**
Return a string representing a CIFS attribute for a file .
* */
char * attrib_string ( TALLOC_CTX * mem_ctx , uint32_t attrib )
{
2020-11-14 16:31:09 +01:00
size_t i , len ;
2022-11-10 11:22:13 +01:00
static const struct {
2011-04-29 12:41:27 +10:00
char c ;
uint16_t attr ;
} attr_strs [ ] = {
{ ' V ' , FILE_ATTRIBUTE_VOLUME } ,
{ ' D ' , FILE_ATTRIBUTE_DIRECTORY } ,
{ ' A ' , FILE_ATTRIBUTE_ARCHIVE } ,
{ ' H ' , FILE_ATTRIBUTE_HIDDEN } ,
{ ' S ' , FILE_ATTRIBUTE_SYSTEM } ,
{ ' N ' , FILE_ATTRIBUTE_NORMAL } ,
{ ' R ' , FILE_ATTRIBUTE_READONLY } ,
{ ' d ' , FILE_ATTRIBUTE_DEVICE } ,
{ ' t ' , FILE_ATTRIBUTE_TEMPORARY } ,
{ ' s ' , FILE_ATTRIBUTE_SPARSE } ,
{ ' r ' , FILE_ATTRIBUTE_REPARSE_POINT } ,
{ ' c ' , FILE_ATTRIBUTE_COMPRESSED } ,
{ ' o ' , FILE_ATTRIBUTE_OFFLINE } ,
{ ' n ' , FILE_ATTRIBUTE_NONINDEXED } ,
{ ' e ' , FILE_ATTRIBUTE_ENCRYPTED }
} ;
char * ret ;
ret = talloc_array ( mem_ctx , char , ARRAY_SIZE ( attr_strs ) + 1 ) ;
if ( ! ret ) {
return NULL ;
}
for ( len = i = 0 ; i < ARRAY_SIZE ( attr_strs ) ; i + + ) {
if ( attrib & attr_strs [ i ] . attr ) {
ret [ len + + ] = attr_strs [ i ] . c ;
}
}
ret [ len ] = 0 ;
talloc_set_name_const ( ret , ret ) ;
return ret ;
}
2011-05-04 21:19:46 +10:00
/****************************************************************************
Map standard UNIX permissions onto wire representations .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32_t unix_perms_to_wire ( mode_t perms )
{
unsigned int ret = 0 ;
ret | = ( ( perms & S_IXOTH ) ? UNIX_X_OTH : 0 ) ;
ret | = ( ( perms & S_IWOTH ) ? UNIX_W_OTH : 0 ) ;
ret | = ( ( perms & S_IROTH ) ? UNIX_R_OTH : 0 ) ;
ret | = ( ( perms & S_IXGRP ) ? UNIX_X_GRP : 0 ) ;
ret | = ( ( perms & S_IWGRP ) ? UNIX_W_GRP : 0 ) ;
ret | = ( ( perms & S_IRGRP ) ? UNIX_R_GRP : 0 ) ;
ret | = ( ( perms & S_IXUSR ) ? UNIX_X_USR : 0 ) ;
ret | = ( ( perms & S_IWUSR ) ? UNIX_W_USR : 0 ) ;
ret | = ( ( perms & S_IRUSR ) ? UNIX_R_USR : 0 ) ;
# ifdef S_ISVTX
ret | = ( ( perms & S_ISVTX ) ? UNIX_STICKY : 0 ) ;
# endif
# ifdef S_ISGID
ret | = ( ( perms & S_ISGID ) ? UNIX_SET_GID : 0 ) ;
# endif
# ifdef S_ISUID
ret | = ( ( perms & S_ISUID ) ? UNIX_SET_UID : 0 ) ;
# endif
return ret ;
}
/****************************************************************************
Map wire permissions to standard UNIX .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
mode_t wire_perms_to_unix ( uint32_t perms )
{
mode_t ret = ( mode_t ) 0 ;
ret | = ( ( perms & UNIX_X_OTH ) ? S_IXOTH : 0 ) ;
ret | = ( ( perms & UNIX_W_OTH ) ? S_IWOTH : 0 ) ;
ret | = ( ( perms & UNIX_R_OTH ) ? S_IROTH : 0 ) ;
ret | = ( ( perms & UNIX_X_GRP ) ? S_IXGRP : 0 ) ;
ret | = ( ( perms & UNIX_W_GRP ) ? S_IWGRP : 0 ) ;
ret | = ( ( perms & UNIX_R_GRP ) ? S_IRGRP : 0 ) ;
ret | = ( ( perms & UNIX_X_USR ) ? S_IXUSR : 0 ) ;
ret | = ( ( perms & UNIX_W_USR ) ? S_IWUSR : 0 ) ;
ret | = ( ( perms & UNIX_R_USR ) ? S_IRUSR : 0 ) ;
# ifdef S_ISVTX
ret | = ( ( perms & UNIX_STICKY ) ? S_ISVTX : 0 ) ;
# endif
# ifdef S_ISGID
ret | = ( ( perms & UNIX_SET_GID ) ? S_ISGID : 0 ) ;
# endif
# ifdef S_ISUID
ret | = ( ( perms & UNIX_SET_UID ) ? S_ISUID : 0 ) ;
# endif
return ret ;
}
/****************************************************************************
Return the file type from the wire filetype for UNIX extensions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
mode_t unix_filetype_from_wire ( uint32_t wire_type )
{
switch ( wire_type ) {
case UNIX_TYPE_FILE :
return S_IFREG ;
case UNIX_TYPE_DIR :
return S_IFDIR ;
# ifdef S_IFLNK
case UNIX_TYPE_SYMLINK :
return S_IFLNK ;
# endif
# ifdef S_IFCHR
case UNIX_TYPE_CHARDEV :
return S_IFCHR ;
# endif
# ifdef S_IFBLK
case UNIX_TYPE_BLKDEV :
return S_IFBLK ;
# endif
# ifdef S_IFIFO
case UNIX_TYPE_FIFO :
return S_IFIFO ;
# endif
# ifdef S_IFSOCK
case UNIX_TYPE_SOCKET :
return S_IFSOCK ;
# endif
default :
return ( mode_t ) 0 ;
}
}
2011-10-26 14:20:53 +02:00
bool smb_buffer_oob ( uint32_t bufsize , uint32_t offset , uint32_t length )
{
if ( ( offset + length < offset ) | | ( offset + length < length ) ) {
/* wrap */
return true ;
}
if ( ( offset > bufsize ) | | ( offset + length > bufsize ) ) {
/* overflow */
return true ;
}
return false ;
}
2016-10-25 13:31:08 +02:00
/***********************************************************
2023-04-27 15:58:18 +02:00
Common function for pushing strings , used by smb_bytes_push_str ( )
2016-10-25 13:31:08 +02:00
and trans_bytes_push_str ( ) . Only difference is the align_odd
parameter setting .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static uint8_t * internal_bytes_push_str ( uint8_t * buf , bool ucs2 ,
const char * str , size_t str_len ,
bool align_odd ,
size_t * pconverted_size )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
size_t buflen ;
char * converted ;
size_t converted_size ;
/*
* This check prevents us from
* ( re ) alloc buf on a NULL TALLOC_CTX .
*/
if ( buf = = NULL ) {
TALLOC_FREE ( frame ) ;
return NULL ;
}
buflen = talloc_get_size ( buf ) ;
if ( ucs2 & &
( ( align_odd & & ( buflen % 2 = = 0 ) ) | |
( ! align_odd & & ( buflen % 2 = = 1 ) ) ) ) {
/*
* We ' re pushing into an SMB buffer , align odd
*/
buf = talloc_realloc ( NULL , buf , uint8_t , buflen + 1 ) ;
if ( buf = = NULL ) {
TALLOC_FREE ( frame ) ;
return NULL ;
}
buf [ buflen ] = ' \0 ' ;
buflen + = 1 ;
}
if ( ! convert_string_talloc ( frame , CH_UNIX ,
ucs2 ? CH_UTF16LE : CH_DOS ,
str , str_len , & converted ,
& converted_size ) ) {
TALLOC_FREE ( frame ) ;
return NULL ;
}
buf = talloc_realloc ( NULL , buf , uint8_t ,
buflen + converted_size ) ;
if ( buf = = NULL ) {
TALLOC_FREE ( frame ) ;
return NULL ;
}
memcpy ( buf + buflen , converted , converted_size ) ;
TALLOC_FREE ( converted ) ;
if ( pconverted_size ) {
* pconverted_size = converted_size ;
}
TALLOC_FREE ( frame ) ;
return buf ;
}
/***********************************************************
Push a string into an SMB buffer , with odd byte alignment
if it ' s a UCS2 string .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint8_t * smb_bytes_push_str ( uint8_t * buf , bool ucs2 ,
const char * str , size_t str_len ,
size_t * pconverted_size )
{
return internal_bytes_push_str ( buf , ucs2 , str , str_len ,
true , pconverted_size ) ;
}
uint8_t * smb_bytes_push_bytes ( uint8_t * buf , uint8_t prefix ,
const uint8_t * bytes , size_t num_bytes )
{
size_t buflen ;
/*
* This check prevents us from
* ( re ) alloc buf on a NULL TALLOC_CTX .
*/
if ( buf = = NULL ) {
return NULL ;
}
buflen = talloc_get_size ( buf ) ;
buf = talloc_realloc ( NULL , buf , uint8_t ,
buflen + 1 + num_bytes ) ;
if ( buf = = NULL ) {
return NULL ;
}
buf [ buflen ] = prefix ;
memcpy ( & buf [ buflen + 1 ] , bytes , num_bytes ) ;
return buf ;
}
/***********************************************************
Same as smb_bytes_push_str ( ) , but without the odd byte
align for ucs2 ( we ' re pushing into a param or data block ) .
static for now , although this will probably change when
other modules use async trans calls .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint8_t * trans2_bytes_push_str ( uint8_t * buf , bool ucs2 ,
const char * str , size_t str_len ,
size_t * pconverted_size )
{
return internal_bytes_push_str ( buf , ucs2 , str , str_len ,
false , pconverted_size ) ;
}
uint8_t * trans2_bytes_push_bytes ( uint8_t * buf ,
const uint8_t * bytes , size_t num_bytes )
{
size_t buflen ;
if ( buf = = NULL ) {
return NULL ;
}
buflen = talloc_get_size ( buf ) ;
buf = talloc_realloc ( NULL , buf , uint8_t ,
buflen + num_bytes ) ;
if ( buf = = NULL ) {
return NULL ;
}
memcpy ( & buf [ buflen ] , bytes , num_bytes ) ;
return buf ;
}
2016-10-25 14:50:41 +02:00
static NTSTATUS internal_bytes_pull_str ( TALLOC_CTX * mem_ctx , char * * _str ,
bool ucs2 , bool align_odd ,
const uint8_t * buf , size_t buf_len ,
2017-03-15 17:04:30 +00:00
const uint8_t * position ,
size_t * p_consumed )
2016-10-25 14:50:41 +02:00
{
size_t pad = 0 ;
2017-03-15 17:04:30 +00:00
size_t offset ;
2016-10-25 14:50:41 +02:00
char * str = NULL ;
size_t str_len = 0 ;
bool ok ;
* _str = NULL ;
2017-03-15 17:04:30 +00:00
if ( p_consumed ! = NULL ) {
* p_consumed = 0 ;
}
if ( position < buf ) {
return NT_STATUS_INTERNAL_ERROR ;
}
offset = PTR_DIFF ( position , buf ) ;
if ( offset > buf_len ) {
return NT_STATUS_BUFFER_TOO_SMALL ;
2016-10-25 14:50:41 +02:00
}
if ( ucs2 & &
2017-03-15 17:04:30 +00:00
( ( align_odd & & ( offset % 2 = = 0 ) ) | |
( ! align_odd & & ( offset % 2 = = 1 ) ) ) ) {
pad + = 1 ;
offset + = 1 ;
}
if ( offset > buf_len ) {
return NT_STATUS_BUFFER_TOO_SMALL ;
2016-10-25 14:50:41 +02:00
}
2017-03-15 17:04:30 +00:00
buf_len - = offset ;
buf + = offset ;
2016-10-25 14:50:41 +02:00
if ( ucs2 ) {
2023-11-09 12:33:43 +13:00
buf_len = utf16_null_terminated_len_n ( buf , buf_len ) ;
2016-10-25 14:50:41 +02:00
} else {
size_t tmp = strnlen ( ( const char * ) buf , buf_len ) ;
if ( tmp < buf_len ) {
tmp + = 1 ;
}
buf_len = tmp ;
}
ok = convert_string_talloc ( mem_ctx ,
ucs2 ? CH_UTF16LE : CH_DOS ,
CH_UNIX ,
buf , buf_len ,
& str , & str_len ) ;
if ( ! ok ) {
return map_nt_error_from_unix_common ( errno ) ;
}
2017-03-15 17:04:30 +00:00
if ( p_consumed ! = NULL ) {
* p_consumed = buf_len + pad ;
2016-10-25 14:50:41 +02:00
}
* _str = str ;
2017-03-15 17:04:30 +00:00
return NT_STATUS_OK ;
2016-10-25 14:50:41 +02:00
}
NTSTATUS smb_bytes_pull_str ( TALLOC_CTX * mem_ctx , char * * _str , bool ucs2 ,
const uint8_t * buf , size_t buf_len ,
2017-03-15 17:04:30 +00:00
const uint8_t * position ,
size_t * _consumed )
2016-10-25 14:50:41 +02:00
{
2017-06-08 15:02:16 +02:00
return internal_bytes_pull_str ( mem_ctx , _str , ucs2 , true ,
2017-03-15 17:04:30 +00:00
buf , buf_len , position , _consumed ) ;
2016-10-25 14:50:41 +02:00
}
2019-10-09 09:38:08 +02:00
/**
* @ brief Translate SMB signing settings as string to an enum .
*
* @ param [ in ] str The string to translate .
*
2023-04-27 15:58:18 +02:00
* @ return A corresponding enum @ smb_signing_setting translated from the string .
2019-10-09 09:38:08 +02:00
*/
enum smb_signing_setting smb_signing_setting_translate ( const char * str )
{
enum smb_signing_setting signing_state = SMB_SIGNING_REQUIRED ;
int32_t val = lpcfg_parse_enum_vals ( " client signing " , str ) ;
if ( val ! = INT32_MIN ) {
signing_state = val ;
}
return signing_state ;
}
2020-05-26 08:39:34 +02:00
/**
* @ brief Translate SMB encryption settings as string to an enum .
*
* @ param [ in ] str The string to translate .
*
2023-04-27 15:58:18 +02:00
* @ return A corresponding enum @ smb_encryption_setting translated from the
2020-05-26 08:39:34 +02:00
* string .
*/
enum smb_encryption_setting smb_encryption_setting_translate ( const char * str )
{
enum smb_encryption_setting encryption_state = SMB_ENCRYPTION_REQUIRED ;
int32_t val = lpcfg_parse_enum_vals ( " client smb encrypt " , str ) ;
if ( val ! = INT32_MIN ) {
encryption_state = val ;
}
return encryption_state ;
}
2021-07-13 18:00:59 +02:00
2021-03-11 11:04:14 +01:00
static const struct enum_list enum_smb3_signing_algorithms [ ] = {
2021-09-08 15:10:14 +02:00
{ SMB2_SIGNING_AES128_GMAC , " AES-128-GMAC " } ,
{ SMB2_SIGNING_AES128_CMAC , " AES-128-CMAC " } ,
{ SMB2_SIGNING_HMAC_SHA256 , " HMAC-SHA256 " } ,
2021-03-11 11:04:14 +01:00
{ - 1 , NULL }
} ;
const char * smb3_signing_algorithm_name ( uint16_t algo )
{
size_t i ;
for ( i = 0 ; i < ARRAY_SIZE ( enum_smb3_signing_algorithms ) ; i + + ) {
if ( enum_smb3_signing_algorithms [ i ] . value ! = algo ) {
continue ;
}
return enum_smb3_signing_algorithms [ i ] . name ;
}
return NULL ;
}
2021-07-13 18:00:59 +02:00
static const struct enum_list enum_smb3_encryption_algorithms [ ] = {
2021-09-08 15:10:14 +02:00
{ SMB2_ENCRYPTION_AES128_GCM , " AES-128-GCM " } ,
{ SMB2_ENCRYPTION_AES128_CCM , " AES-128-CCM " } ,
{ SMB2_ENCRYPTION_AES256_GCM , " AES-256-GCM " } ,
{ SMB2_ENCRYPTION_AES256_CCM , " AES-256-CCM " } ,
2021-07-13 18:00:59 +02:00
{ - 1 , NULL }
} ;
const char * smb3_encryption_algorithm_name ( uint16_t algo )
{
size_t i ;
for ( i = 0 ; i < ARRAY_SIZE ( enum_smb3_encryption_algorithms ) ; i + + ) {
if ( enum_smb3_encryption_algorithms [ i ] . value ! = algo ) {
continue ;
}
return enum_smb3_encryption_algorithms [ i ] . name ;
}
return NULL ;
}
static int32_t parse_enum_val ( const struct enum_list * e ,
const char * param_name ,
const char * param_value )
{
struct parm_struct parm = {
. label = param_name ,
. type = P_LIST ,
. p_class = P_GLOBAL ,
. enum_list = e ,
} ;
int32_t ret = INT32_MIN ;
bool ok ;
ok = lp_set_enum_parm ( & parm , param_value , & ret ) ;
if ( ! ok ) {
return INT32_MIN ;
}
return ret ;
}
struct smb311_capabilities smb311_capabilities_parse ( const char * role ,
2021-07-13 21:26:19 +02:00
const char * const * signing_algos ,
2021-07-13 18:00:59 +02:00
const char * const * encryption_algos )
{
struct smb311_capabilities c = {
2021-03-11 11:04:14 +01:00
. signing = {
. num_algos = 0 ,
} ,
2021-07-13 18:00:59 +02:00
. encryption = {
. num_algos = 0 ,
} ,
} ;
2021-03-11 11:04:14 +01:00
char sign_param [ 64 ] = { 0 , } ;
2021-07-13 18:00:59 +02:00
char enc_param [ 64 ] = { 0 , } ;
size_t ai ;
2021-03-11 11:04:14 +01:00
snprintf ( sign_param , sizeof ( sign_param ) ,
" %s smb3 signing algorithms " , role ) ;
2021-07-13 18:00:59 +02:00
snprintf ( enc_param , sizeof ( enc_param ) ,
" %s smb3 encryption algorithms " , role ) ;
2021-03-11 11:04:14 +01:00
for ( ai = 0 ; signing_algos ! = NULL & & signing_algos [ ai ] ! = NULL ; ai + + ) {
const char * algoname = signing_algos [ ai ] ;
int32_t v32 ;
uint16_t algo ;
size_t di ;
bool ignore = false ;
if ( c . signing . num_algos > = SMB3_ENCRYTION_CAPABILITIES_MAX_ALGOS ) {
DBG_ERR ( " WARNING: Ignoring trailing value '%s' for parameter '%s' \n " ,
algoname , sign_param ) ;
continue ;
}
v32 = parse_enum_val ( enum_smb3_signing_algorithms ,
sign_param , algoname ) ;
if ( v32 = = INT32_MAX ) {
continue ;
}
algo = v32 ;
for ( di = 0 ; di < c . signing . num_algos ; di + + ) {
if ( algo ! = c . signing . algos [ di ] ) {
continue ;
}
ignore = true ;
break ;
}
if ( ignore ) {
DBG_ERR ( " WARNING: Ignoring duplicate value '%s' for parameter '%s' \n " ,
algoname , sign_param ) ;
continue ;
}
c . signing . algos [ c . signing . num_algos ] = algo ;
c . signing . num_algos + = 1 ;
}
2021-07-13 18:00:59 +02:00
for ( ai = 0 ; encryption_algos ! = NULL & & encryption_algos [ ai ] ! = NULL ; ai + + ) {
const char * algoname = encryption_algos [ ai ] ;
int32_t v32 ;
uint16_t algo ;
size_t di ;
bool ignore = false ;
if ( c . encryption . num_algos > = SMB3_ENCRYTION_CAPABILITIES_MAX_ALGOS ) {
DBG_ERR ( " WARNING: Ignoring trailing value '%s' for parameter '%s' \n " ,
algoname , enc_param ) ;
continue ;
}
v32 = parse_enum_val ( enum_smb3_encryption_algorithms ,
enc_param , algoname ) ;
if ( v32 = = INT32_MAX ) {
continue ;
}
algo = v32 ;
for ( di = 0 ; di < c . encryption . num_algos ; di + + ) {
if ( algo ! = c . encryption . algos [ di ] ) {
continue ;
}
ignore = true ;
break ;
}
if ( ignore ) {
DBG_ERR ( " WARNING: Ignoring duplicate value '%s' for parameter '%s' \n " ,
algoname , enc_param ) ;
continue ;
}
c . encryption . algos [ c . encryption . num_algos ] = algo ;
c . encryption . num_algos + = 1 ;
}
return c ;
}
2021-07-14 12:13:49 +02:00
NTSTATUS smb311_capabilities_check ( const struct smb311_capabilities * c ,
const char * debug_prefix ,
int debug_lvl ,
NTSTATUS error_status ,
const char * role ,
enum protocol_types protocol ,
2021-07-13 21:26:19 +02:00
uint16_t sign_algo ,
2021-07-14 12:13:49 +02:00
uint16_t cipher_algo )
{
2021-07-13 21:26:19 +02:00
const struct smb3_signing_capabilities * sign_algos =
& c - > signing ;
2021-07-14 12:13:49 +02:00
const struct smb3_encryption_capabilities * ciphers =
& c - > encryption ;
2021-07-13 21:26:19 +02:00
bool found_signing = false ;
2021-07-14 12:13:49 +02:00
bool found_encryption = false ;
size_t i ;
2021-07-13 21:26:19 +02:00
for ( i = 0 ; i < sign_algos - > num_algos ; i + + ) {
if ( sign_algo = = sign_algos - > algos [ i ] ) {
/*
* We found a match
*/
found_signing = true ;
break ;
}
}
2021-07-14 12:13:49 +02:00
for ( i = 0 ; i < ciphers - > num_algos ; i + + ) {
if ( cipher_algo = = SMB2_ENCRYPTION_NONE ) {
/*
* encryption not supported , we ' ll error out later
*/
found_encryption = true ;
break ;
}
if ( cipher_algo = = ciphers - > algos [ i ] ) {
/*
* We found a match
*/
found_encryption = true ;
break ;
}
}
2021-07-13 21:26:19 +02:00
if ( ! found_signing ) {
/*
* We negotiated a signing algo we don ' t allow ,
* most likely for SMB < 3.1 .1
*/
DEBUG ( debug_lvl , ( " %s: "
" SMB3 signing algorithm[%u][%s] on dialect[%s] "
" not allowed by '%s smb3 signing algorithms' - %s. \n " ,
debug_prefix ,
sign_algo ,
smb3_signing_algorithm_name ( sign_algo ) ,
smb_protocol_types_string ( protocol ) ,
role ,
nt_errstr ( error_status ) ) ) ;
return error_status ;
}
2021-07-14 12:13:49 +02:00
if ( ! found_encryption ) {
/*
* We negotiated a cipher we don ' t allow ,
* most likely for SMB 3.0 and 3.0 .2
*/
DEBUG ( debug_lvl , ( " %s: "
" SMB3 encryption algorithm[%u][%s] on dialect[%s] "
" not allowed by '%s smb3 encryption algorithms' - %s. \n " ,
debug_prefix ,
cipher_algo ,
smb3_encryption_algorithm_name ( cipher_algo ) ,
smb_protocol_types_string ( protocol ) ,
role ,
nt_errstr ( error_status ) ) ) ;
return error_status ;
}
return NT_STATUS_OK ;
}