2005-11-12 10:48:56 +03:00
/*
Unix SMB / CIFS implementation .
SMB2 client getinfo calls
Copyright ( C ) Andrew Tridgell 2005
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
2005-11-12 10:48:56 +03:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-11-12 10:48:56 +03:00
*/
# include "includes.h"
# include "libcli/raw/libcliraw.h"
2008-04-02 06:53:27 +04:00
# include "libcli/raw/raw_proto.h"
2005-11-12 10:48:56 +03:00
# include "libcli/smb2/smb2.h"
# include "libcli/smb2/smb2_calls.h"
/*
send a getinfo request
*/
struct smb2_request * smb2_getinfo_send ( struct smb2_tree * tree , struct smb2_getinfo * io )
{
struct smb2_request * req ;
2008-02-14 09:11:36 +03:00
NTSTATUS status ;
2019-01-08 18:11:15 +03:00
size_t max_payload ;
2005-11-12 10:48:56 +03:00
2008-02-14 09:11:36 +03:00
req = smb2_request_init_tree ( tree , SMB2_OP_GETINFO , 0x28 , true ,
2019-01-08 18:09:46 +03:00
io - > in . input_buffer . length ) ;
2005-11-12 10:48:56 +03:00
if ( req = = NULL ) return NULL ;
2008-02-14 09:11:36 +03:00
SCVAL ( req - > out . body , 0x02 , io - > in . info_type ) ;
SCVAL ( req - > out . body , 0x03 , io - > in . info_class ) ;
SIVAL ( req - > out . body , 0x04 , io - > in . output_buffer_length ) ;
2019-01-08 18:09:46 +03:00
/*
* uint16_t input_buffer_offset
* uint16_t reserved
* uint32_t input_buffer_length
*
* We use smb2_push_o32s32_blob ( ) which would
* expect uint32_t offset , uint32_t length .
*
* Everything is little endian , we can just
* overwrite the reserved field later .
*/
2008-02-14 09:11:36 +03:00
SIVAL ( req - > out . body , 0x10 , io - > in . additional_information ) ;
SIVAL ( req - > out . body , 0x14 , io - > in . getinfo_flags ) ;
2006-06-20 11:03:53 +04:00
smb2_push_handle ( req - > out . body + 0x18 , & io - > in . file . handle ) ;
2005-11-12 10:48:56 +03:00
2008-02-14 09:11:36 +03:00
/* this blob is used for quota queries */
2019-01-08 18:09:46 +03:00
status = smb2_push_o32s32_blob ( & req - > out , 0x08 , io - > in . input_buffer ) ;
2008-02-14 09:11:36 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( req ) ;
return NULL ;
}
2019-01-08 18:09:46 +03:00
SSVAL ( req - > out . body , 0x0C , io - > in . reserved ) ;
2019-01-08 18:11:15 +03:00
max_payload = MAX ( io - > in . output_buffer_length , io - > in . input_buffer . length ) ;
req - > credit_charge = ( MAX ( max_payload , 1 ) - 1 ) / 65536 + 1 ;
2005-11-12 10:48:56 +03:00
smb2_transport_send ( req ) ;
return req ;
}
/*
recv a getinfo reply
*/
NTSTATUS smb2_getinfo_recv ( struct smb2_request * req , TALLOC_CTX * mem_ctx ,
struct smb2_getinfo * io )
{
NTSTATUS status ;
if ( ! smb2_request_receive ( req ) | |
smb2_request_is_error ( req ) ) {
return smb2_request_destroy ( req ) ;
}
2007-10-07 02:28:14 +04:00
SMB2_CHECK_PACKET_RECV ( req , 0x08 , true ) ;
2005-11-12 10:48:56 +03:00
2005-11-16 14:01:15 +03:00
status = smb2_pull_o16s16_blob ( & req - > in , mem_ctx , req - > in . body + 0x02 , & io - > out . blob ) ;
2005-11-12 10:48:56 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return smb2_request_destroy ( req ) ;
}
/*
sync getinfo request
*/
NTSTATUS smb2_getinfo ( struct smb2_tree * tree , TALLOC_CTX * mem_ctx ,
struct smb2_getinfo * io )
{
struct smb2_request * req = smb2_getinfo_send ( tree , io ) ;
return smb2_getinfo_recv ( req , mem_ctx , io ) ;
}
2005-11-14 08:09:26 +03:00
2005-11-18 09:28:15 +03:00
/*
map a generic info level to a SMB2 info level
*/
2009-02-02 11:12:52 +03:00
uint16_t smb2_getinfo_map_level ( uint16_t level , uint8_t info_class )
2005-11-18 09:28:15 +03:00
{
2019-03-29 13:08:12 +03:00
if ( info_class = = SMB2_0_INFO_FILE & &
2005-11-18 13:07:14 +03:00
level = = RAW_FILEINFO_SEC_DESC ) {
2019-03-29 13:08:12 +03:00
return SMB2_0_INFO_SECURITY ;
2005-11-18 13:07:14 +03:00
}
2009-02-02 11:12:52 +03:00
if ( ( level & 0xFF ) = = info_class ) {
2005-11-18 09:28:15 +03:00
return level ;
} else if ( level > 1000 ) {
2009-02-02 11:12:52 +03:00
return ( ( level - 1000 ) < < 8 ) | info_class ;
2005-11-18 09:28:15 +03:00
}
2009-02-02 11:12:52 +03:00
DEBUG ( 0 , ( " Unable to map SMB2 info level 0x%04x of class %d \n " ,
level , info_class ) ) ;
2005-11-18 09:28:15 +03:00
return 0 ;
}
/*
level specific getinfo call - async send
*/
struct smb2_request * smb2_getinfo_file_send ( struct smb2_tree * tree , union smb_fileinfo * io )
{
struct smb2_getinfo b ;
2019-03-29 13:08:12 +03:00
uint16_t smb2_level = smb2_getinfo_map_level (
io - > generic . level , SMB2_0_INFO_FILE ) ;
2005-11-18 09:28:15 +03:00
if ( smb2_level = = 0 ) {
return NULL ;
}
ZERO_STRUCT ( b ) ;
2008-02-14 09:11:36 +03:00
b . in . info_type = smb2_level & 0xFF ;
b . in . info_class = smb2_level > > 8 ;
b . in . output_buffer_length = 0x10000 ;
2019-01-08 18:09:46 +03:00
b . in . input_buffer = data_blob_null ;
2008-02-14 09:11:36 +03:00
b . in . file . handle = io - > generic . in . file . handle ;
2005-11-18 09:28:15 +03:00
if ( io - > generic . level = = RAW_FILEINFO_SEC_DESC ) {
2008-02-14 09:11:36 +03:00
b . in . additional_information = io - > query_secdesc . in . secinfo_flags ;
2005-11-18 09:28:15 +03:00
}
2005-11-19 08:55:08 +03:00
if ( io - > generic . level = = RAW_FILEINFO_SMB2_ALL_EAS ) {
2008-02-14 09:11:36 +03:00
b . in . getinfo_flags = io - > all_eas . in . continue_flags ;
2005-11-19 08:55:08 +03:00
}
2005-11-18 09:28:15 +03:00
return smb2_getinfo_send ( tree , & b ) ;
}
2005-11-14 08:09:26 +03:00
/*
2005-11-17 14:06:13 +03:00
recv a getinfo reply and parse the level info
2005-11-14 08:09:26 +03:00
*/
2005-11-17 14:06:13 +03:00
NTSTATUS smb2_getinfo_file_recv ( struct smb2_request * req , TALLOC_CTX * mem_ctx ,
union smb_fileinfo * io )
2005-11-14 08:09:26 +03:00
{
2005-11-17 14:06:13 +03:00
struct smb2_getinfo b ;
NTSTATUS status ;
2005-11-15 07:38:59 +03:00
2005-11-17 14:06:13 +03:00
status = smb2_getinfo_recv ( req , mem_ctx , & b ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2005-11-15 07:38:59 +03:00
2005-11-17 14:06:13 +03:00
status = smb_raw_fileinfo_passthru_parse ( & b . out . blob , mem_ctx , io - > generic . level , io ) ;
data_blob_free ( & b . out . blob ) ;
return status ;
}
/*
level specific getinfo call
*/
NTSTATUS smb2_getinfo_file ( struct smb2_tree * tree , TALLOC_CTX * mem_ctx ,
union smb_fileinfo * io )
{
2005-11-18 09:28:15 +03:00
struct smb2_request * req = smb2_getinfo_file_send ( tree , io ) ;
return smb2_getinfo_file_recv ( req , mem_ctx , io ) ;
}
2005-11-17 14:06:13 +03:00
2005-11-18 09:28:15 +03:00
/*
level specific getinfo call - async send
*/
struct smb2_request * smb2_getinfo_fs_send ( struct smb2_tree * tree , union smb_fsinfo * io )
{
struct smb2_getinfo b ;
2019-03-29 13:08:12 +03:00
uint16_t smb2_level = smb2_getinfo_map_level (
io - > generic . level , SMB2_0_INFO_FILESYSTEM ) ;
2005-11-18 09:28:15 +03:00
if ( smb2_level = = 0 ) {
return NULL ;
}
2005-11-17 14:06:13 +03:00
ZERO_STRUCT ( b ) ;
2008-02-14 09:11:36 +03:00
b . in . output_buffer_length = 0x10000 ;
b . in . file . handle = io - > generic . handle ;
b . in . info_type = smb2_level & 0xFF ;
b . in . info_class = smb2_level > > 8 ;
2005-11-17 14:06:13 +03:00
2005-11-18 09:28:15 +03:00
return smb2_getinfo_send ( tree , & b ) ;
2005-11-14 08:09:26 +03:00
}
/*
recv a getinfo reply and parse the level info
*/
2005-11-17 14:06:13 +03:00
NTSTATUS smb2_getinfo_fs_recv ( struct smb2_request * req , TALLOC_CTX * mem_ctx ,
union smb_fsinfo * io )
2005-11-14 08:09:26 +03:00
{
2019-07-29 14:22:29 +03:00
struct smb2_getinfo b = {
. in = { 0 } ,
} ;
2005-11-14 08:09:26 +03:00
NTSTATUS status ;
status = smb2_getinfo_recv ( req , mem_ctx , & b ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2005-11-17 14:06:13 +03:00
status = smb_raw_fsinfo_passthru_parse ( b . out . blob , mem_ctx , io - > generic . level , io ) ;
2005-11-14 08:09:26 +03:00
data_blob_free ( & b . out . blob ) ;
return status ;
}
2005-11-15 07:38:59 +03:00
/*
level specific getinfo call
*/
2005-11-17 14:06:13 +03:00
NTSTATUS smb2_getinfo_fs ( struct smb2_tree * tree , TALLOC_CTX * mem_ctx ,
union smb_fsinfo * io )
2005-11-15 07:38:59 +03:00
{
2005-11-18 09:28:15 +03:00
struct smb2_request * req = smb2_getinfo_fs_send ( tree , io ) ;
2005-11-17 14:06:13 +03:00
return smb2_getinfo_fs_recv ( req , mem_ctx , io ) ;
2005-11-15 07:38:59 +03:00
}
2005-11-17 14:06:13 +03:00