2003-12-04 14:01:58 +03:00
/*
Unix SMB / CIFS implementation .
SMBsearch handling
Copyright ( C ) Andrew Tridgell 2003
Copyright ( C ) James J Myers 2003 < myersjj @ samba . org >
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-12-04 14:01:58 +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/>.
2003-12-04 14:01:58 +03:00
*/
/*
This file handles the parsing of transact2 requests
*/
# include "includes.h"
2004-11-02 10:18:24 +03:00
# include "smb_server/smb_server.h"
2005-12-28 01:51:30 +03:00
# include "ntvfs/ntvfs.h"
2004-11-02 10:18:24 +03:00
2003-12-04 14:01:58 +03:00
/* a structure to encapsulate the state information about
* an in - progress search first / next operation */
struct search_state {
2004-06-28 12:39:00 +04:00
struct smbsrv_request * req ;
2003-12-04 14:01:58 +03:00
union smb_search_data * file ;
2004-05-25 21:24:24 +04:00
uint16_t last_entry_offset ;
2003-12-04 14:01:58 +03:00
} ;
/*
fill a single entry in a search find reply
*/
2007-10-07 02:10:49 +04:00
static bool find_fill_info ( struct smbsrv_request * req ,
2007-05-22 13:25:58 +04:00
const union smb_search_data * file )
2003-12-04 14:01:58 +03:00
{
2004-12-04 16:56:25 +03:00
uint8_t * p ;
2004-10-29 10:01:51 +04:00
if ( req - > out . data_size + 43 > req_max_data ( req ) ) {
2007-10-07 02:10:49 +04:00
return false ;
2004-10-29 10:01:51 +04:00
}
2003-12-04 14:01:58 +03:00
2004-09-21 12:46:47 +04:00
req_grow_data ( req , req - > out . data_size + 43 ) ;
p = req - > out . data + req - > out . data_size - 43 ;
SCVAL ( p , 0 , file - > search . id . reserved ) ;
memcpy ( p + 1 , file - > search . id . name , 11 ) ;
SCVAL ( p , 12 , file - > search . id . handle ) ;
SIVAL ( p , 13 , file - > search . id . server_cookie ) ;
SIVAL ( p , 17 , file - > search . id . client_cookie ) ;
SCVAL ( p , 21 , file - > search . attrib ) ;
srv_push_dos_date ( req - > smb_conn , p , 22 , file - > search . write_time ) ;
SIVAL ( p , 26 , file - > search . size ) ;
2004-09-22 16:38:19 +04:00
memset ( p + 30 , ' ' , 12 ) ;
memcpy ( p + 30 , file - > search . name , MIN ( strlen ( file - > search . name ) + 1 , 12 ) ) ;
SCVAL ( p , 42 , 0 ) ;
2004-10-29 10:01:51 +04:00
2007-10-07 02:10:49 +04:00
return true ;
2003-12-04 14:01:58 +03:00
}
/* callback function for search first/next */
2009-02-02 10:39:45 +03:00
static bool find_callback ( void * private_data , const union smb_search_data * file )
2003-12-04 14:01:58 +03:00
{
2009-02-02 10:39:45 +03:00
struct search_state * state = ( struct search_state * ) private_data ;
2003-12-04 14:01:58 +03:00
2004-10-29 10:01:51 +04:00
return find_fill_info ( state - > req , file ) ;
2003-12-04 14:01:58 +03:00
}
2006-03-17 19:42:39 +03:00
/****************************************************************************
Reply to a search first ( async reply )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-03-18 14:10:21 +03:00
static void reply_search_first_send ( struct ntvfs_request * ntvfs )
2006-03-17 19:42:39 +03:00
{
2006-03-18 14:10:21 +03:00
struct smbsrv_request * req ;
2006-03-17 19:42:39 +03:00
union smb_search_first * sf ;
2006-03-18 14:10:21 +03:00
SMBSRV_CHECK_ASYNC_STATUS ( sf , union smb_search_first ) ;
2006-03-17 19:42:39 +03:00
SSVAL ( req - > out . vwv , VWV ( 0 ) , sf - > search_first . out . count ) ;
smbsrv_send_reply ( req ) ;
}
/****************************************************************************
Reply to a search next ( async reply )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-03-18 14:10:21 +03:00
static void reply_search_next_send ( struct ntvfs_request * ntvfs )
2006-03-17 19:42:39 +03:00
{
2006-03-18 14:10:21 +03:00
struct smbsrv_request * req ;
2006-03-17 19:42:39 +03:00
union smb_search_next * sn ;
2006-03-18 14:10:21 +03:00
SMBSRV_CHECK_ASYNC_STATUS ( sn , union smb_search_next ) ;
2006-03-17 19:42:39 +03:00
SSVAL ( req - > out . vwv , VWV ( 0 ) , sn - > search_next . out . count ) ;
smbsrv_send_reply ( req ) ;
}
2003-12-04 14:01:58 +03:00
/****************************************************************************
Reply to a search .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-03-06 18:31:01 +03:00
void smbsrv_reply_search ( struct smbsrv_request * req )
2003-12-04 14:01:58 +03:00
{
union smb_search_first * sf ;
2004-05-25 21:24:24 +04:00
uint16_t resume_key_length ;
2006-03-17 19:42:39 +03:00
struct search_state * state ;
2004-12-04 16:56:25 +03:00
uint8_t * p ;
2004-09-21 12:46:47 +04:00
enum smb_search_level level = RAW_SEARCH_SEARCH ;
uint8_t op = CVAL ( req - > in . hdr , HDR_COM ) ;
if ( op = = SMBffirst ) {
level = RAW_SEARCH_FFIRST ;
} else if ( op = = SMBfunique ) {
level = RAW_SEARCH_FUNIQUE ;
}
2003-12-04 14:01:58 +03:00
/* parse request */
if ( req - > in . wct ! = 2 ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2003-12-04 14:01:58 +03:00
return ;
}
2006-03-17 19:42:39 +03:00
2006-03-18 14:10:21 +03:00
SMBSRV_TALLOC_IO_PTR ( sf , union smb_search_first ) ;
2003-12-04 14:01:58 +03:00
p = req - > in . data ;
2008-02-14 02:12:33 +03:00
p + = req_pull_ascii4 ( & req - > in . bufinfo , & sf - > search_first . in . pattern ,
2004-09-21 12:46:47 +04:00
p , STR_TERMINATE ) ;
2003-12-04 14:01:58 +03:00
if ( ! sf - > search_first . in . pattern ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ;
2003-12-04 14:01:58 +03:00
return ;
}
2004-09-21 12:46:47 +04:00
2008-02-14 02:12:33 +03:00
if ( req_data_oob ( & req - > in . bufinfo , p , 3 ) ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-09-21 12:46:47 +04:00
return ;
}
if ( * p ! = 5 ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-09-21 12:46:47 +04:00
return ;
}
resume_key_length = SVAL ( p , 1 ) ;
2003-12-04 14:01:58 +03:00
p + = 3 ;
/* setup state for callback */
2006-03-18 14:10:21 +03:00
state = talloc ( req , struct search_state ) ;
if ( ! state ) {
smbsrv_send_error ( req , NT_STATUS_NO_MEMORY ) ;
return ;
}
2006-03-17 19:42:39 +03:00
state - > req = req ;
state - > file = NULL ;
state - > last_entry_offset = 0 ;
2003-12-04 14:01:58 +03:00
/* construct reply */
2006-03-06 19:19:27 +03:00
smbsrv_setup_reply ( req , 1 , 0 ) ;
2006-03-17 19:42:39 +03:00
SSVAL ( req - > out . vwv , VWV ( 0 ) , 0 ) ;
2003-12-04 14:01:58 +03:00
req_append_var_block ( req , NULL , 0 ) ;
2004-09-21 12:46:47 +04:00
if ( resume_key_length ! = 0 ) {
2006-03-17 19:42:39 +03:00
union smb_search_next * sn ;
2004-09-21 12:46:47 +04:00
if ( resume_key_length ! = 21 | |
2008-02-14 02:12:33 +03:00
req_data_oob ( & req - > in . bufinfo , p , 21 ) | |
2004-09-21 12:46:47 +04:00
level = = RAW_SEARCH_FUNIQUE ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-09-21 12:46:47 +04:00
return ;
}
/* do a search next operation */
2006-03-18 14:10:21 +03:00
SMBSRV_TALLOC_IO_PTR ( sn , union smb_search_next ) ;
SMBSRV_SETUP_NTVFS_REQUEST ( reply_search_next_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
2004-09-21 12:46:47 +04:00
sn - > search_next . in . id . reserved = CVAL ( p , 0 ) ;
memcpy ( sn - > search_next . in . id . name , p + 1 , 11 ) ;
sn - > search_next . in . id . handle = CVAL ( p , 12 ) ;
sn - > search_next . in . id . server_cookie = IVAL ( p , 13 ) ;
sn - > search_next . in . id . client_cookie = IVAL ( p , 17 ) ;
sn - > search_next . level = level ;
2006-07-06 12:00:24 +04:00
sn - > search_next . data_level = RAW_SEARCH_DATA_SEARCH ;
2003-12-04 14:01:58 +03:00
sn - > search_next . in . max_count = SVAL ( req - > in . vwv , VWV ( 0 ) ) ;
2004-09-21 12:46:47 +04:00
sn - > search_next . in . search_attrib = SVAL ( req - > in . vwv , VWV ( 1 ) ) ;
2006-03-17 19:42:39 +03:00
2003-12-04 14:01:58 +03:00
/* call backend */
2006-03-18 14:10:21 +03:00
SMBSRV_CALL_NTVFS_BACKEND ( ntvfs_search_next ( req - > ntvfs , sn , state , find_callback ) ) ;
2003-12-04 14:01:58 +03:00
} else {
2006-03-18 14:10:21 +03:00
SMBSRV_SETUP_NTVFS_REQUEST ( reply_search_first_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
2003-12-04 14:01:58 +03:00
/* do a search first operation */
2004-09-21 12:46:47 +04:00
sf - > search_first . level = level ;
2006-07-06 12:00:24 +04:00
sf - > search_first . data_level = RAW_SEARCH_DATA_SEARCH ;
2003-12-04 14:01:58 +03:00
sf - > search_first . in . search_attrib = SVAL ( req - > in . vwv , VWV ( 1 ) ) ;
sf - > search_first . in . max_count = SVAL ( req - > in . vwv , VWV ( 0 ) ) ;
2006-03-18 14:10:21 +03:00
SMBSRV_CALL_NTVFS_BACKEND ( ntvfs_search_first ( req - > ntvfs , sf , state , find_callback ) ) ;
2004-09-21 12:46:47 +04:00
}
2003-12-04 14:01:58 +03:00
}
/****************************************************************************
Reply to a fclose ( async reply )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-03-18 14:10:21 +03:00
static void reply_fclose_send ( struct ntvfs_request * ntvfs )
2003-12-04 14:01:58 +03:00
{
2006-03-18 14:10:21 +03:00
struct smbsrv_request * req ;
SMBSRV_CHECK_ASYNC_STATUS_SIMPLE ;
2003-12-04 14:01:58 +03:00
/* construct reply */
2006-03-06 19:19:27 +03:00
smbsrv_setup_reply ( req , 1 , 0 ) ;
2003-12-04 14:01:58 +03:00
2004-09-21 12:46:47 +04:00
SSVAL ( req - > out . vwv , VWV ( 0 ) , 0 ) ;
2006-03-06 19:19:27 +03:00
smbsrv_send_reply ( req ) ;
2003-12-04 14:01:58 +03:00
}
/****************************************************************************
Reply to fclose ( stop directory search ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-03-06 18:31:01 +03:00
void smbsrv_reply_fclose ( struct smbsrv_request * req )
2003-12-04 14:01:58 +03:00
{
2004-09-21 12:46:47 +04:00
union smb_search_close * sc ;
2004-05-25 21:24:24 +04:00
uint16_t resume_key_length ;
2004-12-04 16:56:25 +03:00
uint8_t * p ;
2004-09-21 12:46:47 +04:00
const char * pattern ;
2003-12-04 14:01:58 +03:00
/* parse request */
if ( req - > in . wct ! = 2 ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2003-12-04 14:01:58 +03:00
return ;
}
2006-03-18 14:10:21 +03:00
SMBSRV_TALLOC_IO_PTR ( sc , union smb_search_close ) ;
SMBSRV_SETUP_NTVFS_REQUEST ( reply_fclose_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
2004-09-21 12:46:47 +04:00
p = req - > in . data ;
2008-02-14 02:12:33 +03:00
p + = req_pull_ascii4 ( & req - > in . bufinfo , & pattern , p , STR_TERMINATE ) ;
2004-09-21 12:46:47 +04:00
if ( pattern & & * pattern ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-09-21 12:46:47 +04:00
return ;
}
2003-12-04 14:01:58 +03:00
2008-02-14 02:12:33 +03:00
if ( req_data_oob ( & req - > in . bufinfo , p , 3 ) ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-09-21 12:46:47 +04:00
return ;
}
if ( * p ! = 5 ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-09-21 12:46:47 +04:00
return ;
}
resume_key_length = SVAL ( p , 1 ) ;
p + = 3 ;
if ( resume_key_length ! = 21 ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-09-21 12:46:47 +04:00
return ;
}
2008-02-14 02:12:33 +03:00
if ( req_data_oob ( & req - > in . bufinfo , p , 21 ) ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-09-21 12:46:47 +04:00
return ;
}
sc - > fclose . level = RAW_FINDCLOSE_FCLOSE ;
sc - > fclose . in . max_count = SVAL ( req - > in . vwv , VWV ( 0 ) ) ;
sc - > fclose . in . search_attrib = SVAL ( req - > in . vwv , VWV ( 1 ) ) ;
sc - > fclose . in . id . reserved = CVAL ( p , 0 ) ;
memcpy ( sc - > fclose . in . id . name , p + 1 , 11 ) ;
sc - > fclose . in . id . handle = CVAL ( p , 12 ) ;
sc - > fclose . in . id . server_cookie = IVAL ( p , 13 ) ;
sc - > fclose . in . id . client_cookie = IVAL ( p , 17 ) ;
2003-12-04 14:01:58 +03:00
2006-03-18 14:10:21 +03:00
SMBSRV_CALL_NTVFS_BACKEND ( ntvfs_search_close ( req - > ntvfs , sc ) ) ;
2003-12-04 14:01:58 +03:00
}