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
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"
# include "libcli/raw/libcliraw.h"
# 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 ;
2005-11-16 14:01:15 +03:00
req = smb2_request_init_tree ( tree , SMB2_OP_GETINFO , 0x28 , 0 ) ;
2005-11-12 10:48:56 +03:00
if ( req = = NULL ) return NULL ;
2005-11-16 14:01:15 +03:00
/* this seems to be a bug, they use 0x29 but only send 0x28 bytes */
SSVAL ( req - > out . body , 0x00 , 0x29 ) ;
2005-11-12 10:48:56 +03:00
SSVAL ( req - > out . body , 0x02 , io - > in . level ) ;
SIVAL ( req - > out . body , 0x04 , io - > in . max_response_size ) ;
SIVAL ( req - > out . body , 0x08 , io - > in . unknown1 ) ;
2005-11-17 14:06:13 +03:00
SIVAL ( req - > out . body , 0x0C , io - > in . unknown2 ) ;
SIVAL ( req - > out . body , 0x10 , io - > in . flags ) ;
2005-11-19 08:55:08 +03:00
SIVAL ( req - > out . body , 0x14 , io - > in . flags2 ) ;
2005-11-16 14:01:15 +03:00
smb2_push_handle ( req - > out . body + 0x18 , & io - > in . handle ) ;
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 ) ;
}
2005-11-16 14:01:15 +03: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
*/
uint16_t smb2_getinfo_map_level ( uint16_t level , uint8_t class )
{
2005-11-18 13:07:14 +03:00
if ( class = = SMB2_GETINFO_FILE & &
level = = RAW_FILEINFO_SEC_DESC ) {
return SMB2_GETINFO_SECURITY ;
}
2005-11-18 09:28:15 +03:00
if ( ( level & 0xFF ) = = class ) {
return level ;
} else if ( level > 1000 ) {
return ( ( level - 1000 ) < < 8 ) | class ;
}
DEBUG ( 0 , ( " Unable to map SMB2 info level 0x%04x of class %d \n " , level , class ) ) ;
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 ;
uint16_t smb2_level = smb2_getinfo_map_level ( io - > generic . level , SMB2_GETINFO_FILE ) ;
if ( smb2_level = = 0 ) {
return NULL ;
}
ZERO_STRUCT ( b ) ;
b . in . max_response_size = 0x10000 ;
2006-03-13 01:48:25 +03:00
b . in . handle = io - > generic . in . file . handle ;
2005-11-18 09:28:15 +03:00
b . in . level = smb2_level ;
if ( io - > generic . level = = RAW_FILEINFO_SEC_DESC ) {
2006-03-10 23:49:20 +03:00
b . in . flags = 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 ) {
2006-03-10 23:49:20 +03:00
b . in . flags2 = 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 ;
uint16_t smb2_level = smb2_getinfo_map_level ( io - > generic . level , SMB2_GETINFO_FS ) ;
if ( smb2_level = = 0 ) {
return NULL ;
}
2005-11-17 14:06:13 +03:00
ZERO_STRUCT ( b ) ;
b . in . max_response_size = 0x10000 ;
2005-11-18 09:28:15 +03:00
b . in . handle = io - > generic . handle ;
2005-11-17 14:06:13 +03:00
b . in . level = smb2_level ;
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
{
struct smb2_getinfo b ;
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