2023-10-31 15:48:09 +01:00
/*
2003-08-13 01:53:07 +00:00
Unix SMB / CIFS implementation .
raw trans / trans2 / nttrans operations
Copyright ( C ) James Myers 2003 < myersjj @ samba . org >
2023-10-31 15:48:09 +01:00
2003-08-13 01:53:07 +00:00
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 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 01:53:07 +00:00
( at your option ) any later version .
2023-10-31 15:48:09 +01:00
2003-08-13 01:53:07 +00:00
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 .
2023-10-31 15:48:09 +01:00
2003-08-13 01:53:07 +00:00
You should have received a copy of the GNU General Public License
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 01:53:07 +00:00
*/
# include "includes.h"
2011-09-23 08:35:17 +02:00
# include <tevent.h>
2004-11-01 01:03:22 +00:00
# include "libcli/raw/libcliraw.h"
2008-04-02 04:53:27 +02:00
# include "libcli/raw/raw_proto.h"
2011-09-23 08:35:17 +02:00
# include "../libcli/smb/smbXcli_base.h"
2003-08-13 01:53:07 +00:00
2011-09-23 08:35:17 +02:00
static void smb_raw_trans_backend_done ( struct tevent_req * subreq ) ;
2003-08-13 01:53:07 +00:00
2011-09-23 08:35:17 +02:00
static struct smbcli_request * smb_raw_trans_backend_send ( struct smbcli_tree * tree ,
struct smb_trans2 * parms ,
uint8_t command )
2003-10-28 10:17:05 +00:00
{
2008-07-04 20:46:10 +02:00
struct smbcli_request * req ;
2011-09-23 08:35:17 +02:00
uint8_t additional_flags ;
uint8_t clear_flags ;
uint16_t additional_flags2 ;
uint16_t clear_flags2 ;
uint32_t pid ;
2012-07-23 21:34:58 +02:00
struct smbXcli_tcon * tcon = NULL ;
2012-07-23 20:15:21 +02:00
struct smbXcli_session * session = NULL ;
2011-09-23 08:35:17 +02:00
const char * pipe_name = NULL ;
uint8_t s ;
uint32_t timeout_msec ;
uint32_t tmp ;
tmp = parms - > in . params . length + parms - > in . data . length ;
req = smbcli_request_setup ( tree , command , parms - > in . setup_count , tmp ) ;
if ( req = = NULL ) {
2005-06-30 01:34:53 +00:00
return NULL ;
}
2004-12-16 12:29:04 +00:00
2011-09-23 08:35:17 +02:00
additional_flags = CVAL ( req - > out . hdr , HDR_FLG ) ;
additional_flags2 = SVAL ( req - > out . hdr , HDR_FLG2 ) ;
pid = SVAL ( req - > out . hdr , HDR_PID ) ;
pid | = SVAL ( req - > out . hdr , HDR_PIDHIGH ) < < 16 ;
2012-07-23 20:15:21 +02:00
if ( req - > session ) {
session = req - > session - > smbXcli ;
}
2008-07-04 20:46:10 +02:00
2012-07-23 21:34:58 +02:00
if ( req - > tree ) {
tcon = req - > tree - > smbXcli ;
}
2011-09-23 08:35:17 +02:00
clear_flags = ~ additional_flags ;
clear_flags2 = ~ additional_flags2 ;
2008-07-04 20:46:10 +02:00
2011-09-23 08:35:17 +02:00
timeout_msec = req - > transport - > options . request_timeout * 1000 ;
2008-07-04 20:46:10 +02:00
2011-09-23 08:35:17 +02:00
for ( s = 0 ; s < parms - > in . setup_count ; s + + ) {
SSVAL ( req - > out . vwv , VWV ( s ) , parms - > in . setup [ s ] ) ;
2003-08-13 01:53:07 +00:00
}
2008-07-04 20:46:10 +02:00
2019-05-24 11:00:05 +12:00
if ( parms - > in . params . length > 0 ) {
memcpy ( req - > out . data ,
parms - > in . params . data ,
parms - > in . params . length ) ;
}
if ( parms - > in . data . length > 0 ) {
memcpy ( req - > out . data + parms - > in . params . length ,
parms - > in . data . data ,
parms - > in . data . length ) ;
}
2003-08-13 01:53:07 +00:00
2011-09-23 08:35:17 +02:00
if ( command = = SMBtrans & & parms - > in . trans_name ) {
pipe_name = parms - > in . trans_name ;
}
req - > subreqs [ 0 ] = smb1cli_trans_send ( req ,
req - > transport - > ev ,
req - > transport - > conn ,
command ,
additional_flags ,
clear_flags ,
additional_flags2 ,
clear_flags2 ,
timeout_msec ,
2012-07-23 21:34:58 +02:00
pid ,
tcon ,
2012-07-23 20:15:21 +02:00
session ,
2011-09-23 08:35:17 +02:00
pipe_name ,
0xFFFF , /* fid */
0 , /* function */
parms - > in . flags ,
( uint16_t * ) req - > out . vwv ,
parms - > in . setup_count ,
parms - > in . max_setup ,
req - > out . data ,
parms - > in . params . length ,
parms - > in . max_param ,
req - > out . data +
parms - > in . params . length ,
parms - > in . data . length ,
parms - > in . max_data ) ;
if ( req - > subreqs [ 0 ] = = NULL ) {
talloc_free ( req ) ;
2003-08-13 01:53:07 +00:00
return NULL ;
}
2011-09-23 08:35:17 +02:00
tevent_req_set_callback ( req - > subreqs [ 0 ] ,
smb_raw_trans_backend_done ,
req ) ;
2004-12-16 12:29:04 +00:00
2008-07-04 20:46:10 +02:00
return req ;
}
2004-12-16 12:29:04 +00:00
2011-09-23 08:35:17 +02:00
static void smb_raw_trans_backend_done ( struct tevent_req * subreq )
2008-07-04 20:46:10 +02:00
{
2011-09-23 08:35:17 +02:00
struct smbcli_request * req =
tevent_req_callback_data ( subreq ,
struct smbcli_request ) ;
struct smbcli_transport * transport = req - > transport ;
uint16_t * setup = NULL ;
uint8_t num_setup = 0 ;
uint8_t s ;
uint8_t * param = NULL ;
uint32_t num_param = 0 ;
uint8_t * data = NULL ;
uint32_t num_data = 0 ;
req - > status = smb1cli_trans_recv ( req - > subreqs [ 0 ] , req ,
& req - > flags2 ,
& setup ,
0 , /* min_setup */
& num_setup ,
& param ,
0 , /* min_param */
& num_param ,
& data ,
0 , /* min_data */
& num_data ) ;
TALLOC_FREE ( req - > subreqs [ 0 ] ) ;
if ( NT_STATUS_IS_ERR ( req - > status ) ) {
req - > state = SMBCLI_REQUEST_ERROR ;
transport - > error . e . nt_status = req - > status ;
transport - > error . etype = ETYPE_SMB ;
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
}
return ;
}
req - > trans2 . out . setup_count = num_setup ;
req - > trans2 . out . setup = talloc_array ( req , uint16_t , num_setup ) ;
if ( req - > trans2 . out . setup = = NULL ) {
req - > state = SMBCLI_REQUEST_ERROR ;
req - > status = NT_STATUS_NO_MEMORY ;
transport - > error . e . nt_status = req - > status ;
transport - > error . etype = ETYPE_SMB ;
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
}
return ;
2008-07-04 20:46:10 +02:00
}
2011-09-23 08:35:17 +02:00
for ( s = 0 ; s < num_setup ; s + + ) {
req - > trans2 . out . setup [ s ] = SVAL ( setup , VWV ( s ) ) ;
2004-12-16 12:29:04 +00:00
}
2008-07-04 20:46:10 +02:00
2011-09-23 08:35:17 +02:00
req - > trans2 . out . params . data = param ;
req - > trans2 . out . params . length = num_param ;
2004-12-16 12:29:04 +00:00
2011-09-23 08:35:17 +02:00
req - > trans2 . out . data . data = data ;
req - > trans2 . out . data . length = num_data ;
2004-12-16 12:29:04 +00:00
2011-09-23 08:35:17 +02:00
transport - > error . e . nt_status = req - > status ;
if ( NT_STATUS_IS_OK ( req - > status ) ) {
transport - > error . etype = ETYPE_NONE ;
} else {
transport - > error . etype = ETYPE_SMB ;
2008-07-04 20:46:10 +02:00
}
2004-12-16 12:29:04 +00:00
2011-09-23 08:35:17 +02:00
req - > state = SMBCLI_REQUEST_DONE ;
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
2004-12-16 12:29:04 +00:00
}
2008-07-04 20:46:10 +02:00
}
2011-09-23 08:35:17 +02:00
static NTSTATUS smb_raw_trans_backend_recv ( struct smbcli_request * req ,
TALLOC_CTX * mem_ctx ,
struct smb_trans2 * parms )
2008-07-04 20:46:10 +02:00
{
2011-09-23 08:35:17 +02:00
if ( ! smbcli_request_receive ( req ) | |
smbcli_request_is_error ( req ) ) {
goto failed ;
2008-07-04 20:46:10 +02:00
}
2011-09-23 08:35:17 +02:00
parms - > out = req - > trans2 . out ;
talloc_steal ( mem_ctx , parms - > out . setup ) ;
talloc_steal ( mem_ctx , parms - > out . params . data ) ;
talloc_steal ( mem_ctx , parms - > out . data . data ) ;
2003-10-28 10:17:05 +00:00
2011-09-23 08:35:17 +02:00
failed :
return smbcli_request_destroy ( req ) ;
2003-10-28 10:17:05 +00:00
}
2011-09-23 08:35:17 +02:00
_PUBLIC_ struct smbcli_request * smb_raw_trans_send ( struct smbcli_tree * tree ,
2003-10-28 10:17:05 +00:00
struct smb_trans2 * parms )
{
2011-09-23 08:35:17 +02:00
return smb_raw_trans_backend_send ( tree , parms , SMBtrans ) ;
2003-10-28 10:17:05 +00:00
}
2011-09-23 08:35:17 +02:00
_PUBLIC_ NTSTATUS smb_raw_trans_recv ( struct smbcli_request * req ,
TALLOC_CTX * mem_ctx ,
struct smb_trans2 * parms )
2003-08-13 01:53:07 +00:00
{
2011-09-23 08:35:17 +02:00
return smb_raw_trans_backend_recv ( req , mem_ctx , parms ) ;
2003-08-13 01:53:07 +00:00
}
2008-04-02 04:53:27 +02:00
_PUBLIC_ NTSTATUS smb_raw_trans ( struct smbcli_tree * tree ,
2003-10-28 10:17:05 +00:00
TALLOC_CTX * mem_ctx ,
struct smb_trans2 * parms )
{
2004-08-04 13:23:35 +00:00
struct smbcli_request * req ;
2003-10-28 10:17:05 +00:00
req = smb_raw_trans_send ( tree , parms ) ;
if ( ! req ) return NT_STATUS_UNSUCCESSFUL ;
return smb_raw_trans_recv ( req , mem_ctx , parms ) ;
}
2011-09-23 08:35:17 +02:00
struct smbcli_request * smb_raw_trans2_send ( struct smbcli_tree * tree ,
struct smb_trans2 * parms )
2003-08-13 01:53:07 +00:00
{
2011-09-23 08:35:17 +02:00
return smb_raw_trans_backend_send ( tree , parms , SMBtrans2 ) ;
2008-07-04 20:07:52 +02:00
}
2011-09-23 08:35:17 +02:00
NTSTATUS smb_raw_trans2_recv ( struct smbcli_request * req ,
TALLOC_CTX * mem_ctx ,
struct smb_trans2 * parms )
2008-07-04 20:07:52 +02:00
{
2011-09-23 08:35:17 +02:00
return smb_raw_trans_backend_recv ( req , mem_ctx , parms ) ;
}
2008-07-04 20:07:52 +02:00
2011-09-23 08:35:17 +02:00
NTSTATUS smb_raw_trans2 ( struct smbcli_tree * tree ,
TALLOC_CTX * mem_ctx ,
struct smb_trans2 * parms )
{
struct smbcli_request * req ;
req = smb_raw_trans2_send ( tree , parms ) ;
if ( ! req ) return NT_STATUS_UNSUCCESSFUL ;
return smb_raw_trans2_recv ( req , mem_ctx , parms ) ;
2003-08-13 01:53:07 +00:00
}
2011-09-23 08:35:17 +02:00
static void smb_raw_nttrans_done ( struct tevent_req * subreq ) ;
2004-08-04 13:23:35 +00:00
struct smbcli_request * smb_raw_nttrans_send ( struct smbcli_tree * tree ,
2011-09-23 08:35:17 +02:00
struct smb_nttrans * parms )
2003-08-13 01:53:07 +00:00
{
2011-09-23 08:35:17 +02:00
struct smbcli_request * req ;
uint8_t additional_flags ;
uint8_t clear_flags ;
uint16_t additional_flags2 ;
uint16_t clear_flags2 ;
uint32_t pid ;
2012-07-23 21:34:58 +02:00
struct smbXcli_tcon * tcon = NULL ;
2012-07-23 20:15:21 +02:00
struct smbXcli_session * session = NULL ;
2011-09-23 08:35:17 +02:00
uint32_t timeout_msec ;
uint32_t tmp ;
tmp = parms - > in . params . length + parms - > in . data . length ;
req = smbcli_request_setup ( tree , SMBnttrans , parms - > in . setup_count , tmp ) ;
if ( req = = NULL ) {
2003-08-13 01:53:07 +00:00
return NULL ;
}
2008-07-04 20:07:52 +02:00
2011-09-23 08:35:17 +02:00
additional_flags = CVAL ( req - > out . hdr , HDR_FLG ) ;
additional_flags2 = SVAL ( req - > out . hdr , HDR_FLG2 ) ;
pid = SVAL ( req - > out . hdr , HDR_PID ) ;
pid | = SVAL ( req - > out . hdr , HDR_PIDHIGH ) < < 16 ;
2012-07-23 20:15:21 +02:00
if ( req - > session ) {
session = req - > session - > smbXcli ;
}
2011-09-23 08:35:17 +02:00
2012-07-23 21:34:58 +02:00
if ( req - > tree ) {
tcon = req - > tree - > smbXcli ;
}
2011-09-23 08:35:17 +02:00
clear_flags = ~ additional_flags ;
clear_flags2 = ~ additional_flags2 ;
timeout_msec = req - > transport - > options . request_timeout * 1000 ;
2019-05-24 11:00:05 +12:00
if ( parms - > in . setup_count > 0 ) {
memcpy (
req - > out . vwv , parms - > in . setup , parms - > in . setup_count * 2 ) ;
}
2011-09-23 08:35:17 +02:00
2019-05-24 11:00:05 +12:00
if ( parms - > in . params . length > 0 ) {
memcpy ( req - > out . data ,
parms - > in . params . data ,
parms - > in . params . length ) ;
}
if ( parms - > in . data . length > 0 ) {
memcpy ( req - > out . data + parms - > in . params . length ,
parms - > in . data . data ,
parms - > in . data . length ) ;
}
2011-09-23 08:35:17 +02:00
req - > subreqs [ 0 ] = smb1cli_trans_send ( req ,
req - > transport - > ev ,
req - > transport - > conn ,
SMBnttrans ,
additional_flags ,
clear_flags ,
additional_flags2 ,
clear_flags2 ,
timeout_msec ,
2012-07-23 21:34:58 +02:00
pid ,
tcon ,
2012-07-23 20:15:21 +02:00
session ,
2011-09-23 08:35:17 +02:00
NULL , /* pipe_name */
0xFFFF , /* fid */
parms - > in . function ,
0 , /* flags */
( uint16_t * ) req - > out . vwv ,
parms - > in . setup_count ,
parms - > in . max_setup ,
req - > out . data ,
parms - > in . params . length ,
parms - > in . max_param ,
req - > out . data +
parms - > in . params . length ,
parms - > in . data . length ,
parms - > in . max_data ) ;
if ( req - > subreqs [ 0 ] = = NULL ) {
2008-07-04 20:07:52 +02:00
talloc_free ( req ) ;
return NULL ;
}
2011-09-23 08:35:17 +02:00
tevent_req_set_callback ( req - > subreqs [ 0 ] ,
smb_raw_nttrans_done ,
req ) ;
2008-07-04 20:07:52 +02:00
2011-09-23 08:35:17 +02:00
return req ;
}
2008-07-07 15:04:59 +02:00
2011-09-23 08:35:17 +02:00
static void smb_raw_nttrans_done ( struct tevent_req * subreq )
{
struct smbcli_request * req =
tevent_req_callback_data ( subreq ,
struct smbcli_request ) ;
struct smbcli_transport * transport = req - > transport ;
uint16_t * setup = NULL ;
uint8_t num_setup = 0 ;
uint8_t * param = NULL ;
uint32_t num_param = 0 ;
uint8_t * data = NULL ;
uint32_t num_data = 0 ;
req - > status = smb1cli_trans_recv ( req - > subreqs [ 0 ] , req ,
& req - > flags2 ,
& setup ,
0 , /* min_setup */
& num_setup ,
& param ,
0 , /* min_param */
& num_param ,
& data ,
0 , /* min_data */
& num_data ) ;
TALLOC_FREE ( req - > subreqs [ 0 ] ) ;
if ( NT_STATUS_IS_ERR ( req - > status ) ) {
req - > state = SMBCLI_REQUEST_ERROR ;
transport - > error . e . nt_status = req - > status ;
transport - > error . etype = ETYPE_SMB ;
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
2008-07-07 15:04:59 +02:00
}
2011-09-23 08:35:17 +02:00
return ;
2008-07-07 15:04:59 +02:00
}
2011-09-23 08:35:17 +02:00
req - > nttrans . out . setup_count = num_setup ;
req - > nttrans . out . setup = ( uint8_t * ) setup ;
2008-07-07 15:04:59 +02:00
2011-09-23 08:35:17 +02:00
req - > nttrans . out . params . data = param ;
req - > nttrans . out . params . length = num_param ;
2008-07-07 15:04:59 +02:00
2011-09-23 08:35:17 +02:00
req - > nttrans . out . data . data = data ;
req - > nttrans . out . data . length = num_data ;
2008-07-07 15:04:59 +02:00
2011-09-23 08:35:17 +02:00
transport - > error . e . nt_status = req - > status ;
if ( NT_STATUS_IS_OK ( req - > status ) ) {
transport - > error . etype = ETYPE_NONE ;
} else {
transport - > error . etype = ETYPE_SMB ;
2008-07-07 15:04:59 +02:00
}
2011-09-23 08:35:17 +02:00
req - > state = SMBCLI_REQUEST_DONE ;
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
2003-08-13 01:53:07 +00:00
}
}
2011-09-23 08:35:17 +02:00
NTSTATUS smb_raw_nttrans_recv ( struct smbcli_request * req ,
TALLOC_CTX * mem_ctx ,
struct smb_nttrans * parms )
2008-07-07 15:04:59 +02:00
{
2011-09-23 08:35:17 +02:00
if ( ! smbcli_request_receive ( req ) | |
smbcli_request_is_error ( req ) ) {
2008-07-07 15:04:59 +02:00
goto failed ;
}
2011-09-23 08:35:17 +02:00
parms - > out = req - > nttrans . out ;
talloc_steal ( mem_ctx , parms - > out . setup ) ;
talloc_steal ( mem_ctx , parms - > out . params . data ) ;
talloc_steal ( mem_ctx , parms - > out . data . data ) ;
2008-07-07 15:04:59 +02:00
failed :
2011-09-23 08:35:17 +02:00
return smbcli_request_destroy ( req ) ;
2008-07-07 15:04:59 +02:00
}
2003-08-13 01:53:07 +00:00
/****************************************************************************
receive a SMB nttrans response allocating the necessary memory
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-08-04 13:23:35 +00:00
NTSTATUS smb_raw_nttrans ( struct smbcli_tree * tree ,
2003-08-13 01:53:07 +00:00
TALLOC_CTX * mem_ctx ,
struct smb_nttrans * parms )
{
2004-08-04 13:23:35 +00:00
struct smbcli_request * req ;
2003-08-13 01:53:07 +00:00
req = smb_raw_nttrans_send ( tree , parms ) ;
if ( ! req ) {
return NT_STATUS_UNSUCCESSFUL ;
}
return smb_raw_nttrans_recv ( req , mem_ctx , parms ) ;
}