2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
transaction2 handling
Copyright ( C ) Andrew Tridgell 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 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 .
*/
/*
This file handles the parsing of transact2 requests
*/
# include "includes.h"
2004-12-16 15:31:34 +03:00
# include "dlinklist.h"
2004-11-02 10:18:24 +03:00
# include "smb_server/smb_server.h"
2005-07-28 04:27:28 +04:00
# include "librpc/gen_ndr/ndr_misc.h"
2005-12-28 01:51:30 +03:00
# include "ntvfs/ntvfs.h"
2005-12-28 18:38:36 +03:00
# include "libcli/raw/libcliraw.h"
2004-11-02 10:18:24 +03:00
2006-03-18 14:10:21 +03:00
# define TRANS2_CHECK_ASYNC_STATUS_SIMPLE do { \
if ( ! NT_STATUS_IS_OK ( req - > ntvfs - > async_states - > status ) ) { \
trans2_setup_reply ( trans , 0 , 0 , 0 ) ; \
return req - > ntvfs - > async_states - > status ; \
} \
} while ( 0 )
# define TRANS2_CHECK_ASYNC_STATUS(ptr, type) do { \
TRANS2_CHECK_ASYNC_STATUS_SIMPLE ; \
ptr = talloc_get_type ( op - > op_info , type ) ; \
} while ( 0 )
2006-06-19 22:01:27 +04:00
# define TRANS2_CHECK(cmd) do { \
NTSTATUS _status ; \
_status = cmd ; \
NT_STATUS_NOT_OK_RETURN ( _status ) ; \
} while ( 0 )
2006-03-18 14:10:21 +03:00
2006-03-17 12:42:04 +03:00
/*
hold the state of a nttrans op while in progress . Needed to allow for async backend
functions .
*/
struct trans_op {
struct smbsrv_request * req ;
struct smb_trans2 * trans ;
uint8_t command ;
NTSTATUS ( * send_fn ) ( struct trans_op * ) ;
void * op_info ;
} ;
2003-08-13 05:53:07 +04:00
# define CHECK_MIN_BLOB_SIZE(blob, size) do { \
if ( ( blob ) - > length < ( size ) ) { \
return NT_STATUS_INFO_LENGTH_MISMATCH ; \
} } while ( 0 )
/* grow the data size of a trans2 reply */
2006-06-19 22:01:27 +04:00
static NTSTATUS trans2_grow_data ( TALLOC_CTX * mem_ctx ,
DATA_BLOB * blob ,
uint32_t new_size )
2003-08-13 05:53:07 +04:00
{
2006-06-19 22:01:27 +04:00
if ( new_size > blob - > length ) {
2006-06-20 10:05:10 +04:00
uint8_t * p ;
p = talloc_realloc ( mem_ctx , blob - > data , uint8_t , new_size ) ;
NT_STATUS_HAVE_NO_MEMORY ( p ) ;
blob - > data = p ;
2004-12-20 06:12:09 +03:00
}
2006-06-19 22:01:27 +04:00
blob - > length = new_size ;
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
}
/* grow the data, zero filling any new bytes */
2006-06-19 22:01:27 +04:00
static NTSTATUS trans2_grow_data_fill ( TALLOC_CTX * mem_ctx ,
DATA_BLOB * blob ,
uint32_t new_size )
2003-08-13 05:53:07 +04:00
{
2006-06-19 22:01:27 +04:00
uint32_t old_size = blob - > length ;
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , new_size ) ) ;
2003-08-13 05:53:07 +04:00
if ( new_size > old_size ) {
2006-06-19 22:01:27 +04:00
memset ( blob - > data + old_size , 0 , new_size - old_size ) ;
2003-08-13 05:53:07 +04:00
}
2006-06-19 22:01:27 +04:00
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
}
/* setup a trans2 reply, given the data and params sizes */
2006-06-19 22:01:27 +04:00
static NTSTATUS trans2_setup_reply ( struct smb_trans2 * trans ,
uint16_t param_size , uint16_t data_size ,
uint16_t setup_count )
2003-08-13 05:53:07 +04:00
{
trans - > out . setup_count = setup_count ;
2006-06-19 22:01:27 +04:00
if ( setup_count > 0 ) {
2006-03-17 12:42:04 +03:00
trans - > out . setup = talloc_zero_array ( trans , uint16_t , setup_count ) ;
2006-06-19 22:01:27 +04:00
NT_STATUS_HAVE_NO_MEMORY ( trans - > out . setup ) ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 12:42:04 +03:00
trans - > out . params = data_blob_talloc ( trans , NULL , param_size ) ;
2006-06-19 22:01:27 +04:00
if ( param_size > 0 ) NT_STATUS_HAVE_NO_MEMORY ( trans - > out . params . data ) ;
2006-03-17 12:42:04 +03:00
trans - > out . data = data_blob_talloc ( trans , NULL , data_size ) ;
2006-06-19 22:01:27 +04:00
if ( data_size > 0 ) NT_STATUS_HAVE_NO_MEMORY ( trans - > out . data . data ) ;
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
}
/*
pull a string from a blob in a trans2 request
*/
2004-06-28 12:39:00 +04:00
static size_t trans2_pull_blob_string ( struct smbsrv_request * req ,
2003-08-13 05:53:07 +04:00
const DATA_BLOB * blob ,
2004-05-25 21:24:24 +04:00
uint16_t offset ,
2003-08-13 05:53:07 +04:00
const char * * str ,
int flags )
{
2006-06-20 09:06:10 +04:00
* str = NULL ;
2003-08-13 05:53:07 +04:00
/* we use STR_NO_RANGE_CHECK because the params are allocated
separately in a DATA_BLOB , so we need to do our own range
checking */
if ( offset > = blob - > length ) {
return 0 ;
}
return req_pull_string ( req , str ,
blob - > data + offset ,
blob - > length - offset ,
STR_NO_RANGE_CHECK | flags ) ;
}
/*
push a string into the data section of a trans2 request
return the number of bytes consumed in the output
*/
2006-06-19 22:01:27 +04:00
static size_t trans2_push_data_string ( struct smbsrv_request * req ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * blob ,
2004-12-29 02:28:02 +03:00
uint32_t len_offset ,
uint32_t offset ,
2006-03-11 13:25:59 +03:00
const struct smb_wire_string * str ,
2003-08-13 05:53:07 +04:00
int dest_len ,
int flags )
{
int alignment = 0 , ret = 0 , pkt_len ;
/* we use STR_NO_RANGE_CHECK because the params are allocated
separately in a DATA_BLOB , so we need to do our own range
checking */
2006-06-19 22:01:27 +04:00
if ( ! str - > s | | offset > = blob - > length ) {
2003-08-13 05:53:07 +04:00
if ( flags & STR_LEN8BIT ) {
2006-06-19 22:01:27 +04:00
SCVAL ( blob - > data , len_offset , 0 ) ;
2003-08-13 05:53:07 +04:00
} else {
2006-06-19 22:01:27 +04:00
SIVAL ( blob - > data , len_offset , 0 ) ;
2003-08-13 05:53:07 +04:00
}
return 0 ;
}
flags | = STR_NO_RANGE_CHECK ;
2006-06-19 22:01:27 +04:00
if ( dest_len = = - 1 | | ( dest_len > blob - > length - offset ) ) {
dest_len = blob - > length - offset ;
2003-08-13 05:53:07 +04:00
}
if ( ! ( flags & ( STR_ASCII | STR_UNICODE ) ) ) {
2003-08-16 00:19:30 +04:00
flags | = ( req - > flags2 & FLAGS2_UNICODE_STRINGS ) ? STR_UNICODE : STR_ASCII ;
2003-08-13 05:53:07 +04:00
}
if ( ( offset & 1 ) & & ( flags & STR_UNICODE ) & & ! ( flags & STR_NOALIGN ) ) {
alignment = 1 ;
if ( dest_len > 0 ) {
2006-06-19 22:01:27 +04:00
SCVAL ( blob - > data + offset , 0 , 0 ) ;
ret = push_string ( blob - > data + offset + 1 , str - > s , dest_len - 1 , flags ) ;
2003-08-13 05:53:07 +04:00
}
} else {
2006-06-19 22:01:27 +04:00
ret = push_string ( blob - > data + offset , str - > s , dest_len , flags ) ;
2003-08-13 05:53:07 +04:00
}
/* sometimes the string needs to be terminated, but the length
on the wire must not include the termination ! */
pkt_len = ret ;
if ( ( flags & STR_LEN_NOTERM ) & & ( flags & STR_TERMINATE ) ) {
if ( ( flags & STR_UNICODE ) & & ret > = 2 ) {
pkt_len = ret - 2 ;
}
if ( ( flags & STR_ASCII ) & & ret > = 1 ) {
pkt_len = ret - 1 ;
}
2006-06-19 22:01:27 +04:00
}
2003-08-13 05:53:07 +04:00
if ( flags & STR_LEN8BIT ) {
2006-06-19 22:01:27 +04:00
SCVAL ( blob - > data , len_offset , pkt_len ) ;
2003-08-13 05:53:07 +04:00
} else {
2006-06-19 22:01:27 +04:00
SIVAL ( blob - > data , len_offset , pkt_len ) ;
2003-08-13 05:53:07 +04:00
}
return ret + alignment ;
}
/*
append a string to the data section of a trans2 reply
len_offset points to the place in the packet where the length field
should go
*/
2006-06-19 22:01:27 +04:00
static NTSTATUS trans2_append_data_string ( struct smbsrv_request * req ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * blob ,
const struct smb_wire_string * str ,
uint_t len_offset ,
int flags )
2003-08-13 05:53:07 +04:00
{
size_t ret ;
2004-12-29 02:28:02 +03:00
uint32_t offset ;
2003-08-13 05:53:07 +04:00
const int max_bytes_per_char = 3 ;
2006-06-19 22:01:27 +04:00
offset = blob - > length ;
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , offset + ( 2 + strlen_m ( str - > s ) ) * max_bytes_per_char ) ) ;
ret = trans2_push_data_string ( req , mem_ctx , blob , len_offset , offset , str , - 1 , flags ) ;
if ( ret < 0 ) {
return NT_STATUS_FOOBAR ;
}
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , offset + ret ) ) ;
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
}
2004-10-02 16:16:46 +04:00
/*
align the end of the data section of a trans reply on an even boundary
*/
2006-06-19 22:01:27 +04:00
static NTSTATUS trans2_align_data ( struct smb_trans2 * trans )
2004-10-02 16:16:46 +04:00
{
2006-06-19 22:01:27 +04:00
if ( trans - > out . data . length & 1 ) {
TRANS2_CHECK ( trans2_grow_data_fill ( trans , & trans - > out . data , trans - > out . data . length + 1 ) ) ;
2004-10-02 16:16:46 +04:00
}
2006-06-19 22:01:27 +04:00
return NT_STATUS_OK ;
2004-10-02 16:16:46 +04:00
}
2006-06-20 08:14:37 +04:00
static NTSTATUS trans2_push_fsinfo ( struct smbsrv_request * req ,
union smb_fsinfo * fsinfo ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * blob )
2003-08-13 05:53:07 +04:00
{
uint_t i ;
2003-12-16 12:02:58 +03:00
DATA_BLOB guid_blob ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
switch ( fsinfo - > generic . level ) {
2003-08-13 05:53:07 +04:00
case SMB_QFS_ALLOCATION :
2006-06-20 08:14:37 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 18 ) ) ;
2003-08-13 05:53:07 +04:00
2006-06-20 08:14:37 +04:00
SIVAL ( blob - > data , 0 , fsinfo - > allocation . out . fs_id ) ;
SIVAL ( blob - > data , 4 , fsinfo - > allocation . out . sectors_per_unit ) ;
SIVAL ( blob - > data , 8 , fsinfo - > allocation . out . total_alloc_units ) ;
SIVAL ( blob - > data , 12 , fsinfo - > allocation . out . avail_alloc_units ) ;
SSVAL ( blob - > data , 16 , fsinfo - > allocation . out . bytes_per_sector ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_QFS_VOLUME :
2006-06-20 08:14:37 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 5 ) ) ;
2003-08-13 05:53:07 +04:00
2006-06-20 08:14:37 +04:00
SIVAL ( blob - > data , 0 , fsinfo - > volume . out . serial_number ) ;
2003-08-13 05:53:07 +04:00
/* w2k3 implements this incorrectly for unicode - it
* leaves the last byte off the string */
2006-06-20 08:14:37 +04:00
TRANS2_CHECK ( trans2_append_data_string ( req , mem_ctx , blob ,
& fsinfo - > volume . out . volume_name ,
4 , STR_LEN8BIT | STR_NOALIGN ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_QFS_VOLUME_INFO :
case SMB_QFS_VOLUME_INFORMATION :
2006-06-20 08:14:37 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 18 ) ) ;
2003-08-13 05:53:07 +04:00
2006-06-20 08:14:37 +04:00
push_nttime ( blob - > data , 0 , fsinfo - > volume_info . out . create_time ) ;
SIVAL ( blob - > data , 8 , fsinfo - > volume_info . out . serial_number ) ;
SSVAL ( blob - > data , 16 , 0 ) ; /* padding */
TRANS2_CHECK ( trans2_append_data_string ( req , mem_ctx , blob ,
& fsinfo - > volume_info . out . volume_name ,
12 , STR_UNICODE ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_QFS_SIZE_INFO :
case SMB_QFS_SIZE_INFORMATION :
2006-06-20 08:14:37 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 24 ) ) ;
2003-08-13 05:53:07 +04:00
2006-06-20 08:14:37 +04:00
SBVAL ( blob - > data , 0 , fsinfo - > size_info . out . total_alloc_units ) ;
SBVAL ( blob - > data , 8 , fsinfo - > size_info . out . avail_alloc_units ) ;
SIVAL ( blob - > data , 16 , fsinfo - > size_info . out . sectors_per_unit ) ;
SIVAL ( blob - > data , 20 , fsinfo - > size_info . out . bytes_per_sector ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_QFS_DEVICE_INFO :
case SMB_QFS_DEVICE_INFORMATION :
2006-06-20 08:14:37 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 8 ) ) ;
SIVAL ( blob - > data , 0 , fsinfo - > device_info . out . device_type ) ;
SIVAL ( blob - > data , 4 , fsinfo - > device_info . out . characteristics ) ;
2003-08-13 05:53:07 +04:00
2006-06-20 08:14:37 +04:00
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
case SMB_QFS_ATTRIBUTE_INFO :
case SMB_QFS_ATTRIBUTE_INFORMATION :
2006-06-20 08:14:37 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 12 ) ) ;
2003-08-13 05:53:07 +04:00
2006-06-20 08:14:37 +04:00
SIVAL ( blob - > data , 0 , fsinfo - > attribute_info . out . fs_attr ) ;
SIVAL ( blob - > data , 4 , fsinfo - > attribute_info . out . max_file_component_length ) ;
2003-08-13 05:53:07 +04:00
/* this must not be null terminated or win98 gets
confused ! also note that w2k3 returns this as
unicode even when ascii is negotiated */
2006-06-20 08:14:37 +04:00
TRANS2_CHECK ( trans2_append_data_string ( req , mem_ctx , blob ,
& fsinfo - > attribute_info . out . fs_type ,
8 , STR_UNICODE ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_QFS_QUOTA_INFORMATION :
2006-06-20 08:14:37 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 48 ) ) ;
2003-08-13 05:53:07 +04:00
2006-06-20 08:14:37 +04:00
SBVAL ( blob - > data , 0 , fsinfo - > quota_information . out . unknown [ 0 ] ) ;
SBVAL ( blob - > data , 8 , fsinfo - > quota_information . out . unknown [ 1 ] ) ;
SBVAL ( blob - > data , 16 , fsinfo - > quota_information . out . unknown [ 2 ] ) ;
SBVAL ( blob - > data , 24 , fsinfo - > quota_information . out . quota_soft ) ;
SBVAL ( blob - > data , 32 , fsinfo - > quota_information . out . quota_hard ) ;
SBVAL ( blob - > data , 40 , fsinfo - > quota_information . out . quota_flags ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_QFS_FULL_SIZE_INFORMATION :
2006-06-20 08:14:37 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 32 ) ) ;
2003-08-13 05:53:07 +04:00
2006-06-20 08:14:37 +04:00
SBVAL ( blob - > data , 0 , fsinfo - > full_size_information . out . total_alloc_units ) ;
SBVAL ( blob - > data , 8 , fsinfo - > full_size_information . out . call_avail_alloc_units ) ;
SBVAL ( blob - > data , 16 , fsinfo - > full_size_information . out . actual_avail_alloc_units ) ;
SIVAL ( blob - > data , 24 , fsinfo - > full_size_information . out . sectors_per_unit ) ;
SIVAL ( blob - > data , 28 , fsinfo - > full_size_information . out . bytes_per_sector ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_QFS_OBJECTID_INFORMATION :
2006-06-20 08:14:37 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 64 ) ) ;
2003-12-16 12:02:58 +03:00
2006-06-20 08:14:37 +04:00
TRANS2_CHECK ( ndr_push_struct_blob ( & guid_blob , mem_ctx ,
& fsinfo - > objectid_information . out . guid ,
( ndr_push_flags_fn_t ) ndr_push_GUID ) ) ;
memcpy ( blob - > data , guid_blob . data , guid_blob . length ) ;
2003-12-16 12:02:58 +03:00
2003-08-13 05:53:07 +04:00
for ( i = 0 ; i < 6 ; i + + ) {
2006-06-20 08:14:37 +04:00
SBVAL ( blob - > data , 16 + 8 * i , fsinfo - > objectid_information . out . unknown [ i ] ) ;
2003-08-13 05:53:07 +04:00
}
2006-06-20 08:14:37 +04:00
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
}
return NT_STATUS_INVALID_LEVEL ;
}
2006-06-20 08:14:37 +04:00
/*
trans2 qfsinfo implementation send
*/
static NTSTATUS trans2_qfsinfo_send ( struct trans_op * op )
{
struct smbsrv_request * req = op - > req ;
struct smb_trans2 * trans = op - > trans ;
union smb_fsinfo * fsinfo ;
TRANS2_CHECK_ASYNC_STATUS ( fsinfo , union smb_fsinfo ) ;
TRANS2_CHECK ( trans2_setup_reply ( trans , 0 , 0 , 0 ) ) ;
TRANS2_CHECK ( trans2_push_fsinfo ( req , fsinfo , trans , & trans - > out . data ) ) ;
return NT_STATUS_OK ;
}
2006-03-17 12:42:04 +03:00
/*
trans2 qfsinfo implementation
*/
static NTSTATUS trans2_qfsinfo ( struct smbsrv_request * req , struct trans_op * op )
{
struct smb_trans2 * trans = op - > trans ;
union smb_fsinfo * fsinfo ;
uint16_t level ;
/* make sure we got enough parameters */
if ( trans - > in . params . length ! = 2 ) {
return NT_STATUS_FOOBAR ;
}
fsinfo = talloc ( op , union smb_fsinfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( fsinfo ) ;
op - > op_info = fsinfo ;
op - > send_fn = trans2_qfsinfo_send ;
level = SVAL ( trans - > in . params . data , 0 ) ;
switch ( level ) {
case SMB_QFS_ALLOCATION :
fsinfo - > allocation . level = RAW_QFS_ALLOCATION ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_VOLUME :
fsinfo - > volume . level = RAW_QFS_VOLUME ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_VOLUME_INFO :
case SMB_QFS_VOLUME_INFORMATION :
fsinfo - > volume_info . level = RAW_QFS_VOLUME_INFO ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_SIZE_INFO :
case SMB_QFS_SIZE_INFORMATION :
fsinfo - > size_info . level = RAW_QFS_SIZE_INFO ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_DEVICE_INFO :
case SMB_QFS_DEVICE_INFORMATION :
fsinfo - > device_info . level = RAW_QFS_DEVICE_INFO ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_ATTRIBUTE_INFO :
case SMB_QFS_ATTRIBUTE_INFORMATION :
fsinfo - > attribute_info . level = RAW_QFS_ATTRIBUTE_INFO ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_QUOTA_INFORMATION :
fsinfo - > quota_information . level = RAW_QFS_QUOTA_INFORMATION ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_FULL_SIZE_INFORMATION :
fsinfo - > full_size_information . level = RAW_QFS_FULL_SIZE_INFORMATION ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_OBJECTID_INFORMATION :
fsinfo - > objectid_information . level = RAW_QFS_OBJECTID_INFORMATION ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
}
return NT_STATUS_INVALID_LEVEL ;
}
/*
trans2 open implementation send
*/
static NTSTATUS trans2_open_send ( struct trans_op * op )
{
struct smbsrv_request * req = op - > req ;
struct smb_trans2 * trans = op - > trans ;
union smb_open * io ;
2006-03-18 14:10:21 +03:00
TRANS2_CHECK_ASYNC_STATUS ( io , union smb_open ) ;
2006-03-17 12:42:04 +03:00
2006-06-20 09:06:10 +04:00
TRANS2_CHECK ( trans2_setup_reply ( trans , 30 , 0 , 0 ) ) ;
2006-03-17 12:42:04 +03:00
2006-05-20 12:15:22 +04:00
smbsrv_push_fnum ( trans - > out . params . data , VWV ( 0 ) , io - > t2open . out . file . ntvfs ) ;
2006-03-17 12:42:04 +03:00
SSVAL ( trans - > out . params . data , VWV ( 1 ) , io - > t2open . out . attrib ) ;
srv_push_dos_date3 ( req - > smb_conn , trans - > out . params . data ,
VWV ( 2 ) , io - > t2open . out . write_time ) ;
SIVAL ( trans - > out . params . data , VWV ( 4 ) , io - > t2open . out . size ) ;
SSVAL ( trans - > out . params . data , VWV ( 6 ) , io - > t2open . out . access ) ;
SSVAL ( trans - > out . params . data , VWV ( 7 ) , io - > t2open . out . ftype ) ;
SSVAL ( trans - > out . params . data , VWV ( 8 ) , io - > t2open . out . devstate ) ;
SSVAL ( trans - > out . params . data , VWV ( 9 ) , io - > t2open . out . action ) ;
SIVAL ( trans - > out . params . data , VWV ( 10 ) , 0 ) ; /* reserved */
SSVAL ( trans - > out . params . data , VWV ( 12 ) , 0 ) ; /* EaErrorOffset */
SIVAL ( trans - > out . params . data , VWV ( 13 ) , 0 ) ; /* EaLength */
return NT_STATUS_OK ;
}
2004-11-06 10:58:45 +03:00
/*
trans2 open implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_open ( struct smbsrv_request * req , struct trans_op * op )
2004-11-06 10:58:45 +03:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
2004-11-06 10:58:45 +03:00
union smb_open * io ;
/* make sure we got enough parameters */
if ( trans - > in . params . length < 29 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
io = talloc ( op , union smb_open ) ;
NT_STATUS_HAVE_NO_MEMORY ( io ) ;
2004-11-06 10:58:45 +03:00
2005-07-17 16:57:14 +04:00
io - > t2open . level = RAW_OPEN_T2OPEN ;
io - > t2open . in . flags = SVAL ( trans - > in . params . data , VWV ( 0 ) ) ;
io - > t2open . in . open_mode = SVAL ( trans - > in . params . data , VWV ( 1 ) ) ;
io - > t2open . in . search_attrs = SVAL ( trans - > in . params . data , VWV ( 2 ) ) ;
io - > t2open . in . file_attrs = SVAL ( trans - > in . params . data , VWV ( 3 ) ) ;
io - > t2open . in . write_time = srv_pull_dos_date ( req - > smb_conn ,
2004-11-06 10:58:45 +03:00
trans - > in . params . data + VWV ( 4 ) ) ; ;
2005-07-17 16:57:14 +04:00
io - > t2open . in . open_func = SVAL ( trans - > in . params . data , VWV ( 6 ) ) ;
io - > t2open . in . size = IVAL ( trans - > in . params . data , VWV ( 7 ) ) ;
io - > t2open . in . timeout = IVAL ( trans - > in . params . data , VWV ( 9 ) ) ;
io - > t2open . in . num_eas = 0 ;
io - > t2open . in . eas = NULL ;
2004-11-06 10:58:45 +03:00
trans2_pull_blob_string ( req , & trans - > in . params , 28 , & io - > t2open . in . fname , 0 ) ;
2006-06-20 09:06:10 +04:00
if ( io - > t2open . in . fname = = NULL ) {
return NT_STATUS_FOOBAR ;
}
2004-11-06 10:58:45 +03:00
2006-06-20 09:06:10 +04:00
TRANS2_CHECK ( ea_pull_list ( & trans - > in . data , io , & io - > t2open . in . num_eas , & io - > t2open . in . eas ) ) ;
2004-11-06 10:58:45 +03:00
2006-03-17 12:42:04 +03:00
op - > op_info = io ;
op - > send_fn = trans2_open_send ;
2006-03-18 14:10:21 +03:00
return ntvfs_open ( req - > ntvfs , io ) ;
2006-03-17 12:42:04 +03:00
}
/*
trans2 simple send
*/
static NTSTATUS trans2_simple_send ( struct trans_op * op )
{
struct smbsrv_request * req = op - > req ;
struct smb_trans2 * trans = op - > trans ;
2006-03-18 14:10:21 +03:00
TRANS2_CHECK_ASYNC_STATUS_SIMPLE ;
2004-11-06 10:58:45 +03:00
2006-06-20 09:06:10 +04:00
TRANS2_CHECK ( trans2_setup_reply ( trans , 2 , 0 , 0 ) ) ;
2004-11-06 10:58:45 +03:00
2006-03-17 12:42:04 +03:00
SSVAL ( trans - > out . params . data , VWV ( 0 ) , 0 ) ;
2004-11-06 10:58:45 +03:00
2006-03-17 12:42:04 +03:00
return NT_STATUS_OK ;
2004-11-06 10:58:45 +03:00
}
2004-12-14 02:57:59 +03:00
/*
trans2 mkdir implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_mkdir ( struct smbsrv_request * req , struct trans_op * op )
2004-12-14 02:57:59 +03:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
2004-12-14 02:57:59 +03:00
union smb_mkdir * io ;
/* make sure we got enough parameters */
if ( trans - > in . params . length < 5 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
io = talloc ( op , union smb_mkdir ) ;
NT_STATUS_HAVE_NO_MEMORY ( io ) ;
2004-12-14 02:57:59 +03:00
io - > t2mkdir . level = RAW_MKDIR_T2MKDIR ;
trans2_pull_blob_string ( req , & trans - > in . params , 4 , & io - > t2mkdir . in . path , 0 ) ;
2006-06-20 09:06:10 +04:00
if ( io - > t2mkdir . in . path = = NULL ) {
return NT_STATUS_FOOBAR ;
}
2004-12-14 02:57:59 +03:00
2006-06-20 09:06:10 +04:00
TRANS2_CHECK ( ea_pull_list ( & trans - > in . data , io ,
& io - > t2mkdir . in . num_eas ,
& io - > t2mkdir . in . eas ) ) ;
2004-12-14 02:57:59 +03:00
2006-03-17 12:42:04 +03:00
op - > op_info = io ;
op - > send_fn = trans2_simple_send ;
2004-12-14 02:57:59 +03:00
2006-03-18 14:10:21 +03:00
return ntvfs_mkdir ( req - > ntvfs , io ) ;
2004-12-14 02:57:59 +03:00
}
2006-06-19 22:01:27 +04:00
static NTSTATUS trans2_push_fileinfo ( struct smbsrv_request * req ,
union smb_fileinfo * st ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * blob )
2003-08-13 05:53:07 +04:00
{
uint_t i ;
2004-12-15 06:53:05 +03:00
uint32_t list_size ;
2006-03-17 12:42:04 +03:00
2003-08-13 05:53:07 +04:00
switch ( st - > generic . level ) {
case RAW_FILEINFO_GENERIC :
case RAW_FILEINFO_GETATTR :
case RAW_FILEINFO_GETATTRE :
2004-11-18 04:41:43 +03:00
case RAW_FILEINFO_SEC_DESC :
2003-08-13 05:53:07 +04:00
/* handled elsewhere */
return NT_STATUS_INVALID_LEVEL ;
case RAW_FILEINFO_BASIC_INFO :
case RAW_FILEINFO_BASIC_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 40 ) ) ;
push_nttime ( blob - > data , 0 , st - > basic_info . out . create_time ) ;
push_nttime ( blob - > data , 8 , st - > basic_info . out . access_time ) ;
push_nttime ( blob - > data , 16 , st - > basic_info . out . write_time ) ;
push_nttime ( blob - > data , 24 , st - > basic_info . out . change_time ) ;
SIVAL ( blob - > data , 32 , st - > basic_info . out . attrib ) ;
SIVAL ( blob - > data , 36 , 0 ) ; /* padding */
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_STANDARD :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 22 ) ) ;
srv_push_dos_date2 ( req - > smb_conn , blob - > data , 0 , st - > standard . out . create_time ) ;
srv_push_dos_date2 ( req - > smb_conn , blob - > data , 4 , st - > standard . out . access_time ) ;
srv_push_dos_date2 ( req - > smb_conn , blob - > data , 8 , st - > standard . out . write_time ) ;
SIVAL ( blob - > data , 12 , st - > standard . out . size ) ;
SIVAL ( blob - > data , 16 , st - > standard . out . alloc_size ) ;
SSVAL ( blob - > data , 20 , st - > standard . out . attrib ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_EA_SIZE :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 26 ) ) ;
srv_push_dos_date2 ( req - > smb_conn , blob - > data , 0 , st - > ea_size . out . create_time ) ;
srv_push_dos_date2 ( req - > smb_conn , blob - > data , 4 , st - > ea_size . out . access_time ) ;
srv_push_dos_date2 ( req - > smb_conn , blob - > data , 8 , st - > ea_size . out . write_time ) ;
SIVAL ( blob - > data , 12 , st - > ea_size . out . size ) ;
SIVAL ( blob - > data , 16 , st - > ea_size . out . alloc_size ) ;
SSVAL ( blob - > data , 20 , st - > ea_size . out . attrib ) ;
SIVAL ( blob - > data , 22 , st - > ea_size . out . ea_size ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_NETWORK_OPEN_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 56 ) ) ;
push_nttime ( blob - > data , 0 , st - > network_open_information . out . create_time ) ;
push_nttime ( blob - > data , 8 , st - > network_open_information . out . access_time ) ;
push_nttime ( blob - > data , 16 , st - > network_open_information . out . write_time ) ;
push_nttime ( blob - > data , 24 , st - > network_open_information . out . change_time ) ;
SBVAL ( blob - > data , 32 , st - > network_open_information . out . alloc_size ) ;
SBVAL ( blob - > data , 40 , st - > network_open_information . out . size ) ;
SIVAL ( blob - > data , 48 , st - > network_open_information . out . attrib ) ;
SIVAL ( blob - > data , 52 , 0 ) ; /* padding */
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_STANDARD_INFO :
case RAW_FILEINFO_STANDARD_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 24 ) ) ;
SBVAL ( blob - > data , 0 , st - > standard_info . out . alloc_size ) ;
SBVAL ( blob - > data , 8 , st - > standard_info . out . size ) ;
SIVAL ( blob - > data , 16 , st - > standard_info . out . nlink ) ;
SCVAL ( blob - > data , 20 , st - > standard_info . out . delete_pending ) ;
SCVAL ( blob - > data , 21 , st - > standard_info . out . directory ) ;
SSVAL ( blob - > data , 22 , 0 ) ; /* padding */
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 8 ) ) ;
SIVAL ( blob - > data , 0 , st - > attribute_tag_information . out . attrib ) ;
SIVAL ( blob - > data , 4 , st - > attribute_tag_information . out . reparse_tag ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_EA_INFO :
case RAW_FILEINFO_EA_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 4 ) ) ;
SIVAL ( blob - > data , 0 , st - > ea_info . out . ea_size ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_MODE_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 4 ) ) ;
SIVAL ( blob - > data , 0 , st - > mode_information . out . mode ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_ALIGNMENT_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 4 ) ) ;
SIVAL ( blob - > data , 0 ,
2003-08-13 05:53:07 +04:00
st - > alignment_information . out . alignment_requirement ) ;
return NT_STATUS_OK ;
2004-12-18 01:47:49 +03:00
case RAW_FILEINFO_EA_LIST :
list_size = ea_list_size ( st - > ea_list . out . num_eas ,
st - > ea_list . out . eas ) ;
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , list_size ) ) ;
ea_put_list ( blob - > data ,
2004-12-18 01:47:49 +03:00
st - > ea_list . out . num_eas , st - > ea_list . out . eas ) ;
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
case RAW_FILEINFO_ALL_EAS :
2004-12-15 06:53:05 +03:00
list_size = ea_list_size ( st - > all_eas . out . num_eas ,
2004-12-16 15:31:34 +03:00
st - > all_eas . out . eas ) ;
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , list_size ) ) ;
ea_put_list ( blob - > data ,
2004-12-16 15:31:34 +03:00
st - > all_eas . out . num_eas , st - > all_eas . out . eas ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_ACCESS_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 4 ) ) ;
SIVAL ( blob - > data , 0 , st - > access_information . out . access_flags ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_POSITION_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 8 ) ) ;
SBVAL ( blob - > data , 0 , st - > position_information . out . position ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_COMPRESSION_INFO :
case RAW_FILEINFO_COMPRESSION_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 16 ) ) ;
SBVAL ( blob - > data , 0 , st - > compression_info . out . compressed_size ) ;
SSVAL ( blob - > data , 8 , st - > compression_info . out . format ) ;
SCVAL ( blob - > data , 10 , st - > compression_info . out . unit_shift ) ;
SCVAL ( blob - > data , 11 , st - > compression_info . out . chunk_shift ) ;
SCVAL ( blob - > data , 12 , st - > compression_info . out . cluster_shift ) ;
SSVAL ( blob - > data , 13 , 0 ) ; /* 3 bytes padding */
SCVAL ( blob - > data , 15 , 0 ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_IS_NAME_VALID :
return NT_STATUS_OK ;
case RAW_FILEINFO_INTERNAL_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 8 ) ) ;
SBVAL ( blob - > data , 0 , st - > internal_information . out . file_id ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_ALL_INFO :
case RAW_FILEINFO_ALL_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 72 ) ) ;
push_nttime ( blob - > data , 0 , st - > all_info . out . create_time ) ;
push_nttime ( blob - > data , 8 , st - > all_info . out . access_time ) ;
push_nttime ( blob - > data , 16 , st - > all_info . out . write_time ) ;
push_nttime ( blob - > data , 24 , st - > all_info . out . change_time ) ;
SIVAL ( blob - > data , 32 , st - > all_info . out . attrib ) ;
SIVAL ( blob - > data , 36 , 0 ) ;
SBVAL ( blob - > data , 40 , st - > all_info . out . alloc_size ) ;
SBVAL ( blob - > data , 48 , st - > all_info . out . size ) ;
SIVAL ( blob - > data , 56 , st - > all_info . out . nlink ) ;
SCVAL ( blob - > data , 60 , st - > all_info . out . delete_pending ) ;
SCVAL ( blob - > data , 61 , st - > all_info . out . directory ) ;
SSVAL ( blob - > data , 62 , 0 ) ; /* padding */
SIVAL ( blob - > data , 64 , st - > all_info . out . ea_size ) ;
TRANS2_CHECK ( trans2_append_data_string ( req , mem_ctx , blob ,
& st - > all_info . out . fname ,
68 , STR_UNICODE ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_NAME_INFO :
case RAW_FILEINFO_NAME_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 4 ) ) ;
TRANS2_CHECK ( trans2_append_data_string ( req , mem_ctx , blob ,
& st - > name_info . out . fname ,
0 , STR_UNICODE ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_ALT_NAME_INFO :
case RAW_FILEINFO_ALT_NAME_INFORMATION :
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , 4 ) ) ;
TRANS2_CHECK ( trans2_append_data_string ( req , mem_ctx , blob ,
& st - > alt_name_info . out . fname ,
0 , STR_UNICODE ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_STREAM_INFO :
case RAW_FILEINFO_STREAM_INFORMATION :
for ( i = 0 ; i < st - > stream_info . out . num_streams ; i + + ) {
2006-06-19 22:01:27 +04:00
uint32_t data_size = blob - > length ;
2004-11-25 23:01:47 +03:00
uint8_t * data ;
2003-08-13 05:53:07 +04:00
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data ( mem_ctx , blob , data_size + 24 ) ) ;
data = blob - > data + data_size ;
2003-08-13 05:53:07 +04:00
SBVAL ( data , 8 , st - > stream_info . out . streams [ i ] . size ) ;
SBVAL ( data , 16 , st - > stream_info . out . streams [ i ] . alloc_size ) ;
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_append_data_string ( req , mem_ctx , blob ,
& st - > stream_info . out . streams [ i ] . stream_name ,
data_size + 4 , STR_UNICODE ) ) ;
2003-08-13 05:53:07 +04:00
if ( i = = st - > stream_info . out . num_streams - 1 ) {
2006-06-19 22:01:27 +04:00
SIVAL ( blob - > data , data_size , 0 ) ;
2003-08-13 05:53:07 +04:00
} else {
2006-06-19 22:01:27 +04:00
TRANS2_CHECK ( trans2_grow_data_fill ( mem_ctx , blob , ( blob - > length + 7 ) & ~ 7 ) ) ;
SIVAL ( blob - > data , data_size ,
blob - > length - data_size ) ;
2003-08-13 05:53:07 +04:00
}
}
return NT_STATUS_OK ;
2005-09-16 11:15:40 +04:00
case RAW_FILEINFO_UNIX_BASIC :
case RAW_FILEINFO_UNIX_LINK :
return NT_STATUS_INVALID_LEVEL ;
2005-12-06 15:33:32 +03:00
case RAW_FILEINFO_SMB2_ALL_EAS :
case RAW_FILEINFO_SMB2_ALL_INFORMATION :
return NT_STATUS_INVALID_LEVEL ;
2003-08-13 05:53:07 +04:00
}
return NT_STATUS_INVALID_LEVEL ;
}
2006-06-19 22:01:27 +04:00
/*
fill in the reply from a qpathinfo or qfileinfo call
*/
static NTSTATUS trans2_fileinfo_send ( struct trans_op * op )
{
struct smbsrv_request * req = op - > req ;
struct smb_trans2 * trans = op - > trans ;
union smb_fileinfo * st ;
TRANS2_CHECK_ASYNC_STATUS ( st , union smb_fileinfo ) ;
TRANS2_CHECK ( trans2_setup_reply ( trans , 2 , 0 , 0 ) ) ;
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
TRANS2_CHECK ( trans2_push_fileinfo ( req , st , trans , & trans - > out . data ) ) ;
return NT_STATUS_OK ;
}
2003-08-13 05:53:07 +04:00
/*
trans2 qpathinfo implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_qpathinfo ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
union smb_fileinfo * st ;
2004-05-25 21:24:24 +04:00
uint16_t level ;
2003-08-13 05:53:07 +04:00
/* make sure we got enough parameters */
2004-10-02 16:16:46 +04:00
if ( trans - > in . params . length < 2 ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
st = talloc ( op , union smb_fileinfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( st ) ;
2003-08-13 05:53:07 +04:00
level = SVAL ( trans - > in . params . data , 0 ) ;
2006-03-17 12:42:04 +03:00
trans2_pull_blob_string ( req , & trans - > in . params , 6 , & st - > generic . in . file . path , 0 ) ;
if ( st - > generic . in . file . path = = NULL ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_FOOBAR ;
}
/* work out the backend level - we make it 1-1 in the header */
2006-03-17 12:42:04 +03:00
st - > generic . level = ( enum smb_fileinfo_level ) level ;
if ( st - > generic . level > = RAW_FILEINFO_GENERIC ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_INVALID_LEVEL ;
}
2006-03-17 12:42:04 +03:00
if ( st - > generic . level = = RAW_FILEINFO_EA_LIST ) {
2006-06-20 09:06:10 +04:00
TRANS2_CHECK ( ea_pull_name_list ( & trans - > in . data , req ,
& st - > ea_list . in . num_names ,
& st - > ea_list . in . ea_names ) ) ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 12:42:04 +03:00
op - > op_info = st ;
op - > send_fn = trans2_fileinfo_send ;
2003-08-13 05:53:07 +04:00
2006-03-18 14:10:21 +03:00
return ntvfs_qpathinfo ( req - > ntvfs , st ) ;
2003-08-13 05:53:07 +04:00
}
/*
trans2 qpathinfo implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_qfileinfo ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
union smb_fileinfo * st ;
2006-05-20 12:15:22 +04:00
uint16_t level ;
struct ntvfs_handle * h ;
2003-08-13 05:53:07 +04:00
/* make sure we got enough parameters */
if ( trans - > in . params . length < 4 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
st = talloc ( op , union smb_fileinfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( st ) ;
2006-05-20 12:15:22 +04:00
h = smbsrv_pull_fnum ( req , trans - > in . params . data , 0 ) ;
2003-08-13 05:53:07 +04:00
level = SVAL ( trans - > in . params . data , 2 ) ;
2006-05-20 12:15:22 +04:00
st - > generic . in . file . ntvfs = h ;
2003-08-13 05:53:07 +04:00
/* work out the backend level - we make it 1-1 in the header */
2006-03-17 12:42:04 +03:00
st - > generic . level = ( enum smb_fileinfo_level ) level ;
if ( st - > generic . level > = RAW_FILEINFO_GENERIC ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_INVALID_LEVEL ;
}
2006-03-17 12:42:04 +03:00
if ( st - > generic . level = = RAW_FILEINFO_EA_LIST ) {
2006-06-20 09:06:10 +04:00
TRANS2_CHECK ( ea_pull_name_list ( & trans - > in . data , req ,
& st - > ea_list . in . num_names ,
& st - > ea_list . in . ea_names ) ) ;
2004-12-18 01:47:49 +03:00
}
2006-03-17 12:42:04 +03:00
op - > op_info = st ;
op - > send_fn = trans2_fileinfo_send ;
2003-08-13 05:53:07 +04:00
2006-05-20 12:15:22 +04:00
SMBSRV_CHECK_FILE_HANDLE_NTSTATUS ( st - > generic . in . file . ntvfs ) ;
2006-03-18 14:10:21 +03:00
return ntvfs_qfileinfo ( req - > ntvfs , st ) ;
2003-08-13 05:53:07 +04:00
}
/*
parse a trans2 setfileinfo / setpathinfo data blob
*/
2004-06-28 12:39:00 +04:00
static NTSTATUS trans2_parse_sfileinfo ( struct smbsrv_request * req ,
2003-08-13 05:53:07 +04:00
union smb_setfileinfo * st ,
const DATA_BLOB * blob )
{
2004-05-25 20:24:13 +04:00
uint32_t len ;
2006-06-20 09:06:10 +04:00
DATA_BLOB str_blob ;
2003-08-13 05:53:07 +04:00
switch ( st - > generic . level ) {
case RAW_SFILEINFO_GENERIC :
case RAW_SFILEINFO_SETATTR :
case RAW_SFILEINFO_SETATTRE :
2004-11-18 04:41:43 +03:00
case RAW_SFILEINFO_SEC_DESC :
2003-08-13 05:53:07 +04:00
/* handled elsewhere */
return NT_STATUS_INVALID_LEVEL ;
case RAW_SFILEINFO_STANDARD :
CHECK_MIN_BLOB_SIZE ( blob , 12 ) ;
2006-06-20 09:06:10 +04:00
2004-06-29 11:40:14 +04:00
st - > standard . in . create_time = srv_pull_dos_date2 ( req - > smb_conn , blob - > data + 0 ) ;
st - > standard . in . access_time = srv_pull_dos_date2 ( req - > smb_conn , blob - > data + 4 ) ;
st - > standard . in . write_time = srv_pull_dos_date2 ( req - > smb_conn , blob - > data + 8 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_SFILEINFO_EA_SET :
2004-12-17 07:51:23 +03:00
return ea_pull_list ( blob , req ,
& st - > ea_set . in . num_eas ,
& st - > ea_set . in . eas ) ;
2003-08-13 05:53:07 +04:00
case SMB_SFILEINFO_BASIC_INFO :
case SMB_SFILEINFO_BASIC_INFORMATION :
CHECK_MIN_BLOB_SIZE ( blob , 36 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
st - > basic_info . in . create_time = pull_nttime ( blob - > data , 0 ) ;
st - > basic_info . in . access_time = pull_nttime ( blob - > data , 8 ) ;
st - > basic_info . in . write_time = pull_nttime ( blob - > data , 16 ) ;
st - > basic_info . in . change_time = pull_nttime ( blob - > data , 24 ) ;
st - > basic_info . in . attrib = IVAL ( blob - > data , 32 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_SFILEINFO_DISPOSITION_INFO :
case SMB_SFILEINFO_DISPOSITION_INFORMATION :
CHECK_MIN_BLOB_SIZE ( blob , 1 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
st - > disposition_info . in . delete_on_close = CVAL ( blob - > data , 0 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_SFILEINFO_ALLOCATION_INFO :
case SMB_SFILEINFO_ALLOCATION_INFORMATION :
CHECK_MIN_BLOB_SIZE ( blob , 8 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
st - > allocation_info . in . alloc_size = BVAL ( blob - > data , 0 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_SFILEINFO_END_OF_FILE_INFO :
case RAW_SFILEINFO_END_OF_FILE_INFORMATION :
CHECK_MIN_BLOB_SIZE ( blob , 8 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
st - > end_of_file_info . in . size = BVAL ( blob - > data , 0 ) ;
2006-06-20 09:06:10 +04:00
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
2006-06-20 09:06:10 +04:00
case RAW_SFILEINFO_RENAME_INFORMATION :
2003-08-13 05:53:07 +04:00
CHECK_MIN_BLOB_SIZE ( blob , 12 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
st - > rename_information . in . overwrite = CVAL ( blob - > data , 0 ) ;
st - > rename_information . in . root_fid = IVAL ( blob - > data , 4 ) ;
len = IVAL ( blob - > data , 8 ) ;
2006-06-20 09:06:10 +04:00
str_blob . data = blob - > data + 12 ;
str_blob . length = MIN ( blob - > length , len ) ;
trans2_pull_blob_string ( req , & str_blob , 0 ,
& st - > rename_information . in . new_name ,
STR_UNICODE ) ;
if ( st - > rename_information . in . new_name = = NULL ) {
return NT_STATUS_FOOBAR ;
}
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_SFILEINFO_POSITION_INFORMATION :
CHECK_MIN_BLOB_SIZE ( blob , 8 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
st - > position_information . in . position = BVAL ( blob - > data , 0 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_SFILEINFO_MODE_INFORMATION :
CHECK_MIN_BLOB_SIZE ( blob , 4 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
st - > mode_information . in . mode = IVAL ( blob - > data , 0 ) ;
2006-06-20 09:06:10 +04:00
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
2005-09-16 11:15:40 +04:00
case RAW_SFILEINFO_UNIX_BASIC :
case RAW_SFILEINFO_UNIX_LINK :
case RAW_SFILEINFO_UNIX_HLINK :
case RAW_SFILEINFO_1023 :
case RAW_SFILEINFO_1025 :
case RAW_SFILEINFO_1029 :
case RAW_SFILEINFO_1032 :
case RAW_SFILEINFO_1039 :
case RAW_SFILEINFO_1040 :
return NT_STATUS_INVALID_LEVEL ;
2003-08-13 05:53:07 +04:00
}
return NT_STATUS_INVALID_LEVEL ;
}
/*
trans2 setfileinfo implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_setfileinfo ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
union smb_setfileinfo * st ;
2006-05-20 12:15:22 +04:00
uint16_t level ;
struct ntvfs_handle * h ;
2003-08-13 05:53:07 +04:00
/* make sure we got enough parameters */
if ( trans - > in . params . length < 4 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
st = talloc ( op , union smb_setfileinfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( st ) ;
2006-05-20 12:15:22 +04:00
h = smbsrv_pull_fnum ( req , trans - > in . params . data , 0 ) ;
2003-08-13 05:53:07 +04:00
level = SVAL ( trans - > in . params . data , 2 ) ;
2006-05-20 12:15:22 +04:00
st - > generic . in . file . ntvfs = h ;
2006-03-17 12:42:04 +03:00
/* work out the backend level - we make it 1-1 in the header */
st - > generic . level = ( enum smb_setfileinfo_level ) level ;
if ( st - > generic . level > = RAW_SFILEINFO_GENERIC ) {
return NT_STATUS_INVALID_LEVEL ;
2003-08-13 05:53:07 +04:00
}
2006-06-20 09:06:10 +04:00
TRANS2_CHECK ( trans2_parse_sfileinfo ( req , st , & trans - > in . data ) ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
op - > op_info = st ;
op - > send_fn = trans2_simple_send ;
2006-05-20 12:15:22 +04:00
SMBSRV_CHECK_FILE_HANDLE_NTSTATUS ( st - > generic . in . file . ntvfs ) ;
2006-03-18 14:10:21 +03:00
return ntvfs_setfileinfo ( req - > ntvfs , st ) ;
2003-08-13 05:53:07 +04:00
}
/*
trans2 setpathinfo implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_setpathinfo ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
union smb_setfileinfo * st ;
2004-05-25 21:24:24 +04:00
uint16_t level ;
2003-08-13 05:53:07 +04:00
/* make sure we got enough parameters */
if ( trans - > in . params . length < 4 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
st = talloc ( op , union smb_setfileinfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( st ) ;
2003-08-13 05:53:07 +04:00
level = SVAL ( trans - > in . params . data , 0 ) ;
2006-03-17 12:42:04 +03:00
trans2_pull_blob_string ( req , & trans - > in . params , 6 , & st - > generic . in . file . path , 0 ) ;
if ( st - > generic . in . file . path = = NULL ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
/* work out the backend level - we make it 1-1 in the header */
st - > generic . level = ( enum smb_setfileinfo_level ) level ;
if ( st - > generic . level > = RAW_SFILEINFO_GENERIC ) {
return NT_STATUS_INVALID_LEVEL ;
2003-08-13 05:53:07 +04:00
}
2006-06-20 09:06:10 +04:00
TRANS2_CHECK ( trans2_parse_sfileinfo ( req , st , & trans - > in . data ) ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
op - > op_info = st ;
op - > send_fn = trans2_simple_send ;
2006-03-18 14:10:21 +03:00
return ntvfs_setpathinfo ( req - > ntvfs , st ) ;
2003-08-13 05:53:07 +04:00
}
/* a structure to encapsulate the state information about an in-progress ffirst/fnext operation */
struct find_state {
2006-03-17 12:42:04 +03:00
struct trans_op * op ;
void * search ;
2004-07-19 14:35:05 +04:00
enum smb_search_level level ;
2004-05-25 21:24:24 +04:00
uint16_t last_entry_offset ;
uint16_t flags ;
2003-08-13 05:53:07 +04:00
} ;
/*
fill a single entry in a trans2 find reply
*/
2006-03-17 12:42:04 +03:00
static BOOL find_fill_info ( struct find_state * state ,
2003-08-13 05:53:07 +04:00
union smb_search_data * file )
{
2006-03-17 12:42:04 +03:00
struct smbsrv_request * req = state - > op - > req ;
struct smb_trans2 * trans = state - > op - > trans ;
2004-11-25 23:01:47 +03:00
uint8_t * data ;
2003-08-13 05:53:07 +04:00
uint_t ofs = trans - > out . data . length ;
2004-12-18 07:38:43 +03:00
uint32_t ea_size ;
2003-08-13 05:53:07 +04:00
2003-08-31 07:16:52 +04:00
switch ( state - > level ) {
2003-08-13 05:53:07 +04:00
case RAW_SEARCH_SEARCH :
2004-09-21 12:46:47 +04:00
case RAW_SEARCH_FFIRST :
case RAW_SEARCH_FUNIQUE :
2003-08-13 05:53:07 +04:00
case RAW_SEARCH_GENERIC :
2006-05-20 14:46:38 +04:00
case RAW_SEARCH_SMB2 :
2003-08-13 05:53:07 +04:00
/* handled elsewhere */
2006-05-20 14:31:23 +04:00
return False ;
2003-08-13 05:53:07 +04:00
case RAW_SEARCH_STANDARD :
2003-08-31 07:16:52 +04:00
if ( state - > flags & FLAG_TRANS2_FIND_REQUIRE_RESUME ) {
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , ofs + 27 ) ;
2003-08-31 07:16:52 +04:00
SIVAL ( trans - > out . data . data , ofs , file - > standard . resume_key ) ;
ofs + = 4 ;
} else {
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , ofs + 23 ) ;
2003-08-31 07:16:52 +04:00
}
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
2004-06-29 11:40:14 +04:00
srv_push_dos_date2 ( req - > smb_conn , data , 0 , file - > standard . create_time ) ;
srv_push_dos_date2 ( req - > smb_conn , data , 4 , file - > standard . access_time ) ;
srv_push_dos_date2 ( req - > smb_conn , data , 8 , file - > standard . write_time ) ;
2003-08-13 05:53:07 +04:00
SIVAL ( data , 12 , file - > standard . size ) ;
SIVAL ( data , 16 , file - > standard . alloc_size ) ;
SSVAL ( data , 20 , file - > standard . attrib ) ;
2006-06-19 22:01:27 +04:00
trans2_append_data_string ( req , trans , & trans - > out . data , & file - > standard . name ,
2003-08-13 05:53:07 +04:00
ofs + 22 , STR_LEN8BIT | STR_TERMINATE | STR_LEN_NOTERM ) ;
break ;
case RAW_SEARCH_EA_SIZE :
2003-08-31 07:16:52 +04:00
if ( state - > flags & FLAG_TRANS2_FIND_REQUIRE_RESUME ) {
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , ofs + 31 ) ;
2003-08-31 07:16:52 +04:00
SIVAL ( trans - > out . data . data , ofs , file - > ea_size . resume_key ) ;
ofs + = 4 ;
} else {
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , ofs + 27 ) ;
2003-08-31 07:16:52 +04:00
}
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
2004-06-29 11:40:14 +04:00
srv_push_dos_date2 ( req - > smb_conn , data , 0 , file - > ea_size . create_time ) ;
srv_push_dos_date2 ( req - > smb_conn , data , 4 , file - > ea_size . access_time ) ;
srv_push_dos_date2 ( req - > smb_conn , data , 8 , file - > ea_size . write_time ) ;
2003-08-13 05:53:07 +04:00
SIVAL ( data , 12 , file - > ea_size . size ) ;
SIVAL ( data , 16 , file - > ea_size . alloc_size ) ;
SSVAL ( data , 20 , file - > ea_size . attrib ) ;
SIVAL ( data , 22 , file - > ea_size . ea_size ) ;
2006-06-19 22:01:27 +04:00
trans2_append_data_string ( req , trans , & trans - > out . data , & file - > ea_size . name ,
2004-08-25 08:16:48 +04:00
ofs + 26 , STR_LEN8BIT | STR_NOALIGN ) ;
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , trans - > out . data . length + 1 ) ;
2004-09-21 12:46:47 +04:00
trans - > out . data . data [ trans - > out . data . length - 1 ] = 0 ;
2003-08-13 05:53:07 +04:00
break ;
2004-12-18 07:38:43 +03:00
case RAW_SEARCH_EA_LIST :
ea_size = ea_list_size ( file - > ea_list . eas . num_eas , file - > ea_list . eas . eas ) ;
if ( state - > flags & FLAG_TRANS2_FIND_REQUIRE_RESUME ) {
2006-06-19 22:01:27 +04:00
if ( ! NT_STATUS_IS_OK ( trans2_grow_data ( trans , & trans - > out . data , ofs + 27 + ea_size ) ) ) {
2004-12-20 06:12:09 +03:00
return False ;
}
2004-12-18 07:38:43 +03:00
SIVAL ( trans - > out . data . data , ofs , file - > ea_list . resume_key ) ;
ofs + = 4 ;
} else {
2006-06-19 22:01:27 +04:00
if ( ! NT_STATUS_IS_OK ( trans2_grow_data ( trans , & trans - > out . data , ofs + 23 + ea_size ) ) ) {
2004-12-20 06:12:09 +03:00
return False ;
}
2004-12-18 07:38:43 +03:00
}
data = trans - > out . data . data + ofs ;
srv_push_dos_date2 ( req - > smb_conn , data , 0 , file - > ea_list . create_time ) ;
srv_push_dos_date2 ( req - > smb_conn , data , 4 , file - > ea_list . access_time ) ;
srv_push_dos_date2 ( req - > smb_conn , data , 8 , file - > ea_list . write_time ) ;
SIVAL ( data , 12 , file - > ea_list . size ) ;
SIVAL ( data , 16 , file - > ea_list . alloc_size ) ;
SSVAL ( data , 20 , file - > ea_list . attrib ) ;
ea_put_list ( data + 22 , file - > ea_list . eas . num_eas , file - > ea_list . eas . eas ) ;
2006-06-19 22:01:27 +04:00
trans2_append_data_string ( req , trans , & trans - > out . data , & file - > ea_list . name ,
2004-12-18 07:38:43 +03:00
ofs + 22 + ea_size , STR_LEN8BIT | STR_NOALIGN ) ;
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , trans - > out . data . length + 1 ) ;
2004-12-18 07:38:43 +03:00
trans - > out . data . data [ trans - > out . data . length - 1 ] = 0 ;
break ;
2003-08-13 05:53:07 +04:00
case RAW_SEARCH_DIRECTORY_INFO :
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , ofs + 64 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 4 , file - > directory_info . file_index ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( data , 8 , file - > directory_info . create_time ) ;
push_nttime ( data , 16 , file - > directory_info . access_time ) ;
push_nttime ( data , 24 , file - > directory_info . write_time ) ;
push_nttime ( data , 32 , file - > directory_info . change_time ) ;
2003-08-13 05:53:07 +04:00
SBVAL ( data , 40 , file - > directory_info . size ) ;
SBVAL ( data , 48 , file - > directory_info . alloc_size ) ;
SIVAL ( data , 56 , file - > directory_info . attrib ) ;
2006-06-19 22:01:27 +04:00
trans2_append_data_string ( req , trans , & trans - > out . data , & file - > directory_info . name ,
2003-08-16 01:11:13 +04:00
ofs + 60 , STR_TERMINATE_ASCII ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 0 , trans - > out . data . length - ofs ) ;
break ;
case RAW_SEARCH_FULL_DIRECTORY_INFO :
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , ofs + 68 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 4 , file - > full_directory_info . file_index ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( data , 8 , file - > full_directory_info . create_time ) ;
push_nttime ( data , 16 , file - > full_directory_info . access_time ) ;
push_nttime ( data , 24 , file - > full_directory_info . write_time ) ;
push_nttime ( data , 32 , file - > full_directory_info . change_time ) ;
2003-08-13 05:53:07 +04:00
SBVAL ( data , 40 , file - > full_directory_info . size ) ;
SBVAL ( data , 48 , file - > full_directory_info . alloc_size ) ;
SIVAL ( data , 56 , file - > full_directory_info . attrib ) ;
SIVAL ( data , 64 , file - > full_directory_info . ea_size ) ;
2006-06-19 22:01:27 +04:00
trans2_append_data_string ( req , trans , & trans - > out . data , & file - > full_directory_info . name ,
2003-08-16 01:11:13 +04:00
ofs + 60 , STR_TERMINATE_ASCII ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 0 , trans - > out . data . length - ofs ) ;
break ;
case RAW_SEARCH_NAME_INFO :
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , ofs + 12 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 4 , file - > name_info . file_index ) ;
2006-06-19 22:01:27 +04:00
trans2_append_data_string ( req , trans , & trans - > out . data , & file - > name_info . name ,
2003-08-16 01:11:13 +04:00
ofs + 8 , STR_TERMINATE_ASCII ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 0 , trans - > out . data . length - ofs ) ;
break ;
case RAW_SEARCH_BOTH_DIRECTORY_INFO :
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , ofs + 94 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 4 , file - > both_directory_info . file_index ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( data , 8 , file - > both_directory_info . create_time ) ;
push_nttime ( data , 16 , file - > both_directory_info . access_time ) ;
push_nttime ( data , 24 , file - > both_directory_info . write_time ) ;
push_nttime ( data , 32 , file - > both_directory_info . change_time ) ;
2003-08-13 05:53:07 +04:00
SBVAL ( data , 40 , file - > both_directory_info . size ) ;
SBVAL ( data , 48 , file - > both_directory_info . alloc_size ) ;
SIVAL ( data , 56 , file - > both_directory_info . attrib ) ;
SIVAL ( data , 64 , file - > both_directory_info . ea_size ) ;
SCVAL ( data , 69 , 0 ) ; /* reserved */
memset ( data + 70 , 0 , 24 ) ;
2006-06-19 22:01:27 +04:00
trans2_push_data_string ( req , trans , & trans - > out . data ,
2003-08-13 05:53:07 +04:00
68 + ofs , 70 + ofs ,
& file - > both_directory_info . short_name ,
24 , STR_UNICODE | STR_LEN8BIT ) ;
2006-06-19 22:01:27 +04:00
trans2_append_data_string ( req , trans , & trans - > out . data , & file - > both_directory_info . name ,
2003-08-16 01:11:13 +04:00
ofs + 60 , STR_TERMINATE_ASCII ) ;
2006-06-19 22:01:27 +04:00
trans2_align_data ( trans ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 0 , trans - > out . data . length - ofs ) ;
break ;
2003-09-02 08:37:33 +04:00
case RAW_SEARCH_ID_FULL_DIRECTORY_INFO :
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , ofs + 80 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
2003-09-02 08:37:33 +04:00
SIVAL ( data , 4 , file - > id_full_directory_info . file_index ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( data , 8 , file - > id_full_directory_info . create_time ) ;
push_nttime ( data , 16 , file - > id_full_directory_info . access_time ) ;
push_nttime ( data , 24 , file - > id_full_directory_info . write_time ) ;
push_nttime ( data , 32 , file - > id_full_directory_info . change_time ) ;
2003-09-02 08:37:33 +04:00
SBVAL ( data , 40 , file - > id_full_directory_info . size ) ;
SBVAL ( data , 48 , file - > id_full_directory_info . alloc_size ) ;
SIVAL ( data , 56 , file - > id_full_directory_info . attrib ) ;
SIVAL ( data , 64 , file - > id_full_directory_info . ea_size ) ;
SIVAL ( data , 68 , 0 ) ; /* padding */
SBVAL ( data , 72 , file - > id_full_directory_info . file_id ) ;
2006-06-19 22:01:27 +04:00
trans2_append_data_string ( req , trans , & trans - > out . data , & file - > id_full_directory_info . name ,
2003-08-16 01:11:13 +04:00
ofs + 60 , STR_TERMINATE_ASCII ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 0 , trans - > out . data . length - ofs ) ;
break ;
2003-09-02 08:37:33 +04:00
case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO :
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , ofs + 104 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
2003-09-02 08:37:33 +04:00
SIVAL ( data , 4 , file - > id_both_directory_info . file_index ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( data , 8 , file - > id_both_directory_info . create_time ) ;
push_nttime ( data , 16 , file - > id_both_directory_info . access_time ) ;
push_nttime ( data , 24 , file - > id_both_directory_info . write_time ) ;
push_nttime ( data , 32 , file - > id_both_directory_info . change_time ) ;
2003-09-02 08:37:33 +04:00
SBVAL ( data , 40 , file - > id_both_directory_info . size ) ;
SBVAL ( data , 48 , file - > id_both_directory_info . alloc_size ) ;
SIVAL ( data , 56 , file - > id_both_directory_info . attrib ) ;
SIVAL ( data , 64 , file - > id_both_directory_info . ea_size ) ;
2003-08-13 05:53:07 +04:00
SCVAL ( data , 69 , 0 ) ; /* reserved */
2004-08-25 08:16:48 +04:00
memset ( data + 70 , 0 , 26 ) ;
2006-06-19 22:01:27 +04:00
trans2_push_data_string ( req , trans , & trans - > out . data ,
2003-08-13 05:53:07 +04:00
68 + ofs , 70 + ofs ,
2003-09-02 08:37:33 +04:00
& file - > id_both_directory_info . short_name ,
2003-08-13 05:53:07 +04:00
24 , STR_UNICODE | STR_LEN8BIT ) ;
2004-08-25 08:16:48 +04:00
SBVAL ( data , 96 , file - > id_both_directory_info . file_id ) ;
2006-06-19 22:01:27 +04:00
trans2_append_data_string ( req , trans , & trans - > out . data , & file - > id_both_directory_info . name ,
2003-08-16 01:11:13 +04:00
ofs + 60 , STR_TERMINATE_ASCII ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 0 , trans - > out . data . length - ofs ) ;
break ;
}
2004-12-20 06:12:09 +03:00
return True ;
2003-08-13 05:53:07 +04:00
}
/* callback function for trans2 findfirst/findnext */
static BOOL find_callback ( void * private , union smb_search_data * file )
{
2006-03-17 12:42:04 +03:00
struct find_state * state = talloc_get_type ( private , struct find_state ) ;
struct smb_trans2 * trans = state - > op - > trans ;
2003-08-13 05:53:07 +04:00
uint_t old_length ;
old_length = trans - > out . data . length ;
2006-03-17 12:42:04 +03:00
if ( ! find_fill_info ( state , file ) | |
2004-12-20 06:12:09 +03:00
trans - > out . data . length > trans - > in . max_data ) {
2003-08-13 05:53:07 +04:00
/* restore the old length and tell the backend to stop */
2006-06-19 22:01:27 +04:00
trans2_grow_data ( trans , & trans - > out . data , old_length ) ;
2003-08-13 05:53:07 +04:00
return False ;
}
state - > last_entry_offset = old_length ;
return True ;
}
2006-03-17 12:42:04 +03:00
/*
trans2 findfirst send
*/
static NTSTATUS trans2_findfirst_send ( struct trans_op * op )
{
struct smbsrv_request * req = op - > req ;
struct smb_trans2 * trans = op - > trans ;
union smb_search_first * search ;
struct find_state * state ;
uint8_t * param ;
2006-03-18 14:10:21 +03:00
TRANS2_CHECK_ASYNC_STATUS ( state , struct find_state ) ;
2006-03-17 12:42:04 +03:00
search = talloc_get_type ( state - > search , union smb_search_first ) ;
/* fill in the findfirst reply header */
param = trans - > out . params . data ;
SSVAL ( param , VWV ( 0 ) , search - > t2ffirst . out . handle ) ;
SSVAL ( param , VWV ( 1 ) , search - > t2ffirst . out . count ) ;
SSVAL ( param , VWV ( 2 ) , search - > t2ffirst . out . end_of_search ) ;
SSVAL ( param , VWV ( 3 ) , 0 ) ;
SSVAL ( param , VWV ( 4 ) , state - > last_entry_offset ) ;
return NT_STATUS_OK ;
}
2003-08-13 05:53:07 +04:00
/*
trans2 findfirst implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_findfirst ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
union smb_search_first * search ;
2004-05-25 21:24:24 +04:00
uint16_t level ;
2006-03-17 12:42:04 +03:00
struct find_state * state ;
2003-08-13 05:53:07 +04:00
/* make sure we got all the parameters */
if ( trans - > in . params . length < 14 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
search = talloc ( op , union smb_search_first ) ;
NT_STATUS_HAVE_NO_MEMORY ( search ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
search - > t2ffirst . in . search_attrib = SVAL ( trans - > in . params . data , 0 ) ;
search - > t2ffirst . in . max_count = SVAL ( trans - > in . params . data , 2 ) ;
search - > t2ffirst . in . flags = SVAL ( trans - > in . params . data , 4 ) ;
level = SVAL ( trans - > in . params . data , 6 ) ;
search - > t2ffirst . in . storage_type = IVAL ( trans - > in . params . data , 8 ) ;
trans2_pull_blob_string ( req , & trans - > in . params , 12 , & search - > t2ffirst . in . pattern , 0 ) ;
if ( search - > t2ffirst . in . pattern = = NULL ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
search - > t2ffirst . level = ( enum smb_search_level ) level ;
if ( search - > t2ffirst . level > = RAW_SEARCH_GENERIC ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_INVALID_LEVEL ;
}
2006-03-17 12:42:04 +03:00
if ( search - > t2ffirst . level = = RAW_SEARCH_EA_LIST ) {
2006-06-20 09:06:10 +04:00
TRANS2_CHECK ( ea_pull_name_list ( & trans - > in . data , req ,
& search - > t2ffirst . in . num_names ,
& search - > t2ffirst . in . ea_names ) ) ;
2004-12-18 07:38:43 +03:00
}
2004-12-29 02:28:02 +03:00
/* setup the private state structure that the backend will
give us in the callback */
2006-03-17 12:42:04 +03:00
state = talloc ( op , struct find_state ) ;
NT_STATUS_HAVE_NO_MEMORY ( state ) ;
state - > op = op ;
state - > search = search ;
state - > level = search - > t2ffirst . level ;
state - > last_entry_offset = 0 ;
state - > flags = search - > t2ffirst . in . flags ;
2003-08-13 05:53:07 +04:00
/* setup for just a header in the reply */
2006-06-20 09:06:10 +04:00
TRANS2_CHECK ( trans2_setup_reply ( trans , 10 , 0 , 0 ) ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
op - > op_info = state ;
op - > send_fn = trans2_findfirst_send ;
2006-03-18 14:10:21 +03:00
return ntvfs_search_first ( req - > ntvfs , search , state , find_callback ) ;
2006-03-17 12:42:04 +03:00
}
/*
trans2 findnext send
*/
static NTSTATUS trans2_findnext_send ( struct trans_op * op )
{
struct smbsrv_request * req = op - > req ;
struct smb_trans2 * trans = op - > trans ;
union smb_search_next * search ;
struct find_state * state ;
uint8_t * param ;
2006-03-18 14:10:21 +03:00
TRANS2_CHECK_ASYNC_STATUS ( state , struct find_state ) ;
2006-03-17 12:42:04 +03:00
search = talloc_get_type ( state - > search , union smb_search_next ) ;
2003-08-13 05:53:07 +04:00
/* fill in the findfirst reply header */
param = trans - > out . params . data ;
2006-03-17 12:42:04 +03:00
SSVAL ( param , VWV ( 0 ) , search - > t2fnext . out . count ) ;
SSVAL ( param , VWV ( 1 ) , search - > t2fnext . out . end_of_search ) ;
SSVAL ( param , VWV ( 2 ) , 0 ) ;
SSVAL ( param , VWV ( 3 ) , state - > last_entry_offset ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
}
/*
trans2 findnext implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_findnext ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
union smb_search_next * search ;
2004-05-25 21:24:24 +04:00
uint16_t level ;
2006-03-17 12:42:04 +03:00
struct find_state * state ;
2003-08-13 05:53:07 +04:00
/* make sure we got all the parameters */
if ( trans - > in . params . length < 12 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
search = talloc ( op , union smb_search_next ) ;
NT_STATUS_HAVE_NO_MEMORY ( search ) ;
search - > t2fnext . in . handle = SVAL ( trans - > in . params . data , 0 ) ;
search - > t2fnext . in . max_count = SVAL ( trans - > in . params . data , 2 ) ;
level = SVAL ( trans - > in . params . data , 4 ) ;
search - > t2fnext . in . resume_key = IVAL ( trans - > in . params . data , 6 ) ;
search - > t2fnext . in . flags = SVAL ( trans - > in . params . data , 10 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
trans2_pull_blob_string ( req , & trans - > in . params , 12 , & search - > t2fnext . in . last_name , 0 ) ;
if ( search - > t2fnext . in . last_name = = NULL ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
search - > t2fnext . level = ( enum smb_search_level ) level ;
if ( search - > t2fnext . level > = RAW_SEARCH_GENERIC ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_INVALID_LEVEL ;
}
2006-03-17 12:42:04 +03:00
if ( search - > t2fnext . level = = RAW_SEARCH_EA_LIST ) {
2006-06-20 09:06:10 +04:00
TRANS2_CHECK ( ea_pull_name_list ( & trans - > in . data , req ,
& search - > t2fnext . in . num_names ,
& search - > t2fnext . in . ea_names ) ) ;
2004-12-18 07:38:43 +03:00
}
2003-08-13 05:53:07 +04:00
/* setup the private state structure that the backend will give us in the callback */
2006-03-17 12:42:04 +03:00
state = talloc ( op , struct find_state ) ;
NT_STATUS_HAVE_NO_MEMORY ( state ) ;
state - > op = op ;
state - > search = search ;
state - > level = search - > t2fnext . level ;
state - > last_entry_offset = 0 ;
state - > flags = search - > t2fnext . in . flags ;
2003-08-13 05:53:07 +04:00
/* setup for just a header in the reply */
2006-06-20 09:06:10 +04:00
TRANS2_CHECK ( trans2_setup_reply ( trans , 8 , 0 , 0 ) ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
op - > op_info = state ;
op - > send_fn = trans2_findnext_send ;
2003-08-13 05:53:07 +04:00
2006-03-18 14:10:21 +03:00
return ntvfs_search_next ( req - > ntvfs , search , state , find_callback ) ;
2003-08-13 05:53:07 +04:00
}
/*
backend for trans2 requests
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_backend ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
2004-09-29 17:17:09 +04:00
NTSTATUS status ;
/* direct trans2 pass thru */
2006-03-18 14:10:21 +03:00
status = ntvfs_trans2 ( req - > ntvfs , trans ) ;
2004-09-29 17:17:09 +04:00
if ( ! NT_STATUS_EQUAL ( NT_STATUS_NOT_IMPLEMENTED , status ) ) {
return status ;
2003-08-13 05:53:07 +04:00
}
/* must have at least one setup word */
if ( trans - > in . setup_count < 1 ) {
return NT_STATUS_FOOBAR ;
}
/* the trans2 command is in setup[0] */
switch ( trans - > in . setup [ 0 ] ) {
case TRANSACT2_FINDFIRST :
2006-03-17 12:42:04 +03:00
return trans2_findfirst ( req , op ) ;
2003-08-13 05:53:07 +04:00
case TRANSACT2_FINDNEXT :
2006-03-17 12:42:04 +03:00
return trans2_findnext ( req , op ) ;
2003-08-13 05:53:07 +04:00
case TRANSACT2_QPATHINFO :
2006-03-17 12:42:04 +03:00
return trans2_qpathinfo ( req , op ) ;
2003-08-13 05:53:07 +04:00
case TRANSACT2_QFILEINFO :
2006-03-17 12:42:04 +03:00
return trans2_qfileinfo ( req , op ) ;
2003-08-13 05:53:07 +04:00
case TRANSACT2_SETFILEINFO :
2006-03-17 12:42:04 +03:00
return trans2_setfileinfo ( req , op ) ;
2003-08-13 05:53:07 +04:00
case TRANSACT2_SETPATHINFO :
2006-03-17 12:42:04 +03:00
return trans2_setpathinfo ( req , op ) ;
2003-08-13 05:53:07 +04:00
case TRANSACT2_QFSINFO :
2006-03-17 12:42:04 +03:00
return trans2_qfsinfo ( req , op ) ;
2004-11-06 10:58:45 +03:00
case TRANSACT2_OPEN :
2006-03-17 12:42:04 +03:00
return trans2_open ( req , op ) ;
2004-12-14 02:57:59 +03:00
case TRANSACT2_MKDIR :
2006-03-17 12:42:04 +03:00
return trans2_mkdir ( req , op ) ;
2003-08-13 05:53:07 +04:00
}
/* an unknown trans2 command */
return NT_STATUS_FOOBAR ;
}
2004-12-16 15:31:34 +03:00
/*
send a continue request
*/
2006-03-17 12:42:04 +03:00
static void reply_trans_continue ( struct smbsrv_request * req , uint8_t command ,
2004-12-16 15:31:34 +03:00
struct smb_trans2 * trans )
2003-08-13 05:53:07 +04:00
{
2004-12-16 15:31:34 +03:00
struct smbsrv_trans_partial * tp ;
int count ;
2003-08-13 05:53:07 +04:00
2004-12-16 15:31:34 +03:00
/* make sure they don't flood us */
for ( count = 0 , tp = req - > smb_conn - > trans_partial ; tp ; tp = tp - > next ) count + + ;
if ( count > 100 ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INSUFFICIENT_RESOURCES ) ;
2003-08-13 05:53:07 +04:00
return ;
}
2005-01-27 10:08:20 +03:00
tp = talloc ( req , struct smbsrv_trans_partial ) ;
2003-08-13 05:53:07 +04:00
2004-12-16 15:31:34 +03:00
tp - > req = talloc_reference ( tp , req ) ;
tp - > trans = trans ;
tp - > command = command ;
2003-08-13 05:53:07 +04:00
2004-12-16 15:31:34 +03:00
DLIST_ADD ( req - > smb_conn - > trans_partial , tp ) ;
2003-12-11 12:07:45 +03:00
2004-12-16 15:31:34 +03:00
/* send a 'please continue' reply */
2006-03-06 19:19:27 +03:00
smbsrv_setup_reply ( req , 0 , 0 ) ;
smbsrv_send_reply ( req ) ;
2004-12-16 15:31:34 +03:00
}
2003-08-13 05:53:07 +04:00
2004-12-16 15:31:34 +03:00
/*
answer a reconstructed trans request
*/
2006-03-18 14:10:21 +03:00
static void reply_trans_send ( struct ntvfs_request * ntvfs )
2004-12-16 15:31:34 +03:00
{
2006-03-18 14:10:21 +03:00
struct smbsrv_request * req ;
2006-03-17 12:42:04 +03:00
struct trans_op * op ;
struct smb_trans2 * trans ;
2004-12-16 15:31:34 +03:00
uint16_t params_left , data_left ;
uint8_t * params , * data ;
int i ;
2003-08-13 05:53:07 +04:00
2006-03-18 14:10:21 +03:00
SMBSRV_CHECK_ASYNC_STATUS_ERR ( op , struct trans_op ) ;
2006-03-17 12:42:04 +03:00
trans = op - > trans ;
/* if this function needs work to form the nttrans reply buffer, then
call that now */
if ( op - > send_fn ! = NULL ) {
NTSTATUS status ;
status = op - > send_fn ( op ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
smbsrv_send_error ( req , status ) ;
return ;
}
2003-08-13 05:53:07 +04:00
}
2004-12-16 15:31:34 +03:00
params_left = trans - > out . params . length ;
data_left = trans - > out . data . length ;
params = trans - > out . params . data ;
data = trans - > out . data . data ;
2004-10-29 07:48:49 +04:00
2006-03-06 19:19:27 +03:00
smbsrv_setup_reply ( req , 10 + trans - > out . setup_count , 0 ) ;
2004-10-29 07:48:49 +04:00
2006-03-18 14:10:21 +03:00
if ( ! NT_STATUS_IS_OK ( req - > ntvfs - > async_states - > status ) ) {
smbsrv_setup_error ( req , req - > ntvfs - > async_states - > status ) ;
2004-10-29 07:48:49 +04:00
}
2003-08-13 05:53:07 +04:00
/* we need to divide up the reply into chunks that fit into
the negotiated buffer size */
do {
2004-05-25 21:24:24 +04:00
uint16_t this_data , this_param , max_bytes ;
2003-08-13 05:53:07 +04:00
uint_t align1 = 1 , align2 = ( params_left ? 2 : 0 ) ;
2004-10-29 07:48:49 +04:00
struct smbsrv_request * this_req ;
2003-08-13 05:53:07 +04:00
max_bytes = req_max_data ( req ) - ( align1 + align2 ) ;
this_param = params_left ;
if ( this_param > max_bytes ) {
this_param = max_bytes ;
}
max_bytes - = this_param ;
this_data = data_left ;
if ( this_data > max_bytes ) {
this_data = max_bytes ;
}
2004-10-29 07:48:49 +04:00
/* don't destroy unless this is the last chunk */
if ( params_left - this_param ! = 0 | |
data_left - this_data ! = 0 ) {
2006-03-06 19:19:27 +03:00
this_req = smbsrv_setup_secondary_request ( req ) ;
2004-10-29 07:48:49 +04:00
} else {
this_req = req ;
}
req_grow_data ( this_req , this_param + this_data + ( align1 + align2 ) ) ;
2003-08-13 05:53:07 +04:00
2004-12-16 15:31:34 +03:00
SSVAL ( this_req - > out . vwv , VWV ( 0 ) , trans - > out . params . length ) ;
SSVAL ( this_req - > out . vwv , VWV ( 1 ) , trans - > out . data . length ) ;
2004-10-29 07:48:49 +04:00
SSVAL ( this_req - > out . vwv , VWV ( 2 ) , 0 ) ;
2003-08-13 05:53:07 +04:00
2004-10-29 07:48:49 +04:00
SSVAL ( this_req - > out . vwv , VWV ( 3 ) , this_param ) ;
SSVAL ( this_req - > out . vwv , VWV ( 4 ) , align1 + PTR_DIFF ( this_req - > out . data , this_req - > out . hdr ) ) ;
2004-12-16 15:31:34 +03:00
SSVAL ( this_req - > out . vwv , VWV ( 5 ) , PTR_DIFF ( params , trans - > out . params . data ) ) ;
2003-08-13 05:53:07 +04:00
2004-10-29 07:48:49 +04:00
SSVAL ( this_req - > out . vwv , VWV ( 6 ) , this_data ) ;
SSVAL ( this_req - > out . vwv , VWV ( 7 ) , align1 + align2 +
PTR_DIFF ( this_req - > out . data + this_param , this_req - > out . hdr ) ) ;
2004-12-16 15:31:34 +03:00
SSVAL ( this_req - > out . vwv , VWV ( 8 ) , PTR_DIFF ( data , trans - > out . data . data ) ) ;
2003-08-13 05:53:07 +04:00
2004-12-16 15:31:34 +03:00
SSVAL ( this_req - > out . vwv , VWV ( 9 ) , trans - > out . setup_count ) ;
for ( i = 0 ; i < trans - > out . setup_count ; i + + ) {
SSVAL ( this_req - > out . vwv , VWV ( 10 + i ) , trans - > out . setup [ i ] ) ;
2003-08-13 05:53:07 +04:00
}
2004-10-29 07:48:49 +04:00
memset ( this_req - > out . data , 0 , align1 ) ;
2003-08-13 05:53:07 +04:00
if ( this_param ! = 0 ) {
2004-10-29 07:48:49 +04:00
memcpy ( this_req - > out . data + align1 , params , this_param ) ;
2003-08-13 05:53:07 +04:00
}
2004-10-29 07:48:49 +04:00
memset ( this_req - > out . data + this_param + align1 , 0 , align2 ) ;
2003-08-13 05:53:07 +04:00
if ( this_data ! = 0 ) {
2004-10-29 07:48:49 +04:00
memcpy ( this_req - > out . data + this_param + align1 + align2 , data , this_data ) ;
2003-08-13 05:53:07 +04:00
}
params_left - = this_param ;
data_left - = this_data ;
params + = this_param ;
data + = this_data ;
2006-03-06 19:19:27 +03:00
smbsrv_send_reply ( this_req ) ;
2003-08-13 05:53:07 +04:00
} while ( params_left ! = 0 | | data_left ! = 0 ) ;
}
2003-12-11 12:07:45 +03:00
2006-03-17 12:42:04 +03:00
/*
answer a reconstructed trans request
*/
static void reply_trans_complete ( struct smbsrv_request * req , uint8_t command ,
struct smb_trans2 * trans )
{
struct trans_op * op ;
2006-03-18 14:10:21 +03:00
SMBSRV_TALLOC_IO_PTR ( op , struct trans_op ) ;
SMBSRV_SETUP_NTVFS_REQUEST ( reply_trans_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
2006-03-17 12:42:04 +03:00
op - > req = req ;
op - > trans = trans ;
op - > command = command ;
op - > op_info = NULL ;
op - > send_fn = NULL ;
/* its a full request, give it to the backend */
if ( command = = SMBtrans ) {
2006-03-18 14:10:21 +03:00
SMBSRV_CALL_NTVFS_BACKEND ( ntvfs_trans ( req - > ntvfs , trans ) ) ;
return ;
2006-03-17 12:42:04 +03:00
} else {
2006-03-18 14:10:21 +03:00
SMBSRV_CALL_NTVFS_BACKEND ( trans2_backend ( req , op ) ) ;
return ;
2006-03-17 12:42:04 +03:00
}
}
2004-12-16 15:31:34 +03:00
/*
Reply to an SMBtrans or SMBtrans2 request
*/
2006-03-06 18:04:59 +03:00
static void reply_trans_generic ( struct smbsrv_request * req , uint8_t command )
2004-12-16 15:31:34 +03:00
{
struct smb_trans2 * trans ;
int i ;
uint16_t param_ofs , data_ofs ;
uint16_t param_count , data_count ;
uint16_t param_total , data_total ;
/* parse request */
if ( req - > in . wct < 14 ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-12-16 15:31:34 +03:00
return ;
}
2006-03-17 12:42:04 +03:00
trans = talloc ( req , struct smb_trans2 ) ;
if ( trans = = NULL ) {
smbsrv_send_error ( req , NT_STATUS_NO_MEMORY ) ;
return ;
}
2004-12-16 15:31:34 +03:00
param_total = SVAL ( req - > in . vwv , VWV ( 0 ) ) ;
data_total = SVAL ( req - > in . vwv , VWV ( 1 ) ) ;
trans - > in . max_param = SVAL ( req - > in . vwv , VWV ( 2 ) ) ;
trans - > in . max_data = SVAL ( req - > in . vwv , VWV ( 3 ) ) ;
trans - > in . max_setup = CVAL ( req - > in . vwv , VWV ( 4 ) ) ;
trans - > in . flags = SVAL ( req - > in . vwv , VWV ( 5 ) ) ;
trans - > in . timeout = IVAL ( req - > in . vwv , VWV ( 6 ) ) ;
param_count = SVAL ( req - > in . vwv , VWV ( 9 ) ) ;
param_ofs = SVAL ( req - > in . vwv , VWV ( 10 ) ) ;
data_count = SVAL ( req - > in . vwv , VWV ( 11 ) ) ;
data_ofs = SVAL ( req - > in . vwv , VWV ( 12 ) ) ;
trans - > in . setup_count = CVAL ( req - > in . vwv , VWV ( 13 ) ) ;
if ( req - > in . wct ! = 14 + trans - > in . setup_count ) {
2006-03-06 21:29:48 +03:00
smbsrv_send_error ( req , NT_STATUS_DOS ( ERRSRV , ERRerror ) ) ;
2004-12-16 15:31:34 +03:00
return ;
}
/* parse out the setup words */
2006-03-17 12:42:04 +03:00
trans - > in . setup = talloc_array ( trans , uint16_t , trans - > in . setup_count ) ;
2004-12-16 15:31:34 +03:00
if ( trans - > in . setup_count & & ! trans - > in . setup ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_NO_MEMORY ) ;
2004-12-16 15:31:34 +03:00
return ;
}
for ( i = 0 ; i < trans - > in . setup_count ; i + + ) {
trans - > in . setup [ i ] = SVAL ( req - > in . vwv , VWV ( 14 + i ) ) ;
}
if ( command = = SMBtrans ) {
req_pull_string ( req , & trans - > in . trans_name , req - > in . data , - 1 , STR_TERMINATE ) ;
}
if ( ! req_pull_blob ( req , req - > in . hdr + param_ofs , param_count , & trans - > in . params ) | |
! req_pull_blob ( req , req - > in . hdr + data_ofs , data_count , & trans - > in . data ) ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_FOOBAR ) ;
2004-12-16 15:31:34 +03:00
return ;
}
/* is it a partial request? if so, then send a 'send more' message */
if ( param_total > param_count | | data_total > data_count ) {
reply_trans_continue ( req , command , trans ) ;
return ;
}
reply_trans_complete ( req , command , trans ) ;
}
/*
Reply to an SMBtranss2 request
*/
static void reply_transs_generic ( struct smbsrv_request * req , uint8_t command )
{
struct smbsrv_trans_partial * tp ;
struct smb_trans2 * trans = NULL ;
uint16_t param_ofs , data_ofs ;
uint16_t param_count , data_count ;
uint16_t param_disp , data_disp ;
uint16_t param_total , data_total ;
DATA_BLOB params , data ;
2006-03-17 12:42:04 +03:00
/* parse request */
if ( req - > in . wct < 8 ) {
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
2004-12-16 15:31:34 +03:00
for ( tp = req - > smb_conn - > trans_partial ; tp ; tp = tp - > next ) {
if ( tp - > command = = command & &
SVAL ( tp - > req - > in . hdr , HDR_MID ) = = SVAL ( req - > in . hdr , HDR_MID ) ) {
2006-03-17 12:42:04 +03:00
/* TODO: check the VUID, PID and TID too? */
2004-12-16 15:31:34 +03:00
break ;
}
}
if ( tp = = NULL ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-12-16 15:31:34 +03:00
return ;
}
trans = tp - > trans ;
param_total = SVAL ( req - > in . vwv , VWV ( 0 ) ) ;
data_total = SVAL ( req - > in . vwv , VWV ( 1 ) ) ;
param_count = SVAL ( req - > in . vwv , VWV ( 2 ) ) ;
param_ofs = SVAL ( req - > in . vwv , VWV ( 3 ) ) ;
param_disp = SVAL ( req - > in . vwv , VWV ( 4 ) ) ;
data_count = SVAL ( req - > in . vwv , VWV ( 5 ) ) ;
data_ofs = SVAL ( req - > in . vwv , VWV ( 6 ) ) ;
data_disp = SVAL ( req - > in . vwv , VWV ( 7 ) ) ;
if ( ! req_pull_blob ( req , req - > in . hdr + param_ofs , param_count , & params ) | |
! req_pull_blob ( req , req - > in . hdr + data_ofs , data_count , & data ) ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-12-16 15:31:34 +03:00
return ;
}
/* only allow contiguous requests */
if ( ( param_count ! = 0 & &
param_disp ! = trans - > in . params . length ) | |
( data_count ! = 0 & &
data_disp ! = trans - > in . data . length ) ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-12-16 15:31:34 +03:00
return ;
}
/* add to the existing request */
if ( param_count ! = 0 ) {
2005-01-27 10:08:20 +03:00
trans - > in . params . data = talloc_realloc ( trans ,
2004-12-16 15:31:34 +03:00
trans - > in . params . data ,
uint8_t ,
param_disp + param_count ) ;
if ( trans - > in . params . data = = NULL ) {
goto failed ;
}
trans - > in . params . length = param_disp + param_count ;
}
if ( data_count ! = 0 ) {
2005-01-27 10:08:20 +03:00
trans - > in . data . data = talloc_realloc ( trans ,
2004-12-16 15:31:34 +03:00
trans - > in . data . data ,
uint8_t ,
data_disp + data_count ) ;
if ( trans - > in . data . data = = NULL ) {
goto failed ;
}
trans - > in . data . length = data_disp + data_count ;
}
memcpy ( trans - > in . params . data + param_disp , params . data , params . length ) ;
memcpy ( trans - > in . data . data + data_disp , data . data , data . length ) ;
/* the sequence number of the reply is taken from the last secondary
response */
tp - > req - > seq_num = req - > seq_num ;
/* we don't reply to Transs2 requests */
talloc_free ( req ) ;
if ( trans - > in . params . length = = param_total & &
trans - > in . data . length = = data_total ) {
/* its now complete */
DLIST_REMOVE ( tp - > req - > smb_conn - > trans_partial , tp ) ;
2005-12-06 03:12:32 +03:00
reply_trans_complete ( tp - > req , command , trans ) ;
2004-12-16 15:31:34 +03:00
}
return ;
failed :
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( tp - > req , NT_STATUS_NO_MEMORY ) ;
2004-12-16 15:31:34 +03:00
DLIST_REMOVE ( req - > smb_conn - > trans_partial , tp ) ;
talloc_free ( req ) ;
talloc_free ( tp ) ;
}
/*
Reply to an SMBtrans2
*/
2006-03-06 18:31:01 +03:00
void smbsrv_reply_trans2 ( struct smbsrv_request * req )
2003-12-11 12:07:45 +03:00
{
reply_trans_generic ( req , SMBtrans2 ) ;
}
2004-12-16 15:31:34 +03:00
/*
Reply to an SMBtrans
*/
2006-03-06 18:31:01 +03:00
void smbsrv_reply_trans ( struct smbsrv_request * req )
2003-12-11 12:07:45 +03:00
{
reply_trans_generic ( req , SMBtrans ) ;
}
2004-12-16 15:31:34 +03:00
/*
Reply to an SMBtranss request
*/
2006-03-06 18:31:01 +03:00
void smbsrv_reply_transs ( struct smbsrv_request * req )
2003-12-11 12:07:45 +03:00
{
2004-12-16 15:31:34 +03:00
reply_transs_generic ( req , SMBtrans ) ;
2003-12-11 12:07:45 +03:00
}
2004-12-16 15:31:34 +03:00
/*
Reply to an SMBtranss2 request
*/
2006-03-06 18:31:01 +03:00
void smbsrv_reply_transs2 ( struct smbsrv_request * req )
2004-12-16 15:31:34 +03:00
{
reply_transs_generic ( req , SMBtrans2 ) ;
}